Try   HackMD

wstETH on Optimism: deployment artifacts and log

Cross-chain governance executor

  1. For the governance representation, the token and the bridge admin has been set to the Lido DAO agent contract as a final result of deployment
    The governance executor has been deployed from the following repo:
    https://github.com/lidofinance/governance-crosschain-bridges/tree/master, the contracts correspond to master branch.

  2. Deployment instructions: https://github.com/lidofinance/governance-crosschain-bridges#deploying-the-optimismbridgeexecutor, deployment script: https://github.com/lidofinance/governance-crosschain-bridges/blob/master/deploy/gov-bridge-optimism.ts

Cross-chain governance executor actions log on OP

Mainnet Deployment (01.08.22)

npm run deploy:optimism:mainnet

wstETH Bridge and token

GitHub repo: https://github.com/lidofinance/lido-l2, main branch.

  1. the deployment happened on the pre-bedrock OP version
    The list of the deployed artifacts together with a governance executor module:
    https://docs.lido.fi/deployed-contracts/#optimism

  2. One can use the deployment instructions described in the following sections:
    https://github.com/lidofinance/lido-l2#bridge-deployment (general env setup)
    https://github.com/lidofinance/lido-l2#deploying-optimism-bridge (Optimism case)

wstETH Bridge deployment actions log on OP

Stage I: wstETH bridge and token: Mainnet Deployment (03.08.22)

npm run optimism:deploy
  • Set forking variable in the .env file to false
  • Run script to deploy and setup contracts on mainnet:
