Commit d9d3c738 authored by Mark Tyneway's avatar Mark Tyneway

contracts-bedrock: erc721 bridge single impl

Update the ERC721 bridge so that a single implementation
can be used across many different chains.

Still need to double check the storage layout before this
is good, but the tests are passing.

Also need to update all the code that touches the go bindings.
parent 92855691
...@@ -435,14 +435,9 @@ contract Deploy is Deployer { ...@@ -435,14 +435,9 @@ contract Deploy is Deployer {
/// @notice Deploy the L1ERC721Bridge /// @notice Deploy the L1ERC721Bridge
function deployL1ERC721Bridge() broadcast() public returns (address) { function deployL1ERC721Bridge() broadcast() public returns (address) {
address l1CrossDomainMessengerProxy = mustGetAddress("L1CrossDomainMessengerProxy"); L1ERC721Bridge bridge = new L1ERC721Bridge();
L1ERC721Bridge bridge = new L1ERC721Bridge({
_messenger: l1CrossDomainMessengerProxy,
_otherBridge: Predeploys.L2_ERC721_BRIDGE
});
require(address(bridge.MESSENGER()) == l1CrossDomainMessengerProxy); require(address(bridge.MESSENGER()) == address(0));
require(bridge.OTHER_BRIDGE() == Predeploys.L2_ERC721_BRIDGE); require(bridge.OTHER_BRIDGE() == Predeploys.L2_ERC721_BRIDGE);
save("L1ERC721Bridge", address(bridge)); save("L1ERC721Bridge", address(bridge));
...@@ -574,9 +569,13 @@ contract Deploy is Deployer { ...@@ -574,9 +569,13 @@ contract Deploy is Deployer {
address l1ERC721Bridge = mustGetAddress("L1ERC721Bridge"); address l1ERC721Bridge = mustGetAddress("L1ERC721Bridge");
address l1CrossDomainMessengerProxy = mustGetAddress("L1CrossDomainMessengerProxy"); address l1CrossDomainMessengerProxy = mustGetAddress("L1CrossDomainMessengerProxy");
proxyAdmin.upgrade({ proxyAdmin.upgradeAndCall({
_proxy: payable(l1ERC721BridgeProxy), _proxy: payable(l1ERC721BridgeProxy),
_implementation: l1ERC721Bridge _implementation: l1ERC721Bridge,
_data: abi.encodeCall(
L1ERC721Bridge.initialize,
(CrossDomainMessenger(l1CrossDomainMessengerProxy))
)
}); });
L1ERC721Bridge bridge = L1ERC721Bridge(l1ERC721BridgeProxy); L1ERC721Bridge bridge = L1ERC721Bridge(l1ERC721BridgeProxy);
......
...@@ -6,6 +6,7 @@ import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; ...@@ -6,6 +6,7 @@ import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import { L2ERC721Bridge } from "../L2/L2ERC721Bridge.sol"; import { L2ERC721Bridge } from "../L2/L2ERC721Bridge.sol";
import { Semver } from "../universal/Semver.sol"; import { Semver } from "../universal/Semver.sol";
import { Predeploys } from "../libraries/Predeploys.sol"; import { Predeploys } from "../libraries/Predeploys.sol";
import { CrossDomainMessenger } from "../universal/CrossDomainMessenger.sol";
/// @title L1ERC721Bridge /// @title L1ERC721Bridge
/// @notice The L1 ERC721 bridge is a contract which works together with the L2 ERC721 bridge to /// @notice The L1 ERC721 bridge is a contract which works together with the L2 ERC721 bridge to
...@@ -23,13 +24,13 @@ contract L1ERC721Bridge is ERC721Bridge, Semver { ...@@ -23,13 +24,13 @@ contract L1ERC721Bridge is ERC721Bridge, Semver {
ERC721Bridge(Predeploys.L2_ERC721_BRIDGE) ERC721Bridge(Predeploys.L2_ERC721_BRIDGE)
{ {
initialize({ initialize({
_messenger: address(0) _messenger: CrossDomainMessenger(address(0))
}); });
} }
/// @notice Initializes the contract. /// @notice Initializes the contract.
/// @param _messenger Address of the CrossDomainMessenger on this network. /// @param _messenger Address of the CrossDomainMessenger on this network.
function initialize(address _messenger) public reinitializer(1) { function initialize(CrossDomainMessenger _messenger) public reinitializer(1) {
__ERC721Bridge_init(_messenger); __ERC721Bridge_init(_messenger);
} }
......
...@@ -5,6 +5,7 @@ import { ERC721Bridge } from "../universal/ERC721Bridge.sol"; ...@@ -5,6 +5,7 @@ import { ERC721Bridge } from "../universal/ERC721Bridge.sol";
import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
import { L1ERC721Bridge } from "../L1/L1ERC721Bridge.sol"; import { L1ERC721Bridge } from "../L1/L1ERC721Bridge.sol";
import { IOptimismMintableERC721 } from "../universal/IOptimismMintableERC721.sol"; import { IOptimismMintableERC721 } from "../universal/IOptimismMintableERC721.sol";
import { CrossDomainMessenger } from "../universal/CrossDomainMessenger.sol";
import { Semver } from "../universal/Semver.sol"; import { Semver } from "../universal/Semver.sol";
/// @title L2ERC721Bridge /// @title L2ERC721Bridge
...@@ -25,13 +26,13 @@ contract L2ERC721Bridge is ERC721Bridge, Semver { ...@@ -25,13 +26,13 @@ contract L2ERC721Bridge is ERC721Bridge, Semver {
ERC721Bridge(_otherBridge) ERC721Bridge(_otherBridge)
{ {
initialize({ initialize({
_messenger: address(0) _messenger: CrossDomainMessenger(address(0))
}); });
} }
/// @notice Initializes the contract. /// @notice Initializes the contract.
/// @param _messenger Address of the CrossDomainMessenger on this network. /// @param _messenger Address of the CrossDomainMessenger on this network.
function initialize(address _messenger) public reinitializer(1) { function initialize(CrossDomainMessenger _messenger) public reinitializer(1) {
__ERC721Bridge_init(_messenger); __ERC721Bridge_init(_messenger);
} }
......
...@@ -68,7 +68,6 @@ abstract contract ERC721Bridge is Initializable { ...@@ -68,7 +68,6 @@ abstract contract ERC721Bridge is Initializable {
// @notice Initializes the contract. // @notice Initializes the contract.
/// @param _messenger Address of the CrossDomainMessenger on this network. /// @param _messenger Address of the CrossDomainMessenger on this network.
function __ERC721Bridge_init(CrossDomainMessenger _messenger) internal onlyInitializing { function __ERC721Bridge_init(CrossDomainMessenger _messenger) internal onlyInitializing {
require(address(_messenger) != address(0), "ERC721Bridge: messenger cannot be address(0)");
MESSENGER = _messenger; MESSENGER = _messenger;
} }
......
...@@ -29,6 +29,7 @@ import { ResolvedDelegateProxy } from "../src/legacy/ResolvedDelegateProxy.sol"; ...@@ -29,6 +29,7 @@ import { ResolvedDelegateProxy } from "../src/legacy/ResolvedDelegateProxy.sol";
import { AddressManager } from "../src/legacy/AddressManager.sol"; import { AddressManager } from "../src/legacy/AddressManager.sol";
import { L1ChugSplashProxy } from "../src/legacy/L1ChugSplashProxy.sol"; import { L1ChugSplashProxy } from "../src/legacy/L1ChugSplashProxy.sol";
import { IL1ChugSplashDeployer } from "../src/legacy/L1ChugSplashProxy.sol"; import { IL1ChugSplashDeployer } from "../src/legacy/L1ChugSplashProxy.sol";
import { CrossDomainMessenger } from "../src/universal/CrossDomainMessenger.sol";
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
import { LegacyMintableERC20 } from "../src/legacy/LegacyMintableERC20.sol"; import { LegacyMintableERC20 } from "../src/legacy/LegacyMintableERC20.sol";
import { SystemConfig } from "../src/L1/SystemConfig.sol"; import { SystemConfig } from "../src/L1/SystemConfig.sol";
...@@ -507,7 +508,7 @@ contract ERC721Bridge_Initializer is Messenger_Initializer { ...@@ -507,7 +508,7 @@ contract ERC721Bridge_Initializer is Messenger_Initializer {
address(l1BridgeImpl), address(l1BridgeImpl),
abi.encodeCall( abi.encodeCall(
L1ERC721Bridge.initialize, L1ERC721Bridge.initialize,
address(L1Messenger) (CrossDomainMessenger(L1Messenger))
) )
); );
...@@ -516,14 +517,17 @@ contract ERC721Bridge_Initializer is Messenger_Initializer { ...@@ -516,14 +517,17 @@ contract ERC721Bridge_Initializer is Messenger_Initializer {
// Deploy the implementation for the L2ERC721Bridge and etch it into the predeploy address. // Deploy the implementation for the L2ERC721Bridge and etch it into the predeploy address.
L2ERC721Bridge l2BridgeImpl = new L2ERC721Bridge(address(L1Bridge)); L2ERC721Bridge l2BridgeImpl = new L2ERC721Bridge(address(L1Bridge));
Proxy l2BridgeProxy = new Proxy(multisig); Proxy l2BridgeProxy = new Proxy(multisig);
vm.etch(Predeploys.L2_ERC721_BRIDGE, l2BridgeProxy.code); vm.etch(Predeploys.L2_ERC721_BRIDGE, address(l2BridgeProxy).code);
// set the storage slot for admin and implementation
bytes32 IMPLEMENTATION_KEY = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; // set the storage slot for admin
bytes32 OWNER_KEY = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; bytes32 OWNER_KEY = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
vm.store(Predeploys.L2_ERC721_BRIDGE, OWNER_KEY, bytes32(uint256(uint160(multisig))));
vm.store(Predeploys.L2_ERC721_BRIDGE, IMPLEMENTATION_KEY, address(l2BridgeProxy)); vm.prank(multisig);
vm.store(Predeploys.L2_ERC721_BRIDGE, OWNER_KEY, multisig); Proxy(payable(Predeploys.L2_ERC721_BRIDGE)).upgradeToAndCall(
address(l2BridgeImpl),
abi.encodeCall(L2ERC721Bridge.initialize, (L2Messenger))
);
// Set up a reference to the L2ERC721Bridge. // Set up a reference to the L2ERC721Bridge.
L2Bridge = L2ERC721Bridge(Predeploys.L2_ERC721_BRIDGE); L2Bridge = L2ERC721Bridge(Predeploys.L2_ERC721_BRIDGE);
......
...@@ -2,11 +2,12 @@ ...@@ -2,11 +2,12 @@
pragma solidity 0.8.15; pragma solidity 0.8.15;
// Testing utilities // Testing utilities
import { Messenger_Initializer } from "./CommonTest.t.sol"; import { ERC721Bridge_Initializer } from "./CommonTest.t.sol";
import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
// Target contract dependencies // Target contract dependencies
import { L2ERC721Bridge } from "../src/L2/L2ERC721Bridge.sol"; import { L2ERC721Bridge } from "../src/L2/L2ERC721Bridge.sol";
import { Predeploys } from "../src/libraries/Predeploys.sol";
// Target contract // Target contract
import { L1ERC721Bridge } from "../src/L1/L1ERC721Bridge.sol"; import { L1ERC721Bridge } from "../src/L1/L1ERC721Bridge.sol";
...@@ -20,11 +21,9 @@ contract TestERC721 is ERC721 { ...@@ -20,11 +21,9 @@ contract TestERC721 is ERC721 {
} }
} }
contract L1ERC721Bridge_Test is Messenger_Initializer { contract L1ERC721Bridge_Test is ERC721Bridge_Initializer {
TestERC721 internal localToken; TestERC721 internal localToken;
TestERC721 internal remoteToken; TestERC721 internal remoteToken;
L1ERC721Bridge internal bridge;
address internal constant otherBridge = address(0x3456);
uint256 internal constant tokenId = 1; uint256 internal constant tokenId = 1;
event ERC721BridgeInitiated( event ERC721BridgeInitiated(
...@@ -49,28 +48,23 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { ...@@ -49,28 +48,23 @@ contract L1ERC721Bridge_Test is Messenger_Initializer {
function setUp() public override { function setUp() public override {
super.setUp(); super.setUp();
// Create necessary contracts.
bridge = new L1ERC721Bridge(address(L1Messenger), otherBridge);
localToken = new TestERC721(); localToken = new TestERC721();
remoteToken = new TestERC721(); remoteToken = new TestERC721();
// Label the bridge so we get nice traces.
vm.label(address(bridge), "L1ERC721Bridge");
// Mint alice a token. // Mint alice a token.
localToken.mint(alice, tokenId); localToken.mint(alice, tokenId);
// Approve the bridge to transfer the token. // Approve the bridge to transfer the token.
vm.prank(alice); vm.prank(alice);
localToken.approve(address(bridge), tokenId); localToken.approve(address(L1Bridge), tokenId);
} }
/// @dev Tests that the constructor sets the correct values. /// @dev Tests that the constructor sets the correct values.
function test_constructor_succeeds() public { function test_constructor_succeeds() public {
assertEq(address(bridge.MESSENGER()), address(L1Messenger)); assertEq(address(L1Bridge.MESSENGER()), address(L1Messenger));
assertEq(address(bridge.OTHER_BRIDGE()), otherBridge); assertEq(address(L1Bridge.OTHER_BRIDGE()), Predeploys.L2_ERC721_BRIDGE);
assertEq(address(bridge.messenger()), address(L1Messenger)); assertEq(address(L1Bridge.messenger()), address(L1Messenger));
assertEq(address(bridge.otherBridge()), otherBridge); assertEq(address(L1Bridge.otherBridge()), Predeploys.L2_ERC721_BRIDGE);
} }
/// @dev Tests that the ERC721 can be bridged successfully. /// @dev Tests that the ERC721 can be bridged successfully.
...@@ -81,7 +75,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { ...@@ -81,7 +75,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer {
abi.encodeCall( abi.encodeCall(
L1Messenger.sendMessage, L1Messenger.sendMessage,
( (
address(otherBridge), address(L2Bridge),
abi.encodeCall( abi.encodeCall(
L2ERC721Bridge.finalizeBridgeERC721, L2ERC721Bridge.finalizeBridgeERC721,
( (
...@@ -111,11 +105,11 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { ...@@ -111,11 +105,11 @@ contract L1ERC721Bridge_Test is Messenger_Initializer {
// Bridge the token. // Bridge the token.
vm.prank(alice); vm.prank(alice);
bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678"); L1Bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678");
// Token is locked in the bridge. // Token is locked in the bridge.
assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), true); assertEq(L1Bridge.deposits(address(localToken), address(remoteToken), tokenId), true);
assertEq(localToken.ownerOf(tokenId), address(bridge)); assertEq(localToken.ownerOf(tokenId), address(L1Bridge));
} }
/// @dev Tests that the ERC721 bridge reverts for non externally owned accounts. /// @dev Tests that the ERC721 bridge reverts for non externally owned accounts.
...@@ -124,10 +118,10 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { ...@@ -124,10 +118,10 @@ contract L1ERC721Bridge_Test is Messenger_Initializer {
vm.etch(alice, hex"01"); vm.etch(alice, hex"01");
vm.prank(alice); vm.prank(alice);
vm.expectRevert("ERC721Bridge: account is not externally owned"); vm.expectRevert("ERC721Bridge: account is not externally owned");
bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678"); L1Bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678");
// Token is not locked in the bridge. // Token is not locked in the bridge.
assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false); assertEq(L1Bridge.deposits(address(localToken), address(remoteToken), tokenId), false);
assertEq(localToken.ownerOf(tokenId), alice); assertEq(localToken.ownerOf(tokenId), alice);
} }
...@@ -136,10 +130,10 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { ...@@ -136,10 +130,10 @@ contract L1ERC721Bridge_Test is Messenger_Initializer {
// Bridge the token. // Bridge the token.
vm.prank(alice); vm.prank(alice);
vm.expectRevert(); vm.expectRevert();
bridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex"5678"); L1Bridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex"5678");
// Token is not locked in the bridge. // Token is not locked in the bridge.
assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false); assertEq(L1Bridge.deposits(address(localToken), address(remoteToken), tokenId), false);
assertEq(localToken.ownerOf(tokenId), alice); assertEq(localToken.ownerOf(tokenId), alice);
} }
...@@ -148,10 +142,10 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { ...@@ -148,10 +142,10 @@ contract L1ERC721Bridge_Test is Messenger_Initializer {
// Bridge the token. // Bridge the token.
vm.prank(alice); vm.prank(alice);
vm.expectRevert("L1ERC721Bridge: remote token cannot be address(0)"); vm.expectRevert("L1ERC721Bridge: remote token cannot be address(0)");
bridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex"5678"); L1Bridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex"5678");
// Token is not locked in the bridge. // Token is not locked in the bridge.
assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false); assertEq(L1Bridge.deposits(address(localToken), address(remoteToken), tokenId), false);
assertEq(localToken.ownerOf(tokenId), alice); assertEq(localToken.ownerOf(tokenId), alice);
} }
...@@ -160,10 +154,10 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { ...@@ -160,10 +154,10 @@ contract L1ERC721Bridge_Test is Messenger_Initializer {
// Bridge the token. // Bridge the token.
vm.prank(bob); vm.prank(bob);
vm.expectRevert("ERC721: transfer from incorrect owner"); vm.expectRevert("ERC721: transfer from incorrect owner");
bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678"); L1Bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678");
// Token is not locked in the bridge. // Token is not locked in the bridge.
assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false); assertEq(L1Bridge.deposits(address(localToken), address(remoteToken), tokenId), false);
assertEq(localToken.ownerOf(tokenId), alice); assertEq(localToken.ownerOf(tokenId), alice);
} }
...@@ -176,7 +170,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { ...@@ -176,7 +170,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer {
abi.encodeCall( abi.encodeCall(
L1Messenger.sendMessage, L1Messenger.sendMessage,
( (
address(otherBridge), address(Predeploys.L2_ERC721_BRIDGE),
abi.encodeCall( abi.encodeCall(
L2ERC721Bridge.finalizeBridgeERC721, L2ERC721Bridge.finalizeBridgeERC721,
(address(remoteToken), address(localToken), alice, bob, tokenId, hex"5678") (address(remoteToken), address(localToken), alice, bob, tokenId, hex"5678")
...@@ -199,7 +193,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { ...@@ -199,7 +193,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer {
// Bridge the token. // Bridge the token.
vm.prank(alice); vm.prank(alice);
bridge.bridgeERC721To( L1Bridge.bridgeERC721To(
address(localToken), address(localToken),
address(remoteToken), address(remoteToken),
bob, bob,
...@@ -209,8 +203,8 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { ...@@ -209,8 +203,8 @@ contract L1ERC721Bridge_Test is Messenger_Initializer {
); );
// Token is locked in the bridge. // Token is locked in the bridge.
assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), true); assertEq(L1Bridge.deposits(address(localToken), address(remoteToken), tokenId), true);
assertEq(localToken.ownerOf(tokenId), address(bridge)); assertEq(localToken.ownerOf(tokenId), address(L1Bridge));
} }
/// @dev Tests that the ERC721 bridge reverts for non externally owned accounts /// @dev Tests that the ERC721 bridge reverts for non externally owned accounts
...@@ -219,10 +213,10 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { ...@@ -219,10 +213,10 @@ contract L1ERC721Bridge_Test is Messenger_Initializer {
// Bridge the token. // Bridge the token.
vm.prank(alice); vm.prank(alice);
vm.expectRevert(); vm.expectRevert();
bridge.bridgeERC721To(address(0), address(remoteToken), bob, tokenId, 1234, hex"5678"); L1Bridge.bridgeERC721To(address(0), address(remoteToken), bob, tokenId, 1234, hex"5678");
// Token is not locked in the bridge. // Token is not locked in the bridge.
assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false); assertEq(L1Bridge.deposits(address(localToken), address(remoteToken), tokenId), false);
assertEq(localToken.ownerOf(tokenId), alice); assertEq(localToken.ownerOf(tokenId), alice);
} }
...@@ -232,10 +226,10 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { ...@@ -232,10 +226,10 @@ contract L1ERC721Bridge_Test is Messenger_Initializer {
// Bridge the token. // Bridge the token.
vm.prank(alice); vm.prank(alice);
vm.expectRevert("L1ERC721Bridge: remote token cannot be address(0)"); vm.expectRevert("L1ERC721Bridge: remote token cannot be address(0)");
bridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex"5678"); L1Bridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex"5678");
// Token is not locked in the bridge. // Token is not locked in the bridge.
assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false); assertEq(L1Bridge.deposits(address(localToken), address(remoteToken), tokenId), false);
assertEq(localToken.ownerOf(tokenId), alice); assertEq(localToken.ownerOf(tokenId), alice);
} }
...@@ -245,7 +239,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { ...@@ -245,7 +239,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer {
// Bridge the token. // Bridge the token.
vm.prank(bob); vm.prank(bob);
vm.expectRevert("ERC721: transfer from incorrect owner"); vm.expectRevert("ERC721: transfer from incorrect owner");
bridge.bridgeERC721To( L1Bridge.bridgeERC721To(
address(localToken), address(localToken),
address(remoteToken), address(remoteToken),
bob, bob,
...@@ -255,7 +249,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { ...@@ -255,7 +249,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer {
); );
// Token is not locked in the bridge. // Token is not locked in the bridge.
assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false); assertEq(L1Bridge.deposits(address(localToken), address(remoteToken), tokenId), false);
assertEq(localToken.ownerOf(tokenId), alice); assertEq(localToken.ownerOf(tokenId), alice);
} }
...@@ -263,7 +257,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { ...@@ -263,7 +257,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer {
function test_finalizeBridgeERC721_succeeds() external { function test_finalizeBridgeERC721_succeeds() external {
// Bridge the token. // Bridge the token.
vm.prank(alice); vm.prank(alice);
bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678"); L1Bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678");
// Expect an event to be emitted. // Expect an event to be emitted.
vm.expectEmit(true, true, true, true); vm.expectEmit(true, true, true, true);
...@@ -280,10 +274,10 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { ...@@ -280,10 +274,10 @@ contract L1ERC721Bridge_Test is Messenger_Initializer {
vm.mockCall( vm.mockCall(
address(L1Messenger), address(L1Messenger),
abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector), abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),
abi.encode(otherBridge) abi.encode(Predeploys.L2_ERC721_BRIDGE)
); );
vm.prank(address(L1Messenger)); vm.prank(address(L1Messenger));
bridge.finalizeBridgeERC721( L1Bridge.finalizeBridgeERC721(
address(localToken), address(localToken),
address(remoteToken), address(remoteToken),
alice, alice,
...@@ -293,7 +287,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { ...@@ -293,7 +287,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer {
); );
// Token is not locked in the bridge. // Token is not locked in the bridge.
assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false); assertEq(L1Bridge.deposits(address(localToken), address(remoteToken), tokenId), false);
assertEq(localToken.ownerOf(tokenId), alice); assertEq(localToken.ownerOf(tokenId), alice);
} }
...@@ -303,7 +297,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { ...@@ -303,7 +297,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer {
// Finalize a withdrawal. // Finalize a withdrawal.
vm.prank(alice); vm.prank(alice);
vm.expectRevert("ERC721Bridge: function can only be called from the other bridge"); vm.expectRevert("ERC721Bridge: function can only be called from the other bridge");
bridge.finalizeBridgeERC721( L1Bridge.finalizeBridgeERC721(
address(localToken), address(localToken),
address(remoteToken), address(remoteToken),
alice, alice,
...@@ -324,7 +318,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { ...@@ -324,7 +318,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer {
); );
vm.prank(address(L1Messenger)); vm.prank(address(L1Messenger));
vm.expectRevert("ERC721Bridge: function can only be called from the other bridge"); vm.expectRevert("ERC721Bridge: function can only be called from the other bridge");
bridge.finalizeBridgeERC721( L1Bridge.finalizeBridgeERC721(
address(localToken), address(localToken),
address(remoteToken), address(remoteToken),
alice, alice,
...@@ -341,12 +335,12 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { ...@@ -341,12 +335,12 @@ contract L1ERC721Bridge_Test is Messenger_Initializer {
vm.mockCall( vm.mockCall(
address(L1Messenger), address(L1Messenger),
abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector), abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),
abi.encode(otherBridge) abi.encode(Predeploys.L2_ERC721_BRIDGE)
); );
vm.prank(address(L1Messenger)); vm.prank(address(L1Messenger));
vm.expectRevert("L1ERC721Bridge: local token cannot be self"); vm.expectRevert("L1ERC721Bridge: local token cannot be self");
bridge.finalizeBridgeERC721( L1Bridge.finalizeBridgeERC721(
address(bridge), address(L1Bridge),
address(remoteToken), address(remoteToken),
alice, alice,
alice, alice,
...@@ -362,11 +356,11 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { ...@@ -362,11 +356,11 @@ contract L1ERC721Bridge_Test is Messenger_Initializer {
vm.mockCall( vm.mockCall(
address(L1Messenger), address(L1Messenger),
abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector), abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),
abi.encode(otherBridge) abi.encode(Predeploys.L2_ERC721_BRIDGE)
); );
vm.prank(address(L1Messenger)); vm.prank(address(L1Messenger));
vm.expectRevert("L1ERC721Bridge: Token ID is not escrowed in the L1 Bridge"); vm.expectRevert("L1ERC721Bridge: Token ID is not escrowed in the L1 Bridge");
bridge.finalizeBridgeERC721( L1Bridge.finalizeBridgeERC721(
address(localToken), address(localToken),
address(remoteToken), address(remoteToken),
alice, alice,
......
...@@ -34,8 +34,6 @@ contract TestMintableERC721 is OptimismMintableERC721 { ...@@ -34,8 +34,6 @@ contract TestMintableERC721 is OptimismMintableERC721 {
contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
TestMintableERC721 internal localToken; TestMintableERC721 internal localToken;
TestERC721 internal remoteToken; TestERC721 internal remoteToken;
L2ERC721Bridge internal bridge;
address internal constant otherBridge = address(0x3456);
uint256 internal constant tokenId = 1; uint256 internal constant tokenId = 1;
event ERC721BridgeInitiated( event ERC721BridgeInitiated(
...@@ -61,22 +59,22 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { ...@@ -61,22 +59,22 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
super.setUp(); super.setUp();
remoteToken = new TestERC721(); remoteToken = new TestERC721();
localToken = new TestMintableERC721(address(bridge), address(remoteToken)); localToken = new TestMintableERC721(address(L2Bridge), address(remoteToken));
// Mint alice a token. // Mint alice a token.
localToken.mint(alice, tokenId); localToken.mint(alice, tokenId);
// Approve the bridge to transfer the token. // Approve the bridge to transfer the token.
vm.prank(alice); vm.prank(alice);
localToken.approve(address(bridge), tokenId); localToken.approve(address(L2Bridge), tokenId);
} }
/// @dev Tests that the constructor sets the correct variables. /// @dev Tests that the constructor sets the correct variables.
function test_constructor_succeeds() public { function test_constructor_succeeds() public {
assertEq(address(bridge.MESSENGER()), address(L2Messenger)); assertEq(address(L2Bridge.MESSENGER()), address(L2Messenger));
assertEq(address(bridge.OTHER_BRIDGE()), otherBridge); assertEq(address(L2Bridge.OTHER_BRIDGE()), address(L1Bridge));
assertEq(address(bridge.messenger()), address(L2Messenger)); assertEq(address(L2Bridge.messenger()), address(L2Messenger));
assertEq(address(bridge.otherBridge()), otherBridge); assertEq(address(L2Bridge.otherBridge()), address(L1Bridge));
} }
/// @dev Tests that `bridgeERC721` correctly bridges a token and /// @dev Tests that `bridgeERC721` correctly bridges a token and
...@@ -88,7 +86,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { ...@@ -88,7 +86,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
abi.encodeCall( abi.encodeCall(
L2Messenger.sendMessage, L2Messenger.sendMessage,
( (
address(otherBridge), address(L1Bridge),
abi.encodeCall( abi.encodeCall(
L2ERC721Bridge.finalizeBridgeERC721, L2ERC721Bridge.finalizeBridgeERC721,
( (
...@@ -118,7 +116,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { ...@@ -118,7 +116,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the token. // Bridge the token.
vm.prank(alice); vm.prank(alice);
bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678"); L2Bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678");
// Token is burned. // Token is burned.
vm.expectRevert("ERC721: invalid token ID"); vm.expectRevert("ERC721: invalid token ID");
...@@ -131,7 +129,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { ...@@ -131,7 +129,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
vm.etch(alice, hex"01"); vm.etch(alice, hex"01");
vm.prank(alice); vm.prank(alice);
vm.expectRevert("ERC721Bridge: account is not externally owned"); vm.expectRevert("ERC721Bridge: account is not externally owned");
bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678"); L2Bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678");
// Token is not locked in the bridge. // Token is not locked in the bridge.
assertEq(localToken.ownerOf(tokenId), alice); assertEq(localToken.ownerOf(tokenId), alice);
...@@ -142,7 +140,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { ...@@ -142,7 +140,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the token. // Bridge the token.
vm.prank(alice); vm.prank(alice);
vm.expectRevert(); vm.expectRevert();
bridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex"5678"); L2Bridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex"5678");
// Token is not locked in the bridge. // Token is not locked in the bridge.
assertEq(localToken.ownerOf(tokenId), alice); assertEq(localToken.ownerOf(tokenId), alice);
...@@ -153,7 +151,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { ...@@ -153,7 +151,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the token. // Bridge the token.
vm.prank(alice); vm.prank(alice);
vm.expectRevert("L2ERC721Bridge: remote token cannot be address(0)"); vm.expectRevert("L2ERC721Bridge: remote token cannot be address(0)");
bridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex"5678"); L2Bridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex"5678");
// Token is not locked in the bridge. // Token is not locked in the bridge.
assertEq(localToken.ownerOf(tokenId), alice); assertEq(localToken.ownerOf(tokenId), alice);
...@@ -164,7 +162,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { ...@@ -164,7 +162,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the token. // Bridge the token.
vm.prank(bob); vm.prank(bob);
vm.expectRevert("L2ERC721Bridge: Withdrawal is not being initiated by NFT owner"); vm.expectRevert("L2ERC721Bridge: Withdrawal is not being initiated by NFT owner");
bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678"); L2Bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678");
// Token is not locked in the bridge. // Token is not locked in the bridge.
assertEq(localToken.ownerOf(tokenId), alice); assertEq(localToken.ownerOf(tokenId), alice);
...@@ -179,7 +177,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { ...@@ -179,7 +177,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
abi.encodeCall( abi.encodeCall(
L2Messenger.sendMessage, L2Messenger.sendMessage,
( (
address(otherBridge), address(L1Bridge),
abi.encodeCall( abi.encodeCall(
L1ERC721Bridge.finalizeBridgeERC721, L1ERC721Bridge.finalizeBridgeERC721,
(address(remoteToken), address(localToken), alice, bob, tokenId, hex"5678") (address(remoteToken), address(localToken), alice, bob, tokenId, hex"5678")
...@@ -202,7 +200,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { ...@@ -202,7 +200,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the token. // Bridge the token.
vm.prank(alice); vm.prank(alice);
bridge.bridgeERC721To( L2Bridge.bridgeERC721To(
address(localToken), address(localToken),
address(remoteToken), address(remoteToken),
bob, bob,
...@@ -221,7 +219,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { ...@@ -221,7 +219,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the token. // Bridge the token.
vm.prank(alice); vm.prank(alice);
vm.expectRevert(); vm.expectRevert();
bridge.bridgeERC721To(address(0), address(remoteToken), bob, tokenId, 1234, hex"5678"); L2Bridge.bridgeERC721To(address(0), address(L1Bridge), bob, tokenId, 1234, hex"5678");
// Token is not locked in the bridge. // Token is not locked in the bridge.
assertEq(localToken.ownerOf(tokenId), alice); assertEq(localToken.ownerOf(tokenId), alice);
...@@ -232,7 +230,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { ...@@ -232,7 +230,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the token. // Bridge the token.
vm.prank(alice); vm.prank(alice);
vm.expectRevert("L2ERC721Bridge: remote token cannot be address(0)"); vm.expectRevert("L2ERC721Bridge: remote token cannot be address(0)");
bridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex"5678"); L2Bridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex"5678");
// Token is not locked in the bridge. // Token is not locked in the bridge.
assertEq(localToken.ownerOf(tokenId), alice); assertEq(localToken.ownerOf(tokenId), alice);
...@@ -243,7 +241,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { ...@@ -243,7 +241,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the token. // Bridge the token.
vm.prank(bob); vm.prank(bob);
vm.expectRevert("L2ERC721Bridge: Withdrawal is not being initiated by NFT owner"); vm.expectRevert("L2ERC721Bridge: Withdrawal is not being initiated by NFT owner");
bridge.bridgeERC721To( L2Bridge.bridgeERC721To(
address(localToken), address(localToken),
address(remoteToken), address(remoteToken),
bob, bob,
...@@ -260,7 +258,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { ...@@ -260,7 +258,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
function test_finalizeBridgeERC721_succeeds() external { function test_finalizeBridgeERC721_succeeds() external {
// Bridge the token. // Bridge the token.
vm.prank(alice); vm.prank(alice);
bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678"); L2Bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678");
// Expect an event to be emitted. // Expect an event to be emitted.
vm.expectEmit(true, true, true, true); vm.expectEmit(true, true, true, true);
...@@ -277,10 +275,10 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { ...@@ -277,10 +275,10 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
vm.mockCall( vm.mockCall(
address(L2Messenger), address(L2Messenger),
abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector), abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),
abi.encode(otherBridge) abi.encode(L1Bridge)
); );
vm.prank(address(L2Messenger)); vm.prank(address(L2Messenger));
bridge.finalizeBridgeERC721( L2Bridge.finalizeBridgeERC721(
address(localToken), address(localToken),
address(remoteToken), address(remoteToken),
alice, alice,
...@@ -301,18 +299,18 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { ...@@ -301,18 +299,18 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the non-compliant token. // Bridge the non-compliant token.
vm.prank(alice); vm.prank(alice);
bridge.bridgeERC721(address(nonCompliantToken), address(0x01), tokenId, 1234, hex"5678"); L2Bridge.bridgeERC721(address(nonCompliantToken), address(0x01), tokenId, 1234, hex"5678");
// Attempt to finalize the withdrawal. Should revert because the token does not claim // Attempt to finalize the withdrawal. Should revert because the token does not claim
// to be compliant with the `IOptimismMintableERC721` interface. // to be compliant with the `IOptimismMintableERC721` interface.
vm.mockCall( vm.mockCall(
address(L2Messenger), address(L2Messenger),
abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector), abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),
abi.encode(otherBridge) abi.encode(L1Bridge)
); );
vm.prank(address(L2Messenger)); vm.prank(address(L2Messenger));
vm.expectRevert("L2ERC721Bridge: local token interface is not compliant"); vm.expectRevert("L2ERC721Bridge: local token interface is not compliant");
bridge.finalizeBridgeERC721( L2Bridge.finalizeBridgeERC721(
address(address(nonCompliantToken)), address(address(nonCompliantToken)),
address(address(0x01)), address(address(0x01)),
alice, alice,
...@@ -327,7 +325,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { ...@@ -327,7 +325,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
// Finalize a withdrawal. // Finalize a withdrawal.
vm.prank(alice); vm.prank(alice);
vm.expectRevert("ERC721Bridge: function can only be called from the other bridge"); vm.expectRevert("ERC721Bridge: function can only be called from the other bridge");
bridge.finalizeBridgeERC721( L2Bridge.finalizeBridgeERC721(
address(localToken), address(localToken),
address(remoteToken), address(remoteToken),
alice, alice,
...@@ -347,7 +345,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { ...@@ -347,7 +345,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
); );
vm.prank(address(L2Messenger)); vm.prank(address(L2Messenger));
vm.expectRevert("ERC721Bridge: function can only be called from the other bridge"); vm.expectRevert("ERC721Bridge: function can only be called from the other bridge");
bridge.finalizeBridgeERC721( L2Bridge.finalizeBridgeERC721(
address(localToken), address(localToken),
address(remoteToken), address(remoteToken),
alice, alice,
...@@ -364,12 +362,12 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { ...@@ -364,12 +362,12 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
vm.mockCall( vm.mockCall(
address(L2Messenger), address(L2Messenger),
abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector), abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),
abi.encode(otherBridge) abi.encode(address(L1Bridge))
); );
vm.prank(address(L2Messenger)); vm.prank(address(L2Messenger));
vm.expectRevert("L2ERC721Bridge: local token cannot be self"); vm.expectRevert("L2ERC721Bridge: local token cannot be self");
bridge.finalizeBridgeERC721( L2Bridge.finalizeBridgeERC721(
address(bridge), address(L2Bridge),
address(remoteToken), address(remoteToken),
alice, alice,
alice, alice,
...@@ -384,11 +382,11 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { ...@@ -384,11 +382,11 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
vm.mockCall( vm.mockCall(
address(L2Messenger), address(L2Messenger),
abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector), abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),
abi.encode(otherBridge) abi.encode(address(L1Bridge))
); );
vm.prank(address(L2Messenger)); vm.prank(address(L2Messenger));
vm.expectRevert("ERC721: token already minted"); vm.expectRevert("ERC721: token already minted");
bridge.finalizeBridgeERC721( L2Bridge.finalizeBridgeERC721(
address(localToken), address(localToken),
address(remoteToken), address(remoteToken),
alice, alice,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment