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