npm run optimism:deploy
  • Deployed Contract Addresses:

    • L1ERC20TokenBridge Impl : 0x29C5c51A031165CE62F964966A6399b81165EFA4
    • L1ERC20TokenBridge Proxy: 0x76943C0D61395d8F2edF9060e1533529cAe05dE6
    • ERC20Bridged Impl: 0x92834c37dF982A13bb0f8C3F6608E26F0546538e
    • ERC20Bridged Proxy: 0x1F32b1c2345538c0c6f582fCB022739c4A194Ebb
    • L2ERC20TokenBridge Impl: 0x23B96aDD54c479C6784Dd504670B5376B808f4C7
    • L2ERC20TokenBridge Proxy: 0x8E01013243a96601a86eb3153F0d9Fa4fbFb6957
  • Verify the deployed contracts on Etherscan using the commands generated by the deploy script

  • Run tests for deployed contracts:

    • Set the following variables in the .env file
    ​​​​TESTING_OPT_L2_TOKEN=
    ​​​​TESTING_OPT_L1_ERC20_TOKEN_BRIDGE=
    ​​​​TESTING_OPT_L2_ERC20_TOKEN_BRIDGE=
    ​​​​TESTING_L1_TOKENS_HOLDER=
    
    • Run the forks of the Ethereum and Optimism networks:
    ​​​​npm run fork:eth:mainnet
    ​​​​npm run fork:opt:mainnet
    
    • Run acceptance test
    ​​​​npm run optimism:test:acceptance
    
    • Run integration tests for deployed contracts
    ​​​​npm run optimism:test:integration
    
  • Manually validate the state of the contracts:

    • OssifiableProxy for L1ERC20TokenBridge (0x76943C0D61395d8F2edF9060e1533529cAe05dE6)
      • proxy__getAdmin - 0x3e40D73EB977Dc6a537aF587D48316feE66E9C8c
      • proxy__getImplementation - 0x29C5c51A031165CE62F964966A6399b81165EFA4
      • proxy__getIsOssified == false
      • isDepositsEnabled == false
      • isWithdrawalsEnabled == true
      • isInitialized == true
      • hasRole(DEFAULT_ADMIN_ROLE, 0x3e40D73EB977Dc6a537aF587D48316feE66E9C8c) == true
      • hasRole(DEFAULT_ADMIN_ROLE, 0x2a61d3ba5030Ef471C74f612962c7367ECa3a62d) == false
      • hasRole(DEPOSITS_ENABLER_ROLE, 0x2a61d3ba5030Ef471C74f612962c7367ECa3a62d) == false
      • hasRole(DEPOSITS_ENABLER_ROLE, 0x3cd9F71F80AB08ea5a7Dca348B5e94BC595f26A0) == true
      • hasRole(DEPOSITS_ENABLER_ROLE, 0x3e40D73EB977Dc6a537aF587D48316feE66E9C8c) == true
      • hasRole(DEPOSITS_DISABLER_ROLE, 0x3e40D73EB977Dc6a537aF587D48316feE66E9C8c) == true
      • hasRole(DEPOSITS_DISABLER_ROLE, 0x2a61d3ba5030Ef471C74f612962c7367ECa3a62d) == false
      • hasRole(DEPOSITS_DISABLER_ROLE, 0x73b047fe6337183A454c5217241D780a932777bD) == true
      • hasRole(WITHDRAWALS_ENABLER_ROLE, 0x3e40D73EB977Dc6a537aF587D48316feE66E9C8c) == true
      • hasRole(WITHDRAWALS_ENABLER_ROLE, 0x2a61d3ba5030Ef471C74f612962c7367ECa3a62d) == false
      • hasRole(WITHDRAWALS_DISABLER_ROLE, 0x2a61d3ba5030Ef471C74f612962c7367ECa3a62d) == false
      • hasRole(WITHDRAWALS_DISABLER_ROLE, 0x3e40D73EB977Dc6a537aF587D48316feE66E9C8c) == true
      • hasRole(WITHDRAWALS_DISABLER_ROLE, 0x73b047fe6337183A454c5217241D780a932777bD) == true
    • L1ERC20TokenBridge implementation (0x29C5c51A031165CE62F964966A6399b81165EFA4)
      • l1Token == 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0
      • l2Token - 0x1F32b1c2345538c0c6f582fCB022739c4A194Ebb
      • l2TokenBridge - 0x8E01013243a96601a86eb3153F0d9Fa4fbFb6957
      • messenger == 0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1
    • OssifiableProxy for L2ERC20TokenBridge (0x8E01013243a96601a86eb3153F0d9Fa4fbFb6957)
      • proxy__getAdmin - 0xEfa0dB536d2c8089685630fafe88CF7805966FC3 (Lido’s Optimism Governance Bridge)
      • proxy__getImplementation - 0x23B96aDD54c479C6784Dd504670B5376B808f4C7
      • proxy__getIsOssified == false
      • isDepositsEnabled == true
      • isWithdrawalsEnabled == true
      • isInitialized == true
      • hasRole(DEFAULT_ADMIN_ROLE, 0xEfa0dB536d2c8089685630fafe88CF7805966FC3) == true
      • hasRole(DEFAULT_ADMIN_ROLE, 0x2C01F405e3C525C0cB867789AAf077f3553ccbB7) == false
      • hasRole(DEPOSITS_ENABLER_ROLE, 0x2C01F405e3C525C0cB867789AAf077f3553ccbB7) == false
      • hasRole(DEPOSITS_ENABLER_ROLE, 0xEfa0dB536d2c8089685630fafe88CF7805966FC3) == true
      • hasRole(DEPOSITS_DISABLER_ROLE, 0xEfa0dB536d2c8089685630fafe88CF7805966FC3) == true
      • hasRole(DEPOSITS_DISABLER_ROLE, 0x4Cf8fE0A4c2539F7EFDD2047d8A5D46F14613088) == true
      • hasRole(DEPOSITS_DISABLER_ROLE, 0x2C01F405e3C525C0cB867789AAf077f3553ccbB7) == false
      • hasRole(WITHDRAWALS_ENABLER_ROLE, 0x2C01F405e3C525C0cB867789AAf077f3553ccbB7) == false
      • hasRole(WITHDRAWALS_ENABLER_ROLE, 0xEfa0dB536d2c8089685630fafe88CF7805966FC3) == true
      • hasRole(WITHDRAWALS_DISABLER_ROLE, 0xEfa0dB536d2c8089685630fafe88CF7805966FC3) == true
      • hasRole(WITHDRAWALS_DISABLER_ROLE, 0x4Cf8fE0A4c2539F7EFDD2047d8A5D46F14613088) == true
      • hasRole(WITHDRAWALS_DISABLER_ROLE, 0x2C01F405e3C525C0cB867789AAf077f3553ccbB7) == false
    • L2ERC20TokenBridge implementation (0x23B96aDD54c479C6784Dd504670B5376B808f4C7)
      • l1Token == 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0
      • l2Token - 0x1F32b1c2345538c0c6f582fCB022739c4A194Ebb
      • l1TokenBridge - 0x76943C0D61395d8F2edF9060e1533529cAe05dE6
      • messenger == 0x4200000000000000000000000000000000000007
    • OssifiableProxy for L2ERC20Bridged (0x1F32b1c2345538c0c6f582fCB022739c4A194Ebb)
      • proxy__getAdmin == 0xEfa0dB536d2c8089685630fafe88CF7805966FC3 (Lido’s AAVE Governance Bridge)
      • proxy__getImplementation == 0x92834c37dF982A13bb0f8C3F6608E26F0546538e
      • proxy__getIsOssified == false
      • name == Wrapped liquid staked Ether 2.0
      • symbol == wstETH
      • totalSupply == 0
    • L2ERC20Bridged (0x92834c37dF982A13bb0f8C3F6608E26F0546538e)
      • decimals == 18
      • bridge == 0x8E01013243a96601a86eb3153F0d9Fa4fbFb6957
    • Validate vendor contracts versions are correct
      • L1ERC20TokenBridge Impl :
        Prev: 0x7E1dBD017973871abcFac9e4B830018812056c17
        Current: 0x29C5c51A031165CE62F964966A6399b81165EFA4
      • L2ERC20TokenBridge Impl:
        • Prev: 0x69d02FedAE5E289F467280bC25316D2E835C5864
        • Current: 0x23B96aDD54c479C6784Dd504670B5376B808f4C7
      • ERC20Bridged Impl:
        • Prev: 0x75ff3dd673Ef9fC459A52E1054db5dF2A1101212
        • Current: 0x92834c37dF982A13bb0f8C3F6608E26F0546538e
      • ERC20Bridged Proxy:
        • Prev 0xbADcCcf4156967783fA818Bc4a8c93b5575A07B0
        • Current: 0x1F32b1c2345538c0c6f582fCB022739c4A194Ebb
      • L1ERC20TokenBridge Proxy:
        • Prev 0x89057C7E4c5cD283afF5907B816F61e326047C29
        • Current 0x76943C0D61395d8F2edF9060e1533529cAe05dE6
      • L2ERC20TokenBridge Proxy:
        • Prev 0x0fc3De4B1bbcB315880d328e3f9C81d742D73d01
        • Current 0x8E01013243a96601a86eb3153F0d9Fa4fbFb6957
    • Initialize Bridge implementations and check that ERC20Bridged impl is initialized

    After Deployment Actions

    • Save addresses to setup monitoring on mainnet contracts

    Adding deployed wstETH to Optimism Mainnet UI

    If Something Goes Wrong

    • If the deploy script failed because of environmental reasons (RPC failure or tx frozen up in the mem pool) try to continue it from the failed step or relaunch the whole deploy script
    • If the deploy script failed because of the error, fix it and relaunch
    • if on etherscan are submitted excessive contracts - redeploy the contracts and verify them manually using a flattened contract (low-risk issue)
    • If deployment validation failed because of the wrong values, fix the params and relaunch the script

