changed 23 days ago
Linked with GitHub

Playbook for USDT0 Migration and Integration on Arbitrum Mainnet

1. Repository Review and Deployment Verification

  • Repositories to Review:

    1. ArbitrumExtension Implementation
    2. OApp Configurations
  • Verification Steps:

    • Ensure the USDT address (0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9) is correctly configured in the OApp deployment.
    • Confirm that during migration, the ArbitrumExtension sets the oftExtension to the deployed OApp address (0x14E4A1B13bf7F943c8ff7C51fb60FA964A298D92).
    • Compare deployed contracts and configuration on explorers against repository code and audit findings.
    • Confirm that ownership of OApp and proxy admin of OApp are with 0x4DFF9b5b0143E642a3F63a5bcf2d1C328e600bf8
    • Confirm that Safe is configured in the same manner as ETH Mainnet safe (same address 0x4DFF9b5b0143E642a3F63a5bcf2d1C328e600bf8)

2 initial wire

  • LayerZero Wiring Commands:
    1. Execute the initial configuration:
      ​​​​​npx hardhat lz:oapp:wire --safe --oapp-config layerzero-arbitrum-prod-step-1.config.ts --log-level verbose
      

3. Proxy Upgrade Using ProxyAdmin

  • ProxyAdmin Details:

    • Address: 0x553ec478A66BE27Ba25A6bc5dB20AEc2eD6A1B4A
  • Preparation: To be executed by Multisig

    1. Transfer ownership of the ProxyAdmin for the USDT contract to the USDT0 multisig (0x4DFF9b5b0143E642a3F63a5bcf2d1C328e600bf8) ahead of migration.
      transferOwnership(0x4DFF9b5b0143E642a3F63a5bcf2d1C328e600bf8)
    2. Transfer ownership of the USDT contract (0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9) to the USDT0 multisig (0x4DFF9b5b0143E642a3F63a5bcf2d1C328e600bf8)
      transferOwnership(0x4DFF9b5b0143E642a3F63a5bcf2d1C328e600bf8)
  • Upgrade Process:

    1. Encode the migrate function call:
      ​​​​​const initializeData = newImplementation.interface.encodeFunctionData(
      ​​​​​    "migrate(string,string,address)",
      ​​​​​    [
      ​​​​​        "USD₮0",  // Name
      ​​​​​        "USD₮0",  // Symbol
      ​​​​​        0x14E4A1B13bf7F943c8ff7C51fb60FA964A298D92  // OFT Contract
      ​​​​​    ]
      ​​​​​);
      
      Encoded data:
      0xee14f7d9000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000014e4a1b13bf7f943c8ff7c51fb60fa964a298d920000000000000000000000000000000000000000000000000000000000000007555344e282ae30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007555344e282ae3000000000000000000000000000000000000000000000000000
    2. Schedule the upgradeAndCall transaction:
      ​​​​​await proxyAdmin.connect(proxyAdminOwner).upgradeAndCall(
      ​​​​​    0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9,
      ​​​​​    newImplementation.address,
      ​​​​​    initializeData
      ​​​​​);
      

4. Withdrawal Execution and Monitoring

  • Withdrawal Process:

    1. Trigger the migration via the upgradeAndCall function, which executes the migrate function.
    2. Ensure the outboundTransfer function is called to transfer the total supply to the LayerZero lockbox:
      ​​​​​ARBITRUM_L2_GATEWAY_ROUTER.outboundTransfer(
      ​​​​​    l1Address,
      ​​​​​    USDT0_L1_LOCKBOX,
      ​​​​​    totalSupply(),
      ​​​​​    bytes("")
      ​​​​​);
      
  • Monitoring System:

    1. Deploy Gelato Web3Function with accurate L2TxHash
    2. Code to be found in https://github.com/Everdawn-Labs/web3-functions-usdt0/blob/master/web3-functions/executeArbTransaction/index.ts
    3. monitor functioning of web3function
    4. set manual timer for 1 Week after migration trigger

4.5. OApp Wiring and Configuration

  1. After migration, execute the second wiring step to adjust confirmation settings:
    ​​​​​npx hardhat lz:oapp:wire --safe --oapp-config layerzero-arbitrum-prod-step-2.config.ts --log-level verbose
    
  2. Adjust send confirmations for ETH-to-Arbitrum from 7M to 60 blocks after migration.

5. Testing and Verification

  • Testing Steps:
    1. Conduct tests with mainnet forking to simulate real scenarios.
    2. Use an environment supporting Arbitrum precompiles (ARB_SYS).
    3. Verify:
      • Proxy upgrade safety.
      • Integration of ArbitrumExtensionV2 with the OApp.
      • Ownership transfers (OApp and ProxyAdmin).
      • Correctness of configurations and pathways.
    4. Confirm deployed configurations on explorers match the audited code.

6. Auditor Guidance

  • Key Audit Points:
    1. Verify the correctness of the withdrawal call:
      ​​​​​ARBITRUM_L2_GATEWAY_ROUTER.outboundTransfer(
      ​​​​​    l1Address,
      ​​​​​    USDT0_L1_LOCKBOX,
      ​​​​​    totalSupply(),
      ​​​​​    bytes("")
      ​​​​​);
      
    2. Ensure cross-chain components are functioning as intended.
    3. Highlight that the testing environment uses mocks and does not emulate native bridge behavior.
    4. Upgrade safety via migrate(), lack of initialize due to Initializable at OZ contracts 4.2.0 used

7. Documentation and Governance

  • Verification Steps:
    1. Compare deployed configurations and explorer code against repository and audit findings.
    2. Maintain detailed logs of all actions during migration.
    3. Document pre- and post-migration configurations for contracts and systems.

8. Multisig Participants and Third-Party Auditors

  • Multisig Participants:

    • ETH Multisig: 0x4DFF9b5b0143E642a3F63a5bcf2d1C328e600bf8
    • Arbitrum Multisig: 0x4DFF9b5b0143E642a3F63a5bcf2d1C328e600bf8
  • Tether Multisig

    • Arbitrum: 0x4a9196b06f339Ad9F3Ee752C987b401F2E1E2718
  • Third-Party Auditors:

    • GuardianAudits
    • ChainSecurity
    • OpenZeppelin
Select a repo