├── .clabot ├── .env-sample ├── .env.arb1.sample ├── .eslintignore ├── .eslintrc.js ├── .gitattributes ├── .github ├── dependabot.yml └── workflows │ ├── build-test.yml │ └── slither.yml ├── .gitignore ├── .gitmodules ├── .prettierignore ├── .prettierrc.js ├── .solhint.json ├── LICENSE ├── README.md ├── _deployments ├── 11155111_current_deployment.json ├── 11155111_queued-updates.json ├── 1337_current_deployment.json ├── 1337_queued-updates.json ├── 1_42170_current_deployment.json ├── 1_42170_queued-updates.json ├── 1_current_deployment.json ├── 1_queued-updates.json ├── 421611_current_deployment.json ├── 421611_queued-updates.json ├── 421613_current_deployment.json ├── 421613_queued-updates.json ├── 421614_current_deployment.json ├── 421614_queued-updates.json ├── 42161_current_deployment.json ├── 42161_queued-updates.json ├── 42170_current_deployment.json ├── 42170_queued-updates.json ├── 4_current_deployment.json ├── 4_queued-updates.json ├── 5_current_deployment.json └── 5_queued-updates.json ├── audits ├── ConsenSys_Diligence_Arbitrum_Contracts_11_2021.pdf └── trail_of_bits_governance_report_1_6_2023.pdf ├── contracts ├── rpc-utils │ ├── MulticallV2.sol │ ├── NodeInterface.sol │ └── RetryableTicketCreator.sol └── tokenbridge │ ├── arbitrum │ ├── IArbToken.sol │ ├── L2ArbitrumMessenger.sol │ ├── L2AtomicTokenBridgeFactory.sol │ ├── ReverseArbToken.sol │ ├── StandardArbERC20.sol │ └── gateway │ │ ├── L2ArbitrumGateway.sol │ │ ├── L2CustomGateway.sol │ │ ├── L2ERC20Gateway.sol │ │ ├── L2GatewayRouter.sol │ │ ├── L2ReverseCustomGateway.sol │ │ ├── L2USDCGateway.sol │ │ └── L2WethGateway.sol │ ├── ethereum │ ├── ICustomToken.sol │ ├── L1ArbitrumMessenger.sol │ ├── L1AtomicTokenBridgeCreator.sol │ ├── L1TokenBridgeRetryableSender.sol │ └── gateway │ │ ├── IL1ArbitrumGateway.sol │ │ ├── IL1GatewayRouter.sol │ │ ├── L1ArbitrumExtendedGateway.sol │ │ ├── L1ArbitrumGateway.sol │ │ ├── L1CustomGateway.sol │ │ ├── L1ERC20Gateway.sol │ │ ├── L1ForceOnlyReverseCustomGateway.sol │ │ ├── L1GatewayRouter.sol │ │ ├── L1OrbitCustomGateway.sol │ │ ├── L1OrbitERC20Gateway.sol │ │ ├── L1OrbitGatewayRouter.sol │ │ ├── L1OrbitReverseCustomGateway.sol │ │ ├── L1OrbitUSDCGateway.sol │ │ ├── L1ReverseCustomGateway.sol │ │ ├── L1USDCGateway.sol │ │ └── L1WethGateway.sol │ ├── libraries │ ├── AddressAliasHelper.sol │ ├── BytesLib.sol │ ├── BytesParser.sol │ ├── ClonableBeaconProxy.sol │ ├── Cloneable.sol │ ├── CreationCodeHelper.sol │ ├── ERC165.sol │ ├── ERC20Upgradeable.sol │ ├── ICloneable.sol │ ├── IERC165.sol │ ├── IERC20Bridge.sol │ ├── IFiatToken.sol │ ├── ITransferAndCall.sol │ ├── IWETH9.sol │ ├── L2CustomGatewayToken.sol │ ├── L2GatewayToken.sol │ ├── ProxyUtil.sol │ ├── TransferAndCallToken.sol │ ├── Whitelist.sol │ ├── aeERC20.sol │ ├── aeWETH.sol │ ├── draft-ERC20PermitUpgradeable.sol │ └── gateway │ │ ├── GatewayMessageHandler.sol │ │ ├── GatewayRouter.sol │ │ ├── ICustomGateway.sol │ │ ├── IGatewayRouter.sol │ │ ├── ITokenGateway.sol │ │ └── TokenGateway.sol │ └── test │ ├── AddressMappingTest.sol │ ├── ArbSysMock.sol │ ├── CreationCodeTest.sol │ ├── InboxMock.sol │ ├── InterfaceCompatibilityTester.sol │ ├── TestArbCustomToken.sol │ ├── TestArbCustomTokenBurnFee.sol │ ├── TestBytesParser.sol │ ├── TestCustomTokenL1.sol │ ├── TestERC20.sol │ ├── TestPostDepositCall.sol │ ├── TestWETH9.sol │ └── UpgradeExecutorForVerification.sol ├── deployment-42161.json ├── deployment-421611.json ├── docs ├── deployment.md └── mutation_testing.md ├── foundry.toml ├── hardhat.config.ts ├── package.json ├── remappings.txt ├── scripts ├── atomicTokenBridgeDeployer.ts ├── contractVerifier.ts ├── deploy_buddy_deployer.ts ├── deployment │ ├── createTokenBridge.ts │ └── deployTokenBridgeCreator.ts ├── local-deployment │ ├── deployCreatorAndCreateTokenBridge.ts │ └── localDeploymentLib.ts ├── orbitVerifyOnBlockscout.ts ├── register_custom_token.ts ├── signatures_test.bash ├── storage_layout_test.bash ├── upgradeTemplate.ts ├── usdc-bridge-deployment │ ├── README.md │ ├── deployUsdcBridge.ts │ └── env.example ├── utils.ts └── verify_upgrade.ts ├── slither.config.json ├── slither.db.json ├── tasks ├── compareBytecode.ts ├── index.ts ├── peripheralsTasks.ts └── types.ts ├── test-e2e ├── creationCodeTest.ts ├── orbitTokenBridge.ts └── tokenBridgeDeploymentTest.ts ├── test-foundry ├── AtomicTokenBridgeFactory.t.sol ├── GatewayRouter.t.sol ├── IOwnable.sol ├── L1ArbitrumExtendedGateway.t.sol ├── L1ArbitrumGateway.t.sol ├── L1AtomicTokenBridgeCreator.t.sol ├── L1CustomGateway.t.sol ├── L1ERC20Gateway.t.sol ├── L1ForceOnlyReverseCustomGateway.t.sol ├── L1GatewayRouter.t.sol ├── L1OrbitCustomGateway.t.sol ├── L1OrbitERC20Gateway.t.sol ├── L1OrbitGatewayRouter.t.sol ├── L1OrbitIntegration.t.sol ├── L1OrbitReverseCustomGateway.t.sol ├── L1OrbitUSDCGateway.t.sol ├── L1ReverseCustomGateway.t.sol ├── L1USDCGateway.t.sol ├── L1WethGateway.t.sol ├── L2ArbitrumGateway.t.sol ├── L2AtomicTokenBridgeFactory.t.sol ├── L2CustomGateway.t.sol ├── L2ERC20Gateway.t.sol ├── L2GatewayRouter.t.sol ├── L2ReverseCustomGateway.t.sol ├── L2USDCGateway.t.sol ├── L2WethGateway.t.sol └── util │ └── TestUtil.sol ├── test-mutation ├── all-configs │ ├── config.single.json │ ├── config.tokenbridge-arbitrum.json │ └── config.tokenbridge-ethereum.json ├── config.json └── gambitTester.ts ├── test ├── bytesParser.l1.ts ├── canonicalBridge.e2e.ts ├── canonicalBridge.l1.ts ├── canonicalBridge.l2.ts ├── customGateway.e2e.ts ├── gatewayRouter.l1.ts ├── reverseCustomGateway.e2e.ts ├── signatures │ ├── L1AtomicTokenBridgeCreator │ ├── L1CustomGateway │ ├── L1ERC20Gateway │ ├── L1GatewayRouter │ ├── L1OrbitCustomGateway │ ├── L1OrbitERC20Gateway │ ├── L1OrbitGatewayRouter │ ├── L1OrbitReverseCustomGateway │ ├── L1OrbitUSDCGateway │ ├── L1ReverseCustomGateway │ ├── L1TokenBridgeRetryableSender │ ├── L1USDCGateway │ ├── L1WethGateway │ ├── L2AtomicTokenBridgeFactory │ ├── L2CustomGateway │ ├── L2ERC20Gateway │ ├── L2GatewayRouter │ ├── L2ReverseCustomGateway │ ├── L2USDCGateway │ ├── L2WethGateway │ └── StandardArbERC20 ├── storage │ ├── L1AtomicTokenBridgeCreator │ ├── L1CustomGateway │ ├── L1ERC20Gateway │ ├── L1GatewayRouter │ ├── L1OrbitCustomGateway │ ├── L1OrbitERC20Gateway │ ├── L1OrbitGatewayRouter │ ├── L1OrbitReverseCustomGateway │ ├── L1OrbitUSDCGateway │ ├── L1ReverseCustomGateway │ ├── L1TokenBridgeRetryableSender │ ├── L1USDCGateway │ ├── L1WethGateway │ ├── L2AtomicTokenBridgeFactory │ ├── L2CustomGateway │ ├── L2ERC20Gateway │ ├── L2GatewayRouter │ ├── L2ReverseCustomGateway │ ├── L2USDCGateway │ ├── L2WethGateway │ └── StandardArbERC20 ├── testhelper.ts ├── unused-errors │ └── exceptions.txt ├── wethBridge.l1.ts ├── wethBridge.l2.ts └── wethGateway.e2e.ts ├── tsconfig.json └── yarn.lock /.clabot: -------------------------------------------------------------------------------- 1 | { 2 | "contributors": "https://api.github.com/repos/OffchainLabs/clabot-config/contents/apache-contributors.json", 3 | "message": "We require contributors to sign our Contributor License Agreement. In order for us to review and merge your code, please sign one of the linked documents below to get yourself added. If you're an independent Individual please sign this form: https://na3.docusign.net/Member/PowerFormSigning.aspx?PowerFormId=1353a816-a9c1-47ba-847e-ec79f0f23d31&env=na3&acct=6e152afc-6284-44af-a4c1-d8ef291db402&v=2. If you're with a company (corporate) please sign this form: https://na3.docusign.net/Member/PowerFormSigning.aspx?PowerFormId=2b5fe8ba-51d4-4980-b4ee-605d66e675d4&env=na3&acct=6e152afc-6284-44af-a4c1-d8ef291db402&v=2. To agree to the CLA license, please fill out one of the attached forms." 4 | } 5 | -------------------------------------------------------------------------------- /.env-sample: -------------------------------------------------------------------------------- 1 | ## RPC endpoint 2 | BASECHAIN_RPC="" 3 | 4 | ## Deployer key used for deploying creator or creating token bridge 5 | BASECHAIN_DEPLOYER_KEY="" 6 | 7 | ## WETH address on the basechain. It will be set and used in the TokenBridgeCreator 8 | BASECHAIN_WETH="" 9 | 10 | ## Gas limit for deploying child chain factory needs to be provided to the TokenBridgeCreator when templates are set. 11 | ## If this param is not provided then gas limit will be estimated using SDK from child chain (specified by ORBIT_RPC and ROLLUP_ADDRESS) 12 | GAS_LIMIT_FOR_L2_FACTORY_DEPLOYMENT=6000000 13 | 14 | ## Contract verification 15 | ARBISCAN_API_KEY="" 16 | 17 | ### Vars for creating token bridge from existing TokenBridgeCreator 18 | ## Rollup on top of which token bridge will be created 19 | ROLLUP_ADDRESS="" 20 | ORBIT_RPC="" 21 | ROLLUP_OWNER="" 22 | L1_TOKEN_BRIDGE_CREATOR="" 23 | # needed for verification 24 | L1_RETRYABLE_SENDER="" -------------------------------------------------------------------------------- /.env.arb1.sample: -------------------------------------------------------------------------------- 1 | ## RPC endpoint 2 | BASECHAIN_RPC="https://arb1.arbitrum.io/rpc" 3 | 4 | ## Deployer key used for deploying creator or creating token bridge 5 | BASECHAIN_DEPLOYER_KEY="" 6 | 7 | ## WETH address on the basechain. It will be set and used in the TokenBridgeCreator 8 | BASECHAIN_WETH="0x82aF49447D8a07e3bd95BD0d56f35241523fBab1" 9 | 10 | ## Gas limit for deploying child chain factory needs to be provided to the TokenBridgeCreator when templates are set. 11 | ## If this param is not provided then gas limit will be estimated using SDK from child chain (specified by ORBIT_RPC and ROLLUP_ADDRESS) 12 | GAS_LIMIT_FOR_L2_FACTORY_DEPLOYMENT=6000000 13 | 14 | ## Contract verification 15 | ARBISCAN_API_KEY="" 16 | 17 | 18 | ### Vars for creating token bridge from existing TokenBridgeCreator 19 | ## Rollup on top of which token bridge will be created 20 | # ROLLUP_ADDRESS="" 21 | # ORBIT_RPC="" 22 | # ROLLUP_OWNER="" 23 | # L1_TOKEN_BRIDGE_CREATOR="" 24 | # # needed for verification 25 | # L1_RETRYABLE_SENDER="" -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | cache 2 | coverage 3 | build 4 | _deployments 5 | dist 6 | lib 7 | out -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | commonjs: true, 4 | es6: true, 5 | node: true, 6 | }, 7 | plugins: ['prettier'], 8 | extends: [ 9 | 'eslint:recommended', 10 | 'plugin:prettier/recommended', // Enables eslint-plugin-prettier and displays prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. 11 | ], 12 | parserOptions: { 13 | ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features 14 | sourceType: 'module', // Allows for the use of imports 15 | }, 16 | rules: { 17 | 'prettier/prettier': 'error', 18 | 'no-unused-vars': 'off', 19 | 'prefer-const': [2, { destructuring: 'all' }], 20 | 'object-curly-spacing': ['error', 'always'], 21 | }, 22 | overrides: [ 23 | { 24 | files: [ 25 | 'test/**/*.ts', 26 | 'test/**/*.tsx', 27 | 'scripts/**/*.ts', 28 | 'scripts/**/*.tsx', 29 | ], 30 | parser: '@typescript-eslint/parser', 31 | parserOptions: { 32 | project: 'tsconfig.json', 33 | }, 34 | extends: [ 35 | 'eslint:recommended', 36 | 'plugin:@typescript-eslint/recommended', 37 | 'plugin:prettier/recommended', 38 | ], 39 | plugins: ['@typescript-eslint', 'prettier', '@typescript-eslint/tslint'], 40 | rules: { 41 | 'no-empty-pattern': 'warn', 42 | 'prettier/prettier': ['error', { singleQuote: true }], 43 | '@typescript-eslint/member-delimiter-style': ['off'], 44 | '@typescript-eslint/no-explicit-any': ['off'], 45 | '@typescript-eslint/no-use-before-define': ['off'], 46 | '@typescript-eslint/no-non-null-assertion': ['off'], 47 | '@typescript-eslint/ban-ts-comment': ['warn'], 48 | '@typescript-eslint/no-unused-vars': [ 49 | 'warn', 50 | { 51 | argsIgnorePattern: '^_', 52 | varsIgnorePattern: '^_', 53 | caughtErrorsIgnorePattern: '^_', 54 | }, 55 | ], 56 | '@typescript-eslint/tslint/config': [ 57 | 'error', 58 | { 59 | rules: { 'strict-comparisons': true }, 60 | }, 61 | ], 62 | 'no-implicit-coercion': 'error', 63 | }, 64 | }, 65 | ], 66 | } 67 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: gomod 4 | directory: '/packages/arb-node-core' 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | target-branch: master 9 | - package-ecosystem: gomod 10 | directory: '/packages/arb-rpc-node' 11 | schedule: 12 | interval: daily 13 | open-pull-requests-limit: 10 14 | target-branch: master 15 | - package-ecosystem: gomod 16 | directory: '/packages/arb-avm-cpp' 17 | schedule: 18 | interval: daily 19 | open-pull-requests-limit: 10 20 | target-branch: master 21 | - package-ecosystem: gomod 22 | directory: '/packages/arb-evm' 23 | schedule: 24 | interval: daily 25 | open-pull-requests-limit: 10 26 | target-branch: master 27 | - package-ecosystem: gomod 28 | directory: '/packages/arb-util' 29 | schedule: 30 | interval: daily 31 | open-pull-requests-limit: 10 32 | target-branch: master 33 | - package-ecosystem: npm 34 | directory: '/' 35 | schedule: 36 | interval: daily 37 | open-pull-requests-limit: 10 38 | target-branch: master 39 | - package-ecosystem: gitsubmodule 40 | directory: '/packages/arb-avm-cpp/external' 41 | schedule: 42 | interval: daily 43 | open-pull-requests-limit: 10 44 | target-branch: master 45 | -------------------------------------------------------------------------------- /.github/workflows/slither.yml: -------------------------------------------------------------------------------- 1 | name: Slither Analysis 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | 7 | jobs: 8 | analyze: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v4 12 | 13 | - name: Run Slither 14 | uses: crytic/slither-action@v0.3.1 15 | id: slither 16 | with: 17 | sarif: results.sarif 18 | fail-on: medium 19 | 20 | - name: Upload SARIF file 21 | if: always() 22 | uses: github/codeql-action/upload-sarif@v3 23 | with: 24 | sarif_file: ${{ steps.slither.outputs.sarif }} 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | .env 3 | node_modules 4 | .vscode/ 5 | 6 | #Hardhat files 7 | cache 8 | build 9 | artifacts 10 | deployment.json 11 | 12 | #Foundry files 13 | out/ 14 | forge-cache/ 15 | 16 | #Storage layout test files 17 | test/storage/*-old.dot 18 | test/storage/*-old 19 | test/signatures/*-old 20 | 21 | # local deployment files 22 | network.json 23 | 24 | # Gambit (mutation test) files 25 | gambit_out/ 26 | test-mutation/mutant_test_env/ 27 | 28 | # bridged usdc deployment script 29 | registerUsdcGatewayTx.json -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/forge-std"] 2 | path = lib/forge-std 3 | url = https://github.com/foundry-rs/forge-std 4 | [submodule "lib/nitro-contracts"] 5 | path = lib/nitro-contracts 6 | url = https://github.com/OffchainLabs/nitro-contracts.git 7 | branch = develop 8 | 9 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | cache 2 | build 3 | coverage 4 | deployments 5 | dist 6 | lib 7 | out -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | semi: false, 3 | trailingComma: 'es5', 4 | singleQuote: true, 5 | printWidth: 80, 6 | tabWidth: 2, 7 | arrowParens: 'avoid', 8 | bracketSpacing: true, 9 | overrides: [ 10 | { 11 | files: '*.sol', 12 | options: { 13 | printWidth: 100, 14 | tabWidth: 4, 15 | useTabs: false, 16 | singleQuote: false, 17 | bracketSpacing: true, 18 | explicitTypes: 'always', 19 | }, 20 | }, 21 | ], 22 | } 23 | -------------------------------------------------------------------------------- /.solhint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "solhint:recommended", 3 | "plugins": ["prettier"], 4 | "rules": { 5 | "mark-callable-contracts": "none", 6 | "prettier/prettier": "error", 7 | "compiler-version": ["error", "^0.8.0"] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | # Arbitrum Token Bridge Contracts 4 | 5 | The Arbitrum Token Bridge is a decentralized application that uses [Nitro's](https://github.com/OffchainLabs/nitro) arbitrary cross-chain messaging system to implement an ERC20 token bridge between an EVM compatible base-chain and an Arbitrum chain. 6 | 7 | All public Arbitrum chains include a [canonical token bridge deployment](https://developer.arbitrum.io/useful-addresses#token-bridge). 8 | 9 | The Token Bridge includes "Gateway" contracts — pairs of contracts that implement a particular token-bridging flow — as well as "Gateway Router" contracts, which map tokens to their respective gateways. 10 | 11 | See the [developer documentation](https://developer.arbitrum.io/asset-bridging) for more info. 12 | 13 | See security audit reports [here](./audits). 14 | 15 | This repository is offered under the Apache 2.0 license. See LICENSE for details. 16 | 17 | ## Deployment 18 | Check [this doc](./docs/deployment.md) for instructions on deployment and verification of token bridge. 19 | 20 | ## Contact 21 | 22 | Discord - [Arbitrum](https://discord.com/invite/5KE54JwyTs) 23 | 24 | Twitter: [Arbitrum](https://twitter.com/arbitrum) 25 | -------------------------------------------------------------------------------- /_deployments/11155111_current_deployment.json: -------------------------------------------------------------------------------- 1 | { 2 | "proxyAdminAddress": "0xDBFC2FfB44A5D841aB42b0882711ed6e5A9244b0", 3 | "contracts": { 4 | "L1GatewayRouter": { 5 | "proxyAddress": "0xcE18836b233C83325Cc8848CA4487e94C6288264", 6 | "implAddress": "0xba4F913CEb90ff1a0A8ccf7bd06B807B92B2E34e", 7 | "implDeploymentTxn": "0xfc76c6049cc5cc45dee33ea39c53cecc078cec4805be75d24f11ca1e5bf4fea2", 8 | "implArbitrumCommitHash": "using-sdk-731092406", 9 | "implBuildInfo": "" 10 | }, 11 | "L1ERC20Gateway": { 12 | "proxyAddress": "0x902b3E5f8F19571859F4AB1003B960a5dF693aFF", 13 | "implAddress": "0x98431DDc27633f7315Aa2c153233529bb241445a", 14 | "implDeploymentTxn": "0x3992d29147de172635615554ec76354ffdef5f709c43e59df752898e3fbf504a", 15 | "implArbitrumCommitHash": "using-sdk-731092406", 16 | "implBuildInfo": "" 17 | }, 18 | "L1CustomGateway": { 19 | "proxyAddress": "0xba2F7B6eAe1F9d174199C5E4867b563E0eaC40F3", 20 | "implAddress": "0x065D10fb680CCEC460051281ed150Ff610ECaAfc", 21 | "implDeploymentTxn": "0x32bf8c2cac0ddd0bcc6e032c63abd29e0a6addda7d149ffc6ea927b30c1a329c", 22 | "implArbitrumCommitHash": "using-sdk-731092406", 23 | "implBuildInfo": "" 24 | }, 25 | "L1WethGateway": { 26 | "proxyAddress": "0xA8aD8d7e13cbf556eE75CB0324c13535d8100e1E", 27 | "implAddress": "0x8a3C6102D4435Cd156Ce95d5Dc0cf9df2BAab078", 28 | "implDeploymentTxn": "0xf8af2de122380ce1252f69cf8fe853ef44ef4bfc0ff9825427e1bf591d98d844", 29 | "implArbitrumCommitHash": "using-sdk-731092406", 30 | "implBuildInfo": "" 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /_deployments/11155111_queued-updates.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /_deployments/1337_current_deployment.json: -------------------------------------------------------------------------------- 1 | { 2 | "proxyAdminAddress": "0x9aD46fac0Cf7f790E5be05A0F15223935A0c0aDa", 3 | "contracts": { 4 | "L1GatewayRouter": { 5 | "proxyAddress": "0x72Ce9c846789fdB6fC1f34aC4AD25Dd9ef7031ef", 6 | 7 | "implAddress": "0x4b2cf3be8677096310b32a648b0bdb8c5a8ddc94", 8 | "implDeploymentTxn": "0x", 9 | "implArbitrumCommitHash": "0x" 10 | }, 11 | "L1ERC20Gateway": { 12 | "proxyAddress": "0xa3A7B6F88361F48403514059F1F16C8E78d60EeC", 13 | "implAddress": "0x41ac92014c66c38bbbdef8ccf5a060cca5634fd5", 14 | "implDeploymentTxn": "0x", 15 | "implArbitrumCommitHash": "0x" 16 | }, 17 | "L1CustomGateway": { 18 | "proxyAddress": "0xcEe284F754E854890e311e3280b767F80797180d", 19 | "implAddress": "0xc5199b28d5267f80a7fa7a3313357d50cf4dba6c", 20 | "implDeploymentTxn": "0x", 21 | "implArbitrumCommitHash": "0x" 22 | }, 23 | "L1WethGateway": { 24 | "proxyAddress": "0xd92023E9d9911199a6711321D1277285e6d4e2db", 25 | "implAddress": "0xb0e292c2cefd5c897883f16af6453dc111940d85", 26 | "implDeploymentTxn": "0x", 27 | "implArbitrumCommitHash": "0x" 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /_deployments/1337_queued-updates.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /_deployments/1_42170_current_deployment.json: -------------------------------------------------------------------------------- 1 | { 2 | "proxyAdminAddress": "0xa8f7DdEd54a726eB873E98bFF2C95ABF2d03e560", 3 | "contracts": { 4 | "L1GatewayRouter": { 5 | "proxyAddress": "0xC840838Bc438d73C16c2f8b22D2Ce3669963cD48", 6 | "implAddress": "0x6D1c576Fe3e54313990450f5Fa322306B4cCB47B", 7 | "implDeploymentTxn": "0x0badea7ff78ffcaee80d8b3686debf2f3172a65aa4df26de5aaccc58bc7a6031", 8 | "implArbitrumCommitHash": "265b5ef6a68f4e6c5d891d61b4c733634e49ac74", 9 | "implBuildInfo": "" 10 | }, 11 | "L1ERC20Gateway": { 12 | "proxyAddress": "0xB2535b988dcE19f9D71dfB22dB6da744aCac21bf", 13 | "implAddress": "0xb4299A1F5f26fF6a98B7BA35572290C359fde900", 14 | "implDeploymentTxn": "0x23b0939cffff711071c3270fd7c1e619fd6f464acfbb07ae452f4f091eb0af90", 15 | "implArbitrumCommitHash": "265b5ef6a68f4e6c5d891d61b4c733634e49ac74", 16 | "implBuildInfo": "" 17 | }, 18 | "L1CustomGateway": { 19 | "proxyAddress": "0x23122da8C581AA7E0d07A36Ff1f16F799650232f", 20 | "implAddress": "0xC8D26aB9e132C79140b3376a0Ac7932E4680Aa45", 21 | "implDeploymentTxn": "0xd6ae3ba8c58ef4fa22688950c4849085779b0db441d3d68d84cdca5618e0e565", 22 | "implArbitrumCommitHash": "265b5ef6a68f4e6c5d891d61b4c733634e49ac74", 23 | "implBuildInfo": "" 24 | }, 25 | "L1WethGateway": { 26 | "proxyAddress": "0xE4E2121b479017955Be0b175305B35f312330BaE", 27 | "implAddress": "0x4B8e9b3F253E68837bf719997B1eeB9E8f1960e2", 28 | "implDeploymentTxn": "0xab2fe7d6a85987ba63986267209e1a7b4b1347c6075230f23c8e6d18aaa1a6b3", 29 | "implArbitrumCommitHash": "dce646c6890ab9c7c91c7d2ec70b4d83fa359a76", 30 | "implBuildInfo": "" 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /_deployments/1_42170_queued-updates.json: -------------------------------------------------------------------------------- 1 | { 2 | "L1GatewayRouter": { 3 | "address": "0x52595021fA01B3E14EC6C88953AFc8E35dFf423c", 4 | "deployTxn": "0x2a6dd507b21d4257c8afd00f2590cb5765e29eb371d2b6b2f9a173328b9f2e53", 5 | "arbitrumCommitHash": "162e913442e766b3bcc17e3e62886477313325ac", 6 | "buildInfo": "" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /_deployments/1_current_deployment.json: -------------------------------------------------------------------------------- 1 | { 2 | "proxyAdminAddress": "0x9aD46fac0Cf7f790E5be05A0F15223935A0c0aDa", 3 | "contracts": { 4 | "L1GatewayRouter": { 5 | "proxyAddress": "0x72Ce9c846789fdB6fC1f34aC4AD25Dd9ef7031ef", 6 | "implAddress": "0x6D1c576Fe3e54313990450f5Fa322306B4cCB47B", 7 | "implDeploymentTxn": "0x0badea7ff78ffcaee80d8b3686debf2f3172a65aa4df26de5aaccc58bc7a6031", 8 | "implArbitrumCommitHash": "265b5ef6a68f4e6c5d891d61b4c733634e49ac74", 9 | "implBuildInfo": "" 10 | }, 11 | "L1ERC20Gateway": { 12 | "proxyAddress": "0xa3A7B6F88361F48403514059F1F16C8E78d60EeC", 13 | "implAddress": "0xb4299A1F5f26fF6a98B7BA35572290C359fde900", 14 | "implDeploymentTxn": "0x23b0939cffff711071c3270fd7c1e619fd6f464acfbb07ae452f4f091eb0af90", 15 | "implArbitrumCommitHash": "265b5ef6a68f4e6c5d891d61b4c733634e49ac74", 16 | "implBuildInfo": "" 17 | }, 18 | "L1CustomGateway": { 19 | "proxyAddress": "0xcEe284F754E854890e311e3280b767F80797180d", 20 | "implAddress": "0xC8D26aB9e132C79140b3376a0Ac7932E4680Aa45", 21 | "implDeploymentTxn": "0xd6ae3ba8c58ef4fa22688950c4849085779b0db441d3d68d84cdca5618e0e565", 22 | "implArbitrumCommitHash": "265b5ef6a68f4e6c5d891d61b4c733634e49ac74", 23 | "implBuildInfo": "" 24 | }, 25 | "L1WethGateway": { 26 | "proxyAddress": "0xd92023E9d9911199a6711321D1277285e6d4e2db", 27 | "implAddress": "0x4B8e9b3F253E68837bf719997B1eeB9E8f1960e2", 28 | "implDeploymentTxn": "0xab2fe7d6a85987ba63986267209e1a7b4b1347c6075230f23c8e6d18aaa1a6b3", 29 | "implArbitrumCommitHash": "dce646c6890ab9c7c91c7d2ec70b4d83fa359a76", 30 | "implBuildInfo": "" 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /_deployments/1_queued-updates.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /_deployments/421611_current_deployment.json: -------------------------------------------------------------------------------- 1 | { 2 | "proxyAdminAddress": "0x58816566EB91815Cc07f3Ad5230eE0820fe1A19a", 3 | "contracts": { 4 | "L2GatewayRouter": { 5 | "proxyAddress": "0x9413AD42910c1eA60c737dB5f58d1C504498a3cD", 6 | "implAddress": "0x9BB136adEa1E3dd0B132CAd18d69Ee444aC17bFd", 7 | "implDeploymentTxn": "0xa660838e693561d61189e9ca831d118171509fefdac3ae257c0e422dcc61bcfc", 8 | "implArbitrumCommitHash": "25bf76e8cdd9b00bc181269abcc9b04579a42aca", 9 | "implBuildInfo": "" 10 | }, 11 | "L2ERC20Gateway": { 12 | "proxyAddress": "0x195C107F3F75c4C93Eba7d9a1312F19305d6375f", 13 | "implAddress": "0x5574f6Cd9de0F9D224cE85e1cD6C4Be11132A385", 14 | "implDeploymentTxn": "0xd1e86b6a6162b50fc16f4ae47fd4cbc8d4dce4421a5e9f0ac18c3af49aa0c7da", 15 | "implArbitrumCommitHash": "25bf76e8cdd9b00bc181269abcc9b04579a42aca", 16 | "implBuildInfo": "" 17 | }, 18 | "L2CustomGateway": { 19 | "proxyAddress": "0x9b014455AcC2Fe90c52803849d0002aeEC184a06", 20 | "implAddress": "0x02F95dFAc9B67EdCD9158c04fe30d114A013d08D", 21 | "implDeploymentTxn": "0x4603823d126f5f78f228d2d3431a01d93a082b75e2e3ff2fb7d754c7b5789506", 22 | "implArbitrumCommitHash": "25bf76e8cdd9b00bc181269abcc9b04579a42aca", 23 | "implBuildInfo": "" 24 | }, 25 | "L2WethGateway": { 26 | "proxyAddress": "0xf94bc045c4E926CC0b34e8D1c41Cd7a043304ac9", 27 | "implAddress": "0x675a824f4B940c747caC35DA0CC3f7E441419942", 28 | "implDeploymentTxn": "0x74f56f704a64a0b87306eb9a6480420ea137d043bf4d12c8e9fb490864bb0584", 29 | "implArbitrumCommitHash": "25bf76e8cdd9b00bc181269abcc9b04579a42aca", 30 | "implBuildInfo": "" 31 | }, 32 | "StandardArbERC20": { 33 | "proxyAddress": "0x86B4b312140B4117A7b0D252eC53Fa6D0753fE85", 34 | "implAddress": "0xa5a052BC1dc55118754bca1bB700675Edf1031D0", 35 | "implDeploymentTxn": "", 36 | "implBuildInfo": "" 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /_deployments/421611_queued-updates.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /_deployments/421613_current_deployment.json: -------------------------------------------------------------------------------- 1 | { 2 | "proxyAdminAddress": "0xeC377B42712608B0356CC54Da81B2be1A4982bAb", 3 | "contracts": { 4 | "L2GatewayRouter": { 5 | "proxyAddress": "0xE5B9d8d42d656d1DcB8065A6c012FE3780246041", 6 | "implAddress": "0xa707480046b0Bd1C602CCd1D83FCf7Bd367217E2", 7 | "implDeploymentTxn": "0x3c2adecca82c874282a694a23faec77ae02cd3a19a17527855554fd77d93e4a9", 8 | "implArbitrumCommitHash": "25bf76e8cdd9b00bc181269abcc9b04579a42aca", 9 | "implBuildInfo": "" 10 | }, 11 | "L2ERC20Gateway": { 12 | "proxyAddress": "0x2eC7Bc552CE8E51f098325D2FcF0d3b9d3d2A9a2", 13 | "implAddress": "0xCbD2dC47b287C8324747A5AA2A71A8f939662B3e", 14 | "implDeploymentTxn": "0x07c3734dd047f99ce9955d694517f2fa0b73def14bd46215847a747accb49702", 15 | "implArbitrumCommitHash": "25bf76e8cdd9b00bc181269abcc9b04579a42aca", 16 | "implBuildInfo": "" 17 | }, 18 | "L2CustomGateway": { 19 | "proxyAddress": "0x8b6990830cF135318f75182487A4D7698549C717", 20 | "implAddress": "0x43f7637f712Dca8544539Aa399FDC9697c7965e9", 21 | "implDeploymentTxn": "0x306a01a6164915f923b8ea6f5c1f512783f5c2e67e4d6b613029a26bc3623eca", 22 | "implArbitrumCommitHash": "6f61e3aaf3668ad564139f49063028b1b19010bd", 23 | "implBuildInfo": "" 24 | }, 25 | "L2WethGateway": { 26 | "proxyAddress": "0xf9F2e89c8347BD96742Cc07095dee490e64301d6", 27 | "implAddress": "0x3BD10e97ECa83B362dA291beFdA0f1ba70D31411", 28 | "implDeploymentTxn": "0xe35957e6aef4d5919b8d7d93ff1b575dd5c50aa3b3dc944be07ac913d46a2846", 29 | "implArbitrumCommitHash": "25bf76e8cdd9b00bc181269abcc9b04579a42aca", 30 | "implBuildInfo": "" 31 | }, 32 | "StandardArbERC20": { 33 | "proxyAddress": "0xC0EaEeeb3Bb716ef3e49c2db0331e5bCaAb88865", 34 | "implAddress": "0x2063a7def7614347896c880C0F04788De18A8dEb", 35 | "implDeploymentTxn": "0x7ccdf95b0c6e46d12bfaac47f14343e3c227ad70f03625108e7c300339c63d5e", 36 | "implArbitrumCommitHash": "51dfc9fbe45a0d66c4fcad6ac645386eb50e528a", 37 | "implBuildInfo": "" 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /_deployments/421613_queued-updates.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /_deployments/421614_current_deployment.json: -------------------------------------------------------------------------------- 1 | { 2 | "proxyAdminAddress": "0x715D99480b77A8d9D603638e593a539E21345FdF", 3 | "contracts": { 4 | "L2GatewayRouter": { 5 | "proxyAddress": "0x9fDD1C4E4AA24EEc1d913FABea925594a20d43C7", 6 | "implAddress": "0x6f1ef246894b6269e2a98c741c36385f61ee1e32", 7 | "implDeploymentTxn": "0x8ca7e1fbfdae7f5069cc61454efee4bb6b70b8e5a3a831ed49deb7fbbcdf5dc7", 8 | "implArbitrumCommitHash": "using-sdk-731092406", 9 | "implBuildInfo": "" 10 | }, 11 | "L2ERC20Gateway": { 12 | "proxyAddress": "0x6e244cD02BBB8a6dbd7F626f05B2ef82151Ab502", 13 | "implAddress": "0x391c9b3cb3cae0a653295f42267dab8b0505e760", 14 | "implDeploymentTxn": "0xb90ab1d2f5ddba546747d298c5e2e99635c9ab94cc157baf7e7fa54c8f194e23", 15 | "implArbitrumCommitHash": "using-sdk-731092406", 16 | "implBuildInfo": "" 17 | }, 18 | "L2CustomGateway": { 19 | "proxyAddress": "0x8Ca1e1AC0f260BC4dA7Dd60aCA6CA66208E642C5", 20 | "implAddress": "0xa0a8537a683b49ba4bbe23883d984d4684e0acdd", 21 | "implDeploymentTxn": "0xd47badc672d5173a7c66bb2e2c92fcc4c8c98a27dc30e762f10cd0a73e460eee", 22 | "implArbitrumCommitHash": "using-sdk-731092406", 23 | "implBuildInfo": "" 24 | }, 25 | "L2WethGateway": { 26 | "proxyAddress": "0xCFB1f08A4852699a979909e22c30263ca249556D", 27 | "implAddress": "0x572c749de059f5cb5659ba5c1b4576b237871af4", 28 | "implDeploymentTxn": "0x59fc99d7a7df30b432948933ba0bf5108b47df2c99d52a1fda4fd9acf46549ad", 29 | "implArbitrumCommitHash": "using-sdk-731092406", 30 | "implBuildInfo": "" 31 | }, 32 | "StandardArbERC20": { 33 | "proxyAddress": "0x07ad36d1911da7116f97cbe7c94bc567834c2a09", 34 | "implAddress": "0xdbb3566cd49e221023cff6e710c2e5e50cb8f832", 35 | "implDeploymentTxn": "0xcda2277668a347c1a063af4fcffe18ed3c99337a86f390c18009fd29d1bbf59c", 36 | "implArbitrumCommitHash": "using-sdk-731092406", 37 | "implBuildInfo": "" 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /_deployments/421614_queued-updates.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /_deployments/42161_current_deployment.json: -------------------------------------------------------------------------------- 1 | { 2 | "proxyAdminAddress": "0xd570aCE65C43af47101fC6250FD6fC63D1c22a86", 3 | "contracts": { 4 | "L2GatewayRouter": { 5 | "proxyAddress": "0x5288c571Fd7aD117beA99bF60FE0846C4E84F933", 6 | "implAddress": "0xe80eb0238029333e368e0bDDB7acDf1b9cb28278", 7 | "implDeploymentTxn": "0x42f97c8e518193c04c8aba7b71b08e1c05257070c71b8f5796c4c6fe885a4009", 8 | "implArbitrumCommitHash": "265b5ef6a68f4e6c5d891d61b4c733634e49ac74", 9 | "implBuildInfo": "" 10 | }, 11 | "L2ERC20Gateway": { 12 | "proxyAddress": "0x09e9222E96E7B4AE2a407B98d48e330053351EEe", 13 | "implAddress": "0x1DCf7D03574fbC7C205F41f2e116eE094a652e93", 14 | "implDeploymentTxn": "0x386a8c3b2f12d91644faef8483d13c36e283bb23cb2e05ee946474d7383834d9", 15 | "implArbitrumCommitHash": "265b5ef6a68f4e6c5d891d61b4c733634e49ac74", 16 | "implBuildInfo": "" 17 | }, 18 | "L2CustomGateway": { 19 | "proxyAddress": "0x096760F208390250649E3e8763348E783AEF5562", 20 | "implAddress": "0x190274fEa8f30e3f48CE43aDCBd9a74110118284", 21 | "implDeploymentTxn": "0x55fc2f66a593e317c7cebcc90d43ef465f64158ce0866af30ff5d471155e75d2", 22 | "implArbitrumCommitHash": "6f61e3aaf3668ad564139f49063028b1b19010bd", 23 | "implBuildInfo": "" 24 | }, 25 | "L2WethGateway": { 26 | "proxyAddress": "0x6c411aD3E74De3E7Bd422b94A27770f5B86C623B", 27 | "implAddress": "0x806421D09cDb253aa9d128a658e60c0B95eFFA01", 28 | "implDeploymentTxn": "0xb52586177829d7cb06ca5204994eb63e3ee8245ef8a331e5dc466cba9aa9e35d", 29 | "implArbitrumCommitHash": "dce646c6890ab9c7c91c7d2ec70b4d83fa359a76", 30 | "implBuildInfo": "" 31 | }, 32 | "StandardArbERC20": { 33 | "proxyAddress": "0xE72ba9418b5f2Ce0A6a40501Fe77c6839Aa37333", 34 | "implAddress": "0x3f770Ac673856F105b586bb393d122721265aD46", 35 | "implDeploymentTxn": "0xc7006f7e9f716a73ecee7e2939adacf84a122345dca581ed1f78c06be5cd8a5a", 36 | "implArbitrumCommitHash": "7ac9347a41ece951af883d435cbe7d8e84329e36", 37 | "implBuildInfo": "" 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /_deployments/42161_queued-updates.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /_deployments/42170_current_deployment.json: -------------------------------------------------------------------------------- 1 | { 2 | "proxyAdminAddress": "0xada790b026097BfB36a5ed696859b97a96CEd92C", 3 | "contracts": { 4 | "L2GatewayRouter": { 5 | "proxyAddress": "0x21903d3F8176b1a0c17E953Cd896610Be9fFDFa8", 6 | "implAddress": "0x8f377770289863DF73Fe665B74460579F82321fb", 7 | "implDeploymentTxn": "0x8c917e27e5aeff1f9f2ae781efc24c4ee3502550f4fd6d451af09756a9fbeb41", 8 | "implArbitrumCommitHash": "265b5ef6a68f4e6c5d891d61b4c733634e49ac74", 9 | "implBuildInfo": "" 10 | }, 11 | "L2ERC20Gateway": { 12 | "proxyAddress": "0xcF9bAb7e53DDe48A6DC4f286CB14e05298799257", 13 | "implAddress": "0x466155FD6d8BbF1c0d5ca32818814cB28b6884d8", 14 | "implDeploymentTxn": "0x3d949fdeb42a3ebb04b705358ab5f8559cffbc27d7fbaf3a63649d12e327d592", 15 | "implArbitrumCommitHash": "265b5ef6a68f4e6c5d891d61b4c733634e49ac74", 16 | "implBuildInfo": "" 17 | }, 18 | "L2CustomGateway": { 19 | "proxyAddress": "0xbf544970E6BD77b21C6492C281AB60d0770451F4", 20 | "implAddress": "0x554e12DBAa0fBeB8A35583a6Fd9D04BaA4ff597f", 21 | "implDeploymentTxn": "0x62e1143aea4034c75503f6f46722df4871962dc08c69f709c97885b3a7f44008", 22 | "implArbitrumCommitHash": "6f61e3aaf3668ad564139f49063028b1b19010bd", 23 | "implBuildInfo": "" 24 | }, 25 | "L2WethGateway": { 26 | "proxyAddress": "0x7626841cB6113412F9c88D3ADC720C9FAC88D9eD", 27 | "implAddress": "0xbe04Ab2728c924D678f9FC833E379688c6eFA317", 28 | "implDeploymentTxn": "0x99333784813d8bcfc7ccc34b7cf258deccec9d160afce25c89a9faf0a1a19a92", 29 | "implArbitrumCommitHash": "dce646c6890ab9c7c91c7d2ec70b4d83fa359a76", 30 | "implBuildInfo": "" 31 | }, 32 | "StandardArbERC20": { 33 | "proxyAddress": "0xd31Ed16a8CeCe0A5070AC26024674eB680E3e639", 34 | "implAddress": "0x53923A0d1f4805463584c91b2E55d6c600A94E91", 35 | "implDeploymentTxn": "0x96513ab528683b13d918024d0c410ecaa88b7949cc4a980544af8362f22cc277", 36 | "implArbitrumCommitHash": "51dfc9fbe45a0d66c4fcad6ac645386eb50e528a", 37 | "implBuildInfo": "" 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /_deployments/42170_queued-updates.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /_deployments/4_current_deployment.json: -------------------------------------------------------------------------------- 1 | { 2 | "proxyAdminAddress": "0x0DbAF24efA2bc9Dd1a6c0530DD252BCcF883B89A", 3 | "contracts": { 4 | "L1GatewayRouter": { 5 | "proxyAddress": "0x70C143928eCfFaf9F5b406f7f4fC28Dc43d68380", 6 | "implAddress": "0x8b6990830cF135318f75182487A4D7698549C717", 7 | "implDeploymentTxn": "0xee36d85905a0ef010d85f2d023f30dd8cb91eccba755256ede147d6b3f29e8f9", 8 | "implArbitrumCommitHash": "25bf76e8cdd9b00bc181269abcc9b04579a42aca", 9 | "implBuildInfo": "" 10 | }, 11 | "L1ERC20Gateway": { 12 | "proxyAddress": "0x91169Dbb45e6804743F94609De50D511C437572E", 13 | "implAddress": "0x185ff5e33c4df31C715B386916A49fc2f80fFe4c", 14 | "implDeploymentTxn": "0x041673dd25b9dbc4a831b0ee4d795563ecd67e21c3b3fe58d07d17698b44df4b", 15 | "implArbitrumCommitHash": "25bf76e8cdd9b00bc181269abcc9b04579a42aca", 16 | "implBuildInfo": "" 17 | }, 18 | "L1CustomGateway": { 19 | "proxyAddress": "0x917dc9a69F65dC3082D518192cd3725E1Fa96cA2", 20 | "implAddress": "0xf9F2e89c8347BD96742Cc07095dee490e64301d6", 21 | "implDeploymentTxn": "0xae2522d1fe13f69007fc63869fb8640f69e2ad59df599e284bb39e0ee2f5627e", 22 | "implArbitrumCommitHash": "25bf76e8cdd9b00bc181269abcc9b04579a42aca", 23 | "implBuildInfo": "" 24 | }, 25 | "L1WethGateway": { 26 | "proxyAddress": "0x81d1a19cf7071732D4313c75dE8DD5b8CF697eFD", 27 | "implAddress": "0x2063a7def7614347896c880C0F04788De18A8dEb", 28 | "implDeploymentTxn": "0x45078b798a2f6b9cdcd8a98fc1a8c145b278ee9da56ea5d9f12ea9117b94a153", 29 | "implArbitrumCommitHash": "25bf76e8cdd9b00bc181269abcc9b04579a42aca", 30 | "implBuildInfo": "" 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /_deployments/4_queued-updates.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /_deployments/5_current_deployment.json: -------------------------------------------------------------------------------- 1 | { 2 | "proxyAdminAddress": "0x16101A84B00344221E2983190718bFAba30D9CeE", 3 | "contracts": { 4 | "L1GatewayRouter": { 5 | "proxyAddress": "0x4c7708168395aEa569453Fc36862D2ffcDaC588c", 6 | "implAddress": "0x5664F1f04bb9f5eF1970D6e12Be073F73AacA854", 7 | "implDeploymentTxn": "0xde3262b207e171ee9ef342aed0d631adc8e23e5783079d7a8a2803fe0ad8b01f", 8 | "implArbitrumCommitHash": "25bf76e8cdd9b00bc181269abcc9b04579a42aca", 9 | "implBuildInfo": "" 10 | }, 11 | "L1ERC20Gateway": { 12 | "proxyAddress": "0x715D99480b77A8d9D603638e593a539E21345FdF", 13 | "implAddress": "0xea066056f73156E80090C24ADAC5d47CEc313a2d", 14 | "implDeploymentTxn": "0x02c5ed6eec83e3cc015373f85cb2ca89826d66bf3f5b7caf91d79c4ae561a38f", 15 | "implArbitrumCommitHash": "25bf76e8cdd9b00bc181269abcc9b04579a42aca", 16 | "implBuildInfo": "" 17 | }, 18 | "L1CustomGateway": { 19 | "proxyAddress": "0x9fDD1C4E4AA24EEc1d913FABea925594a20d43C7", 20 | "implAddress": "0x161183c42E54F709Bd7b8c12670957f2Ee150299", 21 | "implDeploymentTxn": "0xb071c5c0153295e0c7e177a3d9d9f770206a305680e3461e16b9c92202f8f219", 22 | "implArbitrumCommitHash": "25bf76e8cdd9b00bc181269abcc9b04579a42aca", 23 | "implBuildInfo": "" 24 | }, 25 | "L1WethGateway": { 26 | "proxyAddress": "0x6e244cD02BBB8a6dbd7F626f05B2ef82151Ab502", 27 | "implAddress": "0xAA82b5384ef36c5EFdCe36300dc1E85CA45ad1D8", 28 | "implDeploymentTxn": "0x2c349a6110c697aebb2fb0a74c71ec78f04b94ec608443052b61e802420de4b9", 29 | "implArbitrumCommitHash": "25bf76e8cdd9b00bc181269abcc9b04579a42aca", 30 | "implBuildInfo": "" 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /_deployments/5_queued-updates.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /audits/ConsenSys_Diligence_Arbitrum_Contracts_11_2021.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OffchainLabs/token-bridge-contracts/5bdf33259d2d9ae52ddc69bc5a9cbc558c4c40c7/audits/ConsenSys_Diligence_Arbitrum_Contracts_11_2021.pdf -------------------------------------------------------------------------------- /audits/trail_of_bits_governance_report_1_6_2023.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OffchainLabs/token-bridge-contracts/5bdf33259d2d9ae52ddc69bc5a9cbc558c4c40c7/audits/trail_of_bits_governance_report_1_6_2023.pdf -------------------------------------------------------------------------------- /contracts/rpc-utils/NodeInterface.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // solhint-disable-next-line compiler-version 3 | pragma solidity >=0.4.21 <0.9.0; 4 | 5 | /** @title Interface for providing Outbox proof data 6 | * @notice This contract doesn't exist on-chain. Instead it is a virtual interface accessible at 0x00000000000000000000000000000000000000C8 7 | * This is a cute trick to allow an Arbitrum node to provide data without us having to implement an additional RPC ) 8 | */ 9 | 10 | interface NodeInterface { 11 | /** 12 | * @notice Returns the proof necessary to redeem a message 13 | * @param batchNum index of outbox entry (i.e., outgoing messages Merkle root) in array of outbox entries 14 | * @param index index of outgoing message in outbox entry 15 | * @return proof Merkle proof of message inclusion in outbox entry 16 | * @return path Merkle path to message 17 | * @return l2Sender sender if original message (i.e., caller of ArbSys.sendTxToL1) 18 | * @return l1Dest destination address for L1 contract call 19 | * @return l2Block l2 block number at which sendTxToL1 call was made 20 | * @return l1Block l1 block number at which sendTxToL1 call was made 21 | * @return timestamp l2 Timestamp at which sendTxToL1 call was made 22 | * @return amount value in L1 message in wei 23 | * @return calldataForL1 abi-encoded L1 message data 24 | */ 25 | function lookupMessageBatchProof(uint256 batchNum, uint64 index) 26 | external 27 | view 28 | returns ( 29 | bytes32[] memory proof, 30 | uint256 path, 31 | address l2Sender, 32 | address l1Dest, 33 | uint256 l2Block, 34 | uint256 l1Block, 35 | uint256 timestamp, 36 | uint256 amount, 37 | bytes memory calldataForL1 38 | ); 39 | 40 | /** 41 | * @notice Estimate the cost of putting a message in the L2 inbox that is reexecuted 42 | * @param sender sender of the L1 and L2 transaction 43 | * @param deposit amount to deposit to sender in L2 44 | * @param destAddr destination L2 contract address 45 | * @param l2CallValue call value for retryable L2 message 46 | * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee 47 | * @param excessFeeRefundAddress maxgas x gasprice - execution cost gets credited here on L2 balance 48 | * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled 49 | * @param maxGas Max gas deducted from user's L2 balance to cover L2 execution 50 | * @param gasPriceBid price bid for L2 execution 51 | * @param data ABI encoded data of L2 message 52 | * @return gas used, and gas price to execute this transaction 53 | */ 54 | function estimateRetryableTicket( 55 | address sender, 56 | uint256 deposit, 57 | address destAddr, 58 | uint256 l2CallValue, 59 | uint256 maxSubmissionCost, 60 | address excessFeeRefundAddress, 61 | address callValueRefundAddress, 62 | uint256 maxGas, 63 | uint256 gasPriceBid, 64 | bytes calldata data 65 | ) external pure returns (uint256, uint256); 66 | } 67 | -------------------------------------------------------------------------------- /contracts/rpc-utils/RetryableTicketCreator.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // solhint-disable-next-line compiler-version 3 | pragma solidity >=0.4.21 <0.9.0; 4 | 5 | interface RetryableTicketCreator { 6 | /** 7 | @notice Put an message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts 8 | * @dev all msg.value will deposited to callValueRefundAddress on L2 9 | * @param destAddr destination L2 contract address 10 | * @param l2CallValue call value for retryable L2 message 11 | * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee 12 | * @param excessFeeRefundAddress maxgas x gasprice - execution cost gets credited here on L2 balance 13 | * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled 14 | * @param maxGas Max gas deducted from user's L2 balance to cover L2 execution 15 | * @param gasPriceBid price bid for L2 execution 16 | * @param data ABI encoded data of L2 message 17 | */ 18 | function createRetryableTicket( 19 | address destAddr, 20 | uint256 l2CallValue, 21 | uint256 maxSubmissionCost, 22 | address excessFeeRefundAddress, 23 | address callValueRefundAddress, 24 | uint256 maxGas, 25 | uint256 gasPriceBid, 26 | bytes calldata data 27 | ) external payable; 28 | } 29 | -------------------------------------------------------------------------------- /contracts/tokenbridge/arbitrum/IArbToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | /** 20 | * @title Minimum expected interface for L2 token that interacts with the L2 token bridge (this is the interface necessary 21 | * for a custom token that interacts with the bridge, see TestArbCustomToken.sol for an example implementation). 22 | * @dev For the token to be compatible out of the box with the tooling available (e.g., the Arbitrum bridge), it is 23 | * recommended to keep the implementation of this interface as close as possible to the `TestArbCustomToken` example. 24 | */ 25 | 26 | // solhint-disable-next-line compiler-version 27 | pragma solidity >=0.6.9 <0.9.0; 28 | 29 | interface IArbToken { 30 | /** 31 | * @notice should increase token supply by amount, and should (probably) only be callable by the L1 bridge. 32 | */ 33 | function bridgeMint(address account, uint256 amount) external; 34 | 35 | /** 36 | * @notice should decrease token supply by amount, and should (probably) only be callable by the L1 bridge. 37 | */ 38 | function bridgeBurn(address account, uint256 amount) external; 39 | 40 | /** 41 | * @return address of layer 1 token 42 | */ 43 | function l1Address() external view returns (address); 44 | } 45 | -------------------------------------------------------------------------------- /contracts/tokenbridge/arbitrum/L2ArbitrumMessenger.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | import "@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; 22 | 23 | /// @notice L2 utility contract to assist with L1 <=> L2 interactions 24 | /// @dev this is an abstract contract instead of library so the functions can be easily overriden when testing 25 | abstract contract L2ArbitrumMessenger { 26 | address internal constant ARB_SYS_ADDRESS = address(100); 27 | 28 | event TxToL1(address indexed _from, address indexed _to, uint256 indexed _id, bytes _data); 29 | 30 | function sendTxToL1( 31 | uint256 _l1CallValue, 32 | address _from, 33 | address _to, 34 | bytes memory _data 35 | ) internal returns (uint256) { 36 | uint256 _id = ArbSys(ARB_SYS_ADDRESS).sendTxToL1{ value: _l1CallValue }(_to, _data); 37 | emit TxToL1(_from, _to, _id, _data); 38 | return _id; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /contracts/tokenbridge/arbitrum/ReverseArbToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | // solhint-disable-next-line compiler-version 20 | pragma solidity >=0.6.9 <0.9.0; 21 | 22 | import "./IArbToken.sol"; 23 | 24 | /// @title Minimum expected interface for L2 token that interacts with the reverse L2 token bridge (this is the interface necessary 25 | /// for a custom token that interacts with the reverse gateway, see TestArbCustomToken.sol for an example implementation). 26 | /// @dev The L2ArbitrumGateway expects objects of type IArbToken, which includes 27 | /// bridgeMint/burn. However when the L2ReverseCustomGateway overrides the functions 28 | /// that make use of bridgeMint/burn and replaces them with safeTransfer/from. 29 | /// We inherit IArbToken so that we fulfil the interface L2ArbitrumGateway expects 30 | /// but since we know that bridgeMint/burn won't/shouldn't be used we override these 31 | /// functions to ensure that if they throw if called during development 32 | abstract contract ReverseArbToken is IArbToken { 33 | function bridgeMint(address, uint256) public override { 34 | revert("BRIDGE_MINT_NOT_IMPLEMENTED"); 35 | } 36 | 37 | function bridgeBurn(address, uint256) public override { 38 | revert("BRIDGE_BURN_NOT_IMPLEMENTED"); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /contracts/tokenbridge/arbitrum/gateway/L2CustomGateway.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | import "./L2ArbitrumGateway.sol"; 22 | import "../../libraries/gateway/ICustomGateway.sol"; 23 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 24 | 25 | contract L2CustomGateway is L2ArbitrumGateway, ICustomGateway { 26 | // stores addresses of L2 tokens to be used 27 | mapping(address => address) public override l1ToL2Token; 28 | 29 | function initialize(address _l1Counterpart, address _router) public { 30 | L2ArbitrumGateway._initialize(_l1Counterpart, _router); 31 | } 32 | 33 | /** 34 | * @notice internal utility function used to handle when no contract is deployed at expected address 35 | */ 36 | function handleNoContract( 37 | address _l1Token, 38 | address, /* expectedL2Address */ 39 | address _from, 40 | address, /* _to */ 41 | uint256 _amount, 42 | bytes memory /* gatewayData */ 43 | ) internal override returns (bool shouldHalt) { 44 | // it is assumed that the custom token is deployed in the L2 before deposits are made 45 | // trigger withdrawal 46 | // we don't need the return value from triggerWithdrawal since this is forcing a withdrawal back to the L1 47 | // instead of composing with a L2 dapp 48 | triggerWithdrawal(_l1Token, address(this), _from, _amount, ""); 49 | return true; 50 | } 51 | 52 | /** 53 | * @notice Calculate the address used when bridging an ERC20 token 54 | * @dev the L1 and L2 address oracles may not always be in sync. 55 | * For example, a custom token may have been registered but not deploy or the contract self destructed. 56 | * @param l1ERC20 address of L1 token 57 | * @return L2 address of a bridged ERC20 token 58 | */ 59 | function calculateL2TokenAddress(address l1ERC20) public view override returns (address) { 60 | return l1ToL2Token[l1ERC20]; 61 | } 62 | 63 | function registerTokenFromL1(address[] calldata l1Address, address[] calldata l2Address) 64 | external 65 | onlyCounterpartGateway 66 | { 67 | // we assume both arrays are the same length, safe since its encoded by the L1 68 | for (uint256 i = 0; i < l1Address.length; i++) { 69 | // here we don't check if l2Address is a contract and instead deal with that behaviour 70 | // in `handleNoContract` this way we keep the l1 and l2 address oracles in sync 71 | l1ToL2Token[l1Address[i]] = l2Address[i]; 72 | emit TokenSet(l1Address[i], l2Address[i]); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /contracts/tokenbridge/arbitrum/gateway/L2ERC20Gateway.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; 22 | import "@openzeppelin/contracts/utils/Create2.sol"; 23 | import "./L2ArbitrumGateway.sol"; 24 | import "../StandardArbERC20.sol"; 25 | import "../../libraries/ClonableBeaconProxy.sol"; 26 | 27 | contract L2ERC20Gateway is L2ArbitrumGateway { 28 | address public beaconProxyFactory; 29 | 30 | function initialize( 31 | address _l1Counterpart, 32 | address _router, 33 | address _beaconProxyFactory 34 | ) public { 35 | L2ArbitrumGateway._initialize(_l1Counterpart, _router); 36 | require(_beaconProxyFactory != address(0), "INVALID_BEACON"); 37 | beaconProxyFactory = _beaconProxyFactory; 38 | } 39 | 40 | /** 41 | * @notice Calculate the address used when bridging an ERC20 token 42 | * @dev the L1 and L2 address oracles may not always be in sync. 43 | * For example, a custom token may have been registered but not deploy or the contract self destructed. 44 | * @param l1ERC20 address of L1 token 45 | * @return L2 address of a bridged ERC20 token 46 | */ 47 | function calculateL2TokenAddress(address l1ERC20) 48 | public 49 | view 50 | virtual 51 | override 52 | returns (address) 53 | { 54 | // this method is marked virtual to be overriden in subclasses used in testing 55 | return 56 | BeaconProxyFactory(beaconProxyFactory).calculateExpectedAddress( 57 | address(this), 58 | getUserSalt(l1ERC20) 59 | ); 60 | } 61 | 62 | function cloneableProxyHash() public view returns (bytes32) { 63 | return BeaconProxyFactory(beaconProxyFactory).cloneableProxyHash(); 64 | } 65 | 66 | function getUserSalt(address l1ERC20) public pure returns (bytes32) { 67 | return keccak256(abi.encode(l1ERC20)); 68 | } 69 | 70 | /** 71 | * @notice internal utility function used to deploy ERC20 tokens with the beacon proxy pattern. 72 | * @dev the transparent proxy implementation by OpenZeppelin can't be used if we want to be able to 73 | * upgrade the token logic. 74 | * @param l1ERC20 L1 address of ERC20 75 | * @param expectedL2Address L2 address of ERC20 76 | * @param deployData encoded symbol/name/decimal data for initial deploy 77 | */ 78 | function handleNoContract( 79 | address l1ERC20, 80 | address expectedL2Address, 81 | address _from, 82 | address, /* _to */ 83 | uint256 _amount, 84 | bytes memory deployData 85 | ) internal override returns (bool shouldHalt) { 86 | bytes32 userSalt = getUserSalt(l1ERC20); 87 | address createdContract = BeaconProxyFactory(beaconProxyFactory).createProxy(userSalt); 88 | 89 | StandardArbERC20(createdContract).bridgeInit(l1ERC20, deployData); 90 | 91 | if (createdContract == expectedL2Address) { 92 | return false; 93 | } else { 94 | // trigger withdrawal then halt 95 | // this codepath should only be hit if the system is setup incorrectly 96 | // this withdrawal is for error recovery, not composing with L2 dapps, so we ignore the return value 97 | triggerWithdrawal(l1ERC20, address(this), _from, _amount, ""); 98 | return true; 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /contracts/tokenbridge/arbitrum/gateway/L2GatewayRouter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | import "../../libraries/gateway/GatewayRouter.sol"; 22 | import "../../ethereum/gateway/L1GatewayRouter.sol"; 23 | import "../L2ArbitrumMessenger.sol"; 24 | import "../../libraries/AddressAliasHelper.sol"; 25 | 26 | /** 27 | * @title Handles withdrawals from Ethereum into Arbitrum. Tokens are routered to their appropriate L2 gateway (Router itself also conforms to the Gateway interface). 28 | * @notice Router also serves as an L2-L1 token address oracle. 29 | */ 30 | contract L2GatewayRouter is GatewayRouter, L2ArbitrumMessenger { 31 | modifier onlyCounterpartGateway() override { 32 | require( 33 | msg.sender == AddressAliasHelper.applyL1ToL2Alias(counterpartGateway), 34 | "ONLY_COUNTERPART_GATEWAY" 35 | ); 36 | _; 37 | } 38 | 39 | function initialize(address _counterpartGateway, address _defaultGateway) public { 40 | GatewayRouter._initialize(_counterpartGateway, address(0), _defaultGateway); 41 | } 42 | 43 | function setGateway(address[] memory _l1Token, address[] memory _gateway) 44 | external 45 | onlyCounterpartGateway 46 | { 47 | // counterpart gateway (L1 router) should never allow wrong lengths 48 | assert(_l1Token.length == _gateway.length); 49 | 50 | for (uint256 i = 0; i < _l1Token.length; i++) { 51 | l1TokenToGateway[_l1Token[i]] = _gateway[i]; 52 | emit GatewaySet(_l1Token[i], _gateway[i]); 53 | } 54 | } 55 | 56 | function outboundTransfer( 57 | address _l1Token, 58 | address _to, 59 | uint256 _amount, 60 | bytes calldata _data 61 | ) public payable returns (bytes memory) { 62 | return outboundTransfer(_l1Token, _to, _amount, 0, 0, _data); 63 | } 64 | 65 | function setDefaultGateway(address newL2DefaultGateway) external onlyCounterpartGateway { 66 | defaultGateway = newL2DefaultGateway; 67 | emit DefaultGatewayUpdated(newL2DefaultGateway); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /contracts/tokenbridge/arbitrum/gateway/L2ReverseCustomGateway.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | import "./L2CustomGateway.sol"; 22 | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 23 | 24 | /** 25 | * @title L2 Gateway for reverse "custom" bridging functionality 26 | * @notice Handles some (but not all!) reverse custom Gateway needs. 27 | * Use the reverse custom gateway instead of the normal custom 28 | * gateway if you want total supply to be tracked on the L2 29 | * rather than the L1. 30 | * @dev The reverse custom gateway burns on the l2 and escrows on the l1 31 | * which is the opposite of the way the normal custom gateway works 32 | * This means that the total supply L2 isn't affected by briding, which 33 | * is helpful for obeservers calculating the total supply especially if 34 | * if minting is also occuring on L2 35 | */ 36 | contract L2ReverseCustomGateway is L2CustomGateway { 37 | using SafeERC20 for IERC20; 38 | 39 | function inboundEscrowTransfer( 40 | address _l2Token, 41 | address _dest, 42 | uint256 _amount 43 | ) internal virtual override { 44 | IERC20(_l2Token).safeTransfer(_dest, _amount); 45 | } 46 | 47 | function outboundEscrowTransfer( 48 | address _l2Token, 49 | address _from, 50 | uint256 _amount 51 | ) internal override returns (uint256) { 52 | uint256 prevBalance = IERC20(_l2Token).balanceOf(address(this)); 53 | // as in the normal custom gateway, in the reverse custom gateway we check 54 | // for the balances of tokens to ensure that inflationary / deflationary changes in the amount 55 | // are taken into account we ignore the return value since we actually query the token before 56 | // and after to calculate the amount of tokens that were transferred 57 | IERC20(_l2Token).safeTransferFrom(_from, address(this), _amount); 58 | uint256 postBalance = IERC20(_l2Token).balanceOf(address(this)); 59 | return postBalance - prevBalance; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | import "./L2ArbitrumGateway.sol"; 22 | import "../../libraries/IWETH9.sol"; 23 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 24 | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 25 | 26 | contract L2WethGateway is L2ArbitrumGateway { 27 | using SafeERC20 for IERC20; 28 | 29 | address public l1Weth; 30 | address public l2Weth; 31 | 32 | function initialize( 33 | address _l1Counterpart, 34 | address _router, 35 | address _l1Weth, 36 | address _l2Weth 37 | ) public { 38 | L2ArbitrumGateway._initialize(_l1Counterpart, _router); 39 | require(_l1Weth != address(0), "INVALID_L1WETH"); 40 | require(_l2Weth != address(0), "INVALID_L2WETH"); 41 | l1Weth = _l1Weth; 42 | l2Weth = _l2Weth; 43 | } 44 | 45 | /** 46 | * @notice internal utility function used to handle when no contract is deployed at expected address 47 | * @param l1ERC20 L1 address of ERC20 48 | */ 49 | function handleNoContract( 50 | address l1ERC20, 51 | address, /* expectedL2Address */ 52 | address _from, 53 | address, /* _to */ 54 | uint256 _amount, 55 | bytes memory /* deployData */ 56 | ) internal override returns (bool shouldHalt) { 57 | // it is assumed that the custom token is deployed in the L2 before deposits are made 58 | // trigger withdrawal 59 | // this codepath should only be hit if the system is setup incorrectly 60 | // this withdrawal is for error recovery, not composing with L2 dapps, so we ignore the return value 61 | triggerWithdrawal(l1ERC20, address(this), _from, _amount, ""); 62 | return true; 63 | } 64 | 65 | /** 66 | * @notice Calculate the address used when bridging an ERC20 token 67 | * @dev the L1 and L2 address oracles may not always be in sync. 68 | * For example, a custom token may have been registered but not deploy or the contract self destructed. 69 | * @param l1ERC20 address of L1 token 70 | * @return L2 address of a bridged ERC20 token 71 | */ 72 | function calculateL2TokenAddress(address l1ERC20) public view override returns (address) { 73 | if (l1ERC20 != l1Weth) { 74 | // invalid L1 weth address 75 | return address(0); 76 | } 77 | return l2Weth; 78 | } 79 | 80 | function inboundEscrowTransfer( 81 | address _l2TokenAddress, 82 | address _dest, 83 | uint256 _amount 84 | ) internal override { 85 | IWETH9(_l2TokenAddress).deposit{ value: _amount }(); 86 | IERC20(_l2TokenAddress).safeTransfer(_dest, _amount); 87 | } 88 | 89 | function createOutboundTx( 90 | address _from, 91 | uint256 _tokenAmount, 92 | bytes memory _outboundCalldata 93 | ) internal override returns (uint256) { 94 | // exitNum incremented after being included in _outboundCalldata 95 | exitNum++; 96 | return 97 | sendTxToL1( 98 | // we send the amount of weth withdrawn as callvalue to the L1 gateway 99 | _tokenAmount, 100 | _from, 101 | counterpartGateway, 102 | _outboundCalldata 103 | ); 104 | } 105 | 106 | receive() external payable {} 107 | } 108 | -------------------------------------------------------------------------------- /contracts/tokenbridge/ethereum/ICustomToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | // solhint-disable-next-line compiler-version 20 | pragma solidity >=0.6.9 <0.9.0; 21 | 22 | interface ArbitrumEnabledToken { 23 | /// @notice should return `0xb1` if token is enabled for arbitrum gateways 24 | /// @dev Previous implmentation used to return `uint8(0xa4b1)`, however that causes compile time error in Solidity 0.8. due to type mismatch. 25 | /// In current version `uint8(0xb1)` shall be returned, which results in no change as that's the same value as truncated `uint8(0xa4b1)`. 26 | function isArbitrumEnabled() external view returns (uint8); 27 | } 28 | 29 | /** 30 | * @title Minimum expected interface for L1 custom token (see TestCustomTokenL1.sol for an example implementation) 31 | */ 32 | interface ICustomToken is ArbitrumEnabledToken { 33 | /** 34 | * @notice Should make an external call to EthERC20Bridge.registerCustomL2Token 35 | */ 36 | function registerTokenOnL2( 37 | address l2CustomTokenAddress, 38 | uint256 maxSubmissionCostForCustomBridge, 39 | uint256 maxSubmissionCostForRouter, 40 | uint256 maxGasForCustomBridge, 41 | uint256 maxGasForRouter, 42 | uint256 gasPriceBid, 43 | uint256 valueForGateway, 44 | uint256 valueForRouter, 45 | address creditBackAddress 46 | ) external payable; 47 | 48 | function transferFrom( 49 | address sender, 50 | address recipient, 51 | uint256 amount 52 | ) external returns (bool); 53 | 54 | function balanceOf(address account) external view returns (uint256); 55 | } 56 | 57 | interface L1MintableToken is ICustomToken { 58 | function bridgeMint(address account, uint256 amount) external; 59 | } 60 | 61 | interface L1ReverseToken is L1MintableToken { 62 | function bridgeBurn(address account, uint256 amount) external; 63 | } 64 | -------------------------------------------------------------------------------- /contracts/tokenbridge/ethereum/gateway/IL1ArbitrumGateway.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | // solhint-disable-next-line compiler-version 20 | pragma solidity >=0.6.9 <0.9.0; 21 | 22 | import "../../libraries/gateway/ITokenGateway.sol"; 23 | import "../../libraries/IERC165.sol"; 24 | 25 | /** 26 | * @title Common interface for gatways on L1 messaging to Arbitrum. 27 | */ 28 | interface IL1ArbitrumGateway is ITokenGateway, IERC165 { 29 | function inbox() external view returns (address); 30 | 31 | /** 32 | * @notice Deposit ERC20 token from Ethereum into Arbitrum. If L2 side hasn't been deployed yet, includes name/symbol/decimals data for initial L2 deploy. Initiate by GatewayRouter. 33 | * @dev L2 address alias will not be applied to the following types of addresses on L1: 34 | * - an externally-owned account 35 | * - a contract in construction 36 | * - an address where a contract will be created 37 | * - an address where a contract lived, but was destroyed 38 | * @param _l1Token L1 address of ERC20 39 | * @param _refundTo Account, or its L2 alias if it have code in L1, to be credited with excess gas refund in L2 40 | * @param _to Account to be credited with the tokens in the L2 (can be the user's L2 account or a contract), not subject to L2 aliasing 41 | This account, or its L2 alias if it have code in L1, will also be able to cancel the retryable ticket and receive callvalue refund 42 | * @param _amount Token Amount 43 | * @param _maxGas Max gas deducted from user's L2 balance to cover L2 execution 44 | * @param _gasPriceBid Gas price for L2 execution 45 | * @param _data encoded data from router and user 46 | * @return res abi encoded inbox sequence number 47 | */ 48 | // * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee 49 | function outboundTransferCustomRefund( 50 | address _l1Token, 51 | address _refundTo, 52 | address _to, 53 | uint256 _amount, 54 | uint256 _maxGas, 55 | uint256 _gasPriceBid, 56 | bytes calldata _data 57 | ) external payable returns (bytes memory); 58 | } 59 | -------------------------------------------------------------------------------- /contracts/tokenbridge/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | import "./L1ReverseCustomGateway.sol"; 22 | 23 | /** 24 | * @title An L1 Reverse gateway which only allows force registration 25 | */ 26 | contract L1ForceOnlyReverseCustomGateway is L1ReverseCustomGateway { 27 | function registerTokenToL2( 28 | address _l2Address, 29 | uint256 _maxGas, 30 | uint256 _gasPriceBid, 31 | uint256 _maxSubmissionCost, 32 | address _creditBackAddress 33 | ) public payable virtual override returns (uint256) { 34 | revert("REGISTER_TOKEN_ON_L2_DISABLED"); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import { L1OrbitCustomGateway } from "./L1OrbitCustomGateway.sol"; 6 | import { IArbToken } from "../../arbitrum/IArbToken.sol"; 7 | 8 | /** 9 | * @title L1 Gateway for reverse "custom" bridging functionality in an ERC20-based rollup. 10 | * @notice Handles some (but not all!) reverse custom Gateway needs. 11 | * Use the reverse custom gateway instead of the normal custom 12 | * gateway if you want total supply to be tracked on the L2 13 | * rather than the L1. 14 | * @dev The reverse custom gateway burns on the l2 and escrows on the l1 15 | * which is the opposite of the way the normal custom gateway works 16 | * This means that the total supply L2 isn't affected by bridging, which 17 | * is helpful for observers calculating the total supply especially if 18 | * if minting is also occuring on L2 19 | */ 20 | contract L1OrbitReverseCustomGateway is L1OrbitCustomGateway { 21 | function inboundEscrowTransfer( 22 | address _l1Address, 23 | address _dest, 24 | uint256 _amount 25 | ) internal virtual override { 26 | IArbToken(_l1Address).bridgeMint(_dest, _amount); 27 | } 28 | 29 | function outboundEscrowTransfer( 30 | address _l1Token, 31 | address _from, 32 | uint256 _amount 33 | ) internal override returns (uint256) { 34 | IArbToken(_l1Token).bridgeBurn(_from, _amount); 35 | // by default we assume that the amount we send to bridgeBurn is the amount burnt 36 | // this might not be the case for every token 37 | return _amount; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /contracts/tokenbridge/ethereum/gateway/L1ReverseCustomGateway.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | import "./L1CustomGateway.sol"; 22 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 23 | 24 | /** 25 | * @title L1 Gateway for reverse "custom" bridging functionality 26 | * @notice Handles some (but not all!) reverse custom Gateway needs. 27 | * Use the reverse custom gateway instead of the normal custom 28 | * gateway if you want total supply to be tracked on the L2 29 | * rather than the L1. 30 | * @dev The reverse custom gateway burns on the l2 and escrows on the l1 31 | * which is the opposite of the way the normal custom gateway works 32 | * This means that the total supply L2 isn't affected by briding, which 33 | * is helpful for observers calculating the total supply especially if 34 | * if minting is also occuring on L2 35 | */ 36 | contract L1ReverseCustomGateway is L1CustomGateway { 37 | function inboundEscrowTransfer( 38 | address _l1Address, 39 | address _dest, 40 | uint256 _amount 41 | ) internal virtual override { 42 | IArbToken(_l1Address).bridgeMint(_dest, _amount); 43 | } 44 | 45 | function outboundEscrowTransfer( 46 | address _l1Token, 47 | address _from, 48 | uint256 _amount 49 | ) internal override returns (uint256) { 50 | IArbToken(_l1Token).bridgeBurn(_from, _amount); 51 | // by default we assume that the amount we send to bridgeBurn is the amount burnt 52 | // this might not be the case for every token 53 | return _amount; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /contracts/tokenbridge/libraries/AddressAliasHelper.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2019-2021, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | library AddressAliasHelper { 22 | uint160 constant offset = uint160(0x1111000000000000000000000000000000001111); 23 | 24 | /// @notice Utility function that converts the address in the L1 that submitted a tx to 25 | /// the inbox to the msg.sender viewed in the L2 26 | /// @param l1Address the address in the L1 that triggered the tx to L2 27 | /// @return l2Address L2 address as viewed in msg.sender 28 | function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) { 29 | unchecked { 30 | l2Address = address(uint160(l1Address) + offset); 31 | } 32 | } 33 | 34 | /// @notice Utility function that converts the msg.sender viewed in the L2 to the 35 | /// address in the L1 that submitted a tx to the inbox 36 | /// @param l2Address L2 address as viewed in msg.sender 37 | /// @return l1Address the address in the L1 that triggered the tx to L2 38 | function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) { 39 | unchecked { 40 | l1Address = address(uint160(l2Address) - offset); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /contracts/tokenbridge/libraries/BytesLib.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | /* 4 | * @title Solidity Bytes Arrays Utils 5 | * @author Gonçalo Sá 6 | * 7 | * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. 8 | * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage. 9 | */ 10 | 11 | pragma solidity ^0.8.0; 12 | 13 | /* solhint-disable no-inline-assembly */ 14 | library BytesLib { 15 | function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) { 16 | require(_bytes.length >= (_start + 20), "Read out of bounds"); 17 | address tempAddress; 18 | 19 | assembly { 20 | tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) 21 | } 22 | 23 | return tempAddress; 24 | } 25 | 26 | function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) { 27 | require(_bytes.length >= (_start + 1), "Read out of bounds"); 28 | uint8 tempUint; 29 | 30 | assembly { 31 | tempUint := mload(add(add(_bytes, 0x1), _start)) 32 | } 33 | 34 | return tempUint; 35 | } 36 | 37 | function toUint(bytes memory _bytes, uint256 _start) internal pure returns (uint256) { 38 | require(_bytes.length >= (_start + 32), "Read out of bounds"); 39 | uint256 tempUint; 40 | 41 | assembly { 42 | tempUint := mload(add(add(_bytes, 0x20), _start)) 43 | } 44 | 45 | return tempUint; 46 | } 47 | 48 | function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) { 49 | require(_bytes.length >= (_start + 32), "Read out of bounds"); 50 | bytes32 tempBytes32; 51 | 52 | assembly { 53 | tempBytes32 := mload(add(add(_bytes, 0x20), _start)) 54 | } 55 | 56 | return tempBytes32; 57 | } 58 | } 59 | /* solhint-enable no-inline-assembly */ 60 | -------------------------------------------------------------------------------- /contracts/tokenbridge/libraries/BytesParser.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | import "./BytesLib.sol"; 22 | 23 | library BytesParser { 24 | using BytesLib for bytes; 25 | 26 | function toUint8(bytes memory input) internal pure returns (bool success, uint8 res) { 27 | if (input.length != 32) { 28 | return (false, 0); 29 | } 30 | // TODO: try catch to handle error 31 | uint256 inputNum = abi.decode(input, (uint256)); 32 | if (inputNum > type(uint8).max) { 33 | return (false, 0); 34 | } 35 | res = uint8(inputNum); 36 | success = true; 37 | } 38 | 39 | function toString(bytes memory input) internal pure returns (bool success, string memory res) { 40 | if (input.length == 0) { 41 | success = false; 42 | // return default value of string 43 | } else if (input.length == 32) { 44 | // TODO: can validate anything other than length and being null terminated? 45 | if (input[31] != bytes1(0x00)) return (false, res); 46 | else success = true; 47 | 48 | // here we assume its a null terminated Bytes32 string 49 | // https://github.com/ethereum/solidity/blob/5852972ec148bc041909400affc778dee66d384d/test/libsolidity/semanticTests/externalContracts/_stringutils/stringutils.sol#L89 50 | // https://github.com/Arachnid/solidity-stringutils 51 | uint256 len = 32; 52 | while (len > 0 && input[len - 1] == bytes1(0x00)) { 53 | len--; 54 | } 55 | 56 | bytes memory inputTruncated = new bytes(len); 57 | for (uint8 i = 0; i < len; i++) { 58 | inputTruncated[i] = input[i]; 59 | } 60 | // we can't just do `res := input` because of the null values in the end 61 | // TODO: can we instead use a bitwise AND? build it dynamically with the length 62 | assembly { 63 | res := inputTruncated 64 | } 65 | } else { 66 | // TODO: try catch to handle error 67 | success = true; 68 | res = abi.decode(input, (string)); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /contracts/tokenbridge/libraries/ClonableBeaconProxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // solhint-disable-next-line compiler-version 3 | pragma solidity >=0.6.0 <0.9.0; 4 | 5 | import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol"; 6 | import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; 7 | import "@openzeppelin/contracts/utils/Create2.sol"; 8 | 9 | interface ProxySetter { 10 | function beacon() external view returns (address); 11 | } 12 | 13 | contract ClonableBeaconProxy is BeaconProxy { 14 | constructor() BeaconProxy(ProxySetter(msg.sender).beacon(), "") {} 15 | } 16 | 17 | contract BeaconProxyFactory is ProxySetter { 18 | bytes32 public constant cloneableProxyHash = keccak256(type(ClonableBeaconProxy).creationCode); 19 | 20 | /** 21 | * @notice utility function used in ClonableBeaconProxy. 22 | * @dev this method makes it possible to use ClonableBeaconProxy.creationCode without encoding constructor parameters 23 | * @return the beacon to be used by the proxy contract. 24 | */ 25 | address public override beacon; 26 | 27 | function initialize(address _beacon) external { 28 | require(_beacon != address(0), "INVALID_BEACON"); 29 | require(beacon == address(0), "ALREADY_INIT"); 30 | beacon = _beacon; 31 | } 32 | 33 | function getSalt(address user, bytes32 userSalt) public pure returns (bytes32) { 34 | return keccak256(abi.encode(user, userSalt)); 35 | } 36 | 37 | function createProxy(bytes32 userSalt) external returns (address) { 38 | // deployment will fail and this function will revert if contract `salt` is not unique 39 | bytes32 salt = getSalt(msg.sender, userSalt); 40 | address createdContract = address(new ClonableBeaconProxy{ salt: salt }()); 41 | return createdContract; 42 | } 43 | 44 | function calculateExpectedAddress(address user, bytes32 userSalt) 45 | public 46 | view 47 | returns (address) 48 | { 49 | bytes32 salt = getSalt(user, userSalt); 50 | return Create2.computeAddress(salt, cloneableProxyHash, address(this)); 51 | } 52 | 53 | function calculateExpectedAddress(bytes32 salt) public view returns (address) { 54 | return Create2.computeAddress(salt, cloneableProxyHash, address(this)); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /contracts/tokenbridge/libraries/Cloneable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2019-2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | import "./ICloneable.sol"; 22 | 23 | contract Cloneable is ICloneable { 24 | string private constant NOT_CLONE = "NOT_CLONE"; 25 | 26 | bool private isMasterCopy; 27 | 28 | constructor() { 29 | isMasterCopy = true; 30 | } 31 | 32 | function isMaster() external view override returns (bool) { 33 | return isMasterCopy; 34 | } 35 | 36 | function safeSelfDestruct(address payable dest) internal { 37 | require(!isMasterCopy, NOT_CLONE); 38 | selfdestruct(dest); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /contracts/tokenbridge/libraries/CreationCodeHelper.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | pragma solidity ^0.8.0; 3 | 4 | library CreationCodeHelper { 5 | /** 6 | * @notice Generate a creation code that results with a contract with `code` as deployed code. 7 | * Generated creation code shall match the one generated by Solidity compiler with an empty constructor. 8 | * @dev Prepended constructor bytecode consists of: 9 | * - 608060405234801561001057600080fd5b50 - store free memory pointer, then check no callvalue is provided 10 | * - 61xxxx - push 2 bytes of `code` length 11 | * - 806100206000396000f3fe - copy deployed code to memory and return the location of it 12 | * @param runtimeCode Deployed bytecode to which constructor bytecode will be prepended 13 | * @return Creation code of a new contract 14 | */ 15 | function getCreationCodeFor(bytes memory runtimeCode) internal pure returns (bytes memory) { 16 | return abi.encodePacked( 17 | hex"608060405234801561001057600080fd5b50", 18 | hex"61", 19 | uint16(runtimeCode.length), 20 | hex"806100206000396000f3fe", 21 | runtimeCode 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /contracts/tokenbridge/libraries/ERC165.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) 3 | 4 | // With pragma modification to support ^0.6.11 5 | // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.6/contracts/utils/introspection/ERC165.sol 6 | 7 | pragma solidity ^0.8.0; 8 | 9 | import "./IERC165.sol"; 10 | 11 | /** 12 | * @dev Implementation of the {IERC165} interface. 13 | * 14 | * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check 15 | * for the additional interface id that will be supported. For example: 16 | * 17 | * ```solidity 18 | * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { 19 | * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); 20 | * } 21 | * ``` 22 | * 23 | * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. 24 | */ 25 | abstract contract ERC165 is IERC165 { 26 | /** 27 | * @dev See {IERC165-supportsInterface}. 28 | */ 29 | function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { 30 | return interfaceId == type(IERC165).interfaceId; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /contracts/tokenbridge/libraries/ICloneable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2019, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | // solhint-disable-next-line compiler-version 20 | pragma solidity >=0.6.9 <0.9.0; 21 | 22 | interface ICloneable { 23 | function isMaster() external view returns (bool); 24 | } 25 | -------------------------------------------------------------------------------- /contracts/tokenbridge/libraries/IERC165.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) 3 | 4 | // With pragma modification to allow interface compatibility with >=0.6.9 <0.9.0 5 | // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.6/contracts/utils/introspection/IERC165.sol 6 | 7 | // solhint-disable-next-line compiler-version 8 | pragma solidity >=0.6.9 <0.9.0; 9 | 10 | /** 11 | * @dev Interface of the ERC165 standard, as defined in the 12 | * https://eips.ethereum.org/EIPS/eip-165[EIP]. 13 | * 14 | * Implementers can declare support of contract interfaces, which can then be 15 | * queried by others ({ERC165Checker}). 16 | * 17 | * For an implementation, see {ERC165}. 18 | */ 19 | interface IERC165 { 20 | /** 21 | * @dev Returns true if this contract implements the interface defined by 22 | * `interfaceId`. See the corresponding 23 | * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] 24 | * to learn more about how these ids are created. 25 | * 26 | * This function call must use less than 30 000 gas. 27 | */ 28 | function supportsInterface(bytes4 interfaceId) external view returns (bool); 29 | } 30 | -------------------------------------------------------------------------------- /contracts/tokenbridge/libraries/IERC20Bridge.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // solhint-disable-next-line compiler-version 4 | pragma solidity >=0.6.9 <0.9.0; 5 | 6 | interface IERC20Bridge { 7 | /** 8 | * @dev token that is escrowed in bridge on L1 side and minted on L2 as native currency. Also fees are paid in this token. 9 | */ 10 | function nativeToken() external view returns (address); 11 | } 12 | -------------------------------------------------------------------------------- /contracts/tokenbridge/libraries/ITransferAndCall.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // solhint-disable-next-line compiler-version 3 | pragma solidity >0.6.0 <0.9.0; 4 | 5 | import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; 6 | 7 | interface ITransferAndCall is IERC20Upgradeable { 8 | function transferAndCall( 9 | address to, 10 | uint256 value, 11 | bytes memory data 12 | ) external returns (bool success); 13 | 14 | event Transfer(address indexed from, address indexed to, uint256 value, bytes data); 15 | } 16 | 17 | /** 18 | * @notice note that implementation of ITransferAndCallReceiver is not expected to return a success bool 19 | */ 20 | interface ITransferAndCallReceiver { 21 | function onTokenTransfer( 22 | address _sender, 23 | uint256 _value, 24 | bytes memory _data 25 | ) external; 26 | } 27 | -------------------------------------------------------------------------------- /contracts/tokenbridge/libraries/IWETH9.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // solhint-disable-next-line compiler-version 4 | pragma solidity >=0.6.9 <0.9.0; 5 | 6 | interface IWETH9 { 7 | function deposit() external payable; 8 | 9 | function withdraw(uint256 _amount) external; 10 | } 11 | -------------------------------------------------------------------------------- /contracts/tokenbridge/libraries/L2CustomGatewayToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | import "./L2GatewayToken.sol"; 22 | 23 | /** 24 | * @title A basic custom token contract that can be used with the custom gateway 25 | */ 26 | contract L2CustomGatewayToken is L2GatewayToken { 27 | /** 28 | * @notice initialize the token 29 | * @dev the L2 bridge assumes this does not fail or revert 30 | * @param name_ ERC20 token name 31 | * @param symbol_ ERC20 token symbol 32 | * @param decimals_ ERC20 decimals 33 | * @param l2Gateway_ L2 gateway this token communicates with 34 | * @param l1Counterpart_ L1 address of ERC20 35 | */ 36 | function initialize( 37 | string memory name_, 38 | string memory symbol_, 39 | uint8 decimals_, 40 | address l2Gateway_, 41 | address l1Counterpart_ 42 | ) public virtual initializer { 43 | _initialize(name_, symbol_, decimals_, l2Gateway_, l1Counterpart_); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /contracts/tokenbridge/libraries/L2GatewayToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | import "./aeERC20.sol"; 22 | import "./BytesParser.sol"; 23 | import "../arbitrum/IArbToken.sol"; 24 | 25 | /** 26 | * @title Standard (i.e., non-custom) contract used as a base for different L2 Gateways 27 | */ 28 | abstract contract L2GatewayToken is aeERC20, IArbToken { 29 | address public l2Gateway; 30 | address public override l1Address; 31 | 32 | modifier onlyGateway() { 33 | require(msg.sender == l2Gateway, "ONLY_GATEWAY"); 34 | _; 35 | } 36 | 37 | /** 38 | * @notice initialize the token 39 | * @dev the L2 bridge assumes this does not fail or revert 40 | * @param name_ ERC20 token name 41 | * @param symbol_ ERC20 token symbol 42 | * @param decimals_ ERC20 decimals 43 | * @param l2Gateway_ L2 gateway this token communicates with 44 | * @param l1Counterpart_ L1 address of ERC20 45 | */ 46 | function _initialize( 47 | string memory name_, 48 | string memory symbol_, 49 | uint8 decimals_, 50 | address l2Gateway_, 51 | address l1Counterpart_ 52 | ) internal virtual { 53 | require(l2Gateway_ != address(0), "INVALID_GATEWAY"); 54 | require(l2Gateway == address(0), "ALREADY_INIT"); 55 | l2Gateway = l2Gateway_; 56 | l1Address = l1Counterpart_; 57 | 58 | aeERC20._initialize(name_, symbol_, decimals_); 59 | } 60 | 61 | /** 62 | * @notice Mint tokens on L2. Callable path is L1Gateway depositToken (which handles L1 escrow), which triggers L2Gateway, which calls this 63 | * @param account recipient of tokens 64 | * @param amount amount of tokens minted 65 | */ 66 | function bridgeMint(address account, uint256 amount) external virtual override onlyGateway { 67 | _mint(account, amount); 68 | } 69 | 70 | /** 71 | * @notice Burn tokens on L2. 72 | * @dev only the token bridge can call this 73 | * @param account owner of tokens 74 | * @param amount amount of tokens burnt 75 | */ 76 | function bridgeBurn(address account, uint256 amount) external virtual override onlyGateway { 77 | _burn(account, amount); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /contracts/tokenbridge/libraries/ProxyUtil.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2021, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | library ProxyUtil { 22 | function getProxyAdmin() internal view returns (address admin) { 23 | // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.0/contracts/proxy/TransparentUpgradeableProxy.sol#L48 24 | // Storage slot with the admin of the proxy contract. 25 | // This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is 26 | bytes32 slot = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; 27 | assembly { 28 | admin := sload(slot) 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /contracts/tokenbridge/libraries/TransferAndCallToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // solhint-disable-next-line compiler-version 3 | pragma solidity >0.6.0 <0.9.0; 4 | 5 | import "./ERC20Upgradeable.sol"; 6 | import "./ITransferAndCall.sol"; 7 | 8 | // Implementation from https://github.com/smartcontractkit/LinkToken/blob/master/contracts/v0.6/TransferAndCallToken.sol 9 | /** 10 | * @notice based on Implementation from https://github.com/smartcontractkit/LinkToken/blob/master/contracts/v0.6/ERC677Token.sol 11 | * The implementation doesn't return a bool on onTokenTransfer. This is similar to the proposed 677 standard, but still incompatible - thus we don't refer to it as such. 12 | */ 13 | abstract contract TransferAndCallToken is ERC20Upgradeable, ITransferAndCall { 14 | /** 15 | * @dev transfer token to a contract address with additional data if the recipient is a contact. 16 | * @param _to The address to transfer to. 17 | * @param _value The amount to be transferred. 18 | * @param _data The extra data to be passed to the receiving contract. 19 | */ 20 | function transferAndCall( 21 | address _to, 22 | uint256 _value, 23 | bytes memory _data 24 | ) public virtual override returns (bool success) { 25 | super.transfer(_to, _value); 26 | emit Transfer(msg.sender, _to, _value, _data); 27 | if (isContract(_to)) { 28 | contractFallback(_to, _value, _data); 29 | } 30 | return true; 31 | } 32 | 33 | // PRIVATE 34 | 35 | function contractFallback( 36 | address _to, 37 | uint256 _value, 38 | bytes memory _data 39 | ) private { 40 | ITransferAndCallReceiver receiver = ITransferAndCallReceiver(_to); 41 | receiver.onTokenTransfer(msg.sender, _value, _data); 42 | } 43 | 44 | function isContract(address _addr) private view returns (bool hasCode) { 45 | uint256 length; 46 | assembly { 47 | length := extcodesize(_addr) 48 | } 49 | return length > 0; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /contracts/tokenbridge/libraries/Whitelist.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2021, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | abstract contract WhitelistConsumer { 22 | address public whitelist; 23 | 24 | event WhitelistSourceUpdated(address newSource); 25 | 26 | modifier onlyWhitelisted() { 27 | if (whitelist != address(0)) { 28 | require(Whitelist(whitelist).isAllowed(msg.sender), "NOT_WHITELISTED"); 29 | } 30 | _; 31 | } 32 | 33 | function updateWhitelistSource(address newSource) external { 34 | require(msg.sender == whitelist, "NOT_FROM_LIST"); 35 | whitelist = newSource; 36 | emit WhitelistSourceUpdated(newSource); 37 | } 38 | } 39 | 40 | contract Whitelist { 41 | address public owner; 42 | mapping(address => bool) public isAllowed; 43 | 44 | event OwnerUpdated(address newOwner); 45 | event WhitelistUpgraded(address newWhitelist, address[] targets); 46 | 47 | constructor() { 48 | owner = msg.sender; 49 | } 50 | 51 | modifier onlyOwner() { 52 | require(msg.sender == owner, "ONLY_OWNER"); 53 | _; 54 | } 55 | 56 | function setOwner(address newOwner) external onlyOwner { 57 | owner = newOwner; 58 | emit OwnerUpdated(newOwner); 59 | } 60 | 61 | function setWhitelist(address[] memory user, bool[] memory val) external onlyOwner { 62 | require(user.length == val.length, "INVALID_INPUT"); 63 | 64 | for (uint256 i = 0; i < user.length; i++) { 65 | isAllowed[user[i]] = val[i]; 66 | } 67 | } 68 | 69 | // set new whitelist to address(0) to disable whitelist 70 | function triggerConsumers(address newWhitelist, address[] memory targets) external onlyOwner { 71 | for (uint256 i = 0; i < targets.length; i++) { 72 | WhitelistConsumer(targets[i]).updateWhitelistSource(newWhitelist); 73 | } 74 | emit WhitelistUpgraded(newWhitelist, targets); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /contracts/tokenbridge/libraries/aeERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | import "../libraries/draft-ERC20PermitUpgradeable.sol"; 22 | import "./TransferAndCallToken.sol"; 23 | 24 | /// @title Arbitrum extended ERC20 25 | /// @notice The recommended ERC20 implementation for Layer 2 tokens 26 | /// @dev This implements the ERC20 standard with transferAndCall extenstion/affordances 27 | contract aeERC20 is ERC20PermitUpgradeable, TransferAndCallToken { 28 | using AddressUpgradeable for address; 29 | 30 | constructor() initializer { 31 | // this is expected to be used as the logic contract behind a proxy 32 | // override the constructor if you don't wish to use the initialize method 33 | } 34 | 35 | function _initialize( 36 | string memory name_, 37 | string memory symbol_, 38 | uint8 decimals_ 39 | ) internal initializer { 40 | __ERC20Permit_init(name_); 41 | __ERC20_init(name_, symbol_); 42 | _setupDecimals(decimals_); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /contracts/tokenbridge/libraries/aeWETH.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | import "./L2GatewayToken.sol"; 22 | import "./IWETH9.sol"; 23 | 24 | /// @title Arbitrum extended WETH 25 | contract aeWETH is L2GatewayToken, IWETH9 { 26 | function initialize( 27 | string memory name_, 28 | string memory symbol_, 29 | uint8 decimals_, 30 | address l2Gateway_, 31 | address l1Address_ 32 | ) external { 33 | L2GatewayToken._initialize(name_, symbol_, decimals_, l2Gateway_, l1Address_); 34 | } 35 | 36 | function bridgeMint( 37 | address, /* account */ 38 | uint256 /* amount */ 39 | ) external virtual override { 40 | // we want weth to always be fully collaterized 41 | revert("NO_BRIDGE_MINT"); 42 | } 43 | 44 | function bridgeBurn(address account, uint256 amount) external virtual override onlyGateway { 45 | _burn(account, amount); 46 | (bool success, ) = msg.sender.call{ value: amount }(""); 47 | require(success, "FAIL_TRANSFER"); 48 | } 49 | 50 | function deposit() external payable override { 51 | depositTo(msg.sender); 52 | } 53 | 54 | function withdraw(uint256 amount) external override { 55 | withdrawTo(msg.sender, amount); 56 | } 57 | 58 | function depositTo(address account) public payable { 59 | _mint(account, msg.value); 60 | } 61 | 62 | function withdrawTo(address account, uint256 amount) public { 63 | _burn(msg.sender, amount); 64 | (bool success, ) = account.call{ value: amount }(""); 65 | require(success, "FAIL_TRANSFER"); 66 | } 67 | 68 | receive() external payable { 69 | depositTo(msg.sender); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /contracts/tokenbridge/libraries/gateway/GatewayMessageHandler.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2021, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | /// @notice this library manages encoding and decoding of gateway communication 22 | library GatewayMessageHandler { 23 | // these are for communication from L1 to L2 gateway 24 | 25 | function encodeToL2GatewayMsg(bytes memory gatewayData, bytes memory callHookData) 26 | internal 27 | pure 28 | returns (bytes memory res) 29 | { 30 | res = abi.encode(gatewayData, callHookData); 31 | } 32 | 33 | function parseFromL1GatewayMsg(bytes calldata _data) 34 | internal 35 | pure 36 | returns (bytes memory gatewayData, bytes memory callHookData) 37 | { 38 | // abi decode may revert, but the encoding is done by L1 gateway, so we trust it 39 | (gatewayData, callHookData) = abi.decode(_data, (bytes, bytes)); 40 | } 41 | 42 | // these are for communication from L2 to L1 gateway 43 | 44 | function encodeFromL2GatewayMsg(uint256 exitNum, bytes memory callHookData) 45 | internal 46 | pure 47 | returns (bytes memory res) 48 | { 49 | res = abi.encode(exitNum, callHookData); 50 | } 51 | 52 | function parseToL1GatewayMsg(bytes calldata _data) 53 | internal 54 | pure 55 | returns (uint256 exitNum, bytes memory callHookData) 56 | { 57 | // abi decode may revert, but the encoding is done by L1 gateway, so we trust it 58 | (exitNum, callHookData) = abi.decode(_data, (uint256, bytes)); 59 | } 60 | 61 | // these are for communication from router to gateway 62 | 63 | function encodeFromRouterToGateway(address _from, bytes calldata _data) 64 | internal 65 | pure 66 | returns (bytes memory res) 67 | { 68 | // abi decode may revert, but the encoding is done by L1 gateway, so we trust it 69 | return abi.encode(_from, _data); 70 | } 71 | 72 | function parseFromRouterToGateway(bytes calldata _data) 73 | internal 74 | pure 75 | returns (address, bytes memory res) 76 | { 77 | // abi decode may revert, but the encoding is done by L1 gateway, so we trust it 78 | return abi.decode(_data, (address, bytes)); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /contracts/tokenbridge/libraries/gateway/ICustomGateway.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | // solhint-disable-next-line compiler-version 20 | pragma solidity >=0.6.9 <0.9.0; 21 | 22 | // import "./ITokenGateway.sol"; 23 | 24 | interface ICustomGateway { 25 | function l1ToL2Token(address _l1Token) external view returns (address _l2Token); 26 | 27 | event TokenSet(address indexed l1Address, address indexed l2Address); 28 | } 29 | -------------------------------------------------------------------------------- /contracts/tokenbridge/libraries/gateway/IGatewayRouter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | import "../ProxyUtil.sol"; 22 | import "@openzeppelin/contracts/utils/Address.sol"; 23 | import "./TokenGateway.sol"; 24 | import "./GatewayMessageHandler.sol"; 25 | 26 | /** 27 | * @title Common interface for L1 and L2 Gateway Routers 28 | */ 29 | interface IGatewayRouter is ITokenGateway { 30 | function defaultGateway() external view returns (address gateway); 31 | 32 | event TransferRouted( 33 | address indexed token, 34 | address indexed _userFrom, 35 | address indexed _userTo, 36 | address gateway 37 | ); 38 | 39 | event GatewaySet(address indexed l1Token, address indexed gateway); 40 | event DefaultGatewayUpdated(address newDefaultGateway); 41 | 42 | function getGateway(address _token) external view returns (address gateway); 43 | } 44 | -------------------------------------------------------------------------------- /contracts/tokenbridge/libraries/gateway/ITokenGateway.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | // solhint-disable-next-line compiler-version 20 | pragma solidity >=0.6.9 <0.9.0; 21 | 22 | interface ITokenGateway { 23 | /// @notice event deprecated in favor of DepositInitiated and WithdrawalInitiated 24 | // event OutboundTransferInitiated( 25 | // address token, 26 | // address indexed _from, 27 | // address indexed _to, 28 | // uint256 indexed _transferId, 29 | // uint256 _amount, 30 | // bytes _data 31 | // ); 32 | 33 | /// @notice event deprecated in favor of DepositFinalized and WithdrawalFinalized 34 | // event InboundTransferFinalized( 35 | // address token, 36 | // address indexed _from, 37 | // address indexed _to, 38 | // uint256 indexed _transferId, 39 | // uint256 _amount, 40 | // bytes _data 41 | // ); 42 | 43 | function outboundTransfer( 44 | address _token, 45 | address _to, 46 | uint256 _amount, 47 | uint256 _maxGas, 48 | uint256 _gasPriceBid, 49 | bytes calldata _data 50 | ) external payable returns (bytes memory); 51 | 52 | function finalizeInboundTransfer( 53 | address _token, 54 | address _from, 55 | address _to, 56 | uint256 _amount, 57 | bytes calldata _data 58 | ) external payable; 59 | 60 | /** 61 | * @notice Calculate the address used when bridging an ERC20 token 62 | * @dev the L1 and L2 address oracles may not always be in sync. 63 | * For example, a custom token may have been registered but not deploy or the contract self destructed. 64 | * @param l1ERC20 address of L1 token 65 | * @return L2 address of a bridged ERC20 token 66 | */ 67 | function calculateL2TokenAddress(address l1ERC20) external view returns (address); 68 | 69 | function getOutboundCalldata( 70 | address _token, 71 | address _from, 72 | address _to, 73 | uint256 _amount, 74 | bytes memory _data 75 | ) external view returns (bytes memory); 76 | } 77 | -------------------------------------------------------------------------------- /contracts/tokenbridge/libraries/gateway/TokenGateway.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | import "./ITokenGateway.sol"; 22 | import "@openzeppelin/contracts/utils/Address.sol"; 23 | 24 | abstract contract TokenGateway is ITokenGateway { 25 | using Address for address; 26 | 27 | address public counterpartGateway; 28 | address public router; 29 | 30 | // This modifier is overriden in gateways to validate the message sender 31 | // For L1 to L2 messages need to be validated against the aliased counterpartGateway 32 | // For L2 to L1 messages need to be validated against the bridge and L2ToL1Sender 33 | // prettier-ignore 34 | modifier onlyCounterpartGateway() virtual; 35 | 36 | function _initialize(address _counterpartGateway, address _router) internal virtual { 37 | // This initializes internal variables of the abstract contract it can be chained together with other functions. 38 | // It is virtual so subclasses can override or wrap around this logic. 39 | // An example where this is useful is different subclasses that validate the router address differently 40 | require(_counterpartGateway != address(0), "INVALID_COUNTERPART"); 41 | require(counterpartGateway == address(0), "ALREADY_INIT"); 42 | counterpartGateway = _counterpartGateway; 43 | router = _router; 44 | } 45 | 46 | function isRouter(address _target) internal view returns (bool isTargetRouter) { 47 | return _target == router; 48 | } 49 | 50 | /** 51 | * @notice Calculate the address used when bridging an ERC20 token 52 | * @dev the L1 and L2 address oracles may not always be in sync. 53 | * For example, a custom token may have been registered but not deploy or the contract self destructed. 54 | * @param l1ERC20 address of L1 token 55 | * @return L2 address of a bridged ERC20 token 56 | */ 57 | function calculateL2TokenAddress(address l1ERC20) 58 | public 59 | view 60 | virtual 61 | override 62 | returns (address); 63 | } 64 | -------------------------------------------------------------------------------- /contracts/tokenbridge/test/AddressMappingTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | import "../arbitrum/L2ArbitrumMessenger.sol"; 22 | import "../libraries/AddressAliasHelper.sol"; 23 | 24 | contract AddressMappingTest is L2ArbitrumMessenger { 25 | function getL1AddressTest(address sender) external pure returns (address l1Address) { 26 | return AddressAliasHelper.undoL1ToL2Alias(sender); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /contracts/tokenbridge/test/ArbSysMock.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.0; 2 | 3 | contract ArbSysMock { 4 | event ArbSysL2ToL1Tx(address from, address to, uint256 value, bytes data); 5 | uint256 counter; 6 | 7 | function sendTxToL1(address destination, bytes calldata calldataForL1) 8 | external 9 | payable 10 | returns (uint256 exitNum) 11 | { 12 | exitNum = counter; 13 | counter = exitNum + 1; 14 | emit ArbSysL2ToL1Tx(msg.sender, destination, msg.value, calldataForL1); 15 | return exitNum; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /contracts/tokenbridge/test/CreationCodeTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | pragma solidity ^0.8.0; 3 | 4 | import {CreationCodeHelper} from "../libraries/CreationCodeHelper.sol"; 5 | 6 | contract CreationCodeTest { 7 | /** 8 | * @dev Wrapper function around CreationCodeHelper.getCreationCodeFor used for testing convenience. 9 | */ 10 | function creationCodeFor(bytes memory code) external pure returns (bytes memory) { 11 | return CreationCodeHelper.getCreationCodeFor(code); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /contracts/tokenbridge/test/InterfaceCompatibilityTester.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2022, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | // solhint-disable-next-line compiler-version 20 | pragma solidity >=0.6.9 <0.9.0; 21 | 22 | import "../arbitrum/IArbToken.sol"; 23 | import "../ethereum/ICustomToken.sol"; 24 | import "../ethereum/gateway/IL1ArbitrumGateway.sol"; 25 | import "../ethereum/gateway/IL1GatewayRouter.sol"; 26 | import "../libraries/IWETH9.sol"; 27 | import "../libraries/IERC165.sol"; 28 | import "../libraries/gateway/ICustomGateway.sol"; 29 | import "../libraries/gateway/ITokenGateway.sol"; 30 | -------------------------------------------------------------------------------- /contracts/tokenbridge/test/TestArbCustomToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | import "../arbitrum/IArbToken.sol"; 22 | import "../arbitrum/ReverseArbToken.sol"; 23 | import "../libraries/aeERC20.sol"; 24 | 25 | contract TestArbCustomToken is aeERC20, IArbToken { 26 | address public l2Gateway; 27 | address public override l1Address; 28 | 29 | modifier onlyGateway() { 30 | require(msg.sender == l2Gateway, "ONLY_l2GATEWAY"); 31 | _; 32 | } 33 | 34 | constructor(address _l2Gateway, address _l1Address) { 35 | l2Gateway = _l2Gateway; 36 | l1Address = _l1Address; 37 | aeERC20._initialize("TestCustomToken", "CARB", uint8(18)); 38 | } 39 | 40 | function someWackyCustomStuff() public {} 41 | 42 | function bridgeMint(address account, uint256 amount) external virtual override onlyGateway { 43 | _mint(account, amount); 44 | } 45 | 46 | function bridgeBurn(address account, uint256 amount) external virtual override onlyGateway { 47 | _burn(account, amount); 48 | } 49 | } 50 | 51 | contract MintableTestArbCustomToken is TestArbCustomToken { 52 | constructor(address _l2Gateway, address _l1Address) 53 | TestArbCustomToken(_l2Gateway, _l1Address) 54 | {} 55 | 56 | function userMint(address account, uint256 amount) external { 57 | _mint(account, amount); 58 | } 59 | } 60 | 61 | contract ReverseTestArbCustomToken is aeERC20, IArbToken, ReverseArbToken { 62 | address public l2Gateway; 63 | address public override l1Address; 64 | 65 | modifier onlyGateway() { 66 | require(msg.sender == l2Gateway, "ONLY_l2GATEWAY"); 67 | _; 68 | } 69 | 70 | constructor(address _l2Gateway, address _l1Address) { 71 | l2Gateway = _l2Gateway; 72 | l1Address = _l1Address; 73 | aeERC20._initialize("TestReverseCustomToken", "RARB", uint8(18)); 74 | } 75 | 76 | function someWackyCustomStuff() public {} 77 | 78 | function mint() external { 79 | _mint(msg.sender, 50000000); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /contracts/tokenbridge/test/TestArbCustomTokenBurnFee.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | import "./TestArbCustomToken.sol"; 22 | 23 | contract TestArbCustomTokenBurnFee is TestArbCustomToken { 24 | constructor(address _l2Gateway, address _l1Address) 25 | TestArbCustomToken(_l2Gateway, _l1Address) 26 | {} 27 | 28 | // this token transfer extra 1 wei from the sender as fee when it burn token 29 | // alternatively, it can also be a callback that pass execution to the user 30 | function _burn(address account, uint256 amount) internal override { 31 | super._burn(account, amount); 32 | _transfer(account, address(1), 1); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /contracts/tokenbridge/test/TestBytesParser.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2021, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | import "../libraries/BytesParser.sol"; 22 | 23 | contract TestBytesParser { 24 | function bytesToString(bytes memory input) 25 | public 26 | pure 27 | returns (bool success, string memory res) 28 | { 29 | return BytesParser.toString(input); 30 | } 31 | 32 | function bytesToUint8(bytes memory input) public pure returns (bool, uint8) { 33 | return BytesParser.toUint8(input); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /contracts/tokenbridge/test/TestERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2020, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | import "../libraries/aeERC20.sol"; 22 | 23 | contract TestERC20 is aeERC20 { 24 | constructor() { 25 | aeERC20._initialize("IntArbTestToken", "IARB", uint8(18)); 26 | } 27 | 28 | function mint() external { 29 | _mint(msg.sender, 50000000); 30 | } 31 | } 32 | 33 | // test token code inspired from maker 34 | contract Bytes32ERC20 { 35 | mapping(address => uint256) public balanceOf; 36 | mapping(address => mapping(address => uint256)) public allowance; 37 | 38 | function transfer(address dst, uint256 wad) public returns (bool) { 39 | return transferFrom(msg.sender, dst, wad); 40 | } 41 | 42 | function transferFrom( 43 | address src, 44 | address dst, 45 | uint256 wad 46 | ) public returns (bool) { 47 | if (src != msg.sender) { 48 | allowance[src][msg.sender] = allowance[src][msg.sender] - wad; 49 | } 50 | 51 | balanceOf[src] = balanceOf[src] - wad; 52 | balanceOf[dst] = balanceOf[dst] + wad; 53 | 54 | return true; 55 | } 56 | 57 | function approve(address guy, uint256 wad) public returns (bool) { 58 | allowance[msg.sender][guy] = wad; 59 | return true; 60 | } 61 | 62 | function mint() public { 63 | balanceOf[msg.sender] += 1 ether; 64 | } 65 | } 66 | 67 | contract Bytes32ERC20WithMetadata is Bytes32ERC20 { 68 | bytes32 public name = 0x4d616b6572000000000000000000000000000000000000000000000000000000; 69 | bytes32 public symbol = 0x4d4b520000000000000000000000000000000000000000000000000000000000; 70 | // TODO: what if this overflows? 71 | uint8 public decimals = 18; 72 | 73 | // no totalSupply field 74 | // uint256 public totalSupply; 75 | } 76 | -------------------------------------------------------------------------------- /contracts/tokenbridge/test/TestPostDepositCall.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | /* 4 | * Copyright 2021, Offchain Labs, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | pragma solidity ^0.8.0; 20 | 21 | import "../libraries/ITransferAndCall.sol"; 22 | 23 | contract L2Called is ITransferAndCallReceiver { 24 | event Called(uint256 num); 25 | 26 | constructor() {} 27 | 28 | // This function can be anything 29 | function postDepositHook(uint256 num) public { 30 | emit Called(num); 31 | } 32 | 33 | function onTokenTransfer( 34 | address, /* sender */ 35 | uint256, /* amount */ 36 | bytes calldata data 37 | ) external override { 38 | uint256 num = abi.decode(data, (uint256)); 39 | 40 | if (num == 5) { 41 | postDepositHook(num); 42 | } else if (num == 7) { 43 | revert("should fail because 7"); 44 | } else if (num == 9) { 45 | // this should use all gas 46 | while (gasleft() > 0) {} 47 | } else { 48 | revert("should fail"); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /contracts/tokenbridge/test/TestWETH9.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "../libraries/IWETH9.sol"; 6 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 7 | import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; 8 | 9 | contract TestWETH9 is ERC20, IWETH9 { 10 | constructor(string memory name_, string memory symbol_) ERC20(name_, symbol_) {} 11 | 12 | function deposit() external payable override { 13 | _mint(msg.sender, msg.value); 14 | } 15 | 16 | function withdraw(uint256 _amount) external override { 17 | _burn(msg.sender, _amount); 18 | payable(address(msg.sender)).transfer(_amount); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /deployment-42161.json: -------------------------------------------------------------------------------- 1 | { 2 | "l1GatewayRouter": "0x72Ce9c846789fdB6fC1f34aC4AD25Dd9ef7031ef", 3 | "l2GatewayRouter": "0x5288c571Fd7aD117beA99bF60FE0846C4E84F933", 4 | "l1ERC20GatewayProxy": "0xa3A7B6F88361F48403514059F1F16C8E78d60EeC", 5 | "l2ERC20GatewayProxy": "0x09e9222E96E7B4AE2a407B98d48e330053351EEe", 6 | "l1ProxyAdmin": "0x9aD46fac0Cf7f790E5be05A0F15223935A0c0aDa", 7 | "l2ProxyAdmin": "0xd570aCE65C43af47101fC6250FD6fC63D1c22a86", 8 | "l1Deployer": "0x5B34380C518da5A8851f762D4fA29605ACc3c0e2", 9 | "l2Deployer": "0xBB1a241DCBd6A3894cB61F659034874Dc9CF65D4", 10 | "inbox": "0x4Dbd4fc535Ac27206064B68FfCf827b0A60BAB3f" 11 | } 12 | -------------------------------------------------------------------------------- /deployment-421611.json: -------------------------------------------------------------------------------- 1 | { 2 | "l1GatewayRouter": "0x70C143928eCfFaf9F5b406f7f4fC28Dc43d68380", 3 | "l2GatewayRouter": "0x9413AD42910c1eA60c737dB5f58d1C504498a3cD", 4 | "l1ERC20GatewayProxy": "0x91169Dbb45e6804743F94609De50D511C437572E", 5 | "l2ERC20GatewayProxy": "0x195C107F3F75c4C93Eba7d9a1312F19305d6375f", 6 | "l1ProxyAdmin": "0x0DbAF24efA2bc9Dd1a6c0530DD252BCcF883B89A", 7 | "l2ProxyAdmin": "0x58816566EB91815Cc07f3Ad5230eE0820fe1A19a", 8 | "l1Deployer": "0xdF8107D1758D1D7dCfB29511557bC92DAa119174", 9 | "l2Deployer": "0xdF8107D1758D1D7dCfB29511557bC92DAa119174", 10 | "inbox": "0x578BAde599406A8fE3d24Fd7f7211c0911F5B29e" 11 | } 12 | -------------------------------------------------------------------------------- /foundry.toml: -------------------------------------------------------------------------------- 1 | [profile.default] 2 | src = 'contracts' 3 | out = 'out' 4 | libs = ["node_modules", "lib"] 5 | test = 'test-foundry' 6 | cache_path = 'forge-cache' 7 | optimizer = true 8 | optimizer_runs = 100 9 | via_ir = false 10 | fs_permissions = [{ access = "read", path = "node_modules/@offchainlabs/stablecoin-evm"}] 11 | 12 | [fmt] 13 | number_underscore = 'thousands' 14 | line_length = 100 15 | # See more config options https://github.com/foundry-rs/foundry/tree/master/config -------------------------------------------------------------------------------- /remappings.txt: -------------------------------------------------------------------------------- 1 | ds-test/=lib/forge-std/lib/ds-test/src/ 2 | forge-std/=lib/forge-std/src/ 3 | @openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/ 4 | @openzeppelin/contracts/=node_modules/@openzeppelin/contracts/ 5 | @arbitrum=node_modules/@arbitrum 6 | @offchainlabs=node_modules/@offchainlabs 7 | -------------------------------------------------------------------------------- /scripts/deploy_buddy_deployer.ts: -------------------------------------------------------------------------------- 1 | // import { ethers } from 'hardhat' 2 | // import { writeFileSync } from 'fs' 3 | // import deployments from '../deployment.json' 4 | 5 | // const main = async () => { 6 | // const BuddyDeployer = await ethers.getContractFactory('BuddyDeployer') 7 | // const buddyDeployer = await BuddyDeployer.deploy() 8 | // console.log('BuddyDeployer deployed to:', buddyDeployer.address) 9 | 10 | // const contracts = JSON.stringify({ 11 | // ...deployments, 12 | // buddyDeployer: buddyDeployer.address, 13 | // l2ChainId: ethers.BigNumber.from( 14 | // ethers.provider.network.chainId 15 | // ).toHexString(), 16 | // }) 17 | // const path = './deployment.json' 18 | // console.log(`Writing to JSON at ${path}`) 19 | 20 | // // TODO: should append/check if previous entries 21 | // writeFileSync(path, contracts) 22 | 23 | // console.log('Done') 24 | // } 25 | 26 | // main() 27 | // .then(() => process.exit(0)) 28 | // .catch(error => { 29 | // console.error(error) 30 | // process.exit(1) 31 | // }) 32 | -------------------------------------------------------------------------------- /scripts/local-deployment/deployCreatorAndCreateTokenBridge.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs' 2 | import { setupTokenBridgeInLocalEnv } from './localDeploymentLib' 3 | 4 | async function main() { 5 | const { 6 | l1Network, 7 | l2Network, 8 | l1TokenBridgeCreatorAddress: l1TokenBridgeCreator, 9 | retryableSenderAddress: retryableSender, 10 | } = await setupTokenBridgeInLocalEnv() 11 | 12 | const NETWORK_FILE = 'network.json' 13 | fs.writeFileSync( 14 | NETWORK_FILE, 15 | JSON.stringify( 16 | { l1Network, l2Network, l1TokenBridgeCreator, retryableSender }, 17 | null, 18 | 2 19 | ) 20 | ) 21 | console.log(NETWORK_FILE + ' updated') 22 | } 23 | 24 | main().then(() => console.log('Done.')) 25 | -------------------------------------------------------------------------------- /scripts/signatures_test.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | output_dir="./test/signatures" 3 | for CONTRACTNAME in L1ERC20Gateway L1CustomGateway L1ReverseCustomGateway L1WethGateway L2ERC20Gateway L2CustomGateway L2ReverseCustomGateway L2WethGateway L1GatewayRouter L2GatewayRouter StandardArbERC20 L1AtomicTokenBridgeCreator L1TokenBridgeRetryableSender L2AtomicTokenBridgeFactory L1OrbitCustomGateway L1OrbitERC20Gateway L1OrbitGatewayRouter L1OrbitReverseCustomGateway L1USDCGateway L1OrbitUSDCGateway L2USDCGateway 4 | do 5 | echo "Checking for signature changes in $CONTRACTNAME" 6 | [ -f "$output_dir/$CONTRACTNAME" ] && mv "$output_dir/$CONTRACTNAME" "$output_dir/$CONTRACTNAME-old" 7 | forge inspect "$CONTRACTNAME" methods > "$output_dir/$CONTRACTNAME" 8 | diff "$output_dir/$CONTRACTNAME-old" "$output_dir/$CONTRACTNAME" 9 | if [[ $? != "0" ]] 10 | then 11 | CHANGED=1 12 | fi 13 | done 14 | if [[ $CHANGED == 1 ]] 15 | then 16 | exit 1 17 | fi -------------------------------------------------------------------------------- /scripts/storage_layout_test.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | output_dir="./test/storage" 3 | for CONTRACTNAME in L1ERC20Gateway L1CustomGateway L1ReverseCustomGateway L1WethGateway L2ERC20Gateway L2CustomGateway L2ReverseCustomGateway L2WethGateway L1GatewayRouter L2GatewayRouter StandardArbERC20 L1AtomicTokenBridgeCreator L1TokenBridgeRetryableSender L2AtomicTokenBridgeFactory L1OrbitCustomGateway L1OrbitERC20Gateway L1OrbitGatewayRouter L1OrbitReverseCustomGateway L1USDCGateway L1OrbitUSDCGateway L2USDCGateway 4 | do 5 | echo "Checking storage change of $CONTRACTNAME" 6 | [ -f "$output_dir/$CONTRACTNAME" ] && mv "$output_dir/$CONTRACTNAME" "$output_dir/$CONTRACTNAME-old" 7 | forge inspect "$CONTRACTNAME" --pretty storage > "$output_dir/$CONTRACTNAME" 8 | diff "$output_dir/$CONTRACTNAME-old" "$output_dir/$CONTRACTNAME" 9 | if [[ $? != "0" ]] 10 | then 11 | CHANGED=1 12 | fi 13 | done 14 | if [[ $CHANGED == 1 ]] 15 | then 16 | exit 1 17 | fi -------------------------------------------------------------------------------- /scripts/upgradeTemplate.ts: -------------------------------------------------------------------------------- 1 | import { JsonRpcProvider } from '@ethersproject/providers' 2 | import { L2AtomicTokenBridgeFactory__factory } from '../build/types' 3 | import dotenv from 'dotenv' 4 | import { Wallet } from 'ethers' 5 | 6 | dotenv.config() 7 | 8 | async function main() { 9 | const deployRpc = process.env['BASECHAIN_RPC'] as string 10 | if (deployRpc == undefined) { 11 | throw new Error("Env var 'BASECHAIN_RPC' not set") 12 | } 13 | const rpc = new JsonRpcProvider(deployRpc) 14 | 15 | const deployKey = process.env['BASECHAIN_DEPLOYER_KEY'] as string 16 | if (deployKey == undefined) { 17 | throw new Error("Env var 'BASECHAIN_DEPLOYER_KEY' not set") 18 | } 19 | const deployer = new Wallet(deployKey).connect(rpc) 20 | 21 | console.log( 22 | 'Deploying L2AtomicTokenBridgeFactory to chain', 23 | await deployer.getChainId() 24 | ) 25 | const l2TokenBridgeFactory = await new L2AtomicTokenBridgeFactory__factory( 26 | deployer 27 | ).deploy() 28 | await l2TokenBridgeFactory.deployed() 29 | 30 | console.log('l2TokenBridgeFactory:', l2TokenBridgeFactory.address) 31 | } 32 | 33 | main().then(() => console.log('Done.')) 34 | -------------------------------------------------------------------------------- /scripts/usdc-bridge-deployment/env.example: -------------------------------------------------------------------------------- 1 | PARENT_RPC= 2 | PARENT_DEPLOYER_KEY= 3 | CHILD_RPC= 4 | CHILD_DEPLOYER_KEY= 5 | L1_ROUTER= 6 | L2_ROUTER= 7 | INBOX= 8 | L1_USDC= 9 | ## OPTIONAL arg. If set, script will register the gateway, otherwise it will store TX payload in a file 10 | ROLLUP_OWNER_KEY= -------------------------------------------------------------------------------- /scripts/verify_upgrade.ts: -------------------------------------------------------------------------------- 1 | import { artifacts } from 'hardhat' 2 | 3 | import { 4 | getStorageLayout, 5 | assertUpgradeSafe, 6 | getContractVersion, 7 | assertStorageUpgradeSafe, 8 | solcInputOutputDecoder, 9 | validate, 10 | RunValidation, 11 | } from '@openzeppelin/upgrades-core' 12 | 13 | const oldContract = 'L1ERC20Gateway' 14 | const newContract = 'L2ERC20Gateway' 15 | 16 | const main = async () => { 17 | const validationContext = {} as RunValidation 18 | 19 | const contracts = (await artifacts.getAllFullyQualifiedNames()).filter( 20 | curr => curr.includes(oldContract) || curr.includes(newContract) 21 | ) 22 | 23 | if (contracts.length < 1) { 24 | throw new Error("Can't find artifacts for contracts") 25 | } 26 | 27 | for (const contract of contracts) { 28 | const buildInfo = await artifacts.getBuildInfo(contract) 29 | if (buildInfo === undefined) { 30 | throw new Error(`Build info not found for contract ${contract}`) 31 | } 32 | const solcOutput = buildInfo.output 33 | const solcInput = buildInfo.input 34 | const decodeSrc = solcInputOutputDecoder(solcInput, solcOutput) 35 | Object.assign(validationContext, validate(solcOutput, decodeSrc)) 36 | } 37 | 38 | console.log(`Looking at ${oldContract} and ${newContract}`) 39 | 40 | const oldVersion = getContractVersion(validationContext, oldContract) 41 | const newVersion = getContractVersion(validationContext, newContract) 42 | 43 | // verifies for errors such as setting arguments in constructors 44 | assertUpgradeSafe([validationContext], oldVersion, { kind: 'transparent' }) 45 | assertUpgradeSafe([validationContext], newVersion, { kind: 'transparent' }) 46 | 47 | const oldStorage = getStorageLayout(validationContext, oldVersion) 48 | const newStorage = getStorageLayout(validationContext, newVersion) 49 | 50 | // verifies that storage layouts match 51 | assertStorageUpgradeSafe(oldStorage, newStorage) 52 | 53 | console.log('Upgrade validation complete, all is good.') 54 | } 55 | 56 | main() 57 | .then(() => process.exit(0)) 58 | .catch(error => { 59 | console.error(error) 60 | process.exit(1) 61 | }) 62 | -------------------------------------------------------------------------------- /slither.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "exclude_dependencies": true, 3 | "exclude_informational": true, 4 | "exclude_low": true, 5 | "exclude_optimization": true, 6 | "filter_paths": "contracts/tokenbridge/test|node_modules/" 7 | } 8 | -------------------------------------------------------------------------------- /tasks/compareBytecode.ts: -------------------------------------------------------------------------------- 1 | import { task } from "hardhat/config"; 2 | import { ethers } from "ethers"; 3 | import "@nomiclabs/hardhat-etherscan" 4 | import { Bytecode } from "@nomiclabs/hardhat-etherscan/dist/src/solc/bytecode" 5 | import { TASK_VERIFY_GET_CONTRACT_INFORMATION, TASK_VERIFY_GET_COMPILER_VERSIONS, TASK_VERIFY_GET_LIBRARIES } from "@nomiclabs/hardhat-etherscan/dist/src/constants" 6 | import fs from "fs"; 7 | 8 | task("compareBytecode", "Compares deployed bytecode with local builds") 9 | .addParam("contractAddrs", "A comma-separated list of deployed contract addresses") 10 | .setAction(async ({ contractAddrs }, hre) => { 11 | const addresses = contractAddrs.split(','); 12 | 13 | // Get all local contract artifact paths 14 | const artifactPaths = await hre.artifacts.getArtifactPaths(); 15 | 16 | for (const contractAddr of addresses) { 17 | 18 | // Fetch deployed contract bytecode 19 | const deployedBytecode = await hre.ethers.provider.getCode(contractAddr.trim()); 20 | const deployedCodeHash = ethers.utils.keccak256(deployedBytecode); 21 | let matchFound = false; 22 | 23 | for (const artifactPath of artifactPaths) { 24 | const artifact = JSON.parse(fs.readFileSync(artifactPath, "utf8")); 25 | if (artifact.deployedBytecode) { 26 | const localCodeHash = ethers.utils.keccak256(artifact.deployedBytecode); 27 | 28 | // Compare codehashes 29 | if (deployedCodeHash === localCodeHash) { 30 | console.log(`Contract Address ${contractAddr.trim()} matches with ${artifact.contractName}`); 31 | matchFound = true; 32 | break; 33 | } 34 | } 35 | } 36 | 37 | if (!matchFound) { 38 | const deployedBytecodeHex = deployedBytecode.startsWith("0x") 39 | ? deployedBytecode.slice(2) 40 | : deployedBytecode; 41 | try { 42 | const info = await hre.run(TASK_VERIFY_GET_CONTRACT_INFORMATION, { 43 | deployedBytecode: new Bytecode(deployedBytecodeHex), 44 | matchingCompilerVersions: await hre.run( 45 | TASK_VERIFY_GET_COMPILER_VERSIONS 46 | ), 47 | libraries: await hre.run(TASK_VERIFY_GET_LIBRARIES), 48 | }) 49 | console.log(`Contract Address ${contractAddr.trim()} matches with ${info.contractName} without checking constructor arguments`); 50 | } catch (error) { 51 | console.log(`No matching contract found for address ${contractAddr.trim()}`); 52 | } 53 | } 54 | } 55 | }); 56 | 57 | export default {}; 58 | -------------------------------------------------------------------------------- /tasks/peripheralsTasks.ts: -------------------------------------------------------------------------------- 1 | import { task } from 'hardhat/config' 2 | import { initUpgrades } from '.' 3 | 4 | task('deploy-logic-one', 'deploy one logic') 5 | .addParam('contract', 'contract to deploy') 6 | .setAction(async (args, hre) => { 7 | const { contract } = args 8 | const { deployLogic } = initUpgrades(hre, process.cwd()) 9 | await deployLogic(contract) 10 | }) 11 | 12 | task('deploy-logic-all', 'deploy all logic contracts').setAction( 13 | async (_, hre) => { 14 | const { deployLogicAll } = initUpgrades(hre, process.cwd()) 15 | await deployLogicAll() 16 | } 17 | ) 18 | 19 | task('trigger-upgrades', 'triggers upgrade').setAction(async (_, hre) => { 20 | const { updateImplementations } = initUpgrades(hre, process.cwd()) 21 | await updateImplementations() 22 | }) 23 | 24 | task('verify-deployments', 'verifies implementations').setAction( 25 | async (_, hre) => { 26 | const { verifyCurrentImplementations } = initUpgrades(hre, process.cwd()) 27 | await verifyCurrentImplementations() 28 | } 29 | ) 30 | 31 | task('transfer-owner', 'deploy one logic') 32 | .addParam('proxyaddress', 'proxy address') 33 | .addParam('newadmin', 'address of new admin') 34 | .setAction(async (args, hre) => { 35 | const { contract } = args 36 | const { transferAdmin } = initUpgrades(hre, process.cwd()) 37 | await transferAdmin(args.proxyaddress, args.newadmin) 38 | }) 39 | 40 | task( 41 | 'remove-build-info', 42 | 'remove giant build info string from current_deployments json' 43 | ).setAction(async (_, hre) => { 44 | const { removeBuildInfoFiles } = initUpgrades(hre, process.cwd()) 45 | await removeBuildInfoFiles() 46 | }) 47 | 48 | task('etherscan-verify', 'verify current deployments in etherscan').setAction( 49 | async (_, hre) => { 50 | const { verifyDeployments } = await initUpgrades(hre, process.cwd()) 51 | await verifyDeployments() 52 | } 53 | ) 54 | -------------------------------------------------------------------------------- /test-foundry/GatewayRouter.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "forge-std/Test.sol"; 6 | import { GatewayRouter } from "contracts/tokenbridge/libraries/gateway/GatewayRouter.sol"; 7 | import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 8 | 9 | abstract contract GatewayRouterTest is Test { 10 | GatewayRouter public router; 11 | address public defaultGateway; 12 | 13 | // retryable params 14 | uint256 public maxSubmissionCost; 15 | uint256 public maxGas = 1000000000; 16 | uint256 public gasPriceBid = 3; 17 | uint256 public retryableCost; 18 | address public creditBackAddress = makeAddr("creditBackAddress"); 19 | 20 | /* solhint-disable func-name-mixedcase */ 21 | function test_getGateway_DefaultGateway(address token) public { 22 | address gateway = router.getGateway(token); 23 | assertEq(gateway, defaultGateway, "Invalid gateway"); 24 | } 25 | 26 | function test_finalizeInboundTransfer() public { 27 | vm.expectRevert("ONLY_OUTBOUND_ROUTER"); 28 | router.finalizeInboundTransfer(address(1), address(2), address(3), 0, ""); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test-foundry/IOwnable.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/nitro/blob/master/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | // solhint-disable-next-line compiler-version 6 | pragma solidity >=0.4.21 <0.9.0; 7 | 8 | interface IOwnable { 9 | function owner() external view returns (address); 10 | } 11 | -------------------------------------------------------------------------------- /test-foundry/L2ArbitrumGateway.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "forge-std/Test.sol"; 6 | 7 | import {L2ArbitrumGateway} from "contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol"; 8 | import {ArbSysMock} from "contracts/tokenbridge/test/ArbSysMock.sol"; 9 | import {ITokenGateway} from "contracts/tokenbridge/libraries/gateway/ITokenGateway.sol"; 10 | 11 | abstract contract L2ArbitrumGatewayTest is Test { 12 | L2ArbitrumGateway public l2Gateway; 13 | ArbSysMock public arbSysMock = new ArbSysMock(); 14 | 15 | address public router = makeAddr("router"); 16 | address public l1Counterpart = makeAddr("l1Counterpart"); 17 | 18 | // token transfer params 19 | address public receiver = makeAddr("to"); 20 | address public sender = makeAddr("from"); 21 | uint256 public amount = 2400; 22 | 23 | /* solhint-disable func-name-mixedcase */ 24 | function test_getOutboundCalldata() public { 25 | address token = makeAddr("token"); 26 | bytes memory data = new bytes(340); 27 | 28 | bytes memory expected = abi.encodeWithSelector( 29 | ITokenGateway.finalizeInboundTransfer.selector, 30 | token, 31 | sender, 32 | receiver, 33 | amount, 34 | abi.encode(0, data) 35 | ); 36 | bytes memory actual = l2Gateway.getOutboundCalldata(token, sender, receiver, amount, data); 37 | 38 | assertEq(actual, expected, "Invalid outbound calldata"); 39 | } 40 | 41 | function test_finalizeInboundTransfer() public virtual; 42 | function test_finalizeInboundTransfer_WithCallHook() public virtual; 43 | 44 | function test_outboundTransfer() public virtual; 45 | 46 | function test_outboundTransfer_4Args() public virtual; 47 | 48 | function test_outboundTransfer_revert_ExtraDataDisabled() public { 49 | vm.expectRevert("EXTRA_DATA_DISABLED"); 50 | bytes memory extraData = new bytes(0x1234); 51 | l2Gateway.outboundTransfer(address(100), address(101), 200, 0, 0, extraData); 52 | } 53 | 54 | function test_outboundTransfer_revert_NoValue() public { 55 | vm.expectRevert("NO_VALUE"); 56 | l2Gateway.outboundTransfer{value: 1 ether}( 57 | address(100), address(101), 200, 0, 0, new bytes(0) 58 | ); 59 | } 60 | 61 | function test_outboundTransfer_revert_NotExpectedL1Token() public virtual; 62 | 63 | function test_outboundTransfer_revert_TokenNotDeployed() public { 64 | address token = makeAddr("someToken"); 65 | vm.expectRevert("TOKEN_NOT_DEPLOYED"); 66 | l2Gateway.outboundTransfer(token, address(101), 200, 0, 0, new bytes(0)); 67 | } 68 | 69 | //// 70 | // Event declarations 71 | //// 72 | event DepositFinalized( 73 | address indexed l1Token, address indexed _from, address indexed _receiver, uint256 _amount 74 | ); 75 | 76 | event WithdrawalInitiated( 77 | address l1Token, 78 | address indexed _from, 79 | address indexed _receiver, 80 | uint256 indexed _l2ToL1Id, 81 | uint256 _exitNum, 82 | uint256 _amount 83 | ); 84 | 85 | event TxToL1( 86 | address indexed _from, address indexed _receiver, uint256 indexed _id, bytes _data 87 | ); 88 | } 89 | -------------------------------------------------------------------------------- /test-foundry/util/TestUtil.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | pragma solidity ^0.8.4; 3 | 4 | import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 5 | import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; 6 | 7 | library TestUtil { 8 | function deployProxy(address logic) public returns (address) { 9 | ProxyAdmin pa = new ProxyAdmin(); 10 | return address(new TransparentUpgradeableProxy(address(logic), address(pa), "")); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /test-mutation/all-configs/config.single.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "filename": "../contracts/tokenbridge/ethereum/gateway/L1ERC20Gateway.sol", 4 | "sourceroot": "..", 5 | "solc_remappings": [ 6 | "@openzeppelin=../node_modules/@openzeppelin", 7 | "@arbitrum=../node_modules/@arbitrum" 8 | ] 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /test-mutation/all-configs/config.tokenbridge-arbitrum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "filename": "../contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol", 4 | "sourceroot": "..", 5 | "solc_remappings": [ 6 | "@openzeppelin=../node_modules/@openzeppelin", 7 | "@arbitrum=../node_modules/@arbitrum" 8 | ] 9 | }, 10 | { 11 | "filename": "../contracts/tokenbridge/arbitrum/gateway/L2CustomGateway.sol", 12 | "sourceroot": "..", 13 | "solc_remappings": [ 14 | "@openzeppelin=../node_modules/@openzeppelin", 15 | "@arbitrum=../node_modules/@arbitrum" 16 | ] 17 | }, 18 | { 19 | "filename": "../contracts/tokenbridge/arbitrum/gateway/L2ERC20Gateway.sol", 20 | "sourceroot": "..", 21 | "solc_remappings": [ 22 | "@openzeppelin=../node_modules/@openzeppelin", 23 | "@arbitrum=../node_modules/@arbitrum" 24 | ] 25 | }, 26 | { 27 | "filename": "../contracts/tokenbridge/arbitrum/gateway/L2GatewayRouter.sol", 28 | "sourceroot": "..", 29 | "solc_remappings": [ 30 | "@openzeppelin=../node_modules/@openzeppelin", 31 | "@arbitrum=../node_modules/@arbitrum" 32 | ] 33 | }, 34 | { 35 | "filename": "../contracts/tokenbridge/arbitrum/gateway/L2ReverseCustomGateway.sol", 36 | "sourceroot": "..", 37 | "solc_remappings": [ 38 | "@openzeppelin=../node_modules/@openzeppelin", 39 | "@arbitrum=../node_modules/@arbitrum" 40 | ] 41 | }, 42 | { 43 | "filename": "../contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", 44 | "sourceroot": "..", 45 | "solc_remappings": [ 46 | "@openzeppelin=../node_modules/@openzeppelin", 47 | "@arbitrum=../node_modules/@arbitrum" 48 | ] 49 | }, 50 | { 51 | "filename": "../contracts/tokenbridge/arbitrum/L2ArbitrumMessenger.sol", 52 | "sourceroot": "..", 53 | "solc_remappings": [ 54 | "@openzeppelin=../node_modules/@openzeppelin", 55 | "@arbitrum=../node_modules/@arbitrum" 56 | ] 57 | }, 58 | { 59 | "filename": "../contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", 60 | "sourceroot": "..", 61 | "solc_remappings": [ 62 | "@openzeppelin=../node_modules/@openzeppelin", 63 | "@arbitrum=../node_modules/@arbitrum" 64 | ] 65 | }, 66 | { 67 | "filename": "../contracts/tokenbridge/arbitrum/ReverseArbToken.sol", 68 | "sourceroot": "..", 69 | "solc_remappings": [ 70 | "@openzeppelin=../node_modules/@openzeppelin", 71 | "@arbitrum=../node_modules/@arbitrum" 72 | ] 73 | }, 74 | { 75 | "filename": "../contracts/tokenbridge/arbitrum/StandardArbERC20.sol", 76 | "sourceroot": "..", 77 | "solc_remappings": [ 78 | "@openzeppelin=../node_modules/@openzeppelin", 79 | "@arbitrum=../node_modules/@arbitrum" 80 | ] 81 | } 82 | ] 83 | -------------------------------------------------------------------------------- /test-mutation/all-configs/config.tokenbridge-ethereum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "filename": "../contracts/tokenbridge/ethereum/L1ArbitrumMessenger.sol", 4 | "sourceroot": "..", 5 | "solc_remappings": [ 6 | "@openzeppelin=../node_modules/@openzeppelin", 7 | "@arbitrum=../node_modules/@arbitrum" 8 | ] 9 | }, 10 | { 11 | "filename": "../contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", 12 | "sourceroot": "..", 13 | "solc_remappings": [ 14 | "@openzeppelin=../node_modules/@openzeppelin", 15 | "@arbitrum=../node_modules/@arbitrum" 16 | ] 17 | }, 18 | { 19 | "filename": "../contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", 20 | "sourceroot": "..", 21 | "solc_remappings": [ 22 | "@openzeppelin=../node_modules/@openzeppelin", 23 | "@arbitrum=../node_modules/@arbitrum" 24 | ] 25 | }, 26 | { 27 | "filename": "../contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol", 28 | "sourceroot": "..", 29 | "solc_remappings": [ 30 | "@openzeppelin=../node_modules/@openzeppelin", 31 | "@arbitrum=../node_modules/@arbitrum" 32 | ] 33 | }, 34 | { 35 | "filename": "../contracts/tokenbridge/ethereum/gateway/L1ERC20Gateway.sol", 36 | "sourceroot": "..", 37 | "solc_remappings": [ 38 | "@openzeppelin=../node_modules/@openzeppelin", 39 | "@arbitrum=../node_modules/@arbitrum" 40 | ] 41 | }, 42 | { 43 | "filename": "../contracts/tokenbridge/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol", 44 | "sourceroot": "..", 45 | "solc_remappings": [ 46 | "@openzeppelin=../node_modules/@openzeppelin", 47 | "@arbitrum=../node_modules/@arbitrum" 48 | ] 49 | }, 50 | { 51 | "filename": "../contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol", 52 | "sourceroot": "..", 53 | "solc_remappings": [ 54 | "@openzeppelin=../node_modules/@openzeppelin", 55 | "@arbitrum=../node_modules/@arbitrum" 56 | ] 57 | }, 58 | { 59 | "filename": "../contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol", 60 | "sourceroot": "..", 61 | "solc_remappings": [ 62 | "@openzeppelin=../node_modules/@openzeppelin", 63 | "@arbitrum=../node_modules/@arbitrum" 64 | ] 65 | }, 66 | { 67 | "filename": "../contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol", 68 | "sourceroot": "..", 69 | "solc_remappings": [ 70 | "@openzeppelin=../node_modules/@openzeppelin", 71 | "@arbitrum=../node_modules/@arbitrum" 72 | ] 73 | }, 74 | { 75 | "filename": "../contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol", 76 | "sourceroot": "..", 77 | "solc_remappings": [ 78 | "@openzeppelin=../node_modules/@openzeppelin", 79 | "@arbitrum=../node_modules/@arbitrum" 80 | ] 81 | }, 82 | { 83 | "filename": "../contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol", 84 | "sourceroot": "..", 85 | "solc_remappings": [ 86 | "@openzeppelin=../node_modules/@openzeppelin", 87 | "@arbitrum=../node_modules/@arbitrum" 88 | ] 89 | }, 90 | { 91 | "filename": "../contracts/tokenbridge/ethereum/gateway/L1ReverseCustomGateway.sol", 92 | "sourceroot": "..", 93 | "solc_remappings": [ 94 | "@openzeppelin=../node_modules/@openzeppelin", 95 | "@arbitrum=../node_modules/@arbitrum" 96 | ] 97 | }, 98 | { 99 | "filename": "../contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", 100 | "sourceroot": "..", 101 | "solc_remappings": [ 102 | "@openzeppelin=../node_modules/@openzeppelin", 103 | "@arbitrum=../node_modules/@arbitrum" 104 | ] 105 | } 106 | ] 107 | -------------------------------------------------------------------------------- /test-mutation/config.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "filename": "../contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol", 4 | "sourceroot": "..", 5 | "solc_remappings": [ 6 | "@openzeppelin=../node_modules/@openzeppelin", 7 | "@arbitrum=../node_modules/@arbitrum" 8 | ] 9 | }, 10 | { 11 | "filename": "../contracts/tokenbridge/arbitrum/gateway/L2CustomGateway.sol", 12 | "sourceroot": "..", 13 | "solc_remappings": [ 14 | "@openzeppelin=../node_modules/@openzeppelin", 15 | "@arbitrum=../node_modules/@arbitrum" 16 | ] 17 | }, 18 | { 19 | "filename": "../contracts/tokenbridge/arbitrum/gateway/L2ERC20Gateway.sol", 20 | "sourceroot": "..", 21 | "solc_remappings": [ 22 | "@openzeppelin=../node_modules/@openzeppelin", 23 | "@arbitrum=../node_modules/@arbitrum" 24 | ] 25 | }, 26 | { 27 | "filename": "../contracts/tokenbridge/arbitrum/gateway/L2GatewayRouter.sol", 28 | "sourceroot": "..", 29 | "solc_remappings": [ 30 | "@openzeppelin=../node_modules/@openzeppelin", 31 | "@arbitrum=../node_modules/@arbitrum" 32 | ] 33 | }, 34 | { 35 | "filename": "../contracts/tokenbridge/arbitrum/gateway/L2ReverseCustomGateway.sol", 36 | "sourceroot": "..", 37 | "solc_remappings": [ 38 | "@openzeppelin=../node_modules/@openzeppelin", 39 | "@arbitrum=../node_modules/@arbitrum" 40 | ] 41 | }, 42 | { 43 | "filename": "../contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", 44 | "sourceroot": "..", 45 | "solc_remappings": [ 46 | "@openzeppelin=../node_modules/@openzeppelin", 47 | "@arbitrum=../node_modules/@arbitrum" 48 | ] 49 | }, 50 | { 51 | "filename": "../contracts/tokenbridge/arbitrum/L2ArbitrumMessenger.sol", 52 | "sourceroot": "..", 53 | "solc_remappings": [ 54 | "@openzeppelin=../node_modules/@openzeppelin", 55 | "@arbitrum=../node_modules/@arbitrum" 56 | ] 57 | }, 58 | { 59 | "filename": "../contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", 60 | "sourceroot": "..", 61 | "solc_remappings": [ 62 | "@openzeppelin=../node_modules/@openzeppelin", 63 | "@arbitrum=../node_modules/@arbitrum" 64 | ] 65 | }, 66 | { 67 | "filename": "../contracts/tokenbridge/arbitrum/ReverseArbToken.sol", 68 | "sourceroot": "..", 69 | "solc_remappings": [ 70 | "@openzeppelin=../node_modules/@openzeppelin", 71 | "@arbitrum=../node_modules/@arbitrum" 72 | ] 73 | }, 74 | { 75 | "filename": "../contracts/tokenbridge/arbitrum/StandardArbERC20.sol", 76 | "sourceroot": "..", 77 | "solc_remappings": [ 78 | "@openzeppelin=../node_modules/@openzeppelin", 79 | "@arbitrum=../node_modules/@arbitrum" 80 | ] 81 | } 82 | ] 83 | -------------------------------------------------------------------------------- /test/signatures/L1AtomicTokenBridgeCreator: -------------------------------------------------------------------------------- 1 | { 2 | "canonicalL2FactoryAddress()": "bfd3e518", 3 | "createTokenBridge(address,address,uint256,uint256)": "8277742b", 4 | "gasLimitForL2FactoryDeployment()": "888139d4", 5 | "getRouter(address)": "8369166d", 6 | "inboxToL1Deployment(address)": "d9ce0ef9", 7 | "inboxToL2Deployment(address)": "46052706", 8 | "initialize(address)": "c4d66de8", 9 | "l1Multicall()": "b1460a71", 10 | "l1Templates()": "a5595da9", 11 | "l1Weth()": "146bf4b1", 12 | "l2CustomGatewayTemplate()": "41083186", 13 | "l2MulticallTemplate()": "8c99e31c", 14 | "l2RouterTemplate()": "381c9d99", 15 | "l2StandardGatewayTemplate()": "d7eee6ca", 16 | "l2TokenBridgeFactoryTemplate()": "1aeef2e2", 17 | "l2WethGatewayTemplate()": "9095765e", 18 | "l2WethTemplate()": "fd40ad85", 19 | "owner()": "8da5cb5b", 20 | "renounceOwnership()": "715018a6", 21 | "retryableSender()": "36dddb97", 22 | "setDeployment(address,(address,address,address,address,address),(address,address,address,address,address,address,address,address,address))": "4c149671", 23 | "setTemplates((address,address,address,address,address,address,address,address),address,address,address,address,address,address,address,address,address,uint256)": "81fb9184", 24 | "transferOwnership(address)": "f2fde38b" 25 | } 26 | -------------------------------------------------------------------------------- /test/signatures/L1CustomGateway: -------------------------------------------------------------------------------- 1 | { 2 | "calculateL2TokenAddress(address)": "a7e28d48", 3 | "counterpartGateway()": "2db09c1c", 4 | "encodeWithdrawal(uint256,address)": "020a6058", 5 | "finalizeInboundTransfer(address,address,address,uint256,bytes)": "2e567b36", 6 | "forceRegisterTokenToL2(address[],address[],uint256,uint256,uint256)": "1d3a689f", 7 | "getExternalCall(uint256,address,bytes)": "f68a9082", 8 | "getOutboundCalldata(address,address,address,uint256,bytes)": "a0c76a96", 9 | "inbox()": "fb0e722b", 10 | "initialize(address,address,address,address)": "f8c8765e", 11 | "l1ToL2Token(address)": "8a2dc014", 12 | "outboundTransfer(address,address,uint256,uint256,uint256,bytes)": "d2ce7d65", 13 | "outboundTransferCustomRefund(address,address,address,uint256,uint256,uint256,bytes)": "4fb1a07b", 14 | "owner()": "8da5cb5b", 15 | "postUpgradeInit()": "95fcea78", 16 | "redirectedExits(bytes32)": "bcf2e6eb", 17 | "registerTokenToL2(address,uint256,uint256,uint256)": "f26bdead", 18 | "registerTokenToL2(address,uint256,uint256,uint256,address)": "ca346d4a", 19 | "router()": "f887ea40", 20 | "setOwner(address)": "13af4035", 21 | "supportsInterface(bytes4)": "01ffc9a7", 22 | "transferExitAndCall(uint256,address,address,bytes,bytes)": "bd5f3e7d", 23 | "whitelist()": "93e59dc1" 24 | } 25 | -------------------------------------------------------------------------------- /test/signatures/L1ERC20Gateway: -------------------------------------------------------------------------------- 1 | { 2 | "calculateL2TokenAddress(address)": "a7e28d48", 3 | "cloneableProxyHash()": "97881f8d", 4 | "counterpartGateway()": "2db09c1c", 5 | "encodeWithdrawal(uint256,address)": "020a6058", 6 | "finalizeInboundTransfer(address,address,address,uint256,bytes)": "2e567b36", 7 | "getExternalCall(uint256,address,bytes)": "f68a9082", 8 | "getOutboundCalldata(address,address,address,uint256,bytes)": "a0c76a96", 9 | "inbox()": "fb0e722b", 10 | "initialize(address,address,address,bytes32,address)": "a01893bf", 11 | "l2BeaconProxyFactory()": "70fc045f", 12 | "outboundTransfer(address,address,uint256,uint256,uint256,bytes)": "d2ce7d65", 13 | "outboundTransferCustomRefund(address,address,address,uint256,uint256,uint256,bytes)": "4fb1a07b", 14 | "postUpgradeInit()": "95fcea78", 15 | "redirectedExits(bytes32)": "bcf2e6eb", 16 | "router()": "f887ea40", 17 | "supportsInterface(bytes4)": "01ffc9a7", 18 | "transferExitAndCall(uint256,address,address,bytes,bytes)": "bd5f3e7d", 19 | "whitelist()": "93e59dc1" 20 | } 21 | -------------------------------------------------------------------------------- /test/signatures/L1GatewayRouter: -------------------------------------------------------------------------------- 1 | { 2 | "calculateL2TokenAddress(address)": "a7e28d48", 3 | "counterpartGateway()": "2db09c1c", 4 | "defaultGateway()": "03295802", 5 | "finalizeInboundTransfer(address,address,address,uint256,bytes)": "2e567b36", 6 | "getGateway(address)": "bda009fe", 7 | "getOutboundCalldata(address,address,address,uint256,bytes)": "a0c76a96", 8 | "inbox()": "fb0e722b", 9 | "initialize(address,address,address,address,address)": "1459457a", 10 | "l1TokenToGateway(address)": "ed08fdc6", 11 | "outboundTransfer(address,address,uint256,uint256,uint256,bytes)": "d2ce7d65", 12 | "outboundTransferCustomRefund(address,address,address,uint256,uint256,uint256,bytes)": "4fb1a07b", 13 | "owner()": "8da5cb5b", 14 | "postUpgradeInit()": "95fcea78", 15 | "router()": "f887ea40", 16 | "setDefaultGateway(address,uint256,uint256,uint256)": "5625a952", 17 | "setGateway(address,uint256,uint256,uint256)": "dd614569", 18 | "setGateway(address,uint256,uint256,uint256,address)": "2d67b72d", 19 | "setGateways(address[],address[],uint256,uint256,uint256)": "658b53f4", 20 | "setOwner(address)": "13af4035", 21 | "supportsInterface(bytes4)": "01ffc9a7", 22 | "updateWhitelistSource(address)": "47466f98", 23 | "whitelist()": "93e59dc1" 24 | } 25 | -------------------------------------------------------------------------------- /test/signatures/L1OrbitCustomGateway: -------------------------------------------------------------------------------- 1 | { 2 | "calculateL2TokenAddress(address)": "a7e28d48", 3 | "counterpartGateway()": "2db09c1c", 4 | "encodeWithdrawal(uint256,address)": "020a6058", 5 | "finalizeInboundTransfer(address,address,address,uint256,bytes)": "2e567b36", 6 | "forceRegisterTokenToL2(address[],address[],uint256,uint256,uint256)": "1d3a689f", 7 | "forceRegisterTokenToL2(address[],address[],uint256,uint256,uint256,uint256)": "85f25597", 8 | "getExternalCall(uint256,address,bytes)": "f68a9082", 9 | "getOutboundCalldata(address,address,address,uint256,bytes)": "a0c76a96", 10 | "inbox()": "fb0e722b", 11 | "initialize(address,address,address,address)": "f8c8765e", 12 | "l1ToL2Token(address)": "8a2dc014", 13 | "outboundTransfer(address,address,uint256,uint256,uint256,bytes)": "d2ce7d65", 14 | "outboundTransferCustomRefund(address,address,address,uint256,uint256,uint256,bytes)": "4fb1a07b", 15 | "owner()": "8da5cb5b", 16 | "postUpgradeInit()": "95fcea78", 17 | "redirectedExits(bytes32)": "bcf2e6eb", 18 | "registerTokenToL2(address,uint256,uint256,uint256)": "f26bdead", 19 | "registerTokenToL2(address,uint256,uint256,uint256,address)": "ca346d4a", 20 | "registerTokenToL2(address,uint256,uint256,uint256,address,uint256)": "37daacad", 21 | "registerTokenToL2(address,uint256,uint256,uint256,uint256)": "3e8ee3df", 22 | "router()": "f887ea40", 23 | "setOwner(address)": "13af4035", 24 | "supportsInterface(bytes4)": "01ffc9a7", 25 | "transferExitAndCall(uint256,address,address,bytes,bytes)": "bd5f3e7d", 26 | "whitelist()": "93e59dc1" 27 | } 28 | -------------------------------------------------------------------------------- /test/signatures/L1OrbitERC20Gateway: -------------------------------------------------------------------------------- 1 | { 2 | "calculateL2TokenAddress(address)": "a7e28d48", 3 | "cloneableProxyHash()": "97881f8d", 4 | "counterpartGateway()": "2db09c1c", 5 | "encodeWithdrawal(uint256,address)": "020a6058", 6 | "finalizeInboundTransfer(address,address,address,uint256,bytes)": "2e567b36", 7 | "getExternalCall(uint256,address,bytes)": "f68a9082", 8 | "getOutboundCalldata(address,address,address,uint256,bytes)": "a0c76a96", 9 | "inbox()": "fb0e722b", 10 | "initialize(address,address,address,bytes32,address)": "a01893bf", 11 | "l2BeaconProxyFactory()": "70fc045f", 12 | "outboundTransfer(address,address,uint256,uint256,uint256,bytes)": "d2ce7d65", 13 | "outboundTransferCustomRefund(address,address,address,uint256,uint256,uint256,bytes)": "4fb1a07b", 14 | "postUpgradeInit()": "95fcea78", 15 | "redirectedExits(bytes32)": "bcf2e6eb", 16 | "router()": "f887ea40", 17 | "supportsInterface(bytes4)": "01ffc9a7", 18 | "transferExitAndCall(uint256,address,address,bytes,bytes)": "bd5f3e7d", 19 | "whitelist()": "93e59dc1" 20 | } 21 | -------------------------------------------------------------------------------- /test/signatures/L1OrbitGatewayRouter: -------------------------------------------------------------------------------- 1 | { 2 | "calculateL2TokenAddress(address)": "a7e28d48", 3 | "counterpartGateway()": "2db09c1c", 4 | "defaultGateway()": "03295802", 5 | "finalizeInboundTransfer(address,address,address,uint256,bytes)": "2e567b36", 6 | "getGateway(address)": "bda009fe", 7 | "getOutboundCalldata(address,address,address,uint256,bytes)": "a0c76a96", 8 | "inbox()": "fb0e722b", 9 | "initialize(address,address,address,address,address)": "1459457a", 10 | "l1TokenToGateway(address)": "ed08fdc6", 11 | "outboundTransfer(address,address,uint256,uint256,uint256,bytes)": "d2ce7d65", 12 | "outboundTransferCustomRefund(address,address,address,uint256,uint256,uint256,bytes)": "4fb1a07b", 13 | "owner()": "8da5cb5b", 14 | "postUpgradeInit()": "95fcea78", 15 | "router()": "f887ea40", 16 | "setDefaultGateway(address,uint256,uint256,uint256)": "5625a952", 17 | "setDefaultGateway(address,uint256,uint256,uint256,uint256)": "c9a96997", 18 | "setGateway(address,uint256,uint256,uint256)": "dd614569", 19 | "setGateway(address,uint256,uint256,uint256,address)": "2d67b72d", 20 | "setGateway(address,uint256,uint256,uint256,address,uint256)": "d7f7459c", 21 | "setGateway(address,uint256,uint256,uint256,uint256)": "dc121927", 22 | "setGateways(address[],address[],uint256,uint256,uint256)": "658b53f4", 23 | "setGateways(address[],address[],uint256,uint256,uint256,uint256)": "55654af8", 24 | "setOwner(address)": "13af4035", 25 | "supportsInterface(bytes4)": "01ffc9a7", 26 | "updateWhitelistSource(address)": "47466f98", 27 | "whitelist()": "93e59dc1" 28 | } 29 | -------------------------------------------------------------------------------- /test/signatures/L1OrbitReverseCustomGateway: -------------------------------------------------------------------------------- 1 | { 2 | "calculateL2TokenAddress(address)": "a7e28d48", 3 | "counterpartGateway()": "2db09c1c", 4 | "encodeWithdrawal(uint256,address)": "020a6058", 5 | "finalizeInboundTransfer(address,address,address,uint256,bytes)": "2e567b36", 6 | "forceRegisterTokenToL2(address[],address[],uint256,uint256,uint256)": "1d3a689f", 7 | "forceRegisterTokenToL2(address[],address[],uint256,uint256,uint256,uint256)": "85f25597", 8 | "getExternalCall(uint256,address,bytes)": "f68a9082", 9 | "getOutboundCalldata(address,address,address,uint256,bytes)": "a0c76a96", 10 | "inbox()": "fb0e722b", 11 | "initialize(address,address,address,address)": "f8c8765e", 12 | "l1ToL2Token(address)": "8a2dc014", 13 | "outboundTransfer(address,address,uint256,uint256,uint256,bytes)": "d2ce7d65", 14 | "outboundTransferCustomRefund(address,address,address,uint256,uint256,uint256,bytes)": "4fb1a07b", 15 | "owner()": "8da5cb5b", 16 | "postUpgradeInit()": "95fcea78", 17 | "redirectedExits(bytes32)": "bcf2e6eb", 18 | "registerTokenToL2(address,uint256,uint256,uint256)": "f26bdead", 19 | "registerTokenToL2(address,uint256,uint256,uint256,address)": "ca346d4a", 20 | "registerTokenToL2(address,uint256,uint256,uint256,address,uint256)": "37daacad", 21 | "registerTokenToL2(address,uint256,uint256,uint256,uint256)": "3e8ee3df", 22 | "router()": "f887ea40", 23 | "setOwner(address)": "13af4035", 24 | "supportsInterface(bytes4)": "01ffc9a7", 25 | "transferExitAndCall(uint256,address,address,bytes,bytes)": "bd5f3e7d", 26 | "whitelist()": "93e59dc1" 27 | } 28 | -------------------------------------------------------------------------------- /test/signatures/L1OrbitUSDCGateway: -------------------------------------------------------------------------------- 1 | { 2 | "burnAmount()": "486a7e6b", 3 | "burnLockedUSDC()": "8a5e52bb", 4 | "burner()": "27810b6e", 5 | "calculateL2TokenAddress(address)": "a7e28d48", 6 | "counterpartGateway()": "2db09c1c", 7 | "depositsPaused()": "60da3e83", 8 | "encodeWithdrawal(uint256,address)": "020a6058", 9 | "finalizeInboundTransfer(address,address,address,uint256,bytes)": "2e567b36", 10 | "getExternalCall(uint256,address,bytes)": "f68a9082", 11 | "getOutboundCalldata(address,address,address,uint256,bytes)": "a0c76a96", 12 | "inbox()": "fb0e722b", 13 | "initialize(address,address,address,address,address,address)": "cc2a9a5b", 14 | "l1USDC()": "a6f73669", 15 | "l2USDC()": "29e96f9e", 16 | "outboundTransfer(address,address,uint256,uint256,uint256,bytes)": "d2ce7d65", 17 | "outboundTransferCustomRefund(address,address,address,uint256,uint256,uint256,bytes)": "4fb1a07b", 18 | "owner()": "8da5cb5b", 19 | "pauseDeposits()": "02191980", 20 | "postUpgradeInit()": "95fcea78", 21 | "redirectedExits(bytes32)": "bcf2e6eb", 22 | "router()": "f887ea40", 23 | "setBurnAmount(uint256)": "cc43f3d3", 24 | "setBurner(address)": "a996d6ce", 25 | "setOwner(address)": "13af4035", 26 | "supportsInterface(bytes4)": "01ffc9a7", 27 | "transferExitAndCall(uint256,address,address,bytes,bytes)": "bd5f3e7d", 28 | "unpauseDeposits()": "63d8882a" 29 | } 30 | -------------------------------------------------------------------------------- /test/signatures/L1ReverseCustomGateway: -------------------------------------------------------------------------------- 1 | { 2 | "calculateL2TokenAddress(address)": "a7e28d48", 3 | "counterpartGateway()": "2db09c1c", 4 | "encodeWithdrawal(uint256,address)": "020a6058", 5 | "finalizeInboundTransfer(address,address,address,uint256,bytes)": "2e567b36", 6 | "forceRegisterTokenToL2(address[],address[],uint256,uint256,uint256)": "1d3a689f", 7 | "getExternalCall(uint256,address,bytes)": "f68a9082", 8 | "getOutboundCalldata(address,address,address,uint256,bytes)": "a0c76a96", 9 | "inbox()": "fb0e722b", 10 | "initialize(address,address,address,address)": "f8c8765e", 11 | "l1ToL2Token(address)": "8a2dc014", 12 | "outboundTransfer(address,address,uint256,uint256,uint256,bytes)": "d2ce7d65", 13 | "outboundTransferCustomRefund(address,address,address,uint256,uint256,uint256,bytes)": "4fb1a07b", 14 | "owner()": "8da5cb5b", 15 | "postUpgradeInit()": "95fcea78", 16 | "redirectedExits(bytes32)": "bcf2e6eb", 17 | "registerTokenToL2(address,uint256,uint256,uint256)": "f26bdead", 18 | "registerTokenToL2(address,uint256,uint256,uint256,address)": "ca346d4a", 19 | "router()": "f887ea40", 20 | "setOwner(address)": "13af4035", 21 | "supportsInterface(bytes4)": "01ffc9a7", 22 | "transferExitAndCall(uint256,address,address,bytes,bytes)": "bd5f3e7d", 23 | "whitelist()": "93e59dc1" 24 | } 25 | -------------------------------------------------------------------------------- /test/signatures/L1TokenBridgeRetryableSender: -------------------------------------------------------------------------------- 1 | { 2 | "initialize()": "8129fc1c", 3 | "owner()": "8da5cb5b", 4 | "renounceOwnership()": "715018a6", 5 | "sendRetryable((address,address,address,address,uint256,uint256,uint256),(address,address,address,address,address,address,address),(address,address,address,address,address),address,address,address,address)": "5fc788d6", 6 | "transferOwnership(address)": "f2fde38b" 7 | } 8 | -------------------------------------------------------------------------------- /test/signatures/L1USDCGateway: -------------------------------------------------------------------------------- 1 | { 2 | "burnAmount()": "486a7e6b", 3 | "burnLockedUSDC()": "8a5e52bb", 4 | "burner()": "27810b6e", 5 | "calculateL2TokenAddress(address)": "a7e28d48", 6 | "counterpartGateway()": "2db09c1c", 7 | "depositsPaused()": "60da3e83", 8 | "encodeWithdrawal(uint256,address)": "020a6058", 9 | "finalizeInboundTransfer(address,address,address,uint256,bytes)": "2e567b36", 10 | "getExternalCall(uint256,address,bytes)": "f68a9082", 11 | "getOutboundCalldata(address,address,address,uint256,bytes)": "a0c76a96", 12 | "inbox()": "fb0e722b", 13 | "initialize(address,address,address,address,address,address)": "cc2a9a5b", 14 | "l1USDC()": "a6f73669", 15 | "l2USDC()": "29e96f9e", 16 | "outboundTransfer(address,address,uint256,uint256,uint256,bytes)": "d2ce7d65", 17 | "outboundTransferCustomRefund(address,address,address,uint256,uint256,uint256,bytes)": "4fb1a07b", 18 | "owner()": "8da5cb5b", 19 | "pauseDeposits()": "02191980", 20 | "postUpgradeInit()": "95fcea78", 21 | "redirectedExits(bytes32)": "bcf2e6eb", 22 | "router()": "f887ea40", 23 | "setBurnAmount(uint256)": "cc43f3d3", 24 | "setBurner(address)": "a996d6ce", 25 | "setOwner(address)": "13af4035", 26 | "supportsInterface(bytes4)": "01ffc9a7", 27 | "transferExitAndCall(uint256,address,address,bytes,bytes)": "bd5f3e7d", 28 | "unpauseDeposits()": "63d8882a" 29 | } 30 | -------------------------------------------------------------------------------- /test/signatures/L1WethGateway: -------------------------------------------------------------------------------- 1 | { 2 | "calculateL2TokenAddress(address)": "a7e28d48", 3 | "counterpartGateway()": "2db09c1c", 4 | "encodeWithdrawal(uint256,address)": "020a6058", 5 | "finalizeInboundTransfer(address,address,address,uint256,bytes)": "2e567b36", 6 | "getExternalCall(uint256,address,bytes)": "f68a9082", 7 | "getOutboundCalldata(address,address,address,uint256,bytes)": "a0c76a96", 8 | "inbox()": "fb0e722b", 9 | "initialize(address,address,address,address,address)": "1459457a", 10 | "l1Weth()": "146bf4b1", 11 | "l2Weth()": "247b2768", 12 | "outboundTransfer(address,address,uint256,uint256,uint256,bytes)": "d2ce7d65", 13 | "outboundTransferCustomRefund(address,address,address,uint256,uint256,uint256,bytes)": "4fb1a07b", 14 | "postUpgradeInit()": "95fcea78", 15 | "redirectedExits(bytes32)": "bcf2e6eb", 16 | "router()": "f887ea40", 17 | "supportsInterface(bytes4)": "01ffc9a7", 18 | "transferExitAndCall(uint256,address,address,bytes,bytes)": "bd5f3e7d" 19 | } 20 | -------------------------------------------------------------------------------- /test/signatures/L2AtomicTokenBridgeFactory: -------------------------------------------------------------------------------- 1 | { 2 | "deployL2Contracts((bytes,bytes,bytes,bytes,bytes,bytes,bytes),address,address,address,address,address,address,address,address)": "b1c7a870" 3 | } 4 | -------------------------------------------------------------------------------- /test/signatures/L2CustomGateway: -------------------------------------------------------------------------------- 1 | { 2 | "calculateL2TokenAddress(address)": "a7e28d48", 3 | "counterpartGateway()": "2db09c1c", 4 | "exitNum()": "015234ab", 5 | "finalizeInboundTransfer(address,address,address,uint256,bytes)": "2e567b36", 6 | "getOutboundCalldata(address,address,address,uint256,bytes)": "a0c76a96", 7 | "initialize(address,address)": "485cc955", 8 | "l1ToL2Token(address)": "8a2dc014", 9 | "outboundTransfer(address,address,uint256,bytes)": "7b3a3c8b", 10 | "outboundTransfer(address,address,uint256,uint256,uint256,bytes)": "d2ce7d65", 11 | "postUpgradeInit()": "95fcea78", 12 | "registerTokenFromL1(address[],address[])": "d4f5532f", 13 | "router()": "f887ea40" 14 | } 15 | -------------------------------------------------------------------------------- /test/signatures/L2ERC20Gateway: -------------------------------------------------------------------------------- 1 | { 2 | "beaconProxyFactory()": "c05e6a95", 3 | "calculateL2TokenAddress(address)": "a7e28d48", 4 | "cloneableProxyHash()": "97881f8d", 5 | "counterpartGateway()": "2db09c1c", 6 | "exitNum()": "015234ab", 7 | "finalizeInboundTransfer(address,address,address,uint256,bytes)": "2e567b36", 8 | "getOutboundCalldata(address,address,address,uint256,bytes)": "a0c76a96", 9 | "getUserSalt(address)": "569f26ff", 10 | "initialize(address,address,address)": "c0c53b8b", 11 | "outboundTransfer(address,address,uint256,bytes)": "7b3a3c8b", 12 | "outboundTransfer(address,address,uint256,uint256,uint256,bytes)": "d2ce7d65", 13 | "postUpgradeInit()": "95fcea78", 14 | "router()": "f887ea40" 15 | } 16 | -------------------------------------------------------------------------------- /test/signatures/L2GatewayRouter: -------------------------------------------------------------------------------- 1 | { 2 | "calculateL2TokenAddress(address)": "a7e28d48", 3 | "counterpartGateway()": "2db09c1c", 4 | "defaultGateway()": "03295802", 5 | "finalizeInboundTransfer(address,address,address,uint256,bytes)": "2e567b36", 6 | "getGateway(address)": "bda009fe", 7 | "getOutboundCalldata(address,address,address,uint256,bytes)": "a0c76a96", 8 | "initialize(address,address)": "485cc955", 9 | "l1TokenToGateway(address)": "ed08fdc6", 10 | "outboundTransfer(address,address,uint256,bytes)": "7b3a3c8b", 11 | "outboundTransfer(address,address,uint256,uint256,uint256,bytes)": "d2ce7d65", 12 | "postUpgradeInit()": "95fcea78", 13 | "router()": "f887ea40", 14 | "setDefaultGateway(address)": "f7c9362f", 15 | "setGateway(address[],address[])": "4201f985" 16 | } 17 | -------------------------------------------------------------------------------- /test/signatures/L2ReverseCustomGateway: -------------------------------------------------------------------------------- 1 | { 2 | "calculateL2TokenAddress(address)": "a7e28d48", 3 | "counterpartGateway()": "2db09c1c", 4 | "exitNum()": "015234ab", 5 | "finalizeInboundTransfer(address,address,address,uint256,bytes)": "2e567b36", 6 | "getOutboundCalldata(address,address,address,uint256,bytes)": "a0c76a96", 7 | "initialize(address,address)": "485cc955", 8 | "l1ToL2Token(address)": "8a2dc014", 9 | "outboundTransfer(address,address,uint256,bytes)": "7b3a3c8b", 10 | "outboundTransfer(address,address,uint256,uint256,uint256,bytes)": "d2ce7d65", 11 | "postUpgradeInit()": "95fcea78", 12 | "registerTokenFromL1(address[],address[])": "d4f5532f", 13 | "router()": "f887ea40" 14 | } 15 | -------------------------------------------------------------------------------- /test/signatures/L2USDCGateway: -------------------------------------------------------------------------------- 1 | { 2 | "calculateL2TokenAddress(address)": "a7e28d48", 3 | "counterpartGateway()": "2db09c1c", 4 | "exitNum()": "015234ab", 5 | "finalizeInboundTransfer(address,address,address,uint256,bytes)": "2e567b36", 6 | "getOutboundCalldata(address,address,address,uint256,bytes)": "a0c76a96", 7 | "initialize(address,address,address,address,address)": "1459457a", 8 | "l1USDC()": "a6f73669", 9 | "l2USDC()": "29e96f9e", 10 | "outboundTransfer(address,address,uint256,bytes)": "7b3a3c8b", 11 | "outboundTransfer(address,address,uint256,uint256,uint256,bytes)": "d2ce7d65", 12 | "owner()": "8da5cb5b", 13 | "pauseWithdrawals()": "56bb54a7", 14 | "postUpgradeInit()": "95fcea78", 15 | "router()": "f887ea40", 16 | "setOwner(address)": "13af4035", 17 | "setUsdcOwnershipTransferrer(address)": "54d3a598", 18 | "transferUSDCRoles(address)": "c689fc34", 19 | "unpauseWithdrawals()": "e4c4be58", 20 | "usdcOwnershipTransferrer()": "77403988", 21 | "withdrawalsPaused()": "e9f2838e" 22 | } 23 | -------------------------------------------------------------------------------- /test/signatures/L2WethGateway: -------------------------------------------------------------------------------- 1 | { 2 | "calculateL2TokenAddress(address)": "a7e28d48", 3 | "counterpartGateway()": "2db09c1c", 4 | "exitNum()": "015234ab", 5 | "finalizeInboundTransfer(address,address,address,uint256,bytes)": "2e567b36", 6 | "getOutboundCalldata(address,address,address,uint256,bytes)": "a0c76a96", 7 | "initialize(address,address,address,address)": "f8c8765e", 8 | "l1Weth()": "146bf4b1", 9 | "l2Weth()": "247b2768", 10 | "outboundTransfer(address,address,uint256,bytes)": "7b3a3c8b", 11 | "outboundTransfer(address,address,uint256,uint256,uint256,bytes)": "d2ce7d65", 12 | "postUpgradeInit()": "95fcea78", 13 | "router()": "f887ea40" 14 | } 15 | -------------------------------------------------------------------------------- /test/signatures/StandardArbERC20: -------------------------------------------------------------------------------- 1 | { 2 | "DOMAIN_SEPARATOR()": "3644e515", 3 | "allowance(address,address)": "dd62ed3e", 4 | "approve(address,uint256)": "095ea7b3", 5 | "balanceOf(address)": "70a08231", 6 | "bridgeBurn(address,uint256)": "74f4f547", 7 | "bridgeInit(address,bytes)": "189db7d2", 8 | "bridgeMint(address,uint256)": "8c2a993e", 9 | "decimals()": "313ce567", 10 | "decreaseAllowance(address,uint256)": "a457c2d7", 11 | "increaseAllowance(address,uint256)": "39509351", 12 | "isMaster()": "6f791d29", 13 | "l1Address()": "c2eeeebd", 14 | "l2Gateway()": "8fa74a0e", 15 | "name()": "06fdde03", 16 | "nonces(address)": "7ecebe00", 17 | "permit(address,address,uint256,uint256,uint8,bytes32,bytes32)": "d505accf", 18 | "symbol()": "95d89b41", 19 | "totalSupply()": "18160ddd", 20 | "transfer(address,uint256)": "a9059cbb", 21 | "transferAndCall(address,uint256,bytes)": "4000aea0", 22 | "transferFrom(address,address,uint256)": "23b872dd" 23 | } 24 | -------------------------------------------------------------------------------- /test/storage/L1CustomGateway: -------------------------------------------------------------------------------- 1 | | Name | Type | Slot | Offset | Bytes | Contract | 2 | |--------------------|---------------------------------------------------------------|------|--------|-------|----------------------------------------------------------------------------| 3 | | counterpartGateway | address | 0 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol:L1CustomGateway | 4 | | router | address | 1 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol:L1CustomGateway | 5 | | inbox | address | 2 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol:L1CustomGateway | 6 | | redirectedExits | mapping(bytes32 => struct L1ArbitrumExtendedGateway.ExitData) | 3 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol:L1CustomGateway | 7 | | l1ToL2Token | mapping(address => address) | 4 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol:L1CustomGateway | 8 | | owner | address | 5 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol:L1CustomGateway | 9 | | whitelist | address | 6 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol:L1CustomGateway | 10 | | _status | uint256 | 7 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol:L1CustomGateway | 11 | -------------------------------------------------------------------------------- /test/storage/L1ERC20Gateway: -------------------------------------------------------------------------------- 1 | | Name | Type | Slot | Offset | Bytes | Contract | 2 | |----------------------|---------------------------------------------------------------|------|--------|-------|--------------------------------------------------------------------------| 3 | | counterpartGateway | address | 0 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1ERC20Gateway.sol:L1ERC20Gateway | 4 | | router | address | 1 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1ERC20Gateway.sol:L1ERC20Gateway | 5 | | inbox | address | 2 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1ERC20Gateway.sol:L1ERC20Gateway | 6 | | redirectedExits | mapping(bytes32 => struct L1ArbitrumExtendedGateway.ExitData) | 3 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1ERC20Gateway.sol:L1ERC20Gateway | 7 | | cloneableProxyHash | bytes32 | 4 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1ERC20Gateway.sol:L1ERC20Gateway | 8 | | l2BeaconProxyFactory | address | 5 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1ERC20Gateway.sol:L1ERC20Gateway | 9 | | whitelist | address | 6 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1ERC20Gateway.sol:L1ERC20Gateway | 10 | | _status | uint256 | 7 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1ERC20Gateway.sol:L1ERC20Gateway | 11 | -------------------------------------------------------------------------------- /test/storage/L1GatewayRouter: -------------------------------------------------------------------------------- 1 | | Name | Type | Slot | Offset | Bytes | Contract | 2 | |--------------------|-----------------------------|------|--------|-------|----------------------------------------------------------------------------| 3 | | whitelist | address | 0 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol:L1GatewayRouter | 4 | | counterpartGateway | address | 1 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol:L1GatewayRouter | 5 | | router | address | 2 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol:L1GatewayRouter | 6 | | l1TokenToGateway | mapping(address => address) | 3 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol:L1GatewayRouter | 7 | | defaultGateway | address | 4 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol:L1GatewayRouter | 8 | | owner | address | 5 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol:L1GatewayRouter | 9 | | inbox | address | 6 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol:L1GatewayRouter | 10 | -------------------------------------------------------------------------------- /test/storage/L1OrbitCustomGateway: -------------------------------------------------------------------------------- 1 | | Name | Type | Slot | Offset | Bytes | Contract | 2 | |--------------------|---------------------------------------------------------------|------|--------|-------|--------------------------------------------------------------------------------------| 3 | | counterpartGateway | address | 0 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol:L1OrbitCustomGateway | 4 | | router | address | 1 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol:L1OrbitCustomGateway | 5 | | inbox | address | 2 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol:L1OrbitCustomGateway | 6 | | redirectedExits | mapping(bytes32 => struct L1ArbitrumExtendedGateway.ExitData) | 3 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol:L1OrbitCustomGateway | 7 | | l1ToL2Token | mapping(address => address) | 4 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol:L1OrbitCustomGateway | 8 | | owner | address | 5 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol:L1OrbitCustomGateway | 9 | | whitelist | address | 6 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol:L1OrbitCustomGateway | 10 | | _status | uint256 | 7 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol:L1OrbitCustomGateway | 11 | -------------------------------------------------------------------------------- /test/storage/L1OrbitERC20Gateway: -------------------------------------------------------------------------------- 1 | | Name | Type | Slot | Offset | Bytes | Contract | 2 | |----------------------|---------------------------------------------------------------|------|--------|-------|------------------------------------------------------------------------------------| 3 | | counterpartGateway | address | 0 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol:L1OrbitERC20Gateway | 4 | | router | address | 1 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol:L1OrbitERC20Gateway | 5 | | inbox | address | 2 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol:L1OrbitERC20Gateway | 6 | | redirectedExits | mapping(bytes32 => struct L1ArbitrumExtendedGateway.ExitData) | 3 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol:L1OrbitERC20Gateway | 7 | | cloneableProxyHash | bytes32 | 4 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol:L1OrbitERC20Gateway | 8 | | l2BeaconProxyFactory | address | 5 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol:L1OrbitERC20Gateway | 9 | | whitelist | address | 6 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol:L1OrbitERC20Gateway | 10 | | _status | uint256 | 7 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol:L1OrbitERC20Gateway | 11 | -------------------------------------------------------------------------------- /test/storage/L1OrbitGatewayRouter: -------------------------------------------------------------------------------- 1 | | Name | Type | Slot | Offset | Bytes | Contract | 2 | |--------------------|-----------------------------|------|--------|-------|--------------------------------------------------------------------------------------| 3 | | whitelist | address | 0 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol:L1OrbitGatewayRouter | 4 | | counterpartGateway | address | 1 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol:L1OrbitGatewayRouter | 5 | | router | address | 2 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol:L1OrbitGatewayRouter | 6 | | l1TokenToGateway | mapping(address => address) | 3 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol:L1OrbitGatewayRouter | 7 | | defaultGateway | address | 4 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol:L1OrbitGatewayRouter | 8 | | owner | address | 5 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol:L1OrbitGatewayRouter | 9 | | inbox | address | 6 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol:L1OrbitGatewayRouter | 10 | -------------------------------------------------------------------------------- /test/storage/L1OrbitReverseCustomGateway: -------------------------------------------------------------------------------- 1 | | Name | Type | Slot | Offset | Bytes | Contract | 2 | |--------------------|---------------------------------------------------------------|------|--------|-------|----------------------------------------------------------------------------------------------------| 3 | | counterpartGateway | address | 0 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol:L1OrbitReverseCustomGateway | 4 | | router | address | 1 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol:L1OrbitReverseCustomGateway | 5 | | inbox | address | 2 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol:L1OrbitReverseCustomGateway | 6 | | redirectedExits | mapping(bytes32 => struct L1ArbitrumExtendedGateway.ExitData) | 3 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol:L1OrbitReverseCustomGateway | 7 | | l1ToL2Token | mapping(address => address) | 4 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol:L1OrbitReverseCustomGateway | 8 | | owner | address | 5 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol:L1OrbitReverseCustomGateway | 9 | | whitelist | address | 6 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol:L1OrbitReverseCustomGateway | 10 | | _status | uint256 | 7 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol:L1OrbitReverseCustomGateway | 11 | -------------------------------------------------------------------------------- /test/storage/L1OrbitUSDCGateway: -------------------------------------------------------------------------------- 1 | | Name | Type | Slot | Offset | Bytes | Contract | 2 | |--------------------|---------------------------------------------------------------|------|--------|-------|----------------------------------------------------------------------------------| 3 | | counterpartGateway | address | 0 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol:L1OrbitUSDCGateway | 4 | | router | address | 1 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol:L1OrbitUSDCGateway | 5 | | inbox | address | 2 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol:L1OrbitUSDCGateway | 6 | | redirectedExits | mapping(bytes32 => struct L1ArbitrumExtendedGateway.ExitData) | 3 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol:L1OrbitUSDCGateway | 7 | | l1USDC | address | 4 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol:L1OrbitUSDCGateway | 8 | | l2USDC | address | 5 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol:L1OrbitUSDCGateway | 9 | | owner | address | 6 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol:L1OrbitUSDCGateway | 10 | | burner | address | 7 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol:L1OrbitUSDCGateway | 11 | | depositsPaused | bool | 7 | 20 | 1 | contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol:L1OrbitUSDCGateway | 12 | | burnAmount | uint256 | 8 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol:L1OrbitUSDCGateway | 13 | -------------------------------------------------------------------------------- /test/storage/L1ReverseCustomGateway: -------------------------------------------------------------------------------- 1 | | Name | Type | Slot | Offset | Bytes | Contract | 2 | |--------------------|---------------------------------------------------------------|------|--------|-------|------------------------------------------------------------------------------------------| 3 | | counterpartGateway | address | 0 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1ReverseCustomGateway.sol:L1ReverseCustomGateway | 4 | | router | address | 1 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1ReverseCustomGateway.sol:L1ReverseCustomGateway | 5 | | inbox | address | 2 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1ReverseCustomGateway.sol:L1ReverseCustomGateway | 6 | | redirectedExits | mapping(bytes32 => struct L1ArbitrumExtendedGateway.ExitData) | 3 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1ReverseCustomGateway.sol:L1ReverseCustomGateway | 7 | | l1ToL2Token | mapping(address => address) | 4 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1ReverseCustomGateway.sol:L1ReverseCustomGateway | 8 | | owner | address | 5 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1ReverseCustomGateway.sol:L1ReverseCustomGateway | 9 | | whitelist | address | 6 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1ReverseCustomGateway.sol:L1ReverseCustomGateway | 10 | | _status | uint256 | 7 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1ReverseCustomGateway.sol:L1ReverseCustomGateway | 11 | -------------------------------------------------------------------------------- /test/storage/L1TokenBridgeRetryableSender: -------------------------------------------------------------------------------- 1 | | Name | Type | Slot | Offset | Bytes | Contract | 2 | |---------------|-------------|------|--------|-------|----------------------------------------------------------------------------------------------| 3 | | _initialized | uint8 | 0 | 0 | 1 | contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol:L1TokenBridgeRetryableSender | 4 | | _initializing | bool | 0 | 1 | 1 | contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol:L1TokenBridgeRetryableSender | 5 | | __gap | uint256[50] | 1 | 0 | 1600 | contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol:L1TokenBridgeRetryableSender | 6 | | _owner | address | 51 | 0 | 20 | contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol:L1TokenBridgeRetryableSender | 7 | | __gap | uint256[49] | 52 | 0 | 1568 | contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol:L1TokenBridgeRetryableSender | 8 | -------------------------------------------------------------------------------- /test/storage/L1USDCGateway: -------------------------------------------------------------------------------- 1 | | Name | Type | Slot | Offset | Bytes | Contract | 2 | |--------------------|---------------------------------------------------------------|------|--------|-------|------------------------------------------------------------------------| 3 | | counterpartGateway | address | 0 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol:L1USDCGateway | 4 | | router | address | 1 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol:L1USDCGateway | 5 | | inbox | address | 2 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol:L1USDCGateway | 6 | | redirectedExits | mapping(bytes32 => struct L1ArbitrumExtendedGateway.ExitData) | 3 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol:L1USDCGateway | 7 | | l1USDC | address | 4 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol:L1USDCGateway | 8 | | l2USDC | address | 5 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol:L1USDCGateway | 9 | | owner | address | 6 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol:L1USDCGateway | 10 | | burner | address | 7 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol:L1USDCGateway | 11 | | depositsPaused | bool | 7 | 20 | 1 | contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol:L1USDCGateway | 12 | | burnAmount | uint256 | 8 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol:L1USDCGateway | 13 | -------------------------------------------------------------------------------- /test/storage/L1WethGateway: -------------------------------------------------------------------------------- 1 | | Name | Type | Slot | Offset | Bytes | Contract | 2 | |--------------------|---------------------------------------------------------------|------|--------|-------|------------------------------------------------------------------------| 3 | | counterpartGateway | address | 0 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol:L1WethGateway | 4 | | router | address | 1 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol:L1WethGateway | 5 | | inbox | address | 2 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol:L1WethGateway | 6 | | redirectedExits | mapping(bytes32 => struct L1ArbitrumExtendedGateway.ExitData) | 3 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol:L1WethGateway | 7 | | l1Weth | address | 4 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol:L1WethGateway | 8 | | l2Weth | address | 5 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol:L1WethGateway | 9 | -------------------------------------------------------------------------------- /test/storage/L2AtomicTokenBridgeFactory: -------------------------------------------------------------------------------- 1 | | Name | Type | Slot | Offset | Bytes | Contract | 2 | |------|------|------|--------|-------|----------| 3 | -------------------------------------------------------------------------------- /test/storage/L2CustomGateway: -------------------------------------------------------------------------------- 1 | | Name | Type | Slot | Offset | Bytes | Contract | 2 | |--------------------|-----------------------------|------|--------|-------|----------------------------------------------------------------------------| 3 | | counterpartGateway | address | 0 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2CustomGateway.sol:L2CustomGateway | 4 | | router | address | 1 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2CustomGateway.sol:L2CustomGateway | 5 | | exitNum | uint256 | 2 | 0 | 32 | contracts/tokenbridge/arbitrum/gateway/L2CustomGateway.sol:L2CustomGateway | 6 | | l1ToL2Token | mapping(address => address) | 3 | 0 | 32 | contracts/tokenbridge/arbitrum/gateway/L2CustomGateway.sol:L2CustomGateway | 7 | -------------------------------------------------------------------------------- /test/storage/L2ERC20Gateway: -------------------------------------------------------------------------------- 1 | | Name | Type | Slot | Offset | Bytes | Contract | 2 | |--------------------|---------|------|--------|-------|--------------------------------------------------------------------------| 3 | | counterpartGateway | address | 0 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2ERC20Gateway.sol:L2ERC20Gateway | 4 | | router | address | 1 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2ERC20Gateway.sol:L2ERC20Gateway | 5 | | exitNum | uint256 | 2 | 0 | 32 | contracts/tokenbridge/arbitrum/gateway/L2ERC20Gateway.sol:L2ERC20Gateway | 6 | | beaconProxyFactory | address | 3 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2ERC20Gateway.sol:L2ERC20Gateway | 7 | -------------------------------------------------------------------------------- /test/storage/L2GatewayRouter: -------------------------------------------------------------------------------- 1 | | Name | Type | Slot | Offset | Bytes | Contract | 2 | |--------------------|-----------------------------|------|--------|-------|----------------------------------------------------------------------------| 3 | | counterpartGateway | address | 0 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2GatewayRouter.sol:L2GatewayRouter | 4 | | router | address | 1 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2GatewayRouter.sol:L2GatewayRouter | 5 | | l1TokenToGateway | mapping(address => address) | 2 | 0 | 32 | contracts/tokenbridge/arbitrum/gateway/L2GatewayRouter.sol:L2GatewayRouter | 6 | | defaultGateway | address | 3 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2GatewayRouter.sol:L2GatewayRouter | 7 | -------------------------------------------------------------------------------- /test/storage/L2ReverseCustomGateway: -------------------------------------------------------------------------------- 1 | | Name | Type | Slot | Offset | Bytes | Contract | 2 | |--------------------|-----------------------------|------|--------|-------|------------------------------------------------------------------------------------------| 3 | | counterpartGateway | address | 0 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2ReverseCustomGateway.sol:L2ReverseCustomGateway | 4 | | router | address | 1 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2ReverseCustomGateway.sol:L2ReverseCustomGateway | 5 | | exitNum | uint256 | 2 | 0 | 32 | contracts/tokenbridge/arbitrum/gateway/L2ReverseCustomGateway.sol:L2ReverseCustomGateway | 6 | | l1ToL2Token | mapping(address => address) | 3 | 0 | 32 | contracts/tokenbridge/arbitrum/gateway/L2ReverseCustomGateway.sol:L2ReverseCustomGateway | 7 | -------------------------------------------------------------------------------- /test/storage/L2USDCGateway: -------------------------------------------------------------------------------- 1 | | Name | Type | Slot | Offset | Bytes | Contract | 2 | |--------------------------|---------|------|--------|-------|------------------------------------------------------------------------| 3 | | counterpartGateway | address | 0 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol:L2USDCGateway | 4 | | router | address | 1 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol:L2USDCGateway | 5 | | exitNum | uint256 | 2 | 0 | 32 | contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol:L2USDCGateway | 6 | | l1USDC | address | 3 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol:L2USDCGateway | 7 | | l2USDC | address | 4 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol:L2USDCGateway | 8 | | owner | address | 5 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol:L2USDCGateway | 9 | | usdcOwnershipTransferrer | address | 6 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol:L2USDCGateway | 10 | | withdrawalsPaused | bool | 6 | 20 | 1 | contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol:L2USDCGateway | 11 | -------------------------------------------------------------------------------- /test/storage/L2WethGateway: -------------------------------------------------------------------------------- 1 | | Name | Type | Slot | Offset | Bytes | Contract | 2 | |--------------------|---------|------|--------|-------|------------------------------------------------------------------------| 3 | | counterpartGateway | address | 0 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol:L2WethGateway | 4 | | router | address | 1 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol:L2WethGateway | 5 | | exitNum | uint256 | 2 | 0 | 32 | contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol:L2WethGateway | 6 | | l1Weth | address | 3 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol:L2WethGateway | 7 | | l2Weth | address | 4 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol:L2WethGateway | 8 | -------------------------------------------------------------------------------- /test/storage/StandardArbERC20: -------------------------------------------------------------------------------- 1 | | Name | Type | Slot | Offset | Bytes | Contract | 2 | |----------------------------------|--------------------------------------------------------|------|--------|-------|----------------------------------------------------------------------| 3 | | _initialized | uint8 | 0 | 0 | 1 | contracts/tokenbridge/arbitrum/StandardArbERC20.sol:StandardArbERC20 | 4 | | _initializing | bool | 0 | 1 | 1 | contracts/tokenbridge/arbitrum/StandardArbERC20.sol:StandardArbERC20 | 5 | | __gap | uint256[50] | 1 | 0 | 1600 | contracts/tokenbridge/arbitrum/StandardArbERC20.sol:StandardArbERC20 | 6 | | _balances | mapping(address => uint256) | 51 | 0 | 32 | contracts/tokenbridge/arbitrum/StandardArbERC20.sol:StandardArbERC20 | 7 | | _allowances | mapping(address => mapping(address => uint256)) | 52 | 0 | 32 | contracts/tokenbridge/arbitrum/StandardArbERC20.sol:StandardArbERC20 | 8 | | _totalSupply | uint256 | 53 | 0 | 32 | contracts/tokenbridge/arbitrum/StandardArbERC20.sol:StandardArbERC20 | 9 | | _name | string | 54 | 0 | 32 | contracts/tokenbridge/arbitrum/StandardArbERC20.sol:StandardArbERC20 | 10 | | _symbol | string | 55 | 0 | 32 | contracts/tokenbridge/arbitrum/StandardArbERC20.sol:StandardArbERC20 | 11 | | _decimals | uint8 | 56 | 0 | 1 | contracts/tokenbridge/arbitrum/StandardArbERC20.sol:StandardArbERC20 | 12 | | __gap | uint256[44] | 57 | 0 | 1408 | contracts/tokenbridge/arbitrum/StandardArbERC20.sol:StandardArbERC20 | 13 | | _HASHED_NAME | bytes32 | 101 | 0 | 32 | contracts/tokenbridge/arbitrum/StandardArbERC20.sol:StandardArbERC20 | 14 | | _HASHED_VERSION | bytes32 | 102 | 0 | 32 | contracts/tokenbridge/arbitrum/StandardArbERC20.sol:StandardArbERC20 | 15 | | __gap | uint256[50] | 103 | 0 | 1600 | contracts/tokenbridge/arbitrum/StandardArbERC20.sol:StandardArbERC20 | 16 | | _nonces | mapping(address => struct CountersUpgradeable.Counter) | 153 | 0 | 32 | contracts/tokenbridge/arbitrum/StandardArbERC20.sol:StandardArbERC20 | 17 | | _PERMIT_TYPEHASH_DEPRECATED_SLOT | bytes32 | 154 | 0 | 32 | contracts/tokenbridge/arbitrum/StandardArbERC20.sol:StandardArbERC20 | 18 | | __gap | uint256[49] | 155 | 0 | 1568 | contracts/tokenbridge/arbitrum/StandardArbERC20.sol:StandardArbERC20 | 19 | | l2Gateway | address | 204 | 0 | 20 | contracts/tokenbridge/arbitrum/StandardArbERC20.sol:StandardArbERC20 | 20 | | l1Address | address | 205 | 0 | 20 | contracts/tokenbridge/arbitrum/StandardArbERC20.sol:StandardArbERC20 | 21 | | isMasterCopy | bool | 205 | 20 | 1 | contracts/tokenbridge/arbitrum/StandardArbERC20.sol:StandardArbERC20 | 22 | | availableGetters | struct StandardArbERC20.ERC20Getters | 206 | 0 | 32 | contracts/tokenbridge/arbitrum/StandardArbERC20.sol:StandardArbERC20 | 23 | -------------------------------------------------------------------------------- /test/testhelper.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2020, Offchain Labs, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* eslint-env node, mocha */ 18 | import { ethers, network } from 'hardhat' 19 | import { ContractTransaction } from 'ethers' 20 | import { 21 | InboxMock, 22 | InboxMock__factory, 23 | ArbSysMock__factory, 24 | } from '../build/types' 25 | 26 | export const processL1ToL2Tx = async ( 27 | tx: Promise | ContractTransaction 28 | ) => { 29 | const receipt = await (await tx).wait() 30 | const iface = InboxMock__factory.createInterface() 31 | const logs = receipt.logs.filter( 32 | log => log.topics[0] === iface.getEventTopic('InboxRetryableTicket') 33 | ) 34 | if (logs.length === 0) throw new Error('No L1 to L2 txs') 35 | const l1ToL2Logs = logs.map(log => { 36 | const event = iface.parseLog(log) 37 | const to = event.args.to 38 | const data = event.args.data 39 | const from = event.args.from 40 | const value = event.args.value 41 | const fromAliased = applyAlias(from) 42 | 43 | return network.provider 44 | .request({ 45 | // Fund fromAliased to send transaction 46 | method: 'hardhat_setBalance', 47 | params: [fromAliased, '0xffffffffffffffffffff'], 48 | }) 49 | .then(() => 50 | network.provider.request({ 51 | method: 'hardhat_impersonateAccount', 52 | params: [fromAliased], 53 | }) 54 | ) 55 | .then(() => ethers.getSigner(fromAliased)) 56 | .then(signer => 57 | signer.sendTransaction({ 58 | to: to, 59 | data: data, 60 | value: value, 61 | }) 62 | ) 63 | }) 64 | return Promise.all(l1ToL2Logs) 65 | } 66 | 67 | export const impersonateAccount = (address: string) => 68 | network.provider 69 | .request({ 70 | // Fund inboxMock to send transaction 71 | method: 'hardhat_setBalance', 72 | params: [address, '0xffffffffffffffffffff'], 73 | }) 74 | .then(() => 75 | network.provider.request({ 76 | method: 'hardhat_impersonateAccount', 77 | params: [address], 78 | }) 79 | ) 80 | .then(() => ethers.getSigner(address)) 81 | 82 | export const applyAlias = (address: string) => 83 | '0x' + 84 | BigInt.asUintN( 85 | 160, 86 | BigInt(address) + BigInt('0x1111000000000000000000000000000000001111') 87 | ) 88 | .toString(16) 89 | .padStart(40, '0') 90 | 91 | export const processL2ToL1Tx = async ( 92 | tx: Promise | ContractTransaction, 93 | inboxMock: InboxMock 94 | ) => { 95 | const receipt = await (await tx).wait() 96 | const iface = ArbSysMock__factory.createInterface() 97 | const logs = receipt.logs.filter( 98 | log => log.topics[0] === iface.getEventTopic('ArbSysL2ToL1Tx') 99 | ) 100 | if (logs.length === 0) throw new Error('No L2 to L1 txs') 101 | const l2ToL1Logs = logs.map(log => { 102 | const event = iface.parseLog(log) 103 | const to = event.args.to 104 | const data = event.args.data 105 | const from = event.args.from 106 | const value = event.args.value 107 | return inboxMock 108 | .setL2ToL1Sender(from, { gasLimit: 5000000 }) 109 | .then(() => impersonateAccount(inboxMock.address)) 110 | .then(signer => 111 | signer.sendTransaction({ 112 | to: to, 113 | data: data, 114 | value: value, 115 | }) 116 | ) 117 | }) 118 | return Promise.all(l2ToL1Logs) 119 | } 120 | -------------------------------------------------------------------------------- /test/unused-errors/exceptions.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OffchainLabs/token-bridge-contracts/5bdf33259d2d9ae52ddc69bc5a9cbc558c4c40c7/test/unused-errors/exceptions.txt -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2018", 4 | "module": "commonjs", 5 | "strict": true, 6 | "esModuleInterop": true, 7 | "outDir": "dist", 8 | "resolveJsonModule": true 9 | }, 10 | "include": ["./scripts", "./test", "./deploy", "./build/**/*.ts"], 11 | "files": ["./hardhat.config.ts"] 12 | } 13 | --------------------------------------------------------------------------------