Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
b4768da2
Commit
b4768da2
authored
Aug 02, 2023
by
Mark Tyneway
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
contracts-bedrock: standard bridge single impl
parent
ec6dc47b
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
95 additions
and
46 deletions
+95
-46
Deploy.s.sol
packages/contracts-bedrock/scripts/Deploy.s.sol
+12
-8
L1StandardBridge.sol
packages/contracts-bedrock/src/L1/L1StandardBridge.sol
+16
-7
L2StandardBridge.sol
packages/contracts-bedrock/src/L2/L2StandardBridge.sol
+16
-6
StandardBridge.sol
packages/contracts-bedrock/src/universal/StandardBridge.sol
+43
-21
CommonTest.t.sol
packages/contracts-bedrock/test/CommonTest.t.sol
+7
-3
StandardBridge.t.sol
packages/contracts-bedrock/test/StandardBridge.t.sol
+1
-1
No files found.
packages/contracts-bedrock/scripts/Deploy.s.sol
View file @
b4768da2
...
...
@@ -419,14 +419,12 @@ contract Deploy is Deployer {
/// @notice Deploy the L1StandardBridge
function deployL1StandardBridge() broadcast() public returns (address) {
address l1CrossDomainMessengerProxy = mustGetAddress("L1CrossDomainMessengerProxy");
L1StandardBridge bridge = new L1StandardBridge({
_messenger: payable(l1CrossDomainMessengerProxy)
});
L1StandardBridge bridge = new L1StandardBridge();
require(address(bridge.MESSENGER()) == l1CrossDomainMessengerProxy);
require(address(bridge.MESSENGER()) == address(0));
require(address(bridge.messenger()) == address(0));
require(address(bridge.OTHER_BRIDGE()) == Predeploys.L2_STANDARD_BRIDGE);
require(address(bridge.otherBridge()) == Predeploys.L2_STANDARD_BRIDGE);
save("L1StandardBridge", address(bridge));
console.log("L1StandardBridge deployed at %s", address(bridge));
...
...
@@ -543,9 +541,13 @@ contract Deploy is Deployer {
}
require(uint256(proxyAdmin.proxyType(l1StandardBridgeProxy)) == uint256(ProxyAdmin.ProxyType.CHUGSPLASH));
proxyAdmin.upgrade({
proxyAdmin.upgrade
AndCall
({
_proxy: payable(l1StandardBridgeProxy),
_implementation: l1StandardBridge
_implementation: l1StandardBridge,
_data: abi.encodeCall(
L1StandardBridge.initialize,
(L1CrossDomainMessenger(l1CrossDomainMessengerProxy))
)
});
string memory version = L1StandardBridge(payable(l1StandardBridgeProxy)).version();
...
...
@@ -553,7 +555,9 @@ contract Deploy is Deployer {
L1StandardBridge bridge = L1StandardBridge(payable(l1StandardBridgeProxy));
require(address(bridge.MESSENGER()) == l1CrossDomainMessengerProxy);
require(address(bridge.messenger()) == l1CrossDomainMessengerProxy);
require(address(bridge.OTHER_BRIDGE()) == Predeploys.L2_STANDARD_BRIDGE);
require(address(bridge.otherBridge()) == Predeploys.L2_STANDARD_BRIDGE);
}
...
...
packages/contracts-bedrock/src/L1/L1StandardBridge.sol
View file @
b4768da2
...
...
@@ -4,6 +4,7 @@ pragma solidity 0.8.15;
import { Predeploys } from "../libraries/Predeploys.sol";
import { StandardBridge } from "../universal/StandardBridge.sol";
import { Semver } from "../universal/Semver.sol";
import { CrossDomainMessenger } from "../universal/CrossDomainMessenger.sol";
/// @custom:proxied
/// @title L1StandardBridge
...
...
@@ -76,13 +77,21 @@ contract L1StandardBridge is StandardBridge, Semver {
bytes extraData
);
/// @custom:semver 1.
1.1
/// @custom:semver 1.
2.0
/// @notice Constructs the L1StandardBridge contract.
/// @param _messenger Address of the L1CrossDomainMessenger.
constructor(address payable _messenger)
Semver(1, 1, 1)
StandardBridge(_messenger, payable(Predeploys.L2_STANDARD_BRIDGE))
{}
constructor()
Semver(1, 2, 0)
StandardBridge(StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE)))
{
initialize(CrossDomainMessenger(address(0)));
}
/// @notice Initializer
function initialize(CrossDomainMessenger _messenger) public reinitializer(2) {
__StandardBridge_init({
_messenger: _messenger
});
}
/// @notice Allows EOAs to bridge ETH by sending directly to the bridge.
receive() external payable override onlyEOA {
...
...
@@ -212,7 +221,7 @@ contract L1StandardBridge is StandardBridge, Semver {
/// @notice Retrieves the access of the corresponding L2 bridge contract.
/// @return Address of the corresponding L2 bridge contract.
function l2TokenBridge() external view returns (address) {
return address(OTHER_BRIDGE);
return address(
_
OTHER_BRIDGE);
}
/// @notice Internal function for initiating an ETH deposit.
...
...
packages/contracts-bedrock/src/L2/L2StandardBridge.sol
View file @
b4768da2
...
...
@@ -5,6 +5,7 @@ import { Predeploys } from "../libraries/Predeploys.sol";
import { StandardBridge } from "../universal/StandardBridge.sol";
import { Semver } from "../universal/Semver.sol";
import { OptimismMintableERC20 } from "../universal/OptimismMintableERC20.sol";
import { CrossDomainMessenger } from "../universal/CrossDomainMessenger.sol";
/// @custom:proxied
/// @custom:predeploy 0x4200000000000000000000000000000000000010
...
...
@@ -50,13 +51,22 @@ contract L2StandardBridge is StandardBridge, Semver {
bytes extraData
);
/// @custom:semver 1.
1.1
/// @custom:semver 1.
2.0
/// @notice Constructs the L2StandardBridge contract.
/// @param _otherBridge Address of the L1StandardBridge.
constructor(address payable _otherBridge)
Semver(1, 1, 1)
StandardBridge(payable(Predeploys.L2_CROSS_DOMAIN_MESSENGER), _otherBridge)
{}
constructor(StandardBridge _otherBridge)
Semver(1, 2, 0)
StandardBridge(_otherBridge)
{
initialize();
}
/// @notice Initializer
function initialize() public reinitializer(2) {
__StandardBridge_init({
_messenger: CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER)
});
}
/// @notice Allows EOAs to bridge ETH by sending directly to the bridge.
receive() external payable override onlyEOA {
...
...
@@ -138,7 +148,7 @@ contract L2StandardBridge is StandardBridge, Semver {
/// @notice Retrieves the access of the corresponding L1 bridge contract.
/// @return Address of the corresponding L1 bridge contract.
function l1TokenBridge() external view returns (address) {
return address(OTHER_BRIDGE);
return address(
_
OTHER_BRIDGE);
}
/// @custom:legacy
...
...
packages/contracts-bedrock/src/universal/StandardBridge.sol
View file @
b4768da2
...
...
@@ -9,23 +9,21 @@ import { SafeCall } from "../libraries/SafeCall.sol";
import { IOptimismMintableERC20, ILegacyMintableERC20 } from "./IOptimismMintableERC20.sol";
import { CrossDomainMessenger } from "./CrossDomainMessenger.sol";
import { OptimismMintableERC20 } from "./OptimismMintableERC20.sol";
import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
/// @custom:upgradeable
/// @title StandardBridge
/// @notice StandardBridge is a base contract for the L1 and L2 standard ERC20 bridges. It handles
/// the core bridging logic, including escrowing tokens that are native to the local chain
/// and minting/burning tokens that are native to the remote chain.
abstract contract StandardBridge {
abstract contract StandardBridge
is Initializable
{
using SafeERC20 for IERC20;
/// @notice The L2 gas limit set when eth is depoisited using the receive() function.
uint32 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 200_000;
/// @notice Messenger contract on this domain.
CrossDomainMessenger public immutable MESSENGER;
/// @notice Corresponding bridge on the other domain.
StandardBridge
public immutable
OTHER_BRIDGE;
StandardBridge
internal immutable _
OTHER_BRIDGE;
/// @custom:legacy
/// @custom:spacer messenger
...
...
@@ -40,10 +38,13 @@ abstract contract StandardBridge {
/// @notice Mapping that stores deposits for a given pair of local and remote tokens.
mapping(address => mapping(address => uint256)) public deposits;
/// @notice Messenger contract on this domain.
CrossDomainMessenger internal _MESSENGER;
/// @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.
/// A gap size of 4
7
was chosen here, so that the first slot used in a child contract
/// A gap size of 4
6
was chosen here, so that the first slot used in a child contract
/// would be a multiple of 50.
uint256[4
7
] private __gap;
uint256[4
6
] private __gap;
/// @notice Emitted when an ETH bridge is initiated to the other chain.
/// @param from Address of the sender.
...
...
@@ -115,29 +116,50 @@ abstract contract StandardBridge {
/// @notice Ensures that the caller is a cross-chain message from the other bridge.
modifier onlyOtherBridge() {
require(
msg.sender == address(MESSENGER) &&
MESSENGER.xDomainMessageSender() == address(
OTHER_BRIDGE),
msg.sender == address(
_
MESSENGER) &&
_MESSENGER.xDomainMessageSender() == address(_
OTHER_BRIDGE),
"StandardBridge: function can only be called from the other bridge"
);
_;
}
/// @param _messenger Address of CrossDomainMessenger on this network.
/// @param _otherBridge Address of the other StandardBridge contract.
constructor(address payable _messenger, address payable _otherBridge) {
MESSENGER = CrossDomainMessenger(_messenger);
OTHER_BRIDGE = StandardBridge(_otherBridge);
constructor(StandardBridge _otherBridge) {
_OTHER_BRIDGE = _otherBridge;
}
/// @notice Initializer.
/// @param _messenger Address of CrossDomainMessenger on this network.
// solhint-disable-next-line func-name-mixedcase
function __StandardBridge_init(CrossDomainMessenger _messenger) internal onlyInitializing {
_MESSENGER = _messenger;
}
/// @notice Allows EOAs to bridge ETH by sending directly to the bridge.
/// Must be implemented by contracts that inherit.
receive() external payable virtual;
/// @custom:legacy
/// @notice Legacy getter for messenger contract.
/// @notice Getter for messenger contract.
/// @return Messenger contract on this domain.
function messenger() external view returns (CrossDomainMessenger) {
return MESSENGER;
return _MESSENGER;
}
/// @notice Legacy getter for messenger contract.
/// @custom:legacy
function MESSENGER() external view returns (CrossDomainMessenger) {
return _MESSENGER;
}
/// @notice Getter for the remote domain bridge contract.
function otherBridge() external view returns (StandardBridge) {
return _OTHER_BRIDGE;
}
/// @notice Legacy getter for the remote domain bridge contract.
/// @custom:legacy
function OTHER_BRIDGE() external view returns (StandardBridge) {
return _OTHER_BRIDGE;
}
/// @notice Sends ETH to the sender's address on the other chain.
...
...
@@ -245,7 +267,7 @@ abstract contract StandardBridge {
) public payable onlyOtherBridge {
require(msg.value == _amount, "StandardBridge: amount sent does not match amount required");
require(_to != address(this), "StandardBridge: cannot send to self");
require(_to != address(MESSENGER), "StandardBridge: cannot send to messenger");
require(_to != address(
_
MESSENGER), "StandardBridge: cannot send to messenger");
// Emit the correct events. By default this will be _amount, but child
// contracts may override this function in order to emit legacy events as well.
...
...
@@ -314,8 +336,8 @@ abstract contract StandardBridge {
// contracts may override this function in order to emit legacy events as well.
_emitETHBridgeInitiated(_from, _to, _amount, _extraData);
MESSENGER.sendMessage{ value: _amount }(
address(OTHER_BRIDGE),
_
MESSENGER.sendMessage{ value: _amount }(
address(
_
OTHER_BRIDGE),
abi.encodeWithSelector(
this.finalizeBridgeETH.selector,
_from,
...
...
@@ -361,8 +383,8 @@ abstract contract StandardBridge {
// contracts may override this function in order to emit legacy events as well.
_emitERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);
MESSENGER.sendMessage(
address(OTHER_BRIDGE),
_
MESSENGER.sendMessage(
address(
_
OTHER_BRIDGE),
abi.encodeWithSelector(
this.finalizeBridgeERC20.selector,
// Because this call will be executed on the remote chain, we reverse the order of
...
...
packages/contracts-bedrock/test/CommonTest.t.sol
View file @
b4768da2
...
...
@@ -7,6 +7,7 @@ import { L2OutputOracle } from "../src/L1/L2OutputOracle.sol";
import { L2ToL1MessagePasser } from "../src/L2/L2ToL1MessagePasser.sol";
import { L1StandardBridge } from "../src/L1/L1StandardBridge.sol";
import { L2StandardBridge } from "../src/L2/L2StandardBridge.sol";
import { StandardBridge } from "../src/universal/StandardBridge.sol";
import { L1ERC721Bridge } from "../src/L1/L1ERC721Bridge.sol";
import { L2ERC721Bridge } from "../src/L2/L2ERC721Bridge.sol";
import { OptimismMintableERC20Factory } from "../src/universal/OptimismMintableERC20Factory.sol";
...
...
@@ -414,21 +415,24 @@ contract Bridge_Initializer is Messenger_Initializer {
abi.encode(true)
);
vm.startPrank(multisig);
proxy.setCode(address(new L1StandardBridge(
payable(address(L1Messenger))
)).code);
proxy.setCode(address(new L1StandardBridge()).code);
vm.clearMockedCalls();
address L1Bridge_Impl = proxy.getImplementation();
vm.stopPrank();
L1Bridge = L1StandardBridge(payable(address(proxy)));
L1Bridge.initialize({
_messenger: L1Messenger
});
vm.label(address(proxy), "L1StandardBridge_Proxy");
vm.label(address(L1Bridge_Impl), "L1StandardBridge_Impl");
// Deploy the L2StandardBridge, move it to the correct predeploy
// address and then initialize it
L2StandardBridge l2B = new L2StandardBridge(payable(proxy));
vm.etch(Predeploys.L2_STANDARD_BRIDGE, address(l2B).code);
vm.etch(Predeploys.L2_STANDARD_BRIDGE, address(new L2StandardBridge(StandardBridge(payable(proxy)))).code);
L2Bridge = L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE));
L2Bridge.initialize();
// Set up the L2 mintable token factory
OptimismMintableERC20Factory factory = new OptimismMintableERC20Factory(
...
...
packages/contracts-bedrock/test/StandardBridge.t.sol
View file @
b4768da2
...
...
@@ -14,7 +14,7 @@ import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
/// internal functions so they can be more easily tested directly.
contract StandardBridgeTester is StandardBridge {
constructor(address payable _messenger, address payable _otherBridge)
StandardBridge(
_messenger, _otherBridge
)
StandardBridge(
StandardBridge(_otherBridge)
)
{}
function isOptimismMintableERC20(address _token) external view returns (bool) {
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment