- 
                Notifications
    You must be signed in to change notification settings 
- Fork 157
Add UpgradeExecutor to token bridge creation flow #38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
79bf267
              cd35fef
              ab468c1
              18ec4b6
              6f7ad28
              c4c517d
              38083c7
              3ca96b2
              d5998c2
              d6b7ff6
              30cdd75
              14a2311
              864fa61
              1525d26
              2ecec9a
              File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -1,4 +1,13 @@ | ||
| ## Goerli - Deploy L1TokenBridgeCreator | ||
| ARB_GOERLI_RPC="" | ||
| ARB_GOERLI_DEPLOYER_KEY="" | ||
| ORBIT_RPC="" | ||
| .env-sample | ||
|  | ||
| ## Rollup on top of which token bridge will be created | ||
| ROLLUP_ADDRESS="" | ||
| ROLLUP_OWNER="" | ||
| L1_TOKEN_BRIDGE_CREATOR="" | ||
|  | ||
| ## RPC endpoints | ||
| BASECHAIN_RPC="" | ||
| ORBIT_RPC="" | ||
|  | ||
| ## Deployer key used for deploying creator and creating token bridge | ||
| BASECHAIN_DEPLOYER_KEY="" | 
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -1,5 +1,7 @@ | ||
| .gitignore | ||
| .env | ||
| node_modules | ||
| .vscode/ | ||
|  | ||
| #Hardhat files | ||
| cache | ||
|  | ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
|  | @@ -6,6 +6,7 @@ import {L2ERC20Gateway} from "./gateway/L2ERC20Gateway.sol"; | |
| import {L2CustomGateway} from "./gateway/L2CustomGateway.sol"; | ||
| import {L2WethGateway} from "./gateway/L2WethGateway.sol"; | ||
| import {StandardArbERC20} from "./StandardArbERC20.sol"; | ||
| import {IUpgradeExecutor} from "@offchainlabs/upgrade-executor/src/IUpgradeExecutor.sol"; | ||
| import {BeaconProxyFactory} from "../libraries/ClonableBeaconProxy.sol"; | ||
| import {aeWETH} from "../libraries/aeWETH.sol"; | ||
| import {UpgradeableBeacon} from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; | ||
|  | @@ -32,24 +33,32 @@ contract L2AtomicTokenBridgeFactory { | |
| address l1WethGateway, | ||
| address l1Weth, | ||
| address l2StandardGatewayCanonicalAddress, | ||
| address rollupOwner | ||
| address rollupOwner, | ||
| address aliasedL1UpgradeExecutor | ||
| ) external { | ||
| // create proxyAdmin which will be used for all contracts. Revert if canonical deployment already exists | ||
| address proxyAdminAddress = Create2.computeAddress( | ||
| _getL2Salt(OrbitSalts.L2_PROXY_ADMIN), | ||
| keccak256(type(ProxyAdmin).creationCode), | ||
| address(this) | ||
| ); | ||
| if (proxyAdminAddress.code.length > 0) { | ||
| revert L2AtomicTokenBridgeFactory_AlreadyExists(); | ||
| // Create proxyAdmin which will be used for all contracts. Revert if canonical deployment already exists | ||
| { | ||
| address proxyAdminAddress = Create2.computeAddress( | ||
| _getL2Salt(OrbitSalts.L2_PROXY_ADMIN), | ||
| keccak256(type(ProxyAdmin).creationCode), | ||
| address(this) | ||
| ); | ||
| if (proxyAdminAddress.code.length > 0) { | ||
| revert L2AtomicTokenBridgeFactory_AlreadyExists(); | ||
| } | ||
| } | ||
| address proxyAdmin = | ||
| address(new ProxyAdmin{ salt: _getL2Salt(OrbitSalts.L2_PROXY_ADMIN) }()); | ||
|  | ||
| // deploy router/gateways | ||
| // deploy router/gateways/executor | ||
| address upgradeExecutor = _deployUpgradeExecutor( | ||
| l2Code.upgradeExecutor, rollupOwner, proxyAdmin, aliasedL1UpgradeExecutor | ||
| ); | ||
| address router = | ||
| _deployRouter(l2Code.router, l1Router, l2StandardGatewayCanonicalAddress, proxyAdmin); | ||
| _deployStandardGateway(l2Code.standardGateway, l1StandardGateway, router, proxyAdmin); | ||
| _deployStandardGateway( | ||
| l2Code.standardGateway, l1StandardGateway, router, proxyAdmin, upgradeExecutor | ||
| ); | ||
| _deployCustomGateway(l2Code.customGateway, l1CustomGateway, router, proxyAdmin); | ||
|  | ||
| // fee token based creator will provide address(0) as WETH is not used in ERC20-based chains | ||
|  | @@ -59,8 +68,39 @@ contract L2AtomicTokenBridgeFactory { | |
| ); | ||
| } | ||
|  | ||
| // transfer ownership to rollup's owner | ||
| ProxyAdmin(proxyAdmin).transferOwnership(rollupOwner); | ||
| // deploy multicall | ||
| Create2.deploy(0, _getL2Salt(OrbitSalts.L2_MULTICALL), _creationCodeFor(l2Code.multicall)); | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we use a proxy in case the multicall implementation changes? Or has it been stable for a long time? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm good q, not sure if it is worth it. Arb multicall hasn't been changed last 2 year as far as I can see. @gzeoneth what do you think? | ||
|  | ||
| // transfer ownership to L2 upgradeExecutor | ||
| ProxyAdmin(proxyAdmin).transferOwnership(upgradeExecutor); | ||
| } | ||
|  | ||
| function _deployUpgradeExecutor( | ||
| bytes calldata runtimeCode, | ||
| address rollupOwner, | ||
| address proxyAdmin, | ||
| address aliasedL1UpgradeExecutor | ||
| ) internal returns (address) { | ||
| // canonical L2 upgrade executor with dummy logic | ||
| address canonicalUpgradeExecutor = _deploySeedProxy( | ||
| proxyAdmin, _getL2Salt(OrbitSalts.L2_EXECUTOR), _getL2Salt(OrbitSalts.L2_EXECUTOR_LOGIC) | ||
| ); | ||
|  | ||
| // create UpgradeExecutor logic and upgrade to it | ||
| address upExecutorLogic = Create2.deploy( | ||
| 0, _getL2Salt(OrbitSalts.L2_EXECUTOR_LOGIC), _creationCodeFor(runtimeCode) | ||
| ); | ||
| ProxyAdmin(proxyAdmin).upgrade( | ||
| ITransparentUpgradeableProxy(canonicalUpgradeExecutor), upExecutorLogic | ||
| ); | ||
|  | ||
| // init upgrade executor | ||
| address[] memory executors = new address[](2); | ||
| executors[0] = rollupOwner; | ||
| executors[1] = aliasedL1UpgradeExecutor; | ||
| IUpgradeExecutor(canonicalUpgradeExecutor).initialize(canonicalUpgradeExecutor, executors); | ||
|  | ||
| return canonicalUpgradeExecutor; | ||
| } | ||
|  | ||
| function _deployRouter( | ||
|  | @@ -89,7 +129,8 @@ contract L2AtomicTokenBridgeFactory { | |
| bytes calldata runtimeCode, | ||
| address l1StandardGateway, | ||
| address router, | ||
| address proxyAdmin | ||
| address proxyAdmin, | ||
| address upgradeExecutor | ||
| ) internal { | ||
| // canonical L2 standard gateway with dummy logic | ||
| address canonicalStdGateway = _deploySeedProxy( | ||
|  | @@ -122,6 +163,9 @@ contract L2AtomicTokenBridgeFactory { | |
| L2ERC20Gateway(canonicalStdGateway).initialize( | ||
| l1StandardGateway, router, address(beaconProxyFactory) | ||
| ); | ||
|  | ||
| // make L2 executor the beacon owner | ||
| beacon.transferOwnership(upgradeExecutor); | ||
| } | ||
|  | ||
| function _deployCustomGateway( | ||
|  | @@ -201,7 +245,7 @@ contract L2AtomicTokenBridgeFactory { | |
| * permissionless. By making msg.sender part of the salt we know exactly which set of contracts is the "canonical" one, | ||
| * deployed by L1TokenBridgeRetryableSender via retryable ticket. | ||
| */ | ||
| function _getL2Salt(bytes32 prefix) internal view returns (bytes32) { | ||
| function _getL2Salt(bytes memory prefix) internal view returns (bytes32) { | ||
| return keccak256(abi.encodePacked(prefix, msg.sender)); | ||
| } | ||
|  | ||
|  | @@ -257,31 +301,35 @@ struct L2RuntimeCode { | |
| bytes customGateway; | ||
| bytes wethGateway; | ||
| bytes aeWeth; | ||
| bytes upgradeExecutor; | ||
| bytes multicall; | ||
| } | ||
|  | ||
| /** | ||
| * Collection of salts used in CREATE2 deployment of L2 token bridge contracts. | ||
| */ | ||
| library OrbitSalts { | ||
| bytes32 public constant L1_PROXY_ADMIN = keccak256(bytes("OrbitL1ProxyAdmin")); | ||
| bytes32 public constant L1_ROUTER = keccak256(bytes("OrbitL1GatewayRouterProxy")); | ||
| bytes32 public constant L1_STANDARD_GATEWAY = keccak256(bytes("OrbitL1StandardGatewayProxy")); | ||
| bytes32 public constant L1_CUSTOM_GATEWAY = keccak256(bytes("OrbitL1CustomGatewayProxy")); | ||
| bytes32 public constant L1_WETH_GATEWAY = keccak256(bytes("OrbitL1WethGatewayProxy")); | ||
|  | ||
| bytes32 public constant L2_PROXY_ADMIN = keccak256(bytes("OrbitL2ProxyAdmin")); | ||
| bytes32 public constant L2_ROUTER_LOGIC = keccak256(bytes("OrbitL2GatewayRouterLogic")); | ||
| bytes32 public constant L2_ROUTER = keccak256(bytes("OrbitL2GatewayRouterProxy")); | ||
| bytes32 public constant L2_STANDARD_GATEWAY_LOGIC = | ||
| keccak256(bytes("OrbitL2StandardGatewayLogic")); | ||
| bytes32 public constant L2_STANDARD_GATEWAY = keccak256(bytes("OrbitL2StandardGatewayProxy")); | ||
| bytes32 public constant L2_CUSTOM_GATEWAY_LOGIC = keccak256(bytes("OrbitL2CustomGatewayLogic")); | ||
| bytes32 public constant L2_CUSTOM_GATEWAY = keccak256(bytes("OrbitL2CustomGatewayProxy")); | ||
| bytes32 public constant L2_WETH_GATEWAY_LOGIC = keccak256(bytes("OrbitL2WethGatewayLogic")); | ||
| bytes32 public constant L2_WETH_GATEWAY = keccak256(bytes("OrbitL2WethGatewayProxy")); | ||
| bytes32 public constant L2_WETH_LOGIC = keccak256(bytes("OrbitL2WETH")); | ||
| bytes32 public constant L2_WETH = keccak256(bytes("OrbitL2WETHProxy")); | ||
| bytes32 public constant L2_STANDARD_ERC20 = keccak256(bytes("OrbitStandardArbERC20")); | ||
| bytes32 public constant UPGRADEABLE_BEACON = keccak256(bytes("OrbitUpgradeableBeacon")); | ||
| bytes32 public constant BEACON_PROXY_FACTORY = keccak256(bytes("OrbitBeaconProxyFactory")); | ||
| bytes public constant L1_PROXY_ADMIN = bytes("OrbitL1ProxyAdmin"); | ||
| bytes public constant L1_ROUTER = bytes("OrbitL1GatewayRouterProxy"); | ||
| bytes public constant L1_STANDARD_GATEWAY = bytes("OrbitL1StandardGatewayProxy"); | ||
| bytes public constant L1_CUSTOM_GATEWAY = bytes("OrbitL1CustomGatewayProxy"); | ||
| bytes public constant L1_WETH_GATEWAY = bytes("OrbitL1WethGatewayProxy"); | ||
|  | ||
| bytes public constant L2_PROXY_ADMIN = bytes("OrbitL2ProxyAdmin"); | ||
| bytes public constant L2_ROUTER_LOGIC = bytes("OrbitL2GatewayRouterLogic"); | ||
| bytes public constant L2_ROUTER = bytes("OrbitL2GatewayRouterProxy"); | ||
| bytes public constant L2_STANDARD_GATEWAY_LOGIC = bytes("OrbitL2StandardGatewayLogic"); | ||
| bytes public constant L2_STANDARD_GATEWAY = bytes("OrbitL2StandardGatewayProxy"); | ||
| bytes public constant L2_CUSTOM_GATEWAY_LOGIC = bytes("OrbitL2CustomGatewayLogic"); | ||
| bytes public constant L2_CUSTOM_GATEWAY = bytes("OrbitL2CustomGatewayProxy"); | ||
| bytes public constant L2_WETH_GATEWAY_LOGIC = bytes("OrbitL2WethGatewayLogic"); | ||
| bytes public constant L2_WETH_GATEWAY = bytes("OrbitL2WethGatewayProxy"); | ||
| bytes public constant L2_WETH_LOGIC = bytes("OrbitL2WETH"); | ||
| bytes public constant L2_WETH = bytes("OrbitL2WETHProxy"); | ||
| bytes public constant L2_STANDARD_ERC20 = bytes("OrbitStandardArbERC20"); | ||
| bytes public constant UPGRADEABLE_BEACON = bytes("OrbitUpgradeableBeacon"); | ||
| bytes public constant BEACON_PROXY_FACTORY = bytes("OrbitBeaconProxyFactory"); | ||
| bytes public constant L2_EXECUTOR_LOGIC = bytes("OrbitL2UpgradeExecutorLogic"); | ||
| bytes public constant L2_EXECUTOR = bytes("OrbitL2UpgradeExecutorProxy"); | ||
| bytes public constant L2_MULTICALL = bytes("OrbitL2Multicall"); | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.