Stage II: Mainnet Deployment Validation (09.08.22)

  • Run forked nodes
npm run fork:eth:mainnet
npm run fork:opt:mainnet
  • Set .env variables
TESTING_OPT_NETWORK=mainnet
TESTING_OPT_L1_TOKEN=0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0
TESTING_OPT_L2_TOKEN=0x1F32b1c2345538c0c6f582fCB022739c4A194Ebb
TESTING_OPT_L1_ERC20_TOKEN_BRIDGE=0x76943C0D61395d8F2edF9060e1533529cAe05dE6
TESTING_OPT_L2_ERC20_TOKEN_BRIDGE=0x8E01013243a96601a86eb3153F0d9Fa4fbFb6957
TESTING_OPT_GOV_BRIDGE_EXECUTOR=0xefa0db536d2c8089685630fafe88cf7805966fc3

TESTING_USE_DEPLOYED_CONTRACTS=true
L1_DEV_MULTISIG=0x3cd9F71F80AB08ea5a7Dca348B5e94BC595f26A0
TESTING_L1_TOKENS_HOLDER=0x23237b849d0e6f392573ee6ae9e3b1256f058143
  • Run executor integration tests
npm run optimism:test:executor
  • Run launch test
npm run optimism:test:launch
  • Validate there are no unstructured storage slot collisions:
    • OssifiableProxy implementation slot:
      • keccak256("eip1967.proxy.implementation") - 1
      • 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc
    • OssifiableProxy admin slot:
      • keccak256("eip1967.proxy.admin") - 1
      • 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103
    • BridgingManager state slot:
      • keccak256("BridgingManager.bridgingState")
      • 0x013e929b381f2fbbac854bd18fb8231dc73c4a2eab0d4cbb4db9436b6ff9b2ba
    • ERC20Metadata state slot:
      • keccak256("ERC20Metdata.dynamicMetadata")
      • 0x3470f8373d566de7ab61e14a030ae865a1f164b610b931eb8aa08ad044e2e68e
  • Validate our own code:
    • L1ERC20TokenBridge Impl : 0x29C5c51A031165CE62F964966A6399b81165EFA4
      • L1ERC20TokenBridge.sol
      • IL1ERC20Bridge.sol
      • IL2ERC20Bridge.sol
      • BridgingManager.sol
      • BridgeableTokens.sol
      • CrossDomainEnabled.sol
      • ICrossDomainMessenger.sol
    • L2ERC20TokenBridge Impl: 0x23B96aDD54c479C6784Dd504670B5376B808f4C7
      • L2ERC20TokenBridge.sol
      • IL1ERC20Bridge.sol
      • IL2ERC20Bridge.sol
      • IERC20Bridged.sol
      • BridgingManager.sol
      • BridgeableTokens.sol
      • CrossDomainEnabled.sol
      • ICrossDomainMessenger.sol
    • ERC20Bridged Impl: 0x92834c37dF982A13bb0f8C3F6608E26F0546538e
      • ERC20Bridged.sol
      • IERC20Bridged.sol
      • ERC20Core.sol
      • ERC20Metadata.sol
      • IERC20Metadata.sol
    • ERC20Bridged Proxy: 0x1F32b1c2345538c0c6f582fCB022739c4A194Ebb
      • OssifiableProxy.sol
    • L1ERC20TokenBridge Proxy: 0x76943C0D61395d8F2edF9060e1533529cAe05dE6
      • OssifiableProxy.sol
    • L2ERC20TokenBridge Proxy: 0x8E01013243a96601a86eb3153F0d9Fa4fbFb6957
      • OssifiableProxy.sol

