|
| 1 | +// SPDX-License-Identifier: MIT |
| 2 | + |
| 3 | +pragma solidity ^0.8.26; |
| 4 | + |
| 5 | +import {IERC1155} from "../../interfaces/IERC1155.sol"; |
| 6 | +import {IERC1155Receiver} from "../../interfaces/IERC1155Receiver.sol"; |
| 7 | +import {IERC1155Errors} from "../../interfaces/draft-IERC6093.sol"; |
| 8 | +import {ERC1155Holder} from "../../token/ERC1155/utils/ERC1155Holder.sol"; |
| 9 | +import {BridgeMultiToken} from "./abstract/BridgeMultiToken.sol"; |
| 10 | + |
| 11 | +/** |
| 12 | + * @dev This is a variant of {BridgeMultiToken} that implements the bridge logic for ERC-1155 tokens that do not expose |
| 13 | + * a crosschain mint and burn mechanism. Instead, it takes custody of bridged assets. |
| 14 | + */ |
| 15 | +// slither-disable-next-line locked-ether |
| 16 | +abstract contract BridgeERC1155 is BridgeMultiToken, ERC1155Holder { |
| 17 | + IERC1155 private immutable _token; |
| 18 | + |
| 19 | + constructor(IERC1155 token_) { |
| 20 | + _token = token_; |
| 21 | + } |
| 22 | + |
| 23 | + /// @dev Return the address of the ERC1155 token this bridge operates on. |
| 24 | + function token() public view virtual returns (IERC1155) { |
| 25 | + return _token; |
| 26 | + } |
| 27 | + |
| 28 | + /** |
| 29 | + * @dev Transfer `amount` tokens to a crosschain receiver. |
| 30 | + * |
| 31 | + * Note: The `to` parameter is the full InteroperableAddress (chain ref + address). |
| 32 | + */ |
| 33 | + function crosschainTransferFrom(address from, bytes memory to, uint256 id, uint256 value) public returns (bytes32) { |
| 34 | + uint256[] memory ids = new uint256[](1); |
| 35 | + uint256[] memory values = new uint256[](1); |
| 36 | + ids[0] = id; |
| 37 | + values[0] = value; |
| 38 | + |
| 39 | + return crosschainTransferFrom(from, to, ids, values); |
| 40 | + } |
| 41 | + |
| 42 | + /** |
| 43 | + * @dev Transfer `amount` tokens to a crosschain receiver. |
| 44 | + * |
| 45 | + * Note: The `to` parameter is the full InteroperableAddress (chain ref + address). |
| 46 | + */ |
| 47 | + function crosschainTransferFrom( |
| 48 | + address from, |
| 49 | + bytes memory to, |
| 50 | + uint256[] memory ids, |
| 51 | + uint256[] memory values |
| 52 | + ) public virtual returns (bytes32) { |
| 53 | + // Permission is handled using the ERC1155's allowance system. This check replicates `ERC1155._checkAuthorized`. |
| 54 | + address spender = _msgSender(); |
| 55 | + require( |
| 56 | + from == spender || token().isApprovedForAll(from, spender), |
| 57 | + IERC1155Errors.ERC1155MissingApprovalForAll(spender, from) |
| 58 | + ); |
| 59 | + |
| 60 | + // Perform the crosschain transfer and return the handler |
| 61 | + return _crosschainTransfer(from, to, ids, values); |
| 62 | + } |
| 63 | + |
| 64 | + /// @dev "Locking" tokens is done by taking custody |
| 65 | + function _onSend(address from, uint256[] memory ids, uint256[] memory values) internal virtual override { |
| 66 | + token().safeBatchTransferFrom(from, address(this), ids, values, ""); |
| 67 | + } |
| 68 | + |
| 69 | + /// @dev "Unlocking" tokens is done by releasing custody |
| 70 | + function _onReceive(address to, uint256[] memory ids, uint256[] memory values) internal virtual override { |
| 71 | + token().safeBatchTransferFrom(address(this), to, ids, values, ""); |
| 72 | + } |
| 73 | + |
| 74 | + /// @dev Support receiving tokens only if the transfer was initiated by the bridge itself. |
| 75 | + function onERC1155Received( |
| 76 | + address operator, |
| 77 | + address /* from */, |
| 78 | + uint256 /* id */, |
| 79 | + uint256 /* value */, |
| 80 | + bytes memory /* data */ |
| 81 | + ) public virtual override returns (bytes4) { |
| 82 | + return |
| 83 | + msg.sender == address(_token) && operator == address(this) |
| 84 | + ? IERC1155Receiver.onERC1155Received.selector |
| 85 | + : bytes4(0); |
| 86 | + } |
| 87 | + |
| 88 | + /// @dev Support receiving tokens only if the transfer was initiated by the bridge itself. |
| 89 | + function onERC1155BatchReceived( |
| 90 | + address operator, |
| 91 | + address /* from */, |
| 92 | + uint256[] memory /* ids */, |
| 93 | + uint256[] memory /* values */, |
| 94 | + bytes memory /* data */ |
| 95 | + ) public virtual override returns (bytes4) { |
| 96 | + return |
| 97 | + msg.sender == address(_token) && operator == address(this) |
| 98 | + ? IERC1155Receiver.onERC1155BatchReceived.selector |
| 99 | + : bytes4(0); |
| 100 | + } |
| 101 | +} |
0 commit comments