Skip to content

Commit 4545fff

Browse files
committed
implemented PoC of bridge and call module
1 parent e0091f2 commit 4545fff

File tree

2 files changed

+127
-0
lines changed

2 files changed

+127
-0
lines changed

remappings.txt

+1
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ forge-std/=lib/forge-std/src/
55
@erc721a-upgradeable/=lib/ERC721A-Upgradeable/contracts/
66
@limitbreak/creator-token-standards/=lib/creator-token-standards/src/
77
@limitbreak/permit-c/=lib/PermitC/src/
8+
@lxly-bridge-and-call/=lib/lxly-bridge-and-call/src/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
pragma solidity ^0.8.20;
3+
4+
import {ModularExtension} from "../../../ModularExtension.sol";
5+
import {Role} from "../../../Role.sol";
6+
import {BeforeTransferCallbackERC721} from "../../../callback/BeforeTransferCallbackERC721.sol";
7+
import {IBridgeAndCall} from "@lxly-bridge-and-call/IBridgeAndCall.sol";
8+
9+
library BridgeAndCallStorage {
10+
/// @custom:storage-location erc7201:token.bridgeAndCall
11+
bytes32 public constant BRIDGE_AND_CALL_STORAGE_POSITION =
12+
keccak256(abi.encode(uint256(keccak256("token.bridgeAndCall")) - 1)) &
13+
~bytes32(uint256(0xff));
14+
15+
struct Data {
16+
address bridgeExtension;
17+
}
18+
19+
function data() internal pure returns (Data storage data_) {
20+
bytes32 position = BRIDGE_AND_CALL_STORAGE_POSITION;
21+
assembly {
22+
data_.slot := position
23+
}
24+
}
25+
}
26+
27+
contract BridgeAndCallERC721 is ModularExtension, BeforeTransferCallbackERC721 {
28+
/*//////////////////////////////////////////////////////////////
29+
ERRORS
30+
//////////////////////////////////////////////////////////////*/
31+
32+
/// @notice Emitted on attempt to transfer a token when the bridge extension is not set.
33+
error bridgeExtensionNotSet();
34+
35+
/*//////////////////////////////////////////////////////////////
36+
EXTENSION CONFIG
37+
//////////////////////////////////////////////////////////////*/
38+
39+
/// @notice Returns all implemented callback and extension functions.
40+
function getExtensionConfig()
41+
external
42+
pure
43+
override
44+
returns (ExtensionConfig memory config)
45+
{
46+
config.fallbackFunctions = new FallbackFunction[](4);
47+
48+
config.fallbackFunctions[0] = FallbackFunction({
49+
selector: this.getBridgeExtension.selector,
50+
permissionBits: 0
51+
});
52+
config.fallbackFunctions[1] = FallbackFunction({
53+
selector: this.setBridgeExtension.selector,
54+
permissionBits: Role._MANAGER_ROLE
55+
});
56+
config.fallbackFunctions[2] = FallbackFunction({
57+
selector: this.bridgeAndCall.selector,
58+
permissionBits: 0
59+
});
60+
61+
config.requiredInterfaces = new bytes4[](1);
62+
config.requiredInterfaces[0] = 0x80ac58cd; // ERC721.
63+
64+
config.registerInstallationCallback = true;
65+
}
66+
67+
/// @dev Called by a Core into an Extension during the installation of the Extension.
68+
function onInstall(bytes calldata data) external {
69+
address bridgeExtension = abi.decode(data, (address));
70+
_bridgeAndCallStorage().bridgeExtension = bridgeExtension;
71+
}
72+
73+
/// @dev Called by a Core into an Extension during the uninstallation of the Extension.
74+
function onUninstall(bytes calldata data) external {}
75+
76+
/*//////////////////////////////////////////////////////////////
77+
FALLBACK FUNCTIONS
78+
//////////////////////////////////////////////////////////////*/
79+
80+
/// @notice Returns whether transfers is enabled for the token.
81+
function getBridgeExtension() external view returns (address) {
82+
return _bridgeAndCallStorage().bridgeExtension;
83+
}
84+
85+
/// @notice Set transferability for a token.
86+
function setBridgeExtension(address enableTransfer) external {
87+
_bridgeAndCallStorage().bridgeExtension = enableTransfer;
88+
}
89+
90+
/// @notice Set transferability for a token.
91+
function bridgeAndCall(
92+
uint256 amount,
93+
uint32 destinationNetwork,
94+
address callAddress,
95+
address fallbackAddress,
96+
bytes calldata callData,
97+
bool forceUpdateGlobalExitRoot
98+
) external {
99+
address bridgeExtension = _bridgeAndCallStorage().bridgeExtension;
100+
if (bridgeExtension == address(0)) {
101+
revert bridgeExtensionNotSet();
102+
}
103+
104+
IBridgeAndCall(bridgeExtension).bridgeAndCall(
105+
address(this),
106+
amount,
107+
destinationNetwork,
108+
callAddress,
109+
fallbackAddress,
110+
callData,
111+
forceUpdateGlobalExitRoot
112+
);
113+
}
114+
115+
/*//////////////////////////////////////////////////////////////
116+
INTERNAL FUNCTIONS
117+
//////////////////////////////////////////////////////////////*/
118+
119+
function _bridgeAndCallStorage()
120+
internal
121+
pure
122+
returns (BridgeAndCallStorage.Data storage)
123+
{
124+
return BridgeAndCallStorage.data();
125+
}
126+
}

0 commit comments

Comments
 (0)