Stage III: Mainnet Bridge Launch (04.08.22-08.08.22)

  • Run launch scenario test

  • Activate deposits on L1 via dev multisig

    • address: 0x76943C0D61395d8F2edF9060e1533529cAe05dE6 (L1ERC20TokenBridge Proxy)
    • method: enableDeposits()
  • Renounce role DEPOSITS_ENABLER_ROLE from the dev multisig:

    • address: 0x76943C0D61395d8F2edF9060e1533529cAe05dE6 (L1ERC20TokenBridge Proxy)
    • method: renounceRole(bytes32 role, address account)
      • role - 0x4b43b36766bde12c5e9cbbc37d15f8d1f769f08f54720ab370faeb4ce893753a
      • address - 0x3cd9F71F80AB08ea5a7Dca348B5e94BC595f26A0
  • Validate state of the contract on Etherescan

    • isDepositsEnabled - true
    • hasRole() - false
  • Re-run launch scenario test

  • Run the e2e test for optimism bridging after activation of deposits with addresses of deployed contracts:

    • Set the following variables in the .env file
    ​​​​TESTING_OPT_NETWORK=mainnet
    ​​​​TESTING_OPT_L1_TOKEN=0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0
    ​​​​TESTING_OPT_L2_TOKEN=0x1F32b1c2345538c0c6f582fCB022739c4A194Ebb
    ​​​​TESTING_OPT_L1_ERC20_TOKEN_BRIDGE=0x76943C0D61395d8F2edF9060e1533529cAe05dE6
    ​​​​TESTING_OPT_L2_ERC20_TOKEN_BRIDGE=0x8E01013243a96601a86eb3153F0d9Fa4fbFb6957
    ​​​​TESTING_PRIVATE_KEY=
    
    • Run e2e tests for deployed contracts
    ​​​​npx hardhat test ./test/optimism/bridging.e2e.test.ts    ```    
    
  • Reach out to Optimism team that bridging was enabled and PR might be merged

  • Test the wstETH bridging via Optimism UI to test that bridging is working

  • Notify dev teams that bridge is enabled

    If Something Goes Wrong

    • If the test failed - figure out the reason of the failure, and fix it if possible on deployed setup. If it’s not possible, reach out Optimism team, and a biz dev team that the launch must be postponed. Fix the problem and schedule a new release date.

Notes and remarks