├── .clabot ├── .env-sample ├── .env.sample.testnode ├── .eslintrc.js ├── .github └── workflows │ ├── audit-ci.yml │ ├── base-branch-check.yml │ ├── contract-tests.yml │ └── slither.yml ├── .gitignore ├── .gitmodules ├── .prettierignore ├── .prettierrc.js ├── .solhint.json ├── .solhintignore ├── LICENSE.md ├── README.md ├── audit-ci.jsonc ├── deploy ├── BridgeCreator.js ├── BridgeStubCreator.js ├── ExpressLaneAuction.js ├── HashProofHelper.js ├── InboxStubCreator.js ├── OneStepProofEntryCreator.js ├── OneStepProver0Creator.js ├── OneStepProverHostIoCreator.js ├── OneStepProverMathCreator.js ├── OneStepProverMemoryCreator.js ├── SequencerInbox.js ├── SequencerInboxStubCreator.js └── ValueArrayTesterCreator.js ├── foundry.toml ├── hardhat.config.ts ├── package.json ├── scripts ├── boldUpgradeCommon.ts ├── boldUpgradeFunctions.ts ├── config.ts.example ├── createERC20Rollup.ts ├── createEthRollup.ts ├── deployment.ts ├── deploymentUtils.ts ├── executeBoldUpgrade.ts ├── files │ ├── arb1DeployedContracts.json │ ├── configs │ │ ├── arb1.ts │ │ ├── custom.ts │ │ ├── index.ts │ │ ├── local.ts │ │ ├── nova.ts │ │ ├── sepolia.ts │ │ └── utils.ts │ ├── novaDeployedContracts.json │ └── sepoliaDeployedContracts.json ├── local-deployment │ ├── deployCacheManager.ts │ └── deployCreatorAndCreateRollup.ts ├── populateLookup.ts ├── prepareBoldUpgrade.ts ├── printMetadataHashes.ts ├── rollupCreation.ts ├── testSetup.ts ├── testUpgrade.bash └── upgrade │ └── deploy4844.ts ├── slither.config.json ├── slither.db.json ├── src ├── assertionStakingPool │ ├── AbsBoldStakingPool.sol │ ├── AssertionStakingPool.sol │ ├── AssertionStakingPoolCreator.sol │ ├── EdgeStakingPool.sol │ ├── EdgeStakingPoolCreator.sol │ ├── StakingPoolCreatorUtils.sol │ └── interfaces │ │ ├── IAbsBoldStakingPool.sol │ │ ├── IAssertionStakingPool.sol │ │ ├── IAssertionStakingPoolCreator.sol │ │ ├── IEdgeStakingPool.sol │ │ └── IEdgeStakingPoolCreator.sol ├── bridge │ ├── AbsBridge.sol │ ├── AbsInbox.sol │ ├── AbsOutbox.sol │ ├── Bridge.sol │ ├── DelayBuffer.sol │ ├── DelayBufferTypes.sol │ ├── ERC20Bridge.sol │ ├── ERC20Inbox.sol │ ├── ERC20Outbox.sol │ ├── GasRefunder.sol │ ├── IBridge.sol │ ├── IDelayedMessageProvider.sol │ ├── IERC20Bridge.sol │ ├── IERC20Inbox.sol │ ├── IEthBridge.sol │ ├── IInbox.sol │ ├── IInboxBase.sol │ ├── IOutbox.sol │ ├── IOwnable.sol │ ├── ISequencerInbox.sol │ ├── Inbox.sol │ ├── Messages.sol │ ├── Outbox.sol │ └── SequencerInbox.sol ├── chain │ └── CacheManager.sol ├── challengeV2 │ ├── EdgeChallengeManager.sol │ ├── IAssertionChain.sol │ ├── IEdgeChallengeManager.sol │ └── libraries │ │ ├── ArrayUtilsLib.sol │ │ ├── ChallengeEdgeLib.sol │ │ ├── ChallengeErrors.sol │ │ ├── EdgeChallengeManagerLib.sol │ │ ├── Enums.sol │ │ ├── MerkleTreeAccumulatorLib.sol │ │ ├── Structs.sol │ │ └── UintUtilsLib.sol ├── express-lane-auction │ ├── Balance.sol │ ├── Burner.sol │ ├── ELCRound.sol │ ├── Errors.sol │ ├── ExpressLaneAuction.sol │ ├── IExpressLaneAuction.sol │ └── RoundTimingInfo.sol ├── libraries │ ├── AddressAliasHelper.sol │ ├── AdminFallbackProxy.sol │ ├── ArbitrumChecker.sol │ ├── CallerChecker.sol │ ├── Constants.sol │ ├── CryptographyPrimitives.sol │ ├── DecimalsConverterHelper.sol │ ├── DelegateCallAware.sol │ ├── DoubleLogicUUPSUpgradeable.sol │ ├── Error.sol │ ├── GasRefundEnabled.sol │ ├── IGasRefunder.sol │ ├── IReader4844.sol │ ├── MerkleLib.sol │ ├── MessageTypes.sol │ └── UUPSNotUpgradeable.sol ├── mocks │ ├── ArbOS11To32UpgradeTest.sol │ ├── Benchmarks.sol │ ├── BigMap.sol │ ├── BridgeStub.sol │ ├── BridgeUnproxied.sol │ ├── CreateTest.sol │ ├── HostioTest.sol │ ├── InboxStub.sol │ ├── MerkleTreeAccess.sol │ ├── MockRollupEventInbox.sol │ ├── MultiCallTest.sol │ ├── PendingBlkTimeAndNrAdvanceCheck.sol │ ├── Program.sol │ ├── ProxyAdminForBinding.sol │ ├── SdkStorage.sol │ ├── SelfDestruct.sol │ ├── SequencerInboxBlobMock.sol │ ├── SequencerInboxStub.sol │ ├── Simple.sol │ ├── SimpleCacheManager.sol │ ├── SimpleOneStepProofEntry.sol │ ├── SimpleProxy.sol │ ├── TestWETH9.sol │ └── UpgradeExecutorMock.sol ├── node-interface │ ├── NodeInterface.sol │ └── NodeInterfaceDebug.sol ├── osp │ ├── HashProofHelper.sol │ ├── IOneStepProofEntry.sol │ ├── IOneStepProver.sol │ ├── OneStepProofEntry.sol │ ├── OneStepProver0.sol │ ├── OneStepProverHostIo.sol │ ├── OneStepProverMath.sol │ └── OneStepProverMemory.sol ├── precompiles │ ├── ArbAddressTable.sol │ ├── ArbAggregator.sol │ ├── ArbBLS.sol │ ├── ArbDebug.sol │ ├── ArbFunctionTable.sol │ ├── ArbGasInfo.sol │ ├── ArbInfo.sol │ ├── ArbOwner.sol │ ├── ArbOwnerPublic.sol │ ├── ArbRetryableTx.sol │ ├── ArbStatistics.sol │ ├── ArbSys.sol │ ├── ArbWasm.sol │ ├── ArbWasmCache.sol │ ├── ArbosActs.sol │ └── ArbosTest.sol ├── rollup │ ├── AbsRollupEventInbox.sol │ ├── Assertion.sol │ ├── AssertionState.sol │ ├── BOLDUpgradeAction.sol │ ├── BridgeCreator.sol │ ├── Config.sol │ ├── DeployHelper.sol │ ├── ERC20RollupEventInbox.sol │ ├── FactoryDeployerHelper.sol │ ├── IRollupAdmin.sol │ ├── IRollupCore.sol │ ├── IRollupEventInbox.sol │ ├── IRollupLogic.sol │ ├── RollupAdminLogic.sol │ ├── RollupCore.sol │ ├── RollupCreator.sol │ ├── RollupEventInbox.sol │ ├── RollupLib.sol │ ├── RollupProxy.sol │ ├── RollupUserLogic.sol │ ├── ValidatorUtils.sol │ ├── ValidatorWallet.sol │ └── ValidatorWalletCreator.sol ├── state │ ├── Deserialize.sol │ ├── GlobalState.sol │ ├── Instructions.sol │ ├── Machine.sol │ ├── MerkleProof.sol │ ├── Module.sol │ ├── ModuleMemory.sol │ ├── ModuleMemoryCompact.sol │ ├── MultiStack.sol │ ├── PcArray.sol │ ├── StackFrame.sol │ ├── Value.sol │ ├── ValueArray.sol │ └── ValueStack.sol ├── stylus │ └── StylusDeployer.sol └── test-helpers │ ├── BridgeTester.sol │ ├── CryptographyPrimitivesTester.sol │ ├── EthVault.sol │ ├── InterfaceCompatibilityTester.sol │ ├── MessageTester.sol │ ├── NoReceiveForwarder.sol │ ├── OutboxWithoutOptTester.sol │ ├── RollupMock.sol │ ├── TestToken.sol │ └── ValueArrayTester.sol ├── test ├── ERC20Mock.sol ├── MockAssertionChain.sol ├── Rollup.t.sol ├── challengeV2 │ ├── ArrayUtilsLib.t.sol │ ├── ChallengeEdgeLib.t.sol │ ├── EdgeChallengeManager.t.sol │ ├── EdgeChallengeManagerLib.t.sol │ ├── MerkleTreeAccumulatorLib.t.sol │ ├── StateTools.sol │ ├── UintUtilsLib.t.sol │ └── Utils.sol ├── contract │ ├── batchData.json │ ├── common │ │ ├── challengeLib.ts │ │ └── globalStateLib.ts │ ├── cryptographyPrimitives.spec.ts │ ├── outbox │ │ └── withdraw-testcase.json │ ├── outboxOptimisation.spec.ts │ ├── sequencerInbox.spec.4844.ts │ ├── sequencerInboxDelayBufferable.spec.ts │ ├── sequencerInboxForceInclude.spec.ts │ ├── testHelpers.ts │ ├── toolkit4844.ts │ ├── types.ts │ ├── utils.ts │ └── validatorWallet.spec.ts ├── e2e │ ├── customFeeRollup.ts │ ├── orbitChain.ts │ ├── stylusDeployer.ts │ └── stylusTestFiles │ │ ├── counter1.txt │ │ ├── counter2.txt │ │ ├── counter3.txt │ │ └── counter4.txt ├── foundry │ ├── AbsBridge.t.sol │ ├── AbsInbox.t.sol │ ├── AbsOutbox.t.sol │ ├── AbsRollupEventInbox.t.sol │ ├── Bridge.t.sol │ ├── BridgeCreator.t.sol │ ├── CacheManager.t.sol │ ├── DecimalsConverterHelper.t.sol │ ├── DelayBuffer.t.sol │ ├── ERC20Bridge.t.sol │ ├── ERC20Inbox.t.sol │ ├── ERC20Outbox.t.sol │ ├── ERC20RollupEventInbox.t.sol │ ├── ExpressLaneAuction.t.sol │ ├── ExpressLaneBalance.t.sol │ ├── ExpressLaneBurner.t.sol │ ├── ExpressLaneELCRound.t.sol │ ├── ExpressLaneRoundTiming.t.sol │ ├── Inbox.t.sol │ ├── Outbox.t.sol │ ├── RollupCreator.t.sol │ ├── RollupEventInbox.t.sol │ ├── SequencerInbox.t.sol │ ├── fee-token-pricers │ │ ├── ConstantExchangeRatePricer.sol │ │ ├── OwnerAdjustableExchangeRatePricer.sol │ │ ├── README.md │ │ ├── trade-tracker │ │ │ ├── TradeTracker.sol │ │ │ └── TradeTracker.t.sol │ │ └── uniswap-v2-twap │ │ │ ├── FixedPoint.sol │ │ │ ├── FullMath.sol │ │ │ └── UniswapV2TwapPricer.sol │ └── util │ │ ├── NoZeroTransferToken.sol │ │ └── TestUtil.sol ├── prover │ ├── hash-proofs.ts │ ├── one-step-proof.ts │ ├── proofs │ │ └── .gitkeep │ └── value-arrays.ts ├── signatures │ ├── Bridge │ ├── BridgeCreator │ ├── CacheManager │ ├── DeployHelper │ ├── ERC20Bridge │ ├── ERC20Inbox │ ├── ERC20Outbox │ ├── EdgeChallengeManager │ ├── Inbox │ ├── OneStepProofEntry │ ├── Outbox │ ├── RollupAdminLogic │ ├── RollupCore │ ├── RollupCreator │ ├── RollupUserLogic │ ├── SequencerInbox │ └── test-sigs.bash ├── stakingPool │ ├── AbsBoldStakingPool.t.sol │ ├── AssertionStakingPool.t.sol │ └── EdgeStakingPool.t.sol ├── storage │ ├── Bridge │ ├── CacheManager │ ├── ERC20Bridge │ ├── ERC20Inbox │ ├── ERC20Outbox │ ├── EdgeChallengeManager │ ├── Inbox │ ├── OneStepProofEntry │ ├── Outbox │ ├── RollupAdminLogic │ ├── RollupCore │ ├── RollupUserLogic │ ├── SequencerInbox │ └── test.bash └── unused-errors │ └── exceptions.txt ├── tsconfig.json ├── yarn.lock └── yul └── Reader4844.yul /.clabot: -------------------------------------------------------------------------------- 1 | { 2 | "contributors": "https://api.github.com/repos/OffchainLabs/clabot-config/contents/nitro-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 the linked documents below to get yourself added. https://na3.docusign.net/Member/PowerFormSigning.aspx?PowerFormId=b15c81cc-b5ea-42a6-9107-3992526f2898&env=na3&acct=6e152afc-6284-44af-a4c1-d8ef291db402&v=2", 4 | "label": "s" 5 | } -------------------------------------------------------------------------------- /.env-sample: -------------------------------------------------------------------------------- 1 | L1_PRIV_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" 2 | CONFIG_NETWORK_NAME="custom" 3 | DEPLOYED_CONTRACTS_DIR="./scripts/files/" 4 | DISABLE_VERIFICATION=true 5 | 6 | # to use the 'custom' hardhat network, set the following variables 7 | CUSTOM_RPC_URL="http://127.0.0.1:8545" 8 | CUSTOM_ETHERSCAN_API_KEY= 9 | CUSTOM_CHAINID=1337 10 | CUSTOM_ETHERSCAN_API_URL= 11 | CUSTOM_ETHERSCAN_BROWSER_URL= -------------------------------------------------------------------------------- /.env.sample.testnode: -------------------------------------------------------------------------------- 1 | L1_RPC_URL="http://localhost:8545" 2 | L1_PRIV_KEY="0xdc04c5399f82306ec4b4d654a342f40e2e0620fe39950d967e1e574b32d4dd36" 3 | CONFIG_NETWORK_NAME="local" 4 | DEPLOYED_CONTRACTS_DIR="./scripts/files/" 5 | DISABLE_VERIFICATION=true 6 | -------------------------------------------------------------------------------- /.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: ['test/**/*.ts'], 25 | parser: '@typescript-eslint/parser', 26 | parserOptions: { 27 | project: 'tsconfig.json', 28 | }, 29 | extends: [ 30 | 'eslint:recommended', 31 | 'plugin:@typescript-eslint/recommended', 32 | 'plugin:prettier/recommended', 33 | ], 34 | plugins: ['@typescript-eslint', 'prettier', '@typescript-eslint/tslint'], 35 | rules: { 36 | 'no-empty-pattern': 'warn', 37 | 'prettier/prettier': ['error', { singleQuote: true }], 38 | '@typescript-eslint/member-delimiter-style': ['off'], 39 | '@typescript-eslint/no-explicit-any': ['off'], 40 | '@typescript-eslint/no-use-before-define': ['off'], 41 | '@typescript-eslint/no-non-null-assertion': ['off'], 42 | '@typescript-eslint/ban-ts-comment': ['warn'], 43 | '@typescript-eslint/no-unused-vars': [ 44 | 'warn', 45 | { 46 | argsIgnorePattern: '^_', 47 | varsIgnorePattern: '^_', 48 | caughtErrorsIgnorePattern: '^_', 49 | }, 50 | ], 51 | '@typescript-eslint/tslint/config': [ 52 | 'error', 53 | { 54 | rules: { 'strict-comparisons': true }, 55 | }, 56 | ], 57 | 'no-implicit-coercion': 'error', 58 | '@typescript-eslint/no-floating-promises': 'error', 59 | }, 60 | }, 61 | ], 62 | } 63 | -------------------------------------------------------------------------------- /.github/workflows/audit-ci.yml: -------------------------------------------------------------------------------- 1 | name: Audit NPM packages 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | merge_group: 7 | push: 8 | branches: 9 | - main 10 | - develop 11 | 12 | jobs: 13 | yarn-audit: 14 | name: Audit 15 | runs-on: ubuntu-latest 16 | strategy: 17 | matrix: 18 | node-version: [18, 20] 19 | steps: 20 | - name: Checkout 21 | uses: actions/checkout@v4 22 | 23 | - name: Set up Node.js 24 | uses: actions/setup-node@v4 25 | with: 26 | node-version: ${{ matrix.node-version }} 27 | 28 | - name: Install node_modules 29 | uses: OffchainLabs/actions/node-modules/install@main 30 | with: 31 | cache-key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}-${{ matrix.node-version }} 32 | 33 | - name: Run audit 34 | run: yarn audit:ci 35 | -------------------------------------------------------------------------------- /.github/workflows/base-branch-check.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | 7 | jobs: 8 | base_branch_check: 9 | name: Pull request base branch check 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Check the pull request base branch 13 | run: | 14 | if [[ "$GITHUB_BASE_REF" == "main" ]] && [[ "$GITHUB_HEAD_REF" != "develop" ]] && [[ "$GITHUB_HEAD_REF" != hotfix* ]]; then 15 | echo -e '\x1b[31mPull requests targeting the main branch must be from the develop branch or a branch name starting with "hotfix".\x1b[0m' 16 | exit 1 17 | fi 18 | -------------------------------------------------------------------------------- /.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.4.0 15 | id: slither 16 | with: 17 | sarif: results.sarif 18 | fail-on: medium 19 | slither-args: --skip-assembly 20 | 21 | - name: Upload SARIF file 22 | if: always() 23 | uses: github/codeql-action/upload-sarif@v3 24 | with: 25 | sarif_file: ${{ steps.slither.outputs.sarif }} 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | cache/ 3 | node_modules/ 4 | deployments/ 5 | /test/prover/proofs/*.json 6 | /test/prover/spec-proofs/*.json 7 | /test/storage/*-old 8 | /test/signatures/*-old 9 | scripts/config.ts 10 | forge-cache/ 11 | out/ 12 | .env 13 | .DS_Store 14 | lcov.info 15 | output_directory -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/forge-std"] 2 | path = lib/forge-std 3 | url = https://github.com/foundry-rs/forge-std 4 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | build/** 2 | cache/** 3 | dist/** 4 | coverage/** 5 | deployments/** 6 | src/lib/abi/** 7 | .nyc_output 8 | out/** 9 | lib/** 10 | src/mocks/MultiCallTest.sol 11 | slither.db.json 12 | LICENSE.md -------------------------------------------------------------------------------- /.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 | } 10 | -------------------------------------------------------------------------------- /.solhint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["solhint:recommended"], 3 | "rules": { 4 | "avoid-throw": "off", 5 | "avoid-suicide": "error", 6 | "avoid-sha3": "warn", 7 | "max-line-length": "off", 8 | "compiler-version": "off", 9 | "func-visibility": ["warn", { "ignoreConstructors": true }], 10 | "no-empty-blocks": "off", 11 | "reason-string": ["warn", { "maxLength": 128 }], 12 | "not-rely-on-time": "off", 13 | "max-states-count": ["warn", 40], 14 | "no-inline-assembly": "off", 15 | "no-global-import": "off", 16 | "custom-errors": "off", 17 | "immutable-vars-naming": "off", 18 | "var-name-mixedcase": "off" 19 | }, 20 | "plugins": [] 21 | } 22 | -------------------------------------------------------------------------------- /.solhintignore: -------------------------------------------------------------------------------- 1 | src/mocks 2 | src/precompiles 3 | src/test-helpers -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Arbitrum Nitro Rollup Contracts 2 | 3 | This is the package with the smart contract code that powers Arbitrum Nitro. 4 | It includes the rollup and fraud proof smart contracts, as well as interfaces for interacting with precompiles. 5 | 6 | For more information see https://developer.arbitrum.io/intro 7 | 8 | For the deployed addresses of these contracts for Arbitrum chains see [https://docs.arbitrum.io/for-devs/dev-tools-and-resources/chain-info#core-contracts](https://docs.arbitrum.io/for-devs/dev-tools-and-resources/chain-info#core-contracts) 9 | 10 | For the token bridge contracts see [https://github.com/OffchainLabs/token-bridge-contracts](https://github.com/OffchainLabs/token-bridge-contracts) 11 | 12 | Compile these contracts locally by running 13 | 14 | ```bash 15 | git clone https://github.com/offchainlabs/nitro-contracts 16 | cd nitro-contracts 17 | yarn install 18 | yarn build 19 | ``` 20 | 21 | ## License 22 | 23 | Nitro is currently licensed under a [Business Source License](./LICENSE.md), similar to our friends at Uniswap and Aave, with an "Additional Use Grant" to ensure that everyone can have full comfort using and running nodes on all public Arbitrum chains. 24 | 25 | The Additional Use Grant also permits the deployment of the Nitro software, in a permissionless fashion and without cost, as a new blockchain provided that the chain settles to either Arbitrum One or Arbitrum Nova. 26 | 27 | For those that prefer to deploy the Nitro software either directly on Ethereum (i.e. an L2) or have it settle to another Layer-2 on top of Ethereum, the [Arbitrum Expansion Program (the "AEP")](https://docs.arbitrum.foundation/aep/ArbitrumExpansionProgramTerms.pdf) was recently established. The AEP allows for the permissionless deployment in the aforementioned fashion provided that 10% of net revenue is contributed back to the Arbitrum community in accordance with the requirements of the AEP. 28 | 29 | ## Contact 30 | 31 | Discord - [Arbitrum](https://discord.com/invite/5KE54JwyTs) 32 | 33 | Twitter: [Arbitrum](https://twitter.com/arbitrum) 34 | -------------------------------------------------------------------------------- /audit-ci.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://github.com/IBM/audit-ci/raw/main/docs/schema.json", 3 | "low": true, 4 | "allowlist": [ 5 | // OpenZeppelin Contracts's GovernorVotesQuorumFraction updates to quorum may affect past defeated proposals 6 | "GHSA-93hq-5wgc-jc82", 7 | // OpenZeppelin: Using ERC2771Context with a custom forwarder can yield address(0) 8 | "GHSA-g4vp-m682-qqmp", 9 | // OpenZeppelin Contracts TransparentUpgradeableProxy clashing selector calls may not be delegated 10 | "GHSA-mx2q-35m2-x2rh", 11 | // OpenZeppelin Contracts's governor proposal creation may be blocked by frontrunning 12 | "GHSA-5h3x-9wvq-w4m2", 13 | // axios cookies data-privacy issue; used only in hardhat-deploy and sol2uml (dev deps) 14 | "GHSA-wf5p-g6vw-rhxx", 15 | // OpenZeppelin Contracts using MerkleProof multiproofs may allow proving arbitrary leaves for specific trees; unused 16 | "GHSA-wprv-93r4-jj2p", 17 | // Open Zeppelin: Base64 encoding may read from potentially dirty memory 18 | "GHSA-9vx6-7xxf-x967", 19 | // semver vulnerable to Regular Expression Denial of Service 20 | "GHSA-c2qf-rxjj-qqgw", 21 | // Server-Side Request Forgery in axios 22 | "GHSA-8hc4-vh64-cxmj", 23 | // Regular Expression Denial of Service (ReDoS) in micromatch 24 | "GHSA-952p-6rrq-rcjv", 25 | // cookie accepts cookie name, path, and domain with out of bounds characters 26 | "GHSA-pxg6-pf52-xh8x", 27 | // Regular Expression Denial of Service (ReDoS) in cross-spawn 28 | "GHSA-3xgq-45jj-v275", 29 | // axios Requests Vulnerable To Possible SSRF and Credential Leakage via Absolute URL 30 | "GHSA-jr5f-v2jv-69x6" 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /deploy/BridgeCreator.js: -------------------------------------------------------------------------------- 1 | module.exports = async hre => { 2 | const { deployments, getNamedAccounts, ethers } = hre 3 | const { deploy } = deployments 4 | const { deployer } = await getNamedAccounts() 5 | 6 | await deploy('Bridge', { from: deployer, args: [] }) 7 | } 8 | 9 | module.exports.tags = ['Bridge'] 10 | module.exports.dependencies = [] 11 | -------------------------------------------------------------------------------- /deploy/BridgeStubCreator.js: -------------------------------------------------------------------------------- 1 | module.exports = async hre => { 2 | const { deployments, getNamedAccounts, ethers } = hre 3 | const { deploy } = deployments 4 | const { deployer } = await getNamedAccounts() 5 | 6 | await deploy('BridgeStub', { from: deployer, args: [] }) 7 | } 8 | 9 | module.exports.tags = ['BridgeStub', 'test'] 10 | module.exports.dependencies = [] 11 | -------------------------------------------------------------------------------- /deploy/ExpressLaneAuction.js: -------------------------------------------------------------------------------- 1 | module.exports = async hre => { 2 | const { deployments, getNamedAccounts } = hre 3 | const { deploy } = deployments 4 | const { deployer } = await getNamedAccounts() 5 | 6 | await deploy('ExpressLaneAuction', { 7 | from: deployer, 8 | args: [], 9 | proxy: { 10 | proxyContract: 'TransparentUpgradeableProxy', 11 | execute: { 12 | init: { 13 | methodName: 'initialize', 14 | args: [ 15 | { 16 | _auctioneer: '0xeee584DA928A94950E177235EcB9A99bb655c7A0', 17 | _biddingToken: '0x980B62Da83eFf3D4576C647993b0c1D7faf17c73', // WETH 18 | _beneficiary: '0xeee584DA928A94950E177235EcB9A99bb655c7A0', 19 | _roundTimingInfo: { 20 | offsetTimestamp: 1727870000, 21 | roundDurationSeconds: 60, 22 | auctionClosingSeconds: 15, 23 | reserveSubmissionSeconds: 15, 24 | }, 25 | _minReservePrice: ethers.utils.parseEther('0.00001'), 26 | _auctioneerAdmin: '0xeee584DA928A94950E177235EcB9A99bb655c7A0', 27 | _minReservePriceSetter: 28 | '0xeee584DA928A94950E177235EcB9A99bb655c7A0', 29 | _reservePriceSetter: '0xeee584DA928A94950E177235EcB9A99bb655c7A0', 30 | _reservePriceSetterAdmin: 31 | '0xeee584DA928A94950E177235EcB9A99bb655c7A0', 32 | _beneficiarySetter: '0xeee584DA928A94950E177235EcB9A99bb655c7A0', 33 | _roundTimingSetter: '0xeee584DA928A94950E177235EcB9A99bb655c7A0', 34 | _masterAdmin: '0xeee584DA928A94950E177235EcB9A99bb655c7A0', 35 | }, 36 | ], 37 | }, 38 | }, 39 | owner: deployer, 40 | }, 41 | }) 42 | } 43 | 44 | module.exports.tags = ['ExpressLaneAuction'] 45 | module.exports.dependencies = [] 46 | -------------------------------------------------------------------------------- /deploy/HashProofHelper.js: -------------------------------------------------------------------------------- 1 | module.exports = async hre => { 2 | const { deployments, getNamedAccounts } = hre 3 | const { deploy } = deployments 4 | const { deployer } = await getNamedAccounts() 5 | 6 | await deploy('HashProofHelper', { 7 | from: deployer, 8 | args: [], 9 | }) 10 | } 11 | 12 | module.exports.tags = ['HashProofHelper', 'test', 'live'] 13 | module.exports.dependencies = [] 14 | -------------------------------------------------------------------------------- /deploy/InboxStubCreator.js: -------------------------------------------------------------------------------- 1 | module.exports = async hre => { 2 | const { deployments, getNamedAccounts, ethers } = hre 3 | const { deployer } = await getNamedAccounts() 4 | 5 | const inboxDeployResult = await deployments.deploy('InboxStub', { 6 | from: deployer, 7 | args: [], 8 | }) 9 | 10 | const bridge = await ethers.getContractAt( 11 | 'BridgeStub', 12 | ( 13 | await deployments.get('BridgeStub') 14 | ).address 15 | ) 16 | const inbox = await ethers.getContractAt( 17 | 'InboxStub', 18 | ( 19 | await deployments.get('InboxStub') 20 | ).address 21 | ) 22 | 23 | if (inboxDeployResult.newlyDeployed) { 24 | await bridge.setDelayedInbox(inbox.address, true) 25 | await inbox.initialize(bridge.address, ethers.constants.AddressZero) 26 | } 27 | } 28 | 29 | module.exports.tags = ['InboxStub', 'test'] 30 | module.exports.dependencies = ['BridgeStub'] 31 | -------------------------------------------------------------------------------- /deploy/OneStepProofEntryCreator.js: -------------------------------------------------------------------------------- 1 | module.exports = async hre => { 2 | const { deployments, getNamedAccounts } = hre 3 | const { deploy } = deployments 4 | const { deployer } = await getNamedAccounts() 5 | 6 | await deploy('OneStepProofEntry', { 7 | from: deployer, 8 | args: [ 9 | (await deployments.get('OneStepProver0')).address, 10 | (await deployments.get('OneStepProverMemory')).address, 11 | (await deployments.get('OneStepProverMath')).address, 12 | (await deployments.get('OneStepProverHostIo')).address, 13 | ], 14 | }) 15 | } 16 | 17 | module.exports.tags = ['OneStepProofEntry'] 18 | module.exports.dependencies = [ 19 | 'OneStepProver0', 20 | 'OneStepProverMemory', 21 | 'OneStepProverMath', 22 | 'OneStepProverHostIo', 23 | ] 24 | -------------------------------------------------------------------------------- /deploy/OneStepProver0Creator.js: -------------------------------------------------------------------------------- 1 | module.exports = async hre => { 2 | const { deployments, getNamedAccounts } = hre 3 | const { deploy } = deployments 4 | const { deployer } = await getNamedAccounts() 5 | 6 | await deploy('OneStepProver0', { 7 | from: deployer, 8 | args: [], 9 | }) 10 | } 11 | 12 | module.exports.tags = ['OneStepProver0', 'live', 'test'] 13 | module.exports.dependencies = [] 14 | -------------------------------------------------------------------------------- /deploy/OneStepProverHostIoCreator.js: -------------------------------------------------------------------------------- 1 | module.exports = async hre => { 2 | const { deployments, getNamedAccounts, ethers } = hre 3 | const { deploy } = deployments 4 | const { deployer } = await getNamedAccounts() 5 | 6 | await deploy('OneStepProverHostIo', { 7 | from: deployer, 8 | args: [], 9 | }) 10 | } 11 | 12 | module.exports.tags = ['OneStepProverHostIo'] 13 | module.exports.dependencies = [] 14 | -------------------------------------------------------------------------------- /deploy/OneStepProverMathCreator.js: -------------------------------------------------------------------------------- 1 | module.exports = async hre => { 2 | const { deployments, getNamedAccounts } = hre 3 | const { deploy } = deployments 4 | const { deployer } = await getNamedAccounts() 5 | 6 | await deploy('OneStepProverMath', { 7 | from: deployer, 8 | args: [], 9 | }) 10 | } 11 | 12 | module.exports.tags = ['OneStepProverMath', 'live', 'test'] 13 | module.exports.dependencies = [] 14 | -------------------------------------------------------------------------------- /deploy/OneStepProverMemoryCreator.js: -------------------------------------------------------------------------------- 1 | module.exports = async hre => { 2 | const { deployments, getNamedAccounts } = hre 3 | const { deploy } = deployments 4 | const { deployer } = await getNamedAccounts() 5 | 6 | await deploy('OneStepProverMemory', { 7 | from: deployer, 8 | args: [], 9 | }) 10 | } 11 | 12 | module.exports.tags = ['OneStepProverMemory', 'live', 'test'] 13 | module.exports.dependencies = [] 14 | -------------------------------------------------------------------------------- /deploy/SequencerInbox.js: -------------------------------------------------------------------------------- 1 | module.exports = async hre => { 2 | const { deployments, getNamedAccounts, ethers } = hre 3 | const { deploy } = deployments 4 | const { deployer } = await getNamedAccounts() 5 | 6 | const blobBasefeeReader = await ethers.getContractAt( 7 | 'BlobBasefeeReader', 8 | ( 9 | await deployments.get('BlobBasefeeReader') 10 | ).address 11 | ) 12 | const dataHashReader = await ethers.getContractAt( 13 | 'DataHashReader', 14 | ( 15 | await deployments.get('DataHashReader') 16 | ).address 17 | ) 18 | 19 | await deploy('SequencerInbox', { from: deployer, args: [117964] }) 20 | } 21 | 22 | module.exports.tags = ['SequencerInbox'] 23 | module.exports.dependencies = [] 24 | -------------------------------------------------------------------------------- /deploy/SequencerInboxStubCreator.js: -------------------------------------------------------------------------------- 1 | import { Toolkit4844 } from '../test/contract/toolkit4844' 2 | 3 | module.exports = async hre => { 4 | const { deployments, getNamedAccounts, ethers } = hre 5 | const { deployer } = await getNamedAccounts() 6 | 7 | const bridge = await deployments.get('BridgeStub') 8 | const reader4844 = await Toolkit4844.deployReader4844( 9 | await ethers.getSigner(deployer) 10 | ) 11 | const maxTime = { 12 | delayBlocks: 10000, 13 | futureBlocks: 10000, 14 | delaySeconds: 10000, 15 | futureSeconds: 10000, 16 | } 17 | await deployments.deploy('SequencerInboxStub', { 18 | from: deployer, 19 | args: [ 20 | bridge.address, 21 | deployer, 22 | maxTime, 23 | 117964, 24 | reader4844.address, 25 | false, 26 | true, 27 | ], 28 | }) 29 | } 30 | 31 | module.exports.tags = ['SequencerInboxStub', 'test'] 32 | module.exports.dependencies = ['BridgeStub'] 33 | -------------------------------------------------------------------------------- /deploy/ValueArrayTesterCreator.js: -------------------------------------------------------------------------------- 1 | module.exports = async hre => { 2 | const { deployments, getNamedAccounts } = hre 3 | const { deploy } = deployments 4 | const { deployer } = await getNamedAccounts() 5 | 6 | await deploy('ValueArrayTester', { 7 | from: deployer, 8 | args: [], 9 | }) 10 | } 11 | 12 | module.exports.tags = ['ValueArrayTester', 'test'] 13 | module.exports.dependencies = [] 14 | -------------------------------------------------------------------------------- /foundry.toml: -------------------------------------------------------------------------------- 1 | [profile.default] 2 | src = 'src' 3 | out = 'out' 4 | libs = ['node_modules', 'lib'] 5 | test = 'test/foundry' 6 | cache_path = 'forge-cache/sol' 7 | optimizer = true 8 | optimizer_runs = 2000 9 | via_ir = false 10 | evm_version = 'cancun' 11 | remappings = ['ds-test/=lib/forge-std/lib/ds-test/src/', 12 | 'forge-std/=lib/forge-std/src/', 13 | '@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/', 14 | '@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/', 15 | '@offchainlabs/upgrade-executor/=node_modules/@offchainlabs/upgrade-executor/', 16 | '@uniswap/v2-core/=node_modules/@uniswap/v2-core/contracts', 17 | '@uniswap/lib/=node_modules/@uniswap/lib/contracts'] 18 | fs_permissions = [{ access = "read", path = "./"}] 19 | 20 | [profile.yul] 21 | src = 'yul' 22 | out = 'out/yul' 23 | libs = ['node_modules', 'lib'] 24 | cache_path = 'forge-cache/yul' 25 | remappings = [] 26 | auto_detect_remappings = false 27 | 28 | [fmt] 29 | line_length = 100 30 | tab_width = 4 31 | bracket_spacing = false 32 | int_types = "long" 33 | multiline_func_header = "params_first" 34 | quote_style = "double" 35 | number_underscore = "preserve" 36 | hex_underscore = "remove" 37 | single_line_statement_blocks = "preserve" 38 | override_spacing = false 39 | wrap_comments = false 40 | ignore = [] 41 | contract_new_lines = false 42 | sort_imports = false 43 | 44 | [fuzz] 45 | runs = 1000 46 | 47 | # See more config options https://github.com/foundry-rs/foundry/tree/master/config 48 | -------------------------------------------------------------------------------- /scripts/config.ts.example: -------------------------------------------------------------------------------- 1 | import { ethers } from 'ethers' 2 | 3 | // 90% of Geth's 128KB tx size limit, leaving ~13KB for proving 4 | // This need to be adjusted for Orbit chains 5 | export const maxDataSize = 117964 6 | 7 | export const isUsingFeeToken = false; 8 | 9 | export const config = { 10 | rollupConfig: { 11 | confirmPeriodBlocks: ethers.BigNumber.from('45818'), 12 | extraChallengeTimeBlocks: ethers.BigNumber.from('200'), 13 | stakeToken: ethers.constants.AddressZero, 14 | baseStake: ethers.utils.parseEther('1'), 15 | wasmModuleRoot: 16 | '0xda4e3ad5e7feacb817c21c8d0220da7650fe9051ece68a3f0b1c5d38bbb27b21', 17 | owner: '0x1234123412341234123412341234123412341234', 18 | loserStakeEscrow: ethers.constants.AddressZero, 19 | chainId: ethers.BigNumber.from('13331370'), 20 | minimumAssertionPeriod: 75, 21 | validatorAfkBlocks: 201600, 22 | chainConfig: 23 | '{"chainId":13331370,"homesteadBlock":0,"daoForkBlock":null,"daoForkSupport":true,"eip150Block":0,"eip150Hash":"0x0000000000000000000000000000000000000000000000000000000000000000","eip155Block":0,"eip158Block":0,"byzantiumBlock":0,"constantinopleBlock":0,"petersburgBlock":0,"istanbulBlock":0,"muirGlacierBlock":0,"berlinBlock":0,"londonBlock":0,"clique":{"period":0,"epoch":0},"arbitrum":{"EnableArbOS":true,"AllowDebugPrecompiles":false,"DataAvailabilityCommittee":false,"InitialArbOSVersion":10,"InitialChainOwner":"0x1234123412341234123412341234123412341234","GenesisBlockNum":0}}', 24 | genesisBlockNum: ethers.BigNumber.from('0'), 25 | sequencerInboxMaxTimeVariation: { 26 | delayBlocks: ethers.BigNumber.from('7200'), 27 | futureBlocks: ethers.BigNumber.from('12'), 28 | delaySeconds: ethers.BigNumber.from('86400'), 29 | futureSeconds: ethers.BigNumber.from('3600'), 30 | }, 31 | bufferConfig: { 32 | threshold: ethers.BigNumber.from('600'), 33 | max: ethers.BigNumber.from('14400'), 34 | replenishRateInBasis: ethers.BigNumber.from('833'), 35 | } 36 | }, 37 | validators: [ 38 | '0x1234123412341234123412341234123412341234', 39 | '0x1234512345123451234512345123451234512345', 40 | ], 41 | batchPosterManager: '0x1234123412341234123412341234123412341234', 42 | batchPosters: [ 43 | '0x1234123412341234123412341234123412341234' 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /scripts/createERC20Rollup.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from 'hardhat' 2 | import '@nomiclabs/hardhat-ethers' 3 | import { Signer } from 'ethers' 4 | import { createRollup } from './rollupCreation' 5 | import { TestToken__factory } from '../build/types' 6 | 7 | async function deployERC20Token(deployer: Signer): Promise { 8 | const factory = await new TestToken__factory(deployer).deploy( 9 | ethers.utils.parseEther('1000000000') 10 | ) 11 | const feeToken = await factory.deployed() 12 | 13 | return feeToken.address 14 | } 15 | 16 | async function main() { 17 | const [deployer] = await ethers.getSigners() 18 | 19 | let customFeeTokenAddress = process.env.FEE_TOKEN_ADDRESS 20 | if (!customFeeTokenAddress) { 21 | console.log( 22 | 'FEE_TOKEN_ADDRESS env var not provided, deploying new ERC20 token' 23 | ) 24 | customFeeTokenAddress = await deployERC20Token(deployer) 25 | } 26 | if (!ethers.utils.isAddress(customFeeTokenAddress)) { 27 | throw new Error( 28 | 'Fee token address ' + customFeeTokenAddress + ' is not a valid address!' 29 | ) 30 | } 31 | 32 | const rollupCreatorAddress = process.env.ROLLUP_CREATOR_ADDRESS 33 | if (!rollupCreatorAddress) { 34 | throw new Error('ROLLUP_CREATOR_ADDRESS not set') 35 | } 36 | const stakeTokenAddress = process.env.STAKE_TOKEN_ADDRESS 37 | if (!stakeTokenAddress) { 38 | throw new Error('STAKE_TOKEN_ADDRESS not set') 39 | } 40 | 41 | let feeTokenPricer = process.env.FEE_TOKEN_PRICER_ADDRESS 42 | if (!feeTokenPricer) { 43 | feeTokenPricer = ethers.constants.AddressZero 44 | } 45 | 46 | console.log( 47 | 'Creating new rollup with', 48 | customFeeTokenAddress, 49 | 'as fee token and', 50 | feeTokenPricer, 51 | 'as fee token pricer' 52 | ) 53 | await createRollup( 54 | deployer, 55 | false, 56 | rollupCreatorAddress, 57 | customFeeTokenAddress, 58 | feeTokenPricer, 59 | stakeTokenAddress 60 | ) 61 | } 62 | 63 | main() 64 | .then(() => process.exit(0)) 65 | .catch((error: Error) => { 66 | console.error(error) 67 | process.exit(1) 68 | }) 69 | -------------------------------------------------------------------------------- /scripts/createEthRollup.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from 'hardhat' 2 | import '@nomiclabs/hardhat-ethers' 3 | import { createRollup } from './rollupCreation' 4 | 5 | async function main() { 6 | const feeToken = ethers.constants.AddressZero 7 | const feeTokenPricer = ethers.constants.AddressZero 8 | const rollupCreatorAddress = process.env.ROLLUP_CREATOR_ADDRESS 9 | if (!rollupCreatorAddress) { 10 | throw new Error('ROLLUP_CREATOR_ADDRESS not set') 11 | } 12 | 13 | const stakeTokenAddress = process.env.STAKE_TOKEN_ADDRESS 14 | if (!stakeTokenAddress) { 15 | throw new Error('STAKE_TOKEN_ADDRESS not set') 16 | } 17 | 18 | const [signer] = await ethers.getSigners() 19 | 20 | await createRollup( 21 | signer, 22 | false, 23 | rollupCreatorAddress, 24 | feeToken, 25 | feeTokenPricer, 26 | stakeTokenAddress 27 | ) 28 | } 29 | 30 | main() 31 | .then(() => process.exit(0)) 32 | .catch((error: Error) => { 33 | console.error(error) 34 | process.exit(1) 35 | }) 36 | -------------------------------------------------------------------------------- /scripts/deployment.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from 'hardhat' 2 | import '@nomiclabs/hardhat-ethers' 3 | import { deployAllContracts, _isRunningOnArbitrum } from './deploymentUtils' 4 | import { maxDataSize } from './config' 5 | 6 | import { ArbSys__factory } from '../build/types' 7 | 8 | async function main() { 9 | const [signer] = await ethers.getSigners() 10 | 11 | console.log('Deploying contracts with maxDataSize:', maxDataSize) 12 | if (process.env['IGNORE_MAX_DATA_SIZE_WARNING'] !== 'true') { 13 | let isArbitrum = await _isRunningOnArbitrum(signer) 14 | if (isArbitrum && (maxDataSize as any) !== 104857) { 15 | throw new Error( 16 | 'maxDataSize should be 104857 when the parent chain is Arbitrum (set IGNORE_MAX_DATA_SIZE_WARNING to ignore)' 17 | ) 18 | } else if (!isArbitrum && (maxDataSize as any) !== 117964) { 19 | throw new Error( 20 | 'maxDataSize should be 117964 when the parent chain is not Arbitrum (set IGNORE_MAX_DATA_SIZE_WARNING to ignore)' 21 | ) 22 | } 23 | } else { 24 | console.log('Ignoring maxDataSize warning') 25 | } 26 | 27 | try { 28 | // Deploying all contracts 29 | const contracts = await deployAllContracts( 30 | signer, 31 | ethers.BigNumber.from(maxDataSize), 32 | true 33 | ) 34 | 35 | // Call setTemplates with the deployed contract addresses 36 | console.log('Waiting for the Template to be set on the Rollup Creator') 37 | await contracts.rollupCreator.setTemplates( 38 | contracts.bridgeCreator.address, 39 | contracts.osp.address, 40 | contracts.challengeManager.address, 41 | contracts.rollupAdmin.address, 42 | contracts.rollupUser.address, 43 | contracts.upgradeExecutor.address, 44 | contracts.validatorWalletCreator.address, 45 | contracts.deployHelper.address 46 | ) 47 | console.log('Template is set on the Rollup Creator') 48 | } catch (error) { 49 | console.error( 50 | 'Deployment failed:', 51 | error instanceof Error ? error.message : error 52 | ) 53 | } 54 | } 55 | 56 | main() 57 | .then(() => process.exit(0)) 58 | .catch((error: Error) => { 59 | console.error(error) 60 | process.exit(1) 61 | }) 62 | -------------------------------------------------------------------------------- /scripts/files/arb1DeployedContracts.json: -------------------------------------------------------------------------------- 1 | { 2 | "bridge": "0x93e8f92327bFa8096F5F6ee5f2a49183D3B3b898", 3 | "seqInbox": "0x98a58ADAb0f8A66A1BF4544d804bc0475dff32c7", 4 | "rei": "0x6D576E220Cb44C3E8eF75D0EfBeb1Ff041e2E4A5", 5 | "outbox": "0x3FFf9BdC3ce99d3D587b0d06Aa7C4a10075193b4", 6 | "inbox": "0x7C058ad1D0Ee415f7e7f30e62DB1BCf568470a10", 7 | "newRollupUser": "0x6490bA0a60Cc7d3a59C9eeE135D9eeD24553a60d", 8 | "newRollupAdmin": "0x7FC126FF51183a78C5E0437467f325f661D8Df17", 9 | "challengeManager": "0x058E1cBb62096189Bc7Cc1FE08A0859905d969Ea", 10 | "prover0": "0x35FBC5F03d86E88973B06Fb9C5a913D54AbdF731", 11 | "proverMem": "0xe0ba77e0E24de5369e3B268Ea79fDe716e2EC48b", 12 | "proverMath": "0xaB9596a0aaF28bc798c453434EC2DC0F8F0bF921", 13 | "proverHostIo": "0xa07cD154340CC74EcF156FFB9fb378Ee29Ca71Cf", 14 | "osp": "0x4397fE1E959Ba81B9D5f1A9679Ddd891955A42d6", 15 | "boldAction": "0xf795ec38701234664f69Dbd761Ee9c511F25ac1D", 16 | "preImageHashLookup": "0x43015a71C89C1C949cC25c9F1b8e761F1ac650fD" 17 | } 18 | -------------------------------------------------------------------------------- /scripts/files/configs/arb1.ts: -------------------------------------------------------------------------------- 1 | import { parseEther } from 'ethers/lib/utils' 2 | import { Config } from '../../boldUpgradeCommon' 3 | import { hoursToBlocks } from './utils' 4 | 5 | export const arb1: Config = { 6 | contracts: { 7 | // it both the excess stake receiver and loser stake escrow 8 | excessStakeReceiver: '0x40Cd7D713D7ae463f95cE5d342Ea6E7F5cF7C999', // parent to child router 9 | rollup: '0x5eF0D09d1E6204141B4d37530808eD19f60FBa35', 10 | bridge: '0x8315177aB297bA92A06054cE80a67Ed4DBd7ed3a', 11 | sequencerInbox: '0x1c479675ad559DC151F6Ec7ed3FbF8ceE79582B6', 12 | rollupEventInbox: '0x57Bd336d579A51938619271a7Cc137a46D0501B1', 13 | outbox: '0x0B9857ae2D4A3DBe74ffE1d7DF045bb7F96E4840', 14 | inbox: '0x4Dbd4fc535Ac27206064B68FfCf827b0A60BAB3f', 15 | upgradeExecutor: '0x3ffFbAdAF827559da092217e474760E2b2c3CeDd', 16 | }, 17 | proxyAdmins: { 18 | outbox: '0x554723262467f125ac9e1cdfa9ce15cc53822dbd', 19 | inbox: '0x554723262467f125ac9e1cdfa9ce15cc53822dbd', 20 | bridge: '0x554723262467f125ac9e1cdfa9ce15cc53822dbd', 21 | rei: '0x554723262467f125ac9e1cdfa9ce15cc53822dbd', 22 | seqInbox: '0x554723262467f125ac9e1cdfa9ce15cc53822dbd', 23 | }, 24 | settings: { 25 | challengeGracePeriodBlocks: hoursToBlocks(48), 26 | confirmPeriodBlocks: 45818, // same as old rollup, ~6.4 days 27 | challengePeriodBlocks: 45818, // same as confirm period 28 | stakeToken: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH 29 | stakeAmt: parseEther('3600'), 30 | miniStakeAmounts: [parseEther('0'), parseEther('555'), parseEther('79')], 31 | chainId: 42161, 32 | minimumAssertionPeriod: 75, 33 | validatorAfkBlocks: 201600, 34 | disableValidatorWhitelist: true, 35 | blockLeafSize: 2 ** 26, 36 | bigStepLeafSize: 2 ** 19, 37 | smallStepLeafSize: 2 ** 23, 38 | numBigStepLevel: 1, 39 | maxDataSize: 117964, 40 | isDelayBufferable: true, 41 | bufferConfig: { 42 | max: hoursToBlocks(48), // 2 days 43 | threshold: hoursToBlocks(0.5), // well above typical posting frequency 44 | replenishRateInBasis: 500, // 5% replenishment rate 45 | }, 46 | }, 47 | // validator whitelist will be disabled 48 | validators: [], 49 | } 50 | -------------------------------------------------------------------------------- /scripts/files/configs/custom.ts: -------------------------------------------------------------------------------- 1 | import { parseEther } from 'ethers/lib/utils' 2 | import { Config } from '../../boldUpgradeCommon' 3 | import { hoursToBlocks } from './utils' 4 | 5 | export const custom: Config = { 6 | contracts: { 7 | bridge: '', 8 | inbox: '', 9 | outbox: '', 10 | rollup: '', 11 | sequencerInbox: '', 12 | excessStakeReceiver: '', // receives losers' stake 13 | rollupEventInbox: '', 14 | upgradeExecutor: '', 15 | }, 16 | proxyAdmins: { 17 | outbox: '', // e.g. the address of the proxy admin for the outbox 18 | inbox: '', 19 | bridge: '', 20 | rei: '', 21 | seqInbox: '', 22 | }, 23 | settings: { 24 | challengeGracePeriodBlocks: hoursToBlocks(48), // 2 days for the chain owner to intervene in case of challenge 25 | confirmPeriodBlocks: 50400, // 7 days in terms of the parent chain's block.number timing 26 | challengePeriodBlocks: 50400, // same as confirm period 27 | stakeToken: '', // rollup stake token 28 | stakeAmt: parseEther('1'), // assertion stake amount 29 | miniStakeAmounts: [parseEther('0'), parseEther('1'), parseEther('1')], // subchallenge stake amounts (0 first level recommended) 30 | chainId: 42161, // child chain id 31 | minimumAssertionPeriod: 75, // minimum number of blocks between assertions 32 | validatorAfkBlocks: 201600, // number of blocks before validator whitelist is dropped due to inactivity 33 | disableValidatorWhitelist: false, // keep or disable validator whitelist 34 | blockLeafSize: 2 ** 26, // do not change unless you know what you're doing 35 | bigStepLeafSize: 2 ** 19, // do not change unless you know what you're doing 36 | smallStepLeafSize: 2 ** 23, // do not change unless you know what you're doing 37 | numBigStepLevel: 1, // do not change unless you know what you're doing 38 | maxDataSize: 117964, // if you're an L3, this should be set to 104857 39 | isDelayBufferable: true, // it is recommended to keep this as true, even if you don't use the feature 40 | bufferConfig: { 41 | max: 2 ** 32 - 1, // maximum buffer size, set artificially high to disable 42 | threshold: 2 ** 32 - 1, // keep above typical posting frequency. set artificially high to disable 43 | replenishRateInBasis: 500, // 5% replenishment rate 44 | }, 45 | }, 46 | // validators to be whitelisted on the new rollup 47 | validators: [], 48 | } 49 | -------------------------------------------------------------------------------- /scripts/files/configs/index.ts: -------------------------------------------------------------------------------- 1 | import { arb1 } from './arb1' 2 | import { nova } from './nova' 3 | import { sepolia } from './sepolia' 4 | import { local } from './local' 5 | import { custom } from './custom' 6 | 7 | export const configs = { 8 | arb1, 9 | nova, 10 | sepolia, 11 | local, 12 | custom, 13 | } 14 | -------------------------------------------------------------------------------- /scripts/files/configs/local.ts: -------------------------------------------------------------------------------- 1 | import { parseEther } from 'ethers/lib/utils' 2 | import { Config } from '../../boldUpgradeCommon' 3 | import { hoursToBlocks } from './utils' 4 | 5 | export const local: Config = { 6 | contracts: { 7 | bridge: '0x5eCF728ffC5C5E802091875f96281B5aeECf6C49', 8 | inbox: '0x9f8c1c641336A371031499e3c362e40d58d0f254', 9 | outbox: '0x50143333b44Ea46255BEb67255C9Afd35551072F', 10 | rollup: '0x3A052fF29EAFdd226Df1C4824d51A56a8Ad5D7A4', 11 | sequencerInbox: '0x18d19C5d3E685f5be5b9C86E097f0E439285D216', 12 | rollupEventInbox: '0x0e73faf857e1ca53e700856fcf19f31f920a1e3c', 13 | upgradeExecutor: '0x513d9f96d4d0563debae8a0dc307ea0e46b10ed7', 14 | excessStakeReceiver: '0xC3124dD1FA0e5D6135c25279760DBF9d9286467B', 15 | }, 16 | proxyAdmins: { 17 | outbox: '0x2a1f38c9097e7883570e0b02bfbe6869cc25d8a3', 18 | inbox: '0x2a1f38c9097e7883570e0b02bfbe6869cc25d8a3', 19 | bridge: '0x2a1f38c9097e7883570e0b02bfbe6869cc25d8a3', 20 | rei: '0x2a1f38c9097e7883570e0b02bfbe6869cc25d8a3', 21 | seqInbox: '0x2a1f38c9097e7883570e0b02bfbe6869cc25d8a3', 22 | }, 23 | settings: { 24 | challengeGracePeriodBlocks: 10, 25 | confirmPeriodBlocks: 100, 26 | challengePeriodBlocks: 110, 27 | stakeToken: '0x408Da76E87511429485C32E4Ad647DD14823Fdc4', 28 | stakeAmt: parseEther('1'), 29 | miniStakeAmounts: [ 30 | parseEther('6'), 31 | parseEther('5'), 32 | parseEther('4'), 33 | parseEther('3'), 34 | parseEther('2'), 35 | parseEther('1'), 36 | ], 37 | chainId: 412346, 38 | minimumAssertionPeriod: 0, 39 | validatorAfkBlocks: 201600, 40 | disableValidatorWhitelist: true, 41 | blockLeafSize: 1048576, 42 | bigStepLeafSize: 512, 43 | smallStepLeafSize: 128, 44 | numBigStepLevel: 4, 45 | maxDataSize: 117964, 46 | isDelayBufferable: true, 47 | bufferConfig: { 48 | max: 2 ** 32, // effectively disableing and will be enabled later 49 | threshold: 2 ** 32, // effectively disableing and will be enabled later 50 | replenishRateInBasis: 500, 51 | }, 52 | }, 53 | validators: ['0x139A0b6B1Dd1e7F912361B32A09cAD89e82F29db'], 54 | } 55 | -------------------------------------------------------------------------------- /scripts/files/configs/sepolia.ts: -------------------------------------------------------------------------------- 1 | import { parseEther } from 'ethers/lib/utils' 2 | import { Config } from '../../boldUpgradeCommon' 3 | import { hoursToBlocks } from './utils' 4 | 5 | export const sepolia: Config = { 6 | contracts: { 7 | excessStakeReceiver: '0x391611E7bba966000AC6c78aFc673C4AE46f8BCa', // chain owner multisig 8 | rollup: '0xd80810638dbDF9081b72C1B33c65375e807281C8', 9 | bridge: '0x38f918D0E9F1b721EDaA41302E399fa1B79333a9', 10 | sequencerInbox: '0x6c97864CE4bEf387dE0b3310A44230f7E3F1be0D', 11 | rollupEventInbox: '0xD5B196dd7EC4D823ff5F695536c61f7c8E642B94', 12 | outbox: '0x65f07C7D521164a4d5DaC6eB8Fac8DA067A3B78F', 13 | inbox: '0xaAe29B0366299461418F5324a79Afc425BE5ae21', 14 | upgradeExecutor: '0x5FEe78FE9AD96c1d8557C6D6BB22Eb5A61eeD315', 15 | }, 16 | proxyAdmins: { 17 | outbox: '0xdd63bcaa89d7c3199ef220c1dd59c49f821078b8', 18 | inbox: '0xdd63bcaa89d7c3199ef220c1dd59c49f821078b8', 19 | bridge: '0xdd63bcaa89d7c3199ef220c1dd59c49f821078b8', 20 | rei: '0xdd63bcaa89d7c3199ef220c1dd59c49f821078b8', 21 | seqInbox: '0xdd63bcaa89d7c3199ef220c1dd59c49f821078b8', 22 | }, 23 | settings: { 24 | challengeGracePeriodBlocks: hoursToBlocks(48), // same as arb1 25 | confirmPeriodBlocks: 20, // current is 20 blocks, 45818 is arb1 config 26 | challengePeriodBlocks: 45818, // same as arb1 27 | stakeToken: '0xefb383126640fe4a760010c6e59c397d2b6c7141', // WETH 28 | stakeAmt: parseEther('36'), // 1/100th of arb1, same for mini stakes 29 | miniStakeAmounts: [parseEther('0'), parseEther('5.5'), parseEther('0.79')], 30 | chainId: 421614, 31 | minimumAssertionPeriod: 75, 32 | validatorAfkBlocks: 201600, 33 | disableValidatorWhitelist: false, 34 | blockLeafSize: 2 ** 26, // leaf sizes same as arb1 35 | bigStepLeafSize: 2 ** 19, 36 | smallStepLeafSize: 2 ** 23, 37 | numBigStepLevel: 1, 38 | maxDataSize: 117964, 39 | isDelayBufferable: true, 40 | bufferConfig: { 41 | max: 2 ** 32, // effectively disableing and will be enabled later 42 | threshold: 2 ** 32, // effectively disableing and will be enabled later 43 | replenishRateInBasis: 500, // 5% replenishment rate 44 | }, 45 | }, 46 | // these validators must still be validators on the old rollup during the upgrade, or the upgrade will fail 47 | validators: [ 48 | // current validators 49 | '0x8a8f0a24d7e58a76FC8F77bb68C7c902b91e182e', 50 | '0x87630025E63A30eCf9Ca9d580d9D95922Fea6aF0', 51 | '0xC32B93e581db6EBc50C08ce381143A259B92f1ED', 52 | ], 53 | } 54 | -------------------------------------------------------------------------------- /scripts/files/configs/utils.ts: -------------------------------------------------------------------------------- 1 | export function hoursToBlocks(hours: number, blockTime = 12) { 2 | const x = (hours * 3600) / blockTime 3 | if (x !== Math.floor(x)) { 4 | throw new Error('hours must be divisible by blockTime') 5 | } 6 | if (x === 0) { 7 | throw new Error('hours must be greater than 0') 8 | } 9 | return x 10 | } 11 | -------------------------------------------------------------------------------- /scripts/files/novaDeployedContracts.json: -------------------------------------------------------------------------------- 1 | { 2 | "bridge": "0x93e8f92327bFa8096F5F6ee5f2a49183D3B3b898", 3 | "seqInbox": "0x98a58ADAb0f8A66A1BF4544d804bc0475dff32c7", 4 | "rei": "0x6D576E220Cb44C3E8eF75D0EfBeb1Ff041e2E4A5", 5 | "outbox": "0x3FFf9BdC3ce99d3D587b0d06Aa7C4a10075193b4", 6 | "inbox": "0x7C058ad1D0Ee415f7e7f30e62DB1BCf568470a10", 7 | "newRollupUser": "0x6490bA0a60Cc7d3a59C9eeE135D9eeD24553a60d", 8 | "newRollupAdmin": "0x7FC126FF51183a78C5E0437467f325f661D8Df17", 9 | "challengeManager": "0x058E1cBb62096189Bc7Cc1FE08A0859905d969Ea", 10 | "prover0": "0x35FBC5F03d86E88973B06Fb9C5a913D54AbdF731", 11 | "proverMem": "0xe0ba77e0E24de5369e3B268Ea79fDe716e2EC48b", 12 | "proverMath": "0xaB9596a0aaF28bc798c453434EC2DC0F8F0bF921", 13 | "proverHostIo": "0xa07cD154340CC74EcF156FFB9fb378Ee29Ca71Cf", 14 | "osp": "0x4397fE1E959Ba81B9D5f1A9679Ddd891955A42d6", 15 | "boldAction": "0xd25B258B55765c9fb5567eCABB6114b03b0f78b5", 16 | "preImageHashLookup": "0x335D7d7f5DB556dAE51857424E36C0878B23a11d" 17 | } 18 | -------------------------------------------------------------------------------- /scripts/files/sepoliaDeployedContracts.json: -------------------------------------------------------------------------------- 1 | { 2 | "bridge": "0xED26e46f38957763f83f2C45f6Fb6702cfEBc7D8", 3 | "seqInbox": "0xBBb2EF6dD70759F6c335c116895c6749ec7427da", 4 | "rei": "0x53554562D5B4B02aeFaE6489481D6fc3C3Fa995B", 5 | "outbox": "0xFeD2027E956fa0a1F367c03a20555839441E224f", 6 | "inbox": "0x4B31D35CE007C9744E71dB8fc649629f3B7C619E", 7 | "newRollupUser": "0xDC2f809Bba33Cbb96a5EA8e9EE2DD4cB104E0BA5", 8 | "newRollupAdmin": "0x3b7aEa898C7F51551DAAff4dae8aB0F553f2AEF8", 9 | "challengeManager": "0xC14422cCa7D6462CCBeA5FEEc08ffbae66713fFE", 10 | "prover0": "0x3Fe73F959C44e04d660dBFBbeffd51FD2c091377", 11 | "proverMem": "0x6268Fc8dB1b5083b405b2C51808Df3619783ec2d", 12 | "proverMath": "0x42f58c90583eC3fA0E0b724dEDF755AE1068e8Fa", 13 | "proverHostIo": "0xdB2c541e20Bd1830c8a050341Fca0Af51489C165", 14 | "osp": "0xB9cf664A1beD8F74f4B893a18c86eCe876CdAE80", 15 | "boldAction": "0xf8199Ca3702C09c78B957D4D820311125753C6d2", 16 | "preImageHashLookup": "0x421f2cE0f49095EB8d50aCB903799845C7315fb9" 17 | } 18 | -------------------------------------------------------------------------------- /scripts/local-deployment/deployCacheManager.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from 'hardhat' 2 | import '@nomiclabs/hardhat-ethers' 3 | import { deployAndSetCacheManager } from '../deploymentUtils' 4 | 5 | async function main() { 6 | /// read env vars needed for deployment 7 | let chainOwnerPrivKey = process.env.CHAIN_OWNER_PRIVKEY as string 8 | if (!chainOwnerPrivKey) { 9 | throw new Error('CHAIN_OWNER_PRIVKEY not set') 10 | } 11 | 12 | const childChainRpc = process.env.CHILD_CHAIN_RPC as string 13 | if (!childChainRpc) { 14 | throw new Error('CHILD_CHAIN_RPC not set') 15 | } 16 | 17 | const chainOwnerWallet = new ethers.Wallet( 18 | chainOwnerPrivKey, 19 | new ethers.providers.JsonRpcProvider(childChainRpc) 20 | ) 21 | 22 | // deploy cache manager 23 | const cacheManager = await deployAndSetCacheManager(chainOwnerWallet, false) 24 | console.log('Cache manager deployed at:', cacheManager.address) 25 | } 26 | 27 | main() 28 | .then(() => process.exit(0)) 29 | .catch((error: Error) => { 30 | console.error(error) 31 | process.exit(1) 32 | }) 33 | -------------------------------------------------------------------------------- /scripts/populateLookup.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from 'hardhat' 2 | import { Wallet } from 'ethers' 3 | import { DeployedContracts, getConfig, getJsonFile } from './boldUpgradeCommon' 4 | import { populateLookup } from './boldUpgradeFunctions' 5 | import dotenv from 'dotenv' 6 | import path from 'path' 7 | 8 | dotenv.config() 9 | 10 | async function main() { 11 | const l1Rpc = ethers.provider 12 | 13 | const l1PrivKey = process.env.L1_PRIV_KEY 14 | if (!l1PrivKey) { 15 | throw new Error('L1_PRIV_KEY env variable not set') 16 | } 17 | const wallet = new Wallet(l1PrivKey, l1Rpc) 18 | 19 | const configNetworkName = process.env.CONFIG_NETWORK_NAME 20 | if (!configNetworkName) { 21 | throw new Error('CONFIG_NETWORK_NAME env variable not set') 22 | } 23 | const config = await getConfig(configNetworkName, l1Rpc) 24 | 25 | const deployedContractsDir = process.env.DEPLOYED_CONTRACTS_DIR 26 | if (!deployedContractsDir) { 27 | throw new Error('DEPLOYED_CONTRACTS_DIR env variable not set') 28 | } 29 | const deployedContractsLocation = path.join( 30 | deployedContractsDir, 31 | configNetworkName + 'DeployedContracts.json' 32 | ) 33 | const deployedContracts = getJsonFile( 34 | deployedContractsLocation 35 | ) as DeployedContracts 36 | if (!deployedContracts?.preImageHashLookup) { 37 | throw new Error( 38 | 'preImageHashLookup not found in ' + deployedContractsLocation 39 | ) 40 | } 41 | 42 | await populateLookup( 43 | wallet, 44 | config.contracts.rollup, 45 | deployedContracts.preImageHashLookup 46 | ) 47 | } 48 | 49 | // execute this script just prior to execution of the bold upgrade 50 | // it populates the hash lookup contract necessary preimages 51 | main().then(() => console.log('Done.')) 52 | -------------------------------------------------------------------------------- /scripts/prepareBoldUpgrade.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from 'hardhat' 2 | import { Wallet } from 'ethers' 3 | import fs from 'fs' 4 | import { DeployedContracts, getConfig, getJsonFile } from './boldUpgradeCommon' 5 | import { deployBoldUpgrade } from './boldUpgradeFunctions' 6 | import dotenv from 'dotenv' 7 | import path from 'path' 8 | 9 | dotenv.config() 10 | 11 | async function main() { 12 | const l1Rpc = ethers.provider 13 | 14 | const l1PrivKey = process.env.L1_PRIV_KEY 15 | if (!l1PrivKey) { 16 | throw new Error('L1_PRIV_KEY env variable not set') 17 | } 18 | const wallet = new Wallet(l1PrivKey, l1Rpc) 19 | 20 | const configNetworkName = process.env.CONFIG_NETWORK_NAME 21 | if (!configNetworkName) { 22 | throw new Error('CONFIG_NETWORK_NAME env variable not set') 23 | } 24 | const config = await getConfig(configNetworkName, l1Rpc) 25 | 26 | const deployedContractsDir = process.env.DEPLOYED_CONTRACTS_DIR 27 | if (!deployedContractsDir) { 28 | throw new Error('DEPLOYED_CONTRACTS_DIR env variable not set') 29 | } 30 | const deployedContractsLocation = path.join( 31 | deployedContractsDir, 32 | configNetworkName + 'DeployedContracts.json' 33 | ) 34 | 35 | // if the deployed contracts exists then we load it and combine 36 | // if not, then we just use the newly created item 37 | let existingDeployedContracts = {} 38 | try { 39 | existingDeployedContracts = getJsonFile( 40 | deployedContractsLocation 41 | ) as DeployedContracts 42 | } catch (err) {} 43 | 44 | const disableVerification = process.env.DISABLE_VERIFICATION === 'true' 45 | const deployedAndBold = await deployBoldUpgrade( 46 | wallet, 47 | config, 48 | true, 49 | !disableVerification 50 | ) 51 | 52 | console.log(`Deployed contracts written to: ${deployedContractsLocation}`) 53 | fs.writeFileSync( 54 | deployedContractsLocation, 55 | JSON.stringify( 56 | { ...existingDeployedContracts, ...deployedAndBold }, 57 | null, 58 | 2 59 | ) 60 | ) 61 | } 62 | 63 | main().then(() => console.log('Done.')) 64 | -------------------------------------------------------------------------------- /scripts/testUpgrade.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ANVILFORK=true 4 | export ANVILFORK 5 | 6 | anvil --fork-url $L1_RPC > /dev/null & 7 | 8 | anvil_pid=$! 9 | 10 | yarn script:bold-prepare && \ 11 | yarn script:bold-populate-lookup && \ 12 | yarn script:bold-local-execute 13 | 14 | ecode=$? 15 | 16 | kill $anvil_pid 17 | 18 | exit $ecode -------------------------------------------------------------------------------- /slither.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "exclude_dependencies": true, 3 | "exclude_informational": true, 4 | "exclude_low": true, 5 | "exclude_optimization": true, 6 | "filter_paths": "src/test-helpers/|src/mocks/|node_modules/" 7 | } 8 | -------------------------------------------------------------------------------- /src/assertionStakingPool/AssertionStakingPoolCreator.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | // 5 | pragma solidity ^0.8.0; 6 | 7 | import "./AssertionStakingPool.sol"; 8 | import "./StakingPoolCreatorUtils.sol"; 9 | import "./interfaces/IAssertionStakingPoolCreator.sol"; 10 | 11 | /// @notice Creates staking pool contract for a target assertion. Can be used for any child Arbitrum chain running on top of the deployed AssertionStakingPoolCreator's chain. 12 | contract AssertionStakingPoolCreator is IAssertionStakingPoolCreator { 13 | /// @inheritdoc IAssertionStakingPoolCreator 14 | function createPool( 15 | address _rollup, 16 | bytes32 _assertionHash 17 | ) external returns (IAssertionStakingPool) { 18 | AssertionStakingPool assertionPool = 19 | new AssertionStakingPool{salt: 0}(_rollup, _assertionHash); 20 | emit NewAssertionPoolCreated(_rollup, _assertionHash, address(assertionPool)); 21 | return assertionPool; 22 | } 23 | 24 | /// @inheritdoc IAssertionStakingPoolCreator 25 | function getPool( 26 | address _rollup, 27 | bytes32 _assertionHash 28 | ) public view returns (IAssertionStakingPool) { 29 | return IAssertionStakingPool( 30 | StakingPoolCreatorUtils.getPool( 31 | type(AssertionStakingPool).creationCode, abi.encode(_rollup, _assertionHash) 32 | ) 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/assertionStakingPool/EdgeStakingPool.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "./AbsBoldStakingPool.sol"; 8 | import "./interfaces/IEdgeStakingPool.sol"; 9 | 10 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 11 | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 12 | 13 | /// @notice Trustless staking pool contract for creating layer zero edges. 14 | /// 15 | /// Allows users to deposit stake, create an edge once required stake amount is reached, 16 | /// and reclaim their stake when and if the edge is confirmed. 17 | /// 18 | /// Tokens sent directly to this contract will be lost. 19 | /// It is assumed that the challenge manager will not return more tokens than the amount deposited by the pool. 20 | /// Any tokens exceeding the deposited amount to the pool will be stuck in the pool forever. 21 | /// 22 | /// @dev Unlike the assertion staking pool, there is no need for a function to claim the stake back into the pool. 23 | /// (see `EdgeChallengeManager.refundStake(bytes32 edgeId)`) 24 | contract EdgeStakingPool is AbsBoldStakingPool, IEdgeStakingPool { 25 | using SafeERC20 for IERC20; 26 | 27 | /// @inheritdoc IEdgeStakingPool 28 | address public immutable challengeManager; 29 | /// @inheritdoc IEdgeStakingPool 30 | bytes32 public immutable edgeId; 31 | 32 | /// @param _challengeManager EdgeChallengeManager contract 33 | /// @param _edgeId The ID of the edge to be created (see ChallengeEdgeLib.id) 34 | constructor( 35 | address _challengeManager, 36 | bytes32 _edgeId 37 | ) AbsBoldStakingPool(address(IEdgeChallengeManager(_challengeManager).stakeToken())) { 38 | if (_edgeId == bytes32(0)) { 39 | revert EmptyEdgeId(); 40 | } 41 | challengeManager = _challengeManager; 42 | edgeId = _edgeId; 43 | } 44 | 45 | /// @inheritdoc IEdgeStakingPool 46 | function createEdge( 47 | CreateEdgeArgs calldata args 48 | ) external { 49 | uint256 requiredStake = IEdgeChallengeManager(challengeManager).stakeAmounts(args.level); 50 | IERC20(stakeToken).safeIncreaseAllowance(address(challengeManager), requiredStake); 51 | bytes32 newEdgeId = IEdgeChallengeManager(challengeManager).createLayerZeroEdge(args); 52 | if (newEdgeId != edgeId) { 53 | revert IncorrectEdgeId(newEdgeId, edgeId); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/assertionStakingPool/EdgeStakingPoolCreator.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | // 5 | pragma solidity ^0.8.0; 6 | 7 | import "./EdgeStakingPool.sol"; 8 | import "./StakingPoolCreatorUtils.sol"; 9 | import "./interfaces/IEdgeStakingPoolCreator.sol"; 10 | 11 | /// @notice Creates EdgeStakingPool contracts. 12 | contract EdgeStakingPoolCreator is IEdgeStakingPoolCreator { 13 | /// @inheritdoc IEdgeStakingPoolCreator 14 | function createPool( 15 | address challengeManager, 16 | bytes32 edgeId 17 | ) external returns (IEdgeStakingPool) { 18 | EdgeStakingPool pool = new EdgeStakingPool{salt: 0}(challengeManager, edgeId); 19 | emit NewEdgeStakingPoolCreated(challengeManager, edgeId); 20 | return pool; 21 | } 22 | 23 | /// @inheritdoc IEdgeStakingPoolCreator 24 | function getPool( 25 | address challengeManager, 26 | bytes32 edgeId 27 | ) public view returns (IEdgeStakingPool) { 28 | return IEdgeStakingPool( 29 | StakingPoolCreatorUtils.getPool( 30 | type(EdgeStakingPool).creationCode, abi.encode(challengeManager, edgeId) 31 | ) 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/assertionStakingPool/StakingPoolCreatorUtils.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | // 5 | pragma solidity ^0.8.0; 6 | 7 | import "@openzeppelin/contracts/utils/Create2.sol"; 8 | import "@openzeppelin/contracts/utils/Address.sol"; 9 | 10 | library StakingPoolCreatorUtils { 11 | error PoolDoesntExist(); 12 | 13 | function getPool( 14 | bytes memory creationCode, 15 | bytes memory args 16 | ) internal view returns (address) { 17 | bytes32 bytecodeHash = keccak256(abi.encodePacked(creationCode, args)); 18 | address pool = Create2.computeAddress(0, bytecodeHash, address(this)); 19 | if (Address.isContract(pool)) { 20 | return pool; 21 | } else { 22 | revert PoolDoesntExist(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/assertionStakingPool/interfaces/IAbsBoldStakingPool.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | interface IAbsBoldStakingPool { 8 | /// @notice Emitted when stake is deposited 9 | event StakeDeposited(address indexed sender, uint256 amount); 10 | /// @notice Emitted when stake is withdrawn 11 | event StakeWithdrawn(address indexed sender, uint256 amount); 12 | 13 | /// @notice Cannot deposit or withdraw zero amount 14 | error ZeroAmount(); 15 | /// @notice Withdraw amount exceeds balance 16 | error AmountExceedsBalance(address account, uint256 amount, uint256 balance); 17 | 18 | /// @notice Deposit stake into pool contract. 19 | /// @param amount amount of stake token to deposit 20 | function depositIntoPool( 21 | uint256 amount 22 | ) external; 23 | 24 | /// @notice Send supplied amount of stake from this contract back to its depositor. 25 | /// @param amount stake amount to withdraw 26 | function withdrawFromPool( 27 | uint256 amount 28 | ) external; 29 | 30 | /// @notice Send full balance of stake from this contract back to its depositor. 31 | function withdrawFromPool() external; 32 | 33 | /// @notice The token that is used for staking 34 | function stakeToken() external view returns (address); 35 | 36 | /// @notice The balance of the given account 37 | /// @param account The account to check the balance of 38 | function depositBalance( 39 | address account 40 | ) external view returns (uint256); 41 | } 42 | -------------------------------------------------------------------------------- /src/assertionStakingPool/interfaces/IAssertionStakingPool.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "../../rollup/IRollupLogic.sol"; 8 | import "./IAbsBoldStakingPool.sol"; 9 | 10 | interface IAssertionStakingPool is IAbsBoldStakingPool { 11 | /// @notice Thrown when assertion id is empty 12 | error EmptyAssertionId(); 13 | 14 | /// @notice Create assertion. Callable only if required stake has been reached and assertion has not been asserted yet. 15 | function createAssertion( 16 | AssertionInputs calldata assertionInputs 17 | ) external; 18 | 19 | /// @notice Make stake withdrawable. 20 | /// @dev Separate call from withdrawStakeBackIntoPool since returnOldDeposit reverts with 0 balance (in e.g., case of admin forceRefundStaker) 21 | function makeStakeWithdrawable() external; 22 | 23 | /// @notice Move stake back from rollup contract to this contract. 24 | /// Callable only if this contract has already created an assertion and it's now inactive. 25 | /// @dev Separate call from makeStakeWithdrawable since returnOldDeposit reverts with 0 balance (in e.g., case of admin forceRefundStaker) 26 | function withdrawStakeBackIntoPool() external; 27 | 28 | /// @notice Combines makeStakeWithdrawable and withdrawStakeBackIntoPool into single call 29 | function makeStakeWithdrawableAndWithdrawBackIntoPool() external; 30 | 31 | /// @notice The targeted rollup contract 32 | function rollup() external view returns (address); 33 | 34 | /// @notice The assertion hash that this pool creates 35 | function assertionHash() external view returns (bytes32); 36 | } 37 | -------------------------------------------------------------------------------- /src/assertionStakingPool/interfaces/IAssertionStakingPoolCreator.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "../../rollup/IRollupLogic.sol"; 8 | import "./IAssertionStakingPool.sol"; 9 | 10 | interface IAssertionStakingPoolCreator { 11 | /// @notice Event emitted when a new staking pool is created 12 | event NewAssertionPoolCreated( 13 | address indexed rollup, bytes32 indexed _assertionHash, address assertionPool 14 | ); 15 | 16 | /// @notice Create a staking pool contract 17 | /// @param _rollup Rollup contract of target chain 18 | /// @param _assertionHash Assertion hash to be passed into Rollup.stakeOnNewAssertion 19 | function createPool( 20 | address _rollup, 21 | bytes32 _assertionHash 22 | ) external returns (IAssertionStakingPool); 23 | 24 | /// @notice get staking pool deployed with provided inputs; reverts if pool contract doesn't exist. 25 | /// @param _rollup Rollup contract of target chain 26 | /// @param _assertionHash Assertion hash to be passed into Rollup.stakeOnNewAssertion 27 | function getPool( 28 | address _rollup, 29 | bytes32 _assertionHash 30 | ) external view returns (IAssertionStakingPool); 31 | } 32 | -------------------------------------------------------------------------------- /src/assertionStakingPool/interfaces/IEdgeStakingPool.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "../../challengeV2/IEdgeChallengeManager.sol"; 8 | import "./IAbsBoldStakingPool.sol"; 9 | 10 | interface IEdgeStakingPool is IAbsBoldStakingPool { 11 | /// @notice The resulting edge does not match the expected edge 12 | error IncorrectEdgeId(bytes32 actual, bytes32 expected); 13 | 14 | /// @notice Thrown when edge id is empty 15 | error EmptyEdgeId(); 16 | 17 | /// @notice Create the edge. Callable only if required stake has been reached and edge has not been created yet. 18 | function createEdge( 19 | CreateEdgeArgs calldata args 20 | ) external; 21 | 22 | /// @notice The targeted challenge manager contract 23 | function challengeManager() external view returns (address); 24 | 25 | /// @notice The edge that this pool will create 26 | function edgeId() external view returns (bytes32); 27 | } 28 | -------------------------------------------------------------------------------- /src/assertionStakingPool/interfaces/IEdgeStakingPoolCreator.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "./IEdgeStakingPool.sol"; 8 | 9 | interface IEdgeStakingPoolCreator { 10 | /// @notice Event emitted when a new staking pool is created 11 | event NewEdgeStakingPoolCreated(address indexed challengeManager, bytes32 indexed edgeId); 12 | 13 | /// @notice Create an edge staking pool contract 14 | /// @param challengeManager EdgeChallengeManager contract 15 | /// @param edgeId The ID of the edge to be created (see ChallengeEdgeLib.id) 16 | function createPool( 17 | address challengeManager, 18 | bytes32 edgeId 19 | ) external returns (IEdgeStakingPool); 20 | 21 | /// @notice get staking pool deployed with provided inputs; reverts if pool contract doesn't exist. 22 | /// @param challengeManager EdgeChallengeManager contract 23 | /// @param edgeId The ID of the edge to be created (see ChallengeEdgeLib.id) 24 | function getPool( 25 | address challengeManager, 26 | bytes32 edgeId 27 | ) external view returns (IEdgeStakingPool); 28 | } 29 | -------------------------------------------------------------------------------- /src/bridge/Bridge.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.4; 6 | 7 | import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; 8 | import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; 9 | import "./AbsBridge.sol"; 10 | import "./IEthBridge.sol"; 11 | import "./Messages.sol"; 12 | import "../libraries/DelegateCallAware.sol"; 13 | 14 | /** 15 | * @title Staging ground for incoming and outgoing messages 16 | * @notice It is also the ETH escrow for value sent with these messages. 17 | */ 18 | contract Bridge is AbsBridge, IEthBridge { 19 | using AddressUpgradeable for address; 20 | 21 | /// @inheritdoc IEthBridge 22 | function initialize( 23 | IOwnable rollup_ 24 | ) external initializer onlyDelegated { 25 | _activeOutbox = EMPTY_ACTIVEOUTBOX; 26 | rollup = rollup_; 27 | } 28 | 29 | /// @inheritdoc IEthBridge 30 | function enqueueDelayedMessage( 31 | uint8 kind, 32 | address sender, 33 | bytes32 messageDataHash 34 | ) external payable returns (uint256) { 35 | return _enqueueDelayedMessage(kind, sender, messageDataHash, msg.value); 36 | } 37 | 38 | function _transferFunds( 39 | uint256 40 | ) internal override { 41 | // do nothing as Eth transfer is part of TX execution 42 | } 43 | 44 | function _executeLowLevelCall( 45 | address to, 46 | uint256 value, 47 | bytes memory data 48 | ) internal override returns (bool success, bytes memory returnData) { 49 | // solhint-disable-next-line avoid-low-level-calls 50 | (success, returnData) = to.call{value: value}(data); 51 | } 52 | 53 | function _baseFeeToReport() internal view override returns (uint256) { 54 | return block.basefee; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/bridge/DelayBufferTypes.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | import "./Messages.sol"; 6 | 7 | pragma solidity >=0.6.9 <0.9.0; 8 | 9 | /// @notice Delay buffer and delay threshold settings 10 | /// @param threshold The maximum amount of blocks that a message is expected to be delayed 11 | /// @param max The maximum buffer in blocks 12 | /// @param replenishRateInBasis The amount to replenish the buffer per block in basis points. 13 | struct BufferConfig { 14 | uint64 threshold; 15 | uint64 max; 16 | uint64 replenishRateInBasis; 17 | } 18 | 19 | /// @notice The delay buffer data. 20 | /// @param bufferBlocks The buffer in blocks. 21 | /// @param max The maximum buffer in blocks 22 | /// @param threshold The maximum amount of blocks that a message is expected to be delayed 23 | /// @param prevBlockNumber The blocknumber of the last included delay message. 24 | /// @param replenishRateInBasis The amount to replenish the buffer per block in basis points. 25 | /// @param prevSequencedBlockNumber The blocknumber when last included delay message was sequenced. 26 | struct BufferData { 27 | uint64 bufferBlocks; 28 | uint64 max; 29 | uint64 threshold; 30 | uint64 prevBlockNumber; 31 | uint64 replenishRateInBasis; 32 | uint64 prevSequencedBlockNumber; 33 | } 34 | 35 | struct DelayProof { 36 | bytes32 beforeDelayedAcc; 37 | Messages.Message delayedMessage; 38 | } 39 | -------------------------------------------------------------------------------- /src/bridge/ERC20Outbox.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.4; 6 | 7 | import "./AbsOutbox.sol"; 8 | import {IERC20Bridge} from "./IERC20Bridge.sol"; 9 | import {DecimalsConverterHelper} from "../libraries/DecimalsConverterHelper.sol"; 10 | 11 | contract ERC20Outbox is AbsOutbox { 12 | /// @dev it is assumed that arb-os never assigns this value to a valid leaf to be redeemed 13 | uint256 private constant AMOUNT_DEFAULT_CONTEXT = type(uint256).max; 14 | 15 | function l2ToL1WithdrawalAmount() external view returns (uint256) { 16 | uint256 amount = context.withdrawalAmount; 17 | if (amount == AMOUNT_DEFAULT_CONTEXT) return 0; 18 | return amount; 19 | } 20 | 21 | /// @inheritdoc AbsOutbox 22 | function _defaultContextAmount() internal pure override returns (uint256) { 23 | // we use type(uint256).max as representation of 0 native token withdrawal amount 24 | return AMOUNT_DEFAULT_CONTEXT; 25 | } 26 | 27 | /// @inheritdoc AbsOutbox 28 | function _getAmountToUnlock( 29 | uint256 value 30 | ) internal view override returns (uint256) { 31 | uint8 nativeTokenDecimals = IERC20Bridge(address(bridge)).nativeTokenDecimals(); 32 | // this might revert due to overflow, but we assume the token supply is less than 2^256 33 | return DecimalsConverterHelper.adjustDecimals(value, 18, nativeTokenDecimals); 34 | } 35 | 36 | /// @inheritdoc AbsOutbox 37 | function _amountToSetInContext( 38 | uint256 value 39 | ) internal pure override returns (uint256) { 40 | // native token withdrawal amount which can be fetched from context 41 | return value; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/bridge/IDelayedMessageProvider.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | // solhint-disable-next-line compiler-version 6 | pragma solidity >=0.6.9 <0.9.0; 7 | 8 | interface IDelayedMessageProvider { 9 | /// @dev event emitted when a inbox message is added to the Bridge's delayed accumulator 10 | event InboxMessageDelivered(uint256 indexed messageNum, bytes data); 11 | 12 | /// @dev event emitted when a inbox message is added to the Bridge's delayed accumulator 13 | /// same as InboxMessageDelivered but the batch data is available in tx.input 14 | event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum); 15 | } 16 | -------------------------------------------------------------------------------- /src/bridge/IERC20Bridge.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | // solhint-disable-next-line compiler-version 6 | pragma solidity >=0.6.9 <0.9.0; 7 | 8 | import "./IOwnable.sol"; 9 | import "./IBridge.sol"; 10 | 11 | interface IERC20Bridge is IBridge { 12 | /** 13 | * @dev token that is escrowed in bridge on L1 side and minted on L2 as native currency. 14 | * Fees are paid in this token. There are certain restrictions on the native token: 15 | * - The token can't be rebasing or have a transfer fee 16 | * - The token must only be transferrable via a call to the token address itself 17 | * - The token must only be able to set allowance via a call to the token address itself 18 | * - The token must not have a callback on transfer, and more generally a user must not be able to make a transfer to themselves revert 19 | */ 20 | function nativeToken() external view returns (address); 21 | 22 | /** 23 | * @dev number of decimals used by the native token 24 | * This is set on bridge initialization using nativeToken.decimals() 25 | * If the token does not have decimals() method, we assume it have 0 decimals 26 | */ 27 | function nativeTokenDecimals() external view returns (uint8); 28 | 29 | /** 30 | * @dev Enqueue a message in the delayed inbox accumulator. 31 | * These messages are later sequenced in the SequencerInbox, either 32 | * by the sequencer as part of a normal batch, or by force inclusion. 33 | */ 34 | function enqueueDelayedMessage( 35 | uint8 kind, 36 | address sender, 37 | bytes32 messageDataHash, 38 | uint256 tokenFeeAmount 39 | ) external returns (uint256); 40 | 41 | // ---------- initializer ---------- 42 | 43 | function initialize(IOwnable rollup_, address nativeToken_) external; 44 | } 45 | -------------------------------------------------------------------------------- /src/bridge/IEthBridge.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | // solhint-disable-next-line compiler-version 6 | pragma solidity >=0.6.9 <0.9.0; 7 | 8 | import "./IOwnable.sol"; 9 | import "./IBridge.sol"; 10 | 11 | interface IEthBridge is IBridge { 12 | /** 13 | * @dev Enqueue a message in the delayed inbox accumulator. 14 | * These messages are later sequenced in the SequencerInbox, either 15 | * by the sequencer as part of a normal batch, or by force inclusion. 16 | */ 17 | function enqueueDelayedMessage( 18 | uint8 kind, 19 | address sender, 20 | bytes32 messageDataHash 21 | ) external payable returns (uint256); 22 | 23 | // ---------- initializer ---------- 24 | 25 | function initialize( 26 | IOwnable rollup_ 27 | ) external; 28 | } 29 | -------------------------------------------------------------------------------- /src/bridge/IOwnable.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/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 | -------------------------------------------------------------------------------- /src/bridge/Messages.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | // solhint-disable-next-line compiler-version 6 | pragma solidity >=0.6.9 <0.9.0; 7 | pragma experimental ABIEncoderV2; 8 | 9 | library Messages { 10 | struct Message { 11 | uint8 kind; 12 | address sender; 13 | uint64 blockNumber; 14 | uint64 timestamp; 15 | uint256 inboxSeqNum; 16 | uint256 baseFeeL1; 17 | bytes32 messageDataHash; 18 | } 19 | 20 | function messageHash( 21 | Message memory message 22 | ) internal pure returns (bytes32) { 23 | return messageHash( 24 | message.kind, 25 | message.sender, 26 | message.blockNumber, 27 | message.timestamp, 28 | message.inboxSeqNum, 29 | message.baseFeeL1, 30 | message.messageDataHash 31 | ); 32 | } 33 | 34 | function messageHash( 35 | uint8 kind, 36 | address sender, 37 | uint64 blockNumber, 38 | uint64 timestamp, 39 | uint256 inboxSeqNum, 40 | uint256 baseFeeL1, 41 | bytes32 messageDataHash 42 | ) internal pure returns (bytes32) { 43 | return keccak256( 44 | abi.encodePacked( 45 | kind, sender, blockNumber, timestamp, inboxSeqNum, baseFeeL1, messageDataHash 46 | ) 47 | ); 48 | } 49 | 50 | function accumulateInboxMessage( 51 | bytes32 prevAcc, 52 | bytes32 message 53 | ) internal pure returns (bytes32) { 54 | return keccak256(abi.encodePacked(prevAcc, message)); 55 | } 56 | 57 | /// @dev Validates a delayed accumulator preimage 58 | /// @param delayedAcc The delayed accumulator to validate against 59 | /// @param beforeDelayedAcc The previous delayed accumulator 60 | /// @param message The message to validate 61 | function isValidDelayedAccPreimage( 62 | bytes32 delayedAcc, 63 | bytes32 beforeDelayedAcc, 64 | Message memory message 65 | ) internal pure returns (bool) { 66 | return delayedAcc == accumulateInboxMessage(beforeDelayedAcc, messageHash(message)); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/bridge/Outbox.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.4; 6 | 7 | import "./AbsOutbox.sol"; 8 | 9 | contract Outbox is AbsOutbox { 10 | /// @inheritdoc AbsOutbox 11 | function _defaultContextAmount() internal pure override returns (uint256) { 12 | // In ETH-based chains withdrawal amount can be read from msg.value. For that reason 13 | // amount slot in context will never be accessed and it has 0 default value 14 | return 0; 15 | } 16 | 17 | /// @inheritdoc AbsOutbox 18 | function _getAmountToUnlock( 19 | uint256 value 20 | ) internal pure override returns (uint256) { 21 | return value; 22 | } 23 | 24 | /// @inheritdoc AbsOutbox 25 | function _amountToSetInContext( 26 | uint256 27 | ) internal pure override returns (uint256) { 28 | // In ETH-based chains withdrawal amount can be read from msg.value. For that reason 29 | // amount slot in context will never be accessed, we keep it as 0 all the time 30 | return 0; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/challengeV2/IAssertionChain.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2023, Offchain Labs, Inc. 2 | // For license information, see https://github.com/offchainlabs/bold/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | // 5 | pragma solidity ^0.8.0; 6 | 7 | import "../bridge/IBridge.sol"; 8 | import "../osp/IOneStepProofEntry.sol"; 9 | import "../rollup/Assertion.sol"; 10 | 11 | /// @title Assertion chain interface 12 | /// @notice The interface required by the EdgeChallengeManager for requesting assertion data from the AssertionChain 13 | interface IAssertionChain { 14 | function bridge() external view returns (IBridge); 15 | function validateAssertionHash( 16 | bytes32 assertionHash, 17 | AssertionState calldata state, 18 | bytes32 prevAssertionHash, 19 | bytes32 inboxAcc 20 | ) external view; 21 | function validateConfig(bytes32 assertionHash, ConfigData calldata configData) external view; 22 | function getFirstChildCreationBlock( 23 | bytes32 assertionHash 24 | ) external view returns (uint64); 25 | function getSecondChildCreationBlock( 26 | bytes32 assertionHash 27 | ) external view returns (uint64); 28 | function isFirstChild( 29 | bytes32 assertionHash 30 | ) external view returns (bool); 31 | function isPending( 32 | bytes32 assertionHash 33 | ) external view returns (bool); 34 | function isValidator( 35 | address 36 | ) external view returns (bool); 37 | function getValidators() external view returns (address[] memory); 38 | function validatorWhitelistDisabled() external view returns (bool); 39 | } 40 | -------------------------------------------------------------------------------- /src/challengeV2/libraries/ArrayUtilsLib.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2023, Offchain Labs, Inc. 2 | // For license information, see https://github.com/offchainlabs/bold/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | // 5 | pragma solidity ^0.8.17; 6 | 7 | /// @title Array utils library 8 | /// @notice Utils for working with bytes32 arrays 9 | library ArrayUtilsLib { 10 | /// @notice Append an item to the end of an array 11 | /// @param arr The array to append to 12 | /// @param newItem The item to append 13 | function append( 14 | bytes32[] memory arr, 15 | bytes32 newItem 16 | ) internal pure returns (bytes32[] memory) { 17 | bytes32[] memory clone = new bytes32[](arr.length + 1); 18 | for (uint256 i = 0; i < arr.length; i++) { 19 | clone[i] = arr[i]; 20 | } 21 | clone[clone.length - 1] = newItem; 22 | return clone; 23 | } 24 | 25 | /// @notice Get a slice of an existing array 26 | /// @dev End index exlusive so slice(arr, 0, 5) gets the first 5 elements of arr 27 | /// @param arr Array to slice 28 | /// @param startIndex The start index of the slice in the original array - inclusive 29 | /// @param endIndex The end index of the slice in the original array - exlusive 30 | function slice( 31 | bytes32[] memory arr, 32 | uint256 startIndex, 33 | uint256 endIndex 34 | ) internal pure returns (bytes32[] memory) { 35 | require(startIndex < endIndex, "Start not less than end"); 36 | require(endIndex <= arr.length, "End not less or equal than length"); 37 | 38 | bytes32[] memory newArr = new bytes32[](endIndex - startIndex); 39 | for (uint256 i = startIndex; i < endIndex; i++) { 40 | newArr[i - startIndex] = arr[i]; 41 | } 42 | return newArr; 43 | } 44 | 45 | /// @notice Concatenated to arrays 46 | /// @param arr1 First array 47 | /// @param arr1 Second array 48 | function concat( 49 | bytes32[] memory arr1, 50 | bytes32[] memory arr2 51 | ) internal pure returns (bytes32[] memory) { 52 | bytes32[] memory full = new bytes32[](arr1.length + arr2.length); 53 | for (uint256 i = 0; i < arr1.length; i++) { 54 | full[i] = arr1[i]; 55 | } 56 | for (uint256 i = 0; i < arr2.length; i++) { 57 | full[arr1.length + i] = arr2[i]; 58 | } 59 | return full; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/challengeV2/libraries/Enums.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2023, Offchain Labs, Inc. 2 | // For license information, see https://github.com/offchainlabs/bold/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | // 5 | pragma solidity ^0.8.17; 6 | 7 | /// @notice The status of the edge 8 | /// - Pending: Yet to be confirmed. Not all edges can be confirmed. 9 | /// - Confirmed: Once confirmed it cannot transition back to pending 10 | enum EdgeStatus { 11 | Pending, 12 | Confirmed 13 | } 14 | 15 | /// @notice The type of the edge. Challenges are decomposed into 3 types of subchallenge 16 | /// represented here by the edge type. Edges are initially created of type Block 17 | /// and are then bisected until they have length one. After that new BigStep edges are 18 | /// added that claim a Block type edge, and are then bisected until they have length one. 19 | /// Then a SmallStep edge is added that claims a length one BigStep edge, and these 20 | /// SmallStep edges are bisected until they reach length one. A length one small step edge 21 | /// can then be directly executed using a one-step proof. 22 | enum EdgeType { 23 | Block, 24 | BigStep, 25 | SmallStep 26 | } 27 | -------------------------------------------------------------------------------- /src/challengeV2/libraries/UintUtilsLib.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2023, Offchain Labs, Inc. 2 | // For license information, see https://github.com/offchainlabs/bold/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | // 5 | pragma solidity ^0.8.17; 6 | 7 | /// @title Uint utils library 8 | /// @notice Some additional bit inspection tools 9 | library UintUtilsLib { 10 | /// @notice The least significant bit in the bit representation of a uint 11 | /// @dev Zero indexed from the least sig bit. Eg 1010 => 1, 1100 => 2, 1001 => 0 12 | /// Finds lsb in linear (uint size) time 13 | /// @param x Cannot be zero, since zero that has no signficant bits 14 | function leastSignificantBit( 15 | uint256 x 16 | ) internal pure returns (uint256 msb) { 17 | require(x > 0, "Zero has no significant bits"); 18 | 19 | // isolate the least sig bit 20 | uint256 isolated = ((x - 1) & x) ^ x; 21 | 22 | // since we removed all higher bits, least sig == most sig 23 | return mostSignificantBit(isolated); 24 | } 25 | 26 | /// @notice The most significant bit in the bit representation of a uint 27 | /// @dev Zero indexed from the least sig bit. Eg 1010 => 3, 110 => 2, 1 => 0 28 | /// Taken from https://solidity-by-example.org/bitwise/ 29 | /// Finds msb in log (uint size) time 30 | /// @param x Cannot be zero, since zero has no sigificant bits 31 | function mostSignificantBit( 32 | uint256 x 33 | ) internal pure returns (uint256 msb) { 34 | require(x != 0, "Zero has no significant bits"); 35 | 36 | // x >= 2 ** 128 37 | if (x >= 0x100000000000000000000000000000000) { 38 | x >>= 128; 39 | msb += 128; 40 | } 41 | // x >= 2 ** 64 42 | if (x >= 0x10000000000000000) { 43 | x >>= 64; 44 | msb += 64; 45 | } 46 | // x >= 2 ** 32 47 | if (x >= 0x100000000) { 48 | x >>= 32; 49 | msb += 32; 50 | } 51 | // x >= 2 ** 16 52 | if (x >= 0x10000) { 53 | x >>= 16; 54 | msb += 16; 55 | } 56 | // x >= 2 ** 8 57 | if (x >= 0x100) { 58 | x >>= 8; 59 | msb += 8; 60 | } 61 | // x >= 2 ** 4 62 | if (x >= 0x10) { 63 | x >>= 4; 64 | msb += 4; 65 | } 66 | // x >= 2 ** 2 67 | if (x >= 0x4) { 68 | x >>= 2; 69 | msb += 2; 70 | } 71 | // x >= 2 ** 1 72 | if (x >= 0x2) msb += 1; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/express-lane-auction/Burner.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BUSL-1.1 2 | pragma solidity ^0.8.0; 3 | 4 | import {ERC20BurnableUpgradeable} from 5 | "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol"; 6 | import "./Errors.sol"; 7 | 8 | /// @notice A simple contract that can burn any tokens that are transferred to it 9 | /// Token must support the ERC20BurnableUpgradeable.burn(uint256) interface 10 | contract Burner { 11 | ERC20BurnableUpgradeable public immutable token; 12 | 13 | constructor( 14 | address _token 15 | ) { 16 | if (_token == address(0)) { 17 | revert ZeroAddress(); 18 | } 19 | token = ERC20BurnableUpgradeable(_token); 20 | } 21 | 22 | /// @notice Can be called at any time by anyone to burn any tokens held by this burner 23 | function burn() external { 24 | token.burn(token.balanceOf(address(this))); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/express-lane-auction/Errors.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BUSL-1.1 2 | pragma solidity ^0.8.0; 3 | 4 | error InsufficientBalance(uint256 amountRequested, uint256 balance); 5 | error InsufficientBalanceAcc(address account, uint256 amountRequested, uint256 balance); 6 | error RoundDurationTooShort(); 7 | error NothingToWithdraw(); 8 | error ZeroAmount(); 9 | error ZeroBiddingToken(); 10 | error WithdrawalInProgress(); 11 | error WithdrawalMaxRound(); 12 | error RoundAlreadyResolved(uint64 round); 13 | error SameBidder(); 14 | error BidsWrongOrder(); 15 | error TieBidsWrongOrder(); 16 | error AuctionNotClosed(); 17 | error ReservePriceTooLow(uint256 reservePrice, uint256 minReservePrice); 18 | error ReservePriceNotMet(uint256 bidAmount, uint256 reservePrice); 19 | error ReserveBlackout(); 20 | error RoundTooOld(uint64 round, uint64 currentRound); 21 | error RoundNotResolved(uint64 round); 22 | error NotExpressLaneController(uint64 round, address controller, address sender); 23 | error FixedTransferor(uint64 fixedUntilRound); 24 | error NotTransferor(uint64 round, address expectedTransferor, address msgSender); 25 | error InvalidNewRound(uint64 currentRound, uint64 newRound); 26 | error InvalidNewStart(uint64 currentStart, uint64 newStart); 27 | error RoundTooLong(uint64 roundDurationSeconds); 28 | error ZeroAuctionClosingSeconds(); 29 | error NegativeOffset(); 30 | error NegativeRoundStart(int64 roundStart); 31 | error ZeroAddress(); 32 | -------------------------------------------------------------------------------- /src/libraries/AddressAliasHelper.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | library AddressAliasHelper { 8 | uint160 internal constant OFFSET = uint160(0x1111000000000000000000000000000000001111); 9 | 10 | /// @notice Utility function that converts the address in the L1 that submitted a tx to 11 | /// the inbox to the msg.sender viewed in the L2 12 | /// @param l1Address the address in the L1 that triggered the tx to L2 13 | /// @return l2Address L2 address as viewed in msg.sender 14 | function applyL1ToL2Alias( 15 | address l1Address 16 | ) internal pure returns (address l2Address) { 17 | unchecked { 18 | l2Address = address(uint160(l1Address) + OFFSET); 19 | } 20 | } 21 | 22 | /// @notice Utility function that converts the msg.sender viewed in the L2 to the 23 | /// address in the L1 that submitted a tx to the inbox 24 | /// @param l2Address L2 address as viewed in msg.sender 25 | /// @return l1Address the address in the L1 that triggered the tx to L2 26 | function undoL1ToL2Alias( 27 | address l2Address 28 | ) internal pure returns (address l1Address) { 29 | unchecked { 30 | l1Address = address(uint160(l2Address) - OFFSET); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/libraries/ArbitrumChecker.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "../precompiles/ArbSys.sol"; 8 | 9 | library ArbitrumChecker { 10 | function runningOnArbitrum() internal view returns (bool) { 11 | (bool ok, bytes memory data) = 12 | address(100).staticcall(abi.encodeWithSelector(ArbSys.arbOSVersion.selector)); 13 | return ok && data.length == 32; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/libraries/CallerChecker.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2024, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | library CallerChecker { 8 | /** 9 | * @notice A EIP-7702 safe check to ensure the caller is the origin and is codeless 10 | * @return bool true if the caller is the origin and is codeless, false otherwise 11 | * @dev If the caller is the origin and is codeless, then msg.data is guaranteed to be same as tx.data 12 | * It also mean the caller would not be able to call a contract multiple times with the same transaction 13 | */ 14 | function isCallerCodelessOrigin() internal view returns (bool) { 15 | // solhint-disable-next-line avoid-tx-origin 16 | return msg.sender == tx.origin && msg.sender.code.length == 0; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/libraries/Constants.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.4; 6 | 7 | uint64 constant NO_CHAL_INDEX = 0; 8 | 9 | // Expected seconds per block in Ethereum PoS 10 | uint256 constant ETH_POS_BLOCK_TIME = 12; 11 | 12 | /// @dev If nativeTokenDecimals is different than 18 decimals, bridge will inflate or deflate token amounts 13 | /// when depositing to child chain to match 18 decimal denomination. Opposite process happens when 14 | /// amount is withdrawn back to parent chain. In order to avoid uint256 overflows we restrict max number 15 | /// of decimals to 36 which should be enough for most practical use-cases. 16 | uint8 constant MAX_ALLOWED_NATIVE_TOKEN_DECIMALS = uint8(36); 17 | 18 | /// @dev Max amount of erc20 native token that can deposit when upscaling is required (i.e. < 18 decimals) 19 | /// Amounts higher than this would risk uint256 overflows when adjusting decimals. Considering 20 | /// 18 decimals are 60 bits, we choose 2^192 as the limit which equals to ~6.3*10^57 weis of token 21 | uint256 constant MAX_UPSCALE_AMOUNT = type(uint192).max; 22 | -------------------------------------------------------------------------------- /src/libraries/DecimalsConverterHelper.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | library DecimalsConverterHelper { 8 | /// @notice generic function for mapping amount from one decimal denomination to another 9 | /// @dev Ie. let's say amount is 752. If token has 16 decimals and is being adjusted to 10 | /// 18 decimals then amount will be 75200. If token has 20 decimals adjusted amount 11 | /// is 7. If token uses no decimals converted amount is 752*10^18. 12 | /// When amount is adjusted from 18 decimals back to native token decimals, opposite 13 | /// process is performed. 14 | /// @param amount amount to convert 15 | /// @param decimalsIn current decimals 16 | /// @param decimalsOut target decimals 17 | /// @return amount converted to 'decimalsOut' decimals 18 | function adjustDecimals( 19 | uint256 amount, 20 | uint8 decimalsIn, 21 | uint8 decimalsOut 22 | ) internal pure returns (uint256) { 23 | if (decimalsIn == decimalsOut) { 24 | return amount; 25 | } else if (decimalsIn < decimalsOut) { 26 | return amount * 10 ** (decimalsOut - decimalsIn); 27 | } else { 28 | return amount / 10 ** (decimalsIn - decimalsOut); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/libraries/DelegateCallAware.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import {NotOwner} from "./Error.sol"; 8 | 9 | /// @dev A stateless contract that allows you to infer if the current call has been delegated or not 10 | /// Pattern used here is from UUPS implementation by the OpenZeppelin team 11 | abstract contract DelegateCallAware { 12 | address private immutable __self = address(this); 13 | 14 | /** 15 | * @dev Check that the execution is being performed through a delegate call. This allows a function to be 16 | * callable on the proxy contract but not on the logic contract. 17 | */ 18 | modifier onlyDelegated() { 19 | require(address(this) != __self, "Function must be called through delegatecall"); 20 | _; 21 | } 22 | 23 | /** 24 | * @dev Check that the execution is not being performed through a delegate call. This allows a function to be 25 | * callable on the implementing contract but not through proxies. 26 | */ 27 | modifier notDelegated() { 28 | require(address(this) == __self, "Function must not be called through delegatecall"); 29 | _; 30 | } 31 | 32 | /// @dev Check that msg.sender is the current EIP 1967 proxy admin 33 | modifier onlyProxyOwner() { 34 | // Storage slot with the admin of the proxy contract 35 | // This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1 36 | bytes32 slot = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; 37 | address admin; 38 | assembly { 39 | admin := sload(slot) 40 | } 41 | if (msg.sender != admin) revert NotOwner(msg.sender, admin); 42 | _; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/libraries/IGasRefunder.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | // solhint-disable-next-line compiler-version 6 | pragma solidity >=0.6.9 <0.9.0; 7 | 8 | interface IGasRefunder { 9 | function onGasSpent( 10 | address payable spender, 11 | uint256 gasUsed, 12 | uint256 calldataSize 13 | ) external returns (bool success); 14 | } 15 | -------------------------------------------------------------------------------- /src/libraries/IReader4844.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2023-2024, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity >=0.6.9 <0.9.0; 6 | 7 | interface IReader4844 { 8 | /// @notice Returns the current BLOBBASEFEE 9 | function getBlobBaseFee() external view returns (uint256); 10 | 11 | /// @notice Returns all the data hashes of all the blobs on the current transaction 12 | function getDataHashes() external view returns (bytes32[] memory); 13 | } 14 | -------------------------------------------------------------------------------- /src/libraries/MerkleLib.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.4; 6 | 7 | import {MerkleProofTooLong} from "./Error.sol"; 8 | 9 | library MerkleLib { 10 | function generateRoot( 11 | bytes32[] memory _hashes 12 | ) internal pure returns (bytes32) { 13 | bytes32[] memory prevLayer = _hashes; 14 | while (prevLayer.length > 1) { 15 | bytes32[] memory nextLayer = new bytes32[]((prevLayer.length + 1) / 2); 16 | for (uint256 i = 0; i < nextLayer.length; i++) { 17 | if (2 * i + 1 < prevLayer.length) { 18 | nextLayer[i] = 19 | keccak256(abi.encodePacked(prevLayer[2 * i], prevLayer[2 * i + 1])); 20 | } else { 21 | nextLayer[i] = prevLayer[2 * i]; 22 | } 23 | } 24 | prevLayer = nextLayer; 25 | } 26 | return prevLayer[0]; 27 | } 28 | 29 | function calculateRoot( 30 | bytes32[] memory nodes, 31 | uint256 route, 32 | bytes32 item 33 | ) internal pure returns (bytes32) { 34 | uint256 proofItems = nodes.length; 35 | if (proofItems > 256) revert MerkleProofTooLong(proofItems, 256); 36 | bytes32 h = item; 37 | for (uint256 i = 0; i < proofItems;) { 38 | bytes32 node = nodes[i]; 39 | if ((route & (1 << i)) == 0) { 40 | assembly { 41 | mstore(0x00, h) 42 | mstore(0x20, node) 43 | h := keccak256(0x00, 0x40) 44 | } 45 | } else { 46 | assembly { 47 | mstore(0x00, node) 48 | mstore(0x20, h) 49 | h := keccak256(0x00, 0x40) 50 | } 51 | } 52 | unchecked { 53 | ++i; 54 | } 55 | } 56 | return h; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/libraries/MessageTypes.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.4; 6 | 7 | uint8 constant L2_MSG = 3; 8 | uint8 constant L1MessageType_L2FundedByL1 = 7; 9 | uint8 constant L1MessageType_submitRetryableTx = 9; 10 | uint8 constant L1MessageType_ethDeposit = 12; 11 | uint8 constant L1MessageType_batchPostingReport = 13; 12 | uint8 constant L2MessageType_unsignedEOATx = 0; 13 | uint8 constant L2MessageType_unsignedContractTx = 1; 14 | 15 | uint8 constant ROLLUP_PROTOCOL_EVENT_TYPE = 8; 16 | uint8 constant INITIALIZATION_MSG_TYPE = 11; 17 | -------------------------------------------------------------------------------- /src/mocks/ArbOS11To32UpgradeTest.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2024, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.24; 6 | 7 | import "../precompiles/ArbSys.sol"; 8 | 9 | contract ArbOS11To32UpgradeTest { 10 | function mcopy() external returns (bytes32 x) { 11 | assembly { 12 | mstore(0x20, 0x9) // Store 0x9 at word 1 in memory 13 | mcopy(0, 0x20, 0x20) // Copies 0x9 to word 0 in memory 14 | x := mload(0) // Returns 32 bytes "0x9" 15 | } 16 | require(ArbSys(address(0x64)).arbOSVersion() == 55 + 32, "EXPECTED_ARBOS_32"); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/mocks/Benchmarks.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2022-2023, Offchain Labs, Inc. 2 | // For license information, see https://github.com/nitro/blob/master/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | contract Benchmarks { 8 | function fillBlockRecover() external payable { 9 | bytes32 bridgeToNova = 0xeddecf107b5740cef7f5a01e3ea7e287665c4e75a8eb6afae2fda2e3d4367786; 10 | address cryptoIsCute = 0x361594F5429D23ECE0A88E4fBE529E1c49D524d8; 11 | uint8 v = 27; 12 | bytes32 r = 0xc6178c2de1078cd36c3bd302cde755340d7f17fcb3fcc0b9c333ba03b217029f; 13 | bytes32 s = 0x5fdbcefe2675e96219cdae57a7894280bf80fd40d44ce146a35e169ea6a78fd3; 14 | while (true) { 15 | require(ecrecover(bridgeToNova, v, r, s) == cryptoIsCute, "WRONG_ARBINAUT"); 16 | } 17 | } 18 | 19 | function fillBlockMulMod() external payable { 20 | uint256 value = 0xeddecf107b5740cef7f5a01e3ea7e287665c4e75a8eb6afae2fda2e3d4367786; 21 | while (true) { 22 | value = mulmod( 23 | value, 24 | 0xc6178c2de1078cd36c3bd302cde755340d7f17fcb3fcc0b9c333ba03b217029f, 25 | 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f 26 | ); 27 | } 28 | } 29 | 30 | function fillBlockHash() external payable { 31 | bytes32 hash = 0xeddecf107b5740cef7f5a01e3ea7e287665c4e75a8eb6afae2fda2e3d4367786; 32 | while (true) { 33 | hash = keccak256(abi.encodePacked(hash)); 34 | } 35 | } 36 | 37 | function fillBlockAdd() external payable { 38 | uint256 value = 0; 39 | while (true) { 40 | unchecked { 41 | value += 0xeddecf107b5740cef7f5a01e3ea7e287665c4e75a8eb6afae2fda2e3d4367786; 42 | } 43 | } 44 | } 45 | 46 | function fillBlockQuickStep() external payable { 47 | uint256 value = 0; 48 | while (true) { 49 | value = msg.value; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/mocks/BigMap.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2025, Offchain Labs, Inc. 2 | // For license information, see: 3 | // https://github.com/OffchainLabs/nitro/blob/master/LICENSE.md 4 | // SPDX-License-Identifier: BUSL-1.1 5 | 6 | pragma solidity ^0.8.0; 7 | 8 | contract BigMap { 9 | mapping(uint256 => uint256) public data; 10 | uint256 size; 11 | 12 | function clearAndAddValues(uint256 clear, uint256 add) external { 13 | uint256 i = size; 14 | while (i < size + add) { 15 | data[i] = 8675309; 16 | i++; 17 | } 18 | size = i; 19 | for (uint256 j = 0; j < clear; j++) { 20 | data[j] = 0; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/mocks/BridgeUnproxied.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "./InboxStub.sol"; 8 | import {BadSequencerMessageNumber} from "../libraries/Error.sol"; 9 | 10 | import "../bridge/Bridge.sol"; 11 | 12 | contract BridgeUnproxied is Bridge { 13 | uint256 public DUMMYVAR = 0; // This is a dummy variable to disambiguous with the Bridge contract 14 | 15 | constructor() { 16 | _activeOutbox = EMPTY_ACTIVEOUTBOX; 17 | rollup = IOwnable(msg.sender); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/mocks/CreateTest.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2024, Offchain Labs, Inc. 2 | // For license information, see https://github.com/nitro/blob/master/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | /* 8 | * This contract is the solidity equivalent of the stylus create test contract. 9 | */ 10 | contract CreateTest { 11 | // solhint-disable no-complex-fallback 12 | // solhint-disable reason-string 13 | // solhint-disable avoid-low-level-calls 14 | // solhint-disable-next-line prettier/prettier 15 | fallback( 16 | bytes calldata input 17 | ) external returns (bytes memory) { 18 | uint8 kind = uint8(input[0]); 19 | input = input[1:]; 20 | 21 | bytes32 endowment = bytes32(input[:32]); 22 | input = input[32:]; 23 | 24 | address addr; 25 | 26 | if (kind == 2) { 27 | bytes32 salt = bytes32(input[:32]); 28 | input = input[32:]; 29 | bytes memory code = input; 30 | assembly { 31 | addr := create2(endowment, add(code, 32), mload(code), salt) 32 | } 33 | } else { 34 | bytes memory code = input; 35 | assembly { 36 | addr := create(endowment, add(code, 32), mload(code)) 37 | } 38 | } 39 | if (addr == address(0)) { 40 | revert("failed to create"); 41 | } 42 | return addr.code; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/mocks/MerkleTreeAccess.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2023, Offchain Labs, Inc. 2 | // For license information, see https://github.com/offchainlabs/bold/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | // 5 | pragma solidity ^0.8.17; 6 | 7 | import "../challengeV2/libraries/MerkleTreeAccumulatorLib.sol"; 8 | import "../challengeV2/libraries/UintUtilsLib.sol"; 9 | 10 | contract MerkleTreeAccess { 11 | function mostSignificantBit( 12 | uint256 x 13 | ) external pure returns (uint256) { 14 | return UintUtilsLib.mostSignificantBit(x); 15 | } 16 | 17 | function leastSignificantBit( 18 | uint256 x 19 | ) external pure returns (uint256) { 20 | return UintUtilsLib.leastSignificantBit(x); 21 | } 22 | 23 | function root( 24 | bytes32[] memory me 25 | ) external pure returns (bytes32) { 26 | return MerkleTreeAccumulatorLib.root(me); 27 | } 28 | 29 | function appendCompleteSubTree( 30 | bytes32[] memory me, 31 | uint256 level, 32 | bytes32 subtreeRoot 33 | ) external pure returns (bytes32[] memory) { 34 | return MerkleTreeAccumulatorLib.appendCompleteSubTree(me, level, subtreeRoot); 35 | } 36 | 37 | function appendLeaf( 38 | bytes32[] memory me, 39 | bytes32 leaf 40 | ) external pure returns (bytes32[] memory) { 41 | return MerkleTreeAccumulatorLib.appendLeaf(me, leaf); 42 | } 43 | 44 | function maximumAppendBetween( 45 | uint256 startSize, 46 | uint256 endSize 47 | ) external pure returns (uint256) { 48 | return MerkleTreeAccumulatorLib.maximumAppendBetween(startSize, endSize); 49 | } 50 | 51 | function verifyPrefixProof( 52 | bytes32 preRoot, 53 | uint256 preSize, 54 | bytes32 postRoot, 55 | uint256 postSize, 56 | bytes32[] memory preExpansion, 57 | bytes32[] memory proof 58 | ) external pure { 59 | return MerkleTreeAccumulatorLib.verifyPrefixProof( 60 | preRoot, preSize, postRoot, postSize, preExpansion, proof 61 | ); 62 | } 63 | 64 | function verifyInclusionProof( 65 | bytes32 rootHash, 66 | bytes32 leaf, 67 | uint256 index, 68 | bytes32[] memory proof 69 | ) external pure { 70 | MerkleTreeAccumulatorLib.verifyInclusionProof(rootHash, leaf, index, proof); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/mocks/MockRollupEventInbox.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "../rollup/IRollupEventInbox.sol"; 8 | import "../bridge/IEthBridge.sol"; 9 | import "../bridge/IDelayedMessageProvider.sol"; 10 | import "../precompiles/ArbGasInfo.sol"; 11 | import "../libraries/DelegateCallAware.sol"; 12 | import "../libraries/ArbitrumChecker.sol"; 13 | import {INITIALIZATION_MSG_TYPE} from "../libraries/MessageTypes.sol"; 14 | import {AlreadyInit, HadZeroInit} from "../libraries/Error.sol"; 15 | 16 | /** 17 | * @title The inbox for rollup protocol events 18 | */ 19 | contract MockRollupEventInbox is IRollupEventInbox, IDelayedMessageProvider, DelegateCallAware { 20 | IBridge public override bridge; 21 | address public override rollup; 22 | 23 | modifier onlyRollup() { 24 | require(msg.sender == rollup, "ONLY_ROLLUP"); 25 | _; 26 | } 27 | 28 | function initialize( 29 | IBridge _bridge 30 | ) external override onlyDelegated { 31 | if (address(bridge) != address(0)) revert AlreadyInit(); 32 | if (address(_bridge) == address(0)) revert HadZeroInit(); 33 | bridge = _bridge; 34 | rollup = address(_bridge.rollup()); 35 | } 36 | 37 | /// @notice Allows the proxy owner to set the rollup address 38 | function updateRollupAddress() external onlyDelegated onlyProxyOwner { 39 | rollup = address(bridge.rollup()); 40 | } 41 | 42 | function rollupInitialized( 43 | uint256 chainId, 44 | string calldata chainConfig 45 | ) external override onlyRollup { 46 | require(bytes(chainConfig).length > 0, "EMPTY_CHAIN_CONFIG"); 47 | uint8 initMsgVersion = 1; 48 | uint256 currentDataCost = 1; // Set to a base fee of 1. 49 | if (ArbitrumChecker.runningOnArbitrum()) { 50 | currentDataCost += ArbGasInfo(address(0x6c)).getL1BaseFeeEstimate(); 51 | } 52 | bytes memory initMsg = 53 | abi.encodePacked(chainId, initMsgVersion, currentDataCost, chainConfig); 54 | uint256 num = IEthBridge(address(bridge)).enqueueDelayedMessage( 55 | INITIALIZATION_MSG_TYPE, address(0), keccak256(initMsg) 56 | ); 57 | emit InboxMessageDelivered(num, initMsg); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/mocks/PendingBlkTimeAndNrAdvanceCheck.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "../precompiles/ArbSys.sol"; 8 | 9 | contract PendingBlkTimeAndNrAdvanceCheck { 10 | uint256 immutable deployedAt; 11 | uint256 immutable deployedAtBlock; 12 | ArbSys constant ARB_SYS = ArbSys(address(100)); 13 | 14 | constructor() { 15 | deployedAt = block.timestamp; 16 | deployedAtBlock = ARB_SYS.arbBlockNumber(); 17 | } 18 | 19 | function isAdvancing() external { 20 | require(block.timestamp > deployedAt, "Time didn't advance"); 21 | require(ARB_SYS.arbBlockNumber() > deployedAtBlock, "Block didn't advance"); 22 | } 23 | 24 | function checkArbBlockHashReturnsLatest( 25 | bytes32 expected 26 | ) external { 27 | bytes32 gotBlockHash = ARB_SYS.arbBlockHash(ARB_SYS.arbBlockNumber() - 1); 28 | require(gotBlockHash != bytes32(0), "ZERO_BLOCK_HASH"); 29 | require(gotBlockHash == expected, "WRONG_BLOCK_HASH"); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/mocks/ProxyAdminForBinding.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; 8 | 9 | contract ProxyAdminForBinding is ProxyAdmin {} 10 | -------------------------------------------------------------------------------- /src/mocks/SelfDestruct.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2024, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | contract SelfDestructInConstructorWithoutDestination { 8 | constructor() public payable { 9 | selfdestruct(payable(address(this))); 10 | } 11 | } 12 | 13 | contract SelfDestructInConstructorWithDestination { 14 | constructor( 15 | address payable destination 16 | ) public payable { 17 | selfdestruct(destination); 18 | } 19 | } 20 | 21 | contract SelfDestructOutsideConstructor { 22 | constructor() public payable {} 23 | 24 | function selfDestructWithDestination( 25 | address payable destination 26 | ) public { 27 | selfdestruct(destination); 28 | } 29 | 30 | function selfDestructWithoutDestination() public { 31 | selfdestruct(payable(address(this))); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/mocks/SequencerInboxBlobMock.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "../bridge/SequencerInbox.sol"; 8 | 9 | contract SequencerInboxBlobMock is SequencerInbox { 10 | constructor( 11 | uint256 maxDataSize_, 12 | IReader4844 reader_, 13 | bool isUsingFeeToken_, 14 | bool isDelayBufferable_ 15 | ) SequencerInbox(maxDataSize_, reader_, isUsingFeeToken_, isDelayBufferable_) {} 16 | 17 | /// @dev Form a hash of the data being provided in 4844 data blobs 18 | /// @param afterDelayedMessagesRead The delayed messages count read up to 19 | /// @return The data hash 20 | /// @return The timebounds within which the message should be processed 21 | /// @return The normalized amount of gas used for blob posting 22 | function formBlobDataHash( 23 | uint256 afterDelayedMessagesRead 24 | ) internal view override returns (bytes32, IBridge.TimeBounds memory, uint256) { 25 | bytes32[3] memory dataHashes = [bytes32(0), bytes32(0), bytes32(0)]; 26 | if (dataHashes.length == 0) revert MissingDataHashes(); 27 | 28 | (bytes memory header, IBridge.TimeBounds memory timeBounds) = 29 | packHeader(afterDelayedMessagesRead); 30 | uint256 BLOB_BASE_FEE = 1 gwei; 31 | uint256 blobCost = BLOB_BASE_FEE * GAS_PER_BLOB * dataHashes.length; 32 | return ( 33 | keccak256(bytes.concat(header, DATA_BLOB_HEADER_FLAG, abi.encodePacked(dataHashes))), 34 | timeBounds, 35 | block.basefee > 0 ? blobCost / block.basefee : 0 36 | ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/mocks/SequencerInboxStub.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "../bridge/SequencerInbox.sol"; 8 | import "../bridge/IEthBridge.sol"; 9 | import {INITIALIZATION_MSG_TYPE} from "../libraries/MessageTypes.sol"; 10 | 11 | contract SequencerInboxStub is SequencerInbox { 12 | constructor( 13 | IBridge bridge_, 14 | address sequencer_, 15 | ISequencerInbox.MaxTimeVariation memory maxTimeVariation_, 16 | uint256 maxDataSize_, 17 | IReader4844 reader4844_, 18 | bool isUsingFeeToken_, 19 | bool isDelayBufferable_ 20 | ) SequencerInbox(maxDataSize_, reader4844_, isUsingFeeToken_, isDelayBufferable_) { 21 | bridge = bridge_; 22 | rollup = IOwnable(msg.sender); 23 | delayBlocks = uint64(maxTimeVariation_.delayBlocks); 24 | futureBlocks = uint64(maxTimeVariation_.futureBlocks); 25 | delaySeconds = uint64(maxTimeVariation_.delaySeconds); 26 | futureSeconds = uint64(maxTimeVariation_.futureSeconds); 27 | isBatchPoster[sequencer_] = true; 28 | } 29 | 30 | function addInitMessage( 31 | uint256 chainId 32 | ) external { 33 | bytes memory initMsg = abi.encodePacked(chainId); 34 | uint256 num = IEthBridge(address(bridge)).enqueueDelayedMessage( 35 | INITIALIZATION_MSG_TYPE, address(0), keccak256(initMsg) 36 | ); 37 | require(num == 0, "ALREADY_DELAYED_INIT"); 38 | emit InboxMessageDelivered(num, initMsg); 39 | (bytes32 dataHash, IBridge.TimeBounds memory timeBounds) = formEmptyDataHash(1); 40 | (uint256 sequencerMessageCount, bytes32 beforeAcc, bytes32 delayedAcc, bytes32 afterAcc) = 41 | addSequencerL2BatchImpl(dataHash, 1, 0, 0, 1); 42 | require(sequencerMessageCount == 0, "ALREADY_SEQ_INIT"); 43 | emit SequencerBatchDelivered( 44 | sequencerMessageCount, 45 | beforeAcc, 46 | afterAcc, 47 | delayedAcc, 48 | totalDelayedMessagesRead, 49 | timeBounds, 50 | IBridge.BatchDataLocation.NoData 51 | ); 52 | } 53 | 54 | function getTimeBounds() internal view override returns (IBridge.TimeBounds memory bounds) { 55 | this; // silence warning about function not being view 56 | return bounds; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/mocks/SimpleCacheManager.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2022-2024, Offchain Labs, Inc. 2 | // For license information, see https://github.com/nitro/blob/master/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "../precompiles/ArbWasmCache.sol"; 8 | 9 | contract SimpleCacheManager { 10 | function cacheProgram( 11 | address program 12 | ) external { 13 | ArbWasmCache(address(0x72)).cacheProgram(program); 14 | } 15 | 16 | function evictProgram( 17 | address program 18 | ) external { 19 | ArbWasmCache(address(0x72)).evictCodehash(codehash(program)); 20 | } 21 | 22 | function codehash( 23 | address program 24 | ) internal view returns (bytes32 hash) { 25 | assembly { 26 | hash := extcodehash(program) 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/mocks/SimpleOneStepProofEntry.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2023, Offchain Labs, Inc. 2 | // For license information, see https://github.com/offchainlabs/bold/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | // 5 | pragma solidity ^0.8.17; 6 | 7 | import "../challengeV2/IEdgeChallengeManager.sol"; 8 | import "../state/Deserialize.sol"; 9 | 10 | contract SimpleOneStepProofEntry is IOneStepProofEntry { 11 | using GlobalStateLib for GlobalState; 12 | 13 | // End the batch after 2000 steps. This results in 11 blocks for an honest validator. 14 | // This constant must be synchronized with the one in execution/engine.go 15 | uint64 public constant STEPS_PER_BATCH = 2000; 16 | 17 | function getStartMachineHash( 18 | bytes32 globalStateHash, 19 | bytes32 wasmModuleRoot 20 | ) external pure returns (bytes32) { 21 | return keccak256(abi.encodePacked("Machine:", globalStateHash, wasmModuleRoot)); 22 | } 23 | 24 | function proveOneStep( 25 | ExecutionContext calldata execCtx, 26 | uint256 step, 27 | bytes32 beforeHash, 28 | bytes calldata proof 29 | ) external view returns (bytes32 afterHash) { 30 | if (proof.length == 0) { 31 | revert("EMPTY_PROOF"); 32 | } 33 | GlobalState memory globalState; 34 | uint256 offset; 35 | (globalState.u64Vals[0], offset) = Deserialize.u64(proof, offset); 36 | (globalState.u64Vals[1], offset) = Deserialize.u64(proof, offset); 37 | if (step > 0 && (beforeHash[0] == 0 || globalState.getPositionInMessage() == 0)) { 38 | // We end the block when the first byte of the hash hits 0 or we advance a batch 39 | return beforeHash; 40 | } 41 | if (globalState.getInboxPosition() >= execCtx.maxInboxMessagesRead) { 42 | // We can't continue further because we've hit the max inbox messages read 43 | return beforeHash; 44 | } 45 | require(globalState.hash() == beforeHash, "BAD_PROOF"); 46 | globalState.u64Vals[1]++; 47 | if (globalState.u64Vals[1] % STEPS_PER_BATCH == 0) { 48 | globalState.u64Vals[0]++; 49 | globalState.u64Vals[1] = 0; 50 | } 51 | return globalState.hash(); 52 | } 53 | 54 | function getMachineHash( 55 | ExecutionState calldata execState 56 | ) external pure override returns (bytes32) { 57 | require(execState.machineStatus == MachineStatus.FINISHED, "BAD_MACHINE_STATUS"); 58 | return execState.globalState.hash(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/mocks/SimpleProxy.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "@openzeppelin/contracts/proxy/Proxy.sol"; 8 | 9 | contract SimpleProxy is Proxy { 10 | address private immutable impl; 11 | 12 | constructor( 13 | address impl_ 14 | ) { 15 | impl = impl_; 16 | } 17 | 18 | function _implementation() internal view override returns (address) { 19 | return impl; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/mocks/TestWETH9.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 8 | 9 | interface IWETH9 { 10 | function deposit() external payable; 11 | 12 | function withdraw( 13 | uint256 _amount 14 | ) external; 15 | } 16 | 17 | contract TestWETH9 is ERC20, IWETH9 { 18 | constructor(string memory name_, string memory symbol_) ERC20(name_, symbol_) {} 19 | 20 | function deposit() external payable override { 21 | _mint(msg.sender, msg.value); 22 | } 23 | 24 | function withdraw( 25 | uint256 _amount 26 | ) external override { 27 | _burn(msg.sender, _amount); 28 | payable(address(msg.sender)).transfer(_amount); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/node-interface/NodeInterfaceDebug.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity >=0.4.21 <0.9.0; 6 | 7 | /** 8 | * @title An extension to NodeInterface not meant for public consumption. Do not call. 9 | * @notice This contract doesn't exist on-chain. Instead it is a virtual interface accessible at 0xc9. 10 | * These methods add additional debugging and network monitoring instruments not intended for end users and 11 | * as such may change without notice. 12 | */ 13 | interface NodeInterfaceDebug { 14 | struct RetryableInfo { 15 | uint64 timeout; 16 | address from; 17 | address to; 18 | uint256 value; 19 | address beneficiary; 20 | uint64 tries; 21 | bytes data; 22 | } 23 | 24 | /** 25 | * @notice gets a retryable 26 | * @param ticket the retryable's id 27 | * @return retryable the serialized retryable 28 | */ 29 | function getRetryable( 30 | bytes32 ticket 31 | ) external view returns (RetryableInfo memory retryable); 32 | } 33 | -------------------------------------------------------------------------------- /src/osp/IOneStepProofEntry.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "./IOneStepProver.sol"; 8 | import "../state/Machine.sol"; 9 | 10 | library OneStepProofEntryLib { 11 | uint256 internal constant MAX_STEPS = 1 << 43; 12 | } 13 | 14 | struct ExecutionState { 15 | GlobalState globalState; 16 | MachineStatus machineStatus; 17 | } 18 | 19 | interface IOneStepProofEntry { 20 | function getStartMachineHash( 21 | bytes32 globalStateHash, 22 | bytes32 wasmModuleRoot 23 | ) external pure returns (bytes32); 24 | 25 | function proveOneStep( 26 | ExecutionContext calldata execCtx, 27 | uint256 machineStep, 28 | bytes32 beforeHash, 29 | bytes calldata proof 30 | ) external view returns (bytes32 afterHash); 31 | 32 | function getMachineHash( 33 | ExecutionState calldata execState 34 | ) external pure returns (bytes32); 35 | } 36 | -------------------------------------------------------------------------------- /src/osp/IOneStepProver.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "../state/Machine.sol"; 8 | import "../state/Module.sol"; 9 | import "../state/Instructions.sol"; 10 | import "../state/GlobalState.sol"; 11 | import "../bridge/ISequencerInbox.sol"; 12 | import "../bridge/IBridge.sol"; 13 | 14 | struct ExecutionContext { 15 | uint256 maxInboxMessagesRead; 16 | IBridge bridge; 17 | bytes32 initialWasmModuleRoot; 18 | } 19 | 20 | abstract contract IOneStepProver { 21 | function executeOneStep( 22 | ExecutionContext memory execCtx, 23 | Machine calldata mach, 24 | Module calldata mod, 25 | Instruction calldata instruction, 26 | bytes calldata proof 27 | ) external view virtual returns (Machine memory result, Module memory resultMod); 28 | } 29 | -------------------------------------------------------------------------------- /src/precompiles/ArbAddressTable.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity >=0.4.21 <0.9.0; 6 | 7 | /** 8 | * @title Allows registering / retrieving addresses at uint indices, saving calldata. 9 | * @notice Precompiled contract that exists in every Arbitrum chain at 0x0000000000000000000000000000000000000066. 10 | */ 11 | interface ArbAddressTable { 12 | /** 13 | * @notice Check whether an address exists in the address table 14 | * @param addr address to check for presence in table 15 | * @return true if address is in table 16 | */ 17 | function addressExists( 18 | address addr 19 | ) external view returns (bool); 20 | 21 | /** 22 | * @notice compress an address and return the result 23 | * @param addr address to compress 24 | * @return compressed address bytes 25 | */ 26 | function compress( 27 | address addr 28 | ) external returns (bytes memory); 29 | 30 | /** 31 | * @notice read a compressed address from a bytes buffer 32 | * @param buf bytes buffer containing an address 33 | * @param offset offset of target address 34 | * @return resulting address and updated offset into the buffer (revert if buffer is too short) 35 | */ 36 | function decompress( 37 | bytes calldata buf, 38 | uint256 offset 39 | ) external view returns (address, uint256); 40 | 41 | /** 42 | * @param addr address to lookup 43 | * @return index of an address in the address table (revert if address isn't in the table) 44 | */ 45 | function lookup( 46 | address addr 47 | ) external view returns (uint256); 48 | 49 | /** 50 | * @param index index to lookup address 51 | * @return address at a given index in address table (revert if index is beyond end of table) 52 | */ 53 | function lookupIndex( 54 | uint256 index 55 | ) external view returns (address); 56 | 57 | /** 58 | * @notice Register an address in the address table 59 | * @param addr address to register 60 | * @return index of the address (existing index, or newly created index if not already registered) 61 | */ 62 | function register( 63 | address addr 64 | ) external returns (uint256); 65 | 66 | /** 67 | * @return size of address table (= first unused index) 68 | */ 69 | function size() external view returns (uint256); 70 | } 71 | -------------------------------------------------------------------------------- /src/precompiles/ArbBLS.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity >=0.4.21 <0.9.0; 6 | 7 | /// @title Disabled precompile, formerly used to register BLS public keys. 8 | /// @notice Precompiled contract that exists in every Arbitrum chain at 0x0000000000000000000000000000000000000067. 9 | interface ArbBLS {} 10 | -------------------------------------------------------------------------------- /src/precompiles/ArbDebug.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2023, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity >=0.4.21 <0.9.0; 6 | 7 | /** 8 | * @title A test contract whose methods are only accessible in debug mode 9 | * @notice Precompiled contract that exists in every Arbitrum chain at 0x00000000000000000000000000000000000000ff. 10 | */ 11 | interface ArbDebug { 12 | /// @notice Caller becomes a chain owner 13 | function becomeChainOwner() external; 14 | 15 | /// @notice Emit events with values based on the args provided 16 | function events(bool flag, bytes32 value) external payable returns (address, uint256); 17 | 18 | /// @notice Tries (and fails) to emit logs in a view context 19 | function eventsView() external view; 20 | 21 | // Events that exist for testing log creation and pricing 22 | event Basic(bool flag, bytes32 indexed value); 23 | event Mixed( 24 | bool indexed flag, bool not, bytes32 indexed value, address conn, address indexed caller 25 | ); 26 | event Store( 27 | bool indexed flag, address indexed field, uint24 number, bytes32 value, bytes store 28 | ); 29 | 30 | function customRevert( 31 | uint64 number 32 | ) external pure; 33 | 34 | function panic() external; 35 | 36 | function legacyError() external pure; 37 | 38 | error Custom(uint64, string, bool); 39 | error Unused(); 40 | } 41 | -------------------------------------------------------------------------------- /src/precompiles/ArbFunctionTable.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity >=0.4.21 <0.9.0; 6 | 7 | /// @title Deprecated - Provided aggregator's the ability to manage function tables, 8 | // this enables one form of transaction compression. 9 | /// @notice The Nitro aggregator implementation does not use these, 10 | // so these methods have been stubbed and their effects disabled. 11 | /// They are kept for backwards compatibility. 12 | /// Precompiled contract that exists in every Arbitrum chain at 0x0000000000000000000000000000000000000068. 13 | interface ArbFunctionTable { 14 | /// @notice Reverts since the table is empty 15 | function upload( 16 | bytes calldata buf 17 | ) external; 18 | 19 | /// @notice Returns the empty table's size, which is 0 20 | function size( 21 | address addr 22 | ) external view returns (uint256); 23 | 24 | /// @notice No-op 25 | function get(address addr, uint256 index) external view returns (uint256, bool, uint256); 26 | } 27 | -------------------------------------------------------------------------------- /src/precompiles/ArbInfo.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity >=0.4.21 <0.9.0; 6 | 7 | /// @title Lookup for basic info about accounts and contracts. 8 | /// @notice Precompiled contract that exists in every Arbitrum chain at 0x0000000000000000000000000000000000000065. 9 | interface ArbInfo { 10 | /// @notice Retrieves an account's balance 11 | function getBalance( 12 | address account 13 | ) external view returns (uint256); 14 | 15 | /// @notice Retrieves a contract's deployed code 16 | function getCode( 17 | address account 18 | ) external view returns (bytes memory); 19 | } 20 | -------------------------------------------------------------------------------- /src/precompiles/ArbOwnerPublic.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity >=0.4.21 <0.9.0; 6 | 7 | /// @title Provides non-owners with info about the current chain owners. 8 | /// @notice Precompiled contract that exists in every Arbitrum chain at 0x000000000000000000000000000000000000006b. 9 | interface ArbOwnerPublic { 10 | /// @notice See if the user is a chain owner 11 | function isChainOwner( 12 | address addr 13 | ) external view returns (bool); 14 | 15 | /** 16 | * @notice Rectify the list of chain owners 17 | * If successful, emits ChainOwnerRectified event 18 | * Available in ArbOS version 11 19 | */ 20 | function rectifyChainOwner( 21 | address ownerToRectify 22 | ) external; 23 | 24 | /// @notice Retrieves the list of chain owners 25 | function getAllChainOwners() external view returns (address[] memory); 26 | 27 | /// @notice Gets the network fee collector 28 | function getNetworkFeeAccount() external view returns (address); 29 | 30 | /// @notice Get the infrastructure fee collector 31 | function getInfraFeeAccount() external view returns (address); 32 | 33 | /// @notice Get the Brotli compression level used for fast compression 34 | function getBrotliCompressionLevel() external view returns (uint64); 35 | 36 | /// @notice Get the next scheduled ArbOS version upgrade and its activation timestamp. 37 | /// Returns (0, 0) if no ArbOS upgrade is scheduled. 38 | /// Available in ArbOS version 20. 39 | function getScheduledUpgrade() 40 | external 41 | view 42 | returns (uint64 arbosVersion, uint64 scheduledForTimestamp); 43 | 44 | /** 45 | * @notice Checks if the increased calldata price feature (EIP-7623) is enabled 46 | * Available in ArbOS version 40 with default as false 47 | */ 48 | function isCalldataPriceIncreaseEnabled() external view returns (bool); 49 | 50 | event ChainOwnerRectified(address rectifiedOwner); 51 | } 52 | -------------------------------------------------------------------------------- /src/precompiles/ArbStatistics.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity >=0.4.21 <0.9.0; 6 | 7 | /// @title Deprecated - Info about the rollup just prior to the Nitro upgrade 8 | /// @notice Precompiled contract in every Arbitrum chain for retryable transaction related data retrieval and interactions. Exists at 0x000000000000000000000000000000000000006f 9 | interface ArbStatistics { 10 | /// @notice Get Arbitrum block number and other statistics as they were right before the Nitro upgrade. 11 | /// @return ( 12 | /// Number of accounts, 13 | /// Total storage allocated (includes storage that was later deallocated), 14 | /// Total ArbGas used, 15 | /// Number of transaction receipt issued, 16 | /// Number of contracts created, 17 | /// ) 18 | function getStats() 19 | external 20 | view 21 | returns (uint256, uint256, uint256, uint256, uint256, uint256); 22 | } 23 | -------------------------------------------------------------------------------- /src/precompiles/ArbWasmCache.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2022-2024, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity >=0.4.21 <0.9.0; 6 | 7 | /** 8 | * @title Methods for managing Stylus caches 9 | * @notice Precompiled contract that exists in every Arbitrum chain at 0x0000000000000000000000000000000000000072. 10 | */ 11 | interface ArbWasmCache { 12 | /// @notice See if the user is a cache manager. 13 | function isCacheManager( 14 | address manager 15 | ) external view returns (bool); 16 | 17 | /// @notice Retrieve all address managers. 18 | /// @return managers the list of managers. 19 | function allCacheManagers() external view returns (address[] memory managers); 20 | 21 | /// @dev Deprecated, replaced with cacheProgram 22 | function cacheCodehash( 23 | bytes32 codehash 24 | ) external; 25 | 26 | /// @notice Caches all programs with a codehash equal to the given address. 27 | /// @notice Reverts if the programs have expired. 28 | /// @notice Caller must be a cache manager or chain owner. 29 | /// @notice If you're looking for how to bid for position, interact with the chain's cache manager contract. 30 | function cacheProgram( 31 | address addr 32 | ) external; 33 | 34 | /// @notice Evicts all programs with the given codehash. 35 | /// @notice Caller must be a cache manager or chain owner. 36 | function evictCodehash( 37 | bytes32 codehash 38 | ) external; 39 | 40 | /// @notice Gets whether a program is cached. Note that the program may be expired. 41 | function codehashIsCached( 42 | bytes32 codehash 43 | ) external view returns (bool); 44 | 45 | event UpdateProgramCache(address indexed manager, bytes32 indexed codehash, bool cached); 46 | } 47 | -------------------------------------------------------------------------------- /src/precompiles/ArbosActs.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.4.21 <0.9.0; 20 | 21 | /** 22 | * @title This precompile represents ArbOS's internal actions as calls it makes to itself 23 | * @notice Calling this precompile will always revert and should not be done. 24 | */ 25 | interface ArbosActs { 26 | /** 27 | * @notice ArbOS "calls" this when starting a block 28 | * @param l1BaseFee the L1 BaseFee 29 | * @param l1BlockNumber the L1 block number 30 | * @param timePassed number of seconds since the last block 31 | */ 32 | function startBlock( 33 | uint256 l1BaseFee, 34 | uint64 l1BlockNumber, 35 | uint64 l2BlockNumber, 36 | uint64 timePassed 37 | ) external; 38 | 39 | function batchPostingReport( 40 | uint256 batchTimestamp, 41 | address batchPosterAddress, 42 | uint64 batchNumber, 43 | uint64 batchDataGas, 44 | uint256 l1BaseFeeWei 45 | ) external; 46 | 47 | error CallerNotArbOS(); 48 | } 49 | -------------------------------------------------------------------------------- /src/precompiles/ArbosTest.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity >=0.4.21 <0.9.0; 6 | 7 | /// @title Deprecated - Provides a method of burning arbitrary amounts of gas, 8 | /// @notice This exists for historical reasons. Pre-Nitro, `ArbosTest` had additional methods only the zero address could call. 9 | /// These have been removed since users don't use them and calls to missing methods revert. 10 | /// Precompiled contract that exists in every Arbitrum chain at 0x0000000000000000000000000000000000000069. 11 | interface ArbosTest { 12 | /// @notice Unproductively burns the amount of L2 ArbGas 13 | function burnArbGas( 14 | uint256 gasAmount 15 | ) external pure; 16 | } 17 | -------------------------------------------------------------------------------- /src/rollup/AbsRollupEventInbox.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "./IRollupEventInbox.sol"; 8 | import "../bridge/IBridge.sol"; 9 | import "../bridge/IEthBridge.sol"; 10 | import "../precompiles/ArbGasInfo.sol"; 11 | import "../libraries/ArbitrumChecker.sol"; 12 | import "../bridge/IDelayedMessageProvider.sol"; 13 | import "../libraries/DelegateCallAware.sol"; 14 | import {AlreadyInit, HadZeroInit, RollupNotChanged} from "../libraries/Error.sol"; 15 | 16 | /** 17 | * @title The inbox for rollup protocol events 18 | */ 19 | abstract contract AbsRollupEventInbox is 20 | IRollupEventInbox, 21 | IDelayedMessageProvider, 22 | DelegateCallAware 23 | { 24 | IBridge public override bridge; 25 | address public override rollup; 26 | 27 | modifier onlyRollup() { 28 | require(msg.sender == rollup, "ONLY_ROLLUP"); 29 | _; 30 | } 31 | 32 | function initialize( 33 | IBridge _bridge 34 | ) external override onlyDelegated { 35 | if (address(bridge) != address(0)) revert AlreadyInit(); 36 | if (address(_bridge) == address(0)) revert HadZeroInit(); 37 | bridge = _bridge; 38 | rollup = address(_bridge.rollup()); 39 | } 40 | 41 | /// @notice Allows the rollup owner to sync the rollup address 42 | function updateRollupAddress() external { 43 | if (msg.sender != IOwnable(rollup).owner()) { 44 | revert NotOwner(msg.sender, IOwnable(rollup).owner()); 45 | } 46 | address newRollup = address(bridge.rollup()); 47 | if (rollup == newRollup) revert RollupNotChanged(); 48 | rollup = newRollup; 49 | } 50 | 51 | function rollupInitialized( 52 | uint256 chainId, 53 | string calldata chainConfig 54 | ) external override onlyRollup { 55 | require(bytes(chainConfig).length > 0, "EMPTY_CHAIN_CONFIG"); 56 | uint8 initMsgVersion = 1; 57 | uint256 currentDataCost = _currentDataCostToReport(); 58 | bytes memory initMsg = 59 | abi.encodePacked(chainId, initMsgVersion, currentDataCost, chainConfig); 60 | uint256 num = _enqueueInitializationMsg(initMsg); 61 | emit InboxMessageDelivered(num, initMsg); 62 | } 63 | 64 | function _enqueueInitializationMsg( 65 | bytes memory initMsg 66 | ) internal virtual returns (uint256); 67 | 68 | function _currentDataCostToReport() internal virtual returns (uint256); 69 | } 70 | -------------------------------------------------------------------------------- /src/rollup/AssertionState.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "../state/GlobalState.sol"; 8 | import "../state/Machine.sol"; 9 | import "../osp/IOneStepProofEntry.sol"; 10 | 11 | struct AssertionState { 12 | GlobalState globalState; 13 | MachineStatus machineStatus; 14 | bytes32 endHistoryRoot; 15 | } 16 | 17 | library AssertionStateLib { 18 | function toExecutionState( 19 | AssertionState memory state 20 | ) internal pure returns (ExecutionState memory) { 21 | return ExecutionState(state.globalState, state.machineStatus); 22 | } 23 | 24 | function hash( 25 | AssertionState memory state 26 | ) internal pure returns (bytes32) { 27 | return keccak256(abi.encode(state)); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/rollup/Config.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "../state/GlobalState.sol"; 8 | import "../state/Machine.sol"; 9 | import "../bridge/ISequencerInbox.sol"; 10 | import "../bridge/IBridge.sol"; 11 | import "../bridge/IOutbox.sol"; 12 | import "../bridge/IInboxBase.sol"; 13 | import "./IRollupEventInbox.sol"; 14 | import "./IRollupLogic.sol"; 15 | import "../challengeV2/IEdgeChallengeManager.sol"; 16 | 17 | struct Config { 18 | uint64 confirmPeriodBlocks; 19 | address stakeToken; 20 | uint256 baseStake; 21 | bytes32 wasmModuleRoot; 22 | address owner; 23 | address loserStakeEscrow; 24 | uint256 chainId; 25 | string chainConfig; 26 | uint256 minimumAssertionPeriod; 27 | uint64 validatorAfkBlocks; 28 | uint256[] miniStakeValues; 29 | ISequencerInbox.MaxTimeVariation sequencerInboxMaxTimeVariation; 30 | uint256 layerZeroBlockEdgeHeight; 31 | uint256 layerZeroBigStepEdgeHeight; 32 | uint256 layerZeroSmallStepEdgeHeight; 33 | /// @notice The execution state to be used in the genesis assertion 34 | AssertionState genesisAssertionState; 35 | /// @notice The inbox size at the time the genesis execution state was created 36 | uint256 genesisInboxCount; 37 | address anyTrustFastConfirmer; 38 | uint8 numBigStepLevel; 39 | uint64 challengeGracePeriodBlocks; 40 | BufferConfig bufferConfig; 41 | } 42 | 43 | struct ContractDependencies { 44 | IBridge bridge; 45 | ISequencerInbox sequencerInbox; 46 | IInboxBase inbox; 47 | IOutbox outbox; 48 | IRollupEventInbox rollupEventInbox; 49 | IEdgeChallengeManager challengeManager; 50 | address rollupAdminLogic; // this cannot be IRollupAdmin because of circular dependencies 51 | IRollupUser rollupUserLogic; 52 | address validatorWalletCreator; 53 | } 54 | -------------------------------------------------------------------------------- /src/rollup/ERC20RollupEventInbox.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "./AbsRollupEventInbox.sol"; 8 | import "../bridge/IERC20Bridge.sol"; 9 | import "../bridge/ISequencerInbox.sol"; 10 | import {INITIALIZATION_MSG_TYPE} from "../libraries/MessageTypes.sol"; 11 | 12 | /** 13 | * @title The inbox for rollup protocol events 14 | */ 15 | contract ERC20RollupEventInbox is AbsRollupEventInbox { 16 | constructor() AbsRollupEventInbox() {} 17 | 18 | function _enqueueInitializationMsg( 19 | bytes memory initMsg 20 | ) internal override returns (uint256) { 21 | uint256 tokenAmount = 0; 22 | return IERC20Bridge(address(bridge)).enqueueDelayedMessage( 23 | INITIALIZATION_MSG_TYPE, address(0), keccak256(initMsg), tokenAmount 24 | ); 25 | } 26 | 27 | function _currentDataCostToReport() internal override returns (uint256) { 28 | // if a fee token pricer is configured then it can be used to charge for data posting fees 29 | ISequencerInbox seqInbox = ISequencerInbox(bridge.sequencerInbox()); 30 | IFeeTokenPricer feeTokenPricer = seqInbox.feeTokenPricer(); 31 | if (address(feeTokenPricer) != address(0)) { 32 | uint256 gasPrice = block.basefee; 33 | if (ArbitrumChecker.runningOnArbitrum()) { 34 | gasPrice += ArbGasInfo(address(0x6c)).getL1BaseFeeEstimate(); 35 | } 36 | // scale the current gas price to the child chain gas price 37 | uint256 exchangeRate = feeTokenPricer.getExchangeRate(); 38 | return (gasPrice * exchangeRate) / 1e18; 39 | } 40 | 41 | // if no fee token pricer is configured then data costs cant be reimbursed, and l1 price is set to 0 42 | return 0; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/rollup/FactoryDeployerHelper.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | pragma solidity ^0.8.0; 3 | 4 | /** 5 | * @title Helper contract for cross-chain deployment of deterministic factories when rollup uses custom fee token 6 | * @notice It bundles sending the fee token to inbox and invoking the factory deployment function. 7 | * Prerequisite: fee token must be approved for this contract to send it to inbox. 8 | */ 9 | contract FactoryDeployerHelper { 10 | address public constant DEPLOY_HELPER = address(0x90D68B056c411015eaE3EC0b98AD94E2C91419F1); 11 | uint256 public constant MAX_FEE_PER_GAS = 100_000_000; 12 | 13 | function deploy( 14 | address inbox 15 | ) external { 16 | deploy(inbox, MAX_FEE_PER_GAS); 17 | } 18 | 19 | function deploy(address inbox, uint256 maxFeePerGas) public { 20 | address bridge = address(IInboxBase(inbox).bridge()); 21 | address feeToken = IERC20Bridge(bridge).nativeToken(); 22 | 23 | uint256 amount = IDeployHelper(DEPLOY_HELPER).getDeploymentTotalCost(inbox, maxFeePerGas); 24 | IERC20(feeToken).transferFrom(msg.sender, inbox, amount); 25 | IDeployHelper(DEPLOY_HELPER).perform(inbox, feeToken, maxFeePerGas); 26 | } 27 | } 28 | 29 | interface IERC20 { 30 | function transferFrom(address from, address to, uint256 value) external returns (bool); 31 | } 32 | 33 | interface IDeployHelper { 34 | function getDeploymentTotalCost( 35 | address inbox, 36 | uint256 maxFeePerGas 37 | ) external view returns (uint256); 38 | 39 | function perform( 40 | address _inbox, 41 | address _nativeToken, 42 | uint256 _maxFeePerGas 43 | ) external payable; 44 | } 45 | 46 | interface IInboxBase { 47 | function bridge() external view returns (address); 48 | } 49 | 50 | interface IERC20Bridge { 51 | function nativeToken() external view returns (address); 52 | } 53 | -------------------------------------------------------------------------------- /src/rollup/IRollupEventInbox.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "../bridge/IBridge.sol"; 8 | 9 | interface IRollupEventInbox { 10 | function bridge() external view returns (IBridge); 11 | 12 | function initialize( 13 | IBridge _bridge 14 | ) external; 15 | 16 | function rollup() external view returns (address); 17 | 18 | function updateRollupAddress() external; 19 | 20 | function rollupInitialized(uint256 chainId, string calldata chainConfig) external; 21 | } 22 | -------------------------------------------------------------------------------- /src/rollup/IRollupLogic.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "./IRollupCore.sol"; 8 | import "../bridge/ISequencerInbox.sol"; 9 | import "../bridge/IOutbox.sol"; 10 | import "../bridge/IOwnable.sol"; 11 | 12 | interface IRollupUser is IRollupCore, IOwnable { 13 | /// @dev the user logic just validated configuration and shouldn't write to state during init 14 | /// this allows the admin logic to ensure consistency on parameters. 15 | function initialize( 16 | address stakeToken 17 | ) external view; 18 | 19 | function removeWhitelistAfterFork() external; 20 | 21 | function removeWhitelistAfterValidatorAfk() external; 22 | 23 | function confirmAssertion( 24 | bytes32 assertionHash, 25 | bytes32 prevAssertionHash, 26 | AssertionState calldata confirmState, 27 | bytes32 winningEdgeId, 28 | ConfigData calldata prevConfig, 29 | bytes32 inboxAcc 30 | ) external; 31 | 32 | function stakeOnNewAssertion( 33 | AssertionInputs calldata assertion, 34 | bytes32 expectedAssertionHash 35 | ) external; 36 | 37 | function returnOldDeposit() external; 38 | 39 | function returnOldDepositFor( 40 | address stakerAddress 41 | ) external; 42 | 43 | function reduceDeposit( 44 | uint256 target 45 | ) external; 46 | 47 | function withdrawStakerFunds() external returns (uint256); 48 | 49 | function newStakeOnNewAssertion( 50 | uint256 tokenAmount, 51 | AssertionInputs calldata assertion, 52 | bytes32 expectedAssertionHash 53 | ) external; 54 | 55 | function newStakeOnNewAssertion( 56 | uint256 tokenAmount, 57 | AssertionInputs calldata assertion, 58 | bytes32 expectedAssertionHash, 59 | address withdrawalAddress 60 | ) external; 61 | 62 | function newStake(uint256 tokenAmount, address withdrawalAddress) external; 63 | 64 | function addToDeposit( 65 | address stakerAddress, 66 | address expectedWithdrawalAddress, 67 | uint256 tokenAmount 68 | ) external; 69 | } 70 | -------------------------------------------------------------------------------- /src/rollup/RollupEventInbox.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "./AbsRollupEventInbox.sol"; 8 | import "../bridge/IEthBridge.sol"; 9 | import {INITIALIZATION_MSG_TYPE} from "../libraries/MessageTypes.sol"; 10 | 11 | /** 12 | * @title The inbox for rollup protocol events 13 | */ 14 | contract RollupEventInbox is AbsRollupEventInbox { 15 | constructor() AbsRollupEventInbox() {} 16 | 17 | function _enqueueInitializationMsg( 18 | bytes memory initMsg 19 | ) internal override returns (uint256) { 20 | return IEthBridge(address(bridge)).enqueueDelayedMessage( 21 | INITIALIZATION_MSG_TYPE, address(0), keccak256(initMsg) 22 | ); 23 | } 24 | 25 | function _currentDataCostToReport() internal view override returns (uint256) { 26 | uint256 currentDataCost = block.basefee; 27 | if (ArbitrumChecker.runningOnArbitrum()) { 28 | currentDataCost += ArbGasInfo(address(0x6c)).getL1BaseFeeEstimate(); 29 | } 30 | return currentDataCost; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/rollup/RollupProxy.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "../libraries/AdminFallbackProxy.sol"; 8 | import "./IRollupAdmin.sol"; 9 | import "./Config.sol"; 10 | 11 | contract RollupProxy is AdminFallbackProxy { 12 | function initializeProxy( 13 | Config memory config, 14 | ContractDependencies memory connectedContracts 15 | ) external { 16 | if ( 17 | _getAdmin() == address(0) && _getImplementation() == address(0) 18 | && _getSecondaryImplementation() == address(0) 19 | ) { 20 | _initialize( 21 | address(connectedContracts.rollupAdminLogic), 22 | abi.encodeCall(IRollupAdmin.initialize, (config, connectedContracts)), 23 | address(connectedContracts.rollupUserLogic), 24 | abi.encodeCall(IRollupUser.initialize, (config.stakeToken)), 25 | config.owner 26 | ); 27 | } else { 28 | _fallback(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/rollup/ValidatorUtils.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.0; 2 | -------------------------------------------------------------------------------- /src/rollup/ValidatorWalletCreator.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; 8 | import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 9 | import "@openzeppelin/contracts/access/Ownable.sol"; 10 | 11 | import "./ValidatorWallet.sol"; 12 | 13 | contract ValidatorWalletCreator is Ownable { 14 | event WalletCreated( 15 | address indexed walletAddress, 16 | address indexed executorAddress, 17 | address indexed ownerAddress, 18 | address adminProxy 19 | ); 20 | event TemplateUpdated(); 21 | 22 | address public template; 23 | 24 | constructor() Ownable() { 25 | template = address(new ValidatorWallet()); 26 | } 27 | 28 | function setTemplate( 29 | address _template 30 | ) external onlyOwner { 31 | template = _template; 32 | emit TemplateUpdated(); 33 | } 34 | 35 | function createWallet( 36 | address[] calldata initialExecutorAllowedDests 37 | ) external returns (address) { 38 | address _executor = msg.sender; 39 | address _owner = msg.sender; 40 | ProxyAdmin admin = new ProxyAdmin(); 41 | address proxy = 42 | address(new TransparentUpgradeableProxy(address(template), address(admin), "")); 43 | admin.transferOwnership(_owner); 44 | ValidatorWallet(payable(proxy)).initialize(_executor, _owner, initialExecutorAllowedDests); 45 | emit WalletCreated(proxy, _executor, _owner, address(admin)); 46 | return proxy; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/state/Module.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2023, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "./ModuleMemoryCompact.sol"; 8 | 9 | struct Module { 10 | bytes32 globalsMerkleRoot; 11 | ModuleMemory moduleMemory; 12 | bytes32 tablesMerkleRoot; 13 | bytes32 functionsMerkleRoot; 14 | bytes32 extraHash; 15 | uint32 internalsOffset; 16 | } 17 | 18 | library ModuleLib { 19 | using ModuleMemoryCompactLib for ModuleMemory; 20 | 21 | function hash( 22 | Module memory mod 23 | ) internal pure returns (bytes32) { 24 | return keccak256( 25 | abi.encodePacked( 26 | "Module:", 27 | mod.globalsMerkleRoot, 28 | mod.moduleMemory.hash(), 29 | mod.tablesMerkleRoot, 30 | mod.functionsMerkleRoot, 31 | mod.extraHash, 32 | mod.internalsOffset 33 | ) 34 | ); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/state/ModuleMemoryCompact.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | struct ModuleMemory { 8 | uint64 size; 9 | uint64 maxSize; 10 | bytes32 merkleRoot; 11 | } 12 | 13 | library ModuleMemoryCompactLib { 14 | function hash( 15 | ModuleMemory memory mem 16 | ) internal pure returns (bytes32) { 17 | return keccak256(abi.encodePacked("Memory:", mem.size, mem.maxSize, mem.merkleRoot)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/state/MultiStack.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2024, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | struct MultiStack { 8 | bytes32 inactiveStackHash; // NO_STACK_HASH if no stack, 0 if empty stack 9 | bytes32 remainingHash; // 0 if less than 2 cothreads exist 10 | } 11 | 12 | library MultiStackLib { 13 | bytes32 internal constant NO_STACK_HASH = ~bytes32(0); 14 | 15 | function hash( 16 | MultiStack memory multi, 17 | bytes32 activeStackHash, 18 | bool cothread 19 | ) internal pure returns (bytes32) { 20 | require(activeStackHash != NO_STACK_HASH, "MULTISTACK_NOSTACK_ACTIVE"); 21 | if (cothread) { 22 | require(multi.inactiveStackHash != NO_STACK_HASH, "MULTISTACK_NOSTACK_MAIN"); 23 | return keccak256( 24 | abi.encodePacked( 25 | "multistack:", multi.inactiveStackHash, activeStackHash, multi.remainingHash 26 | ) 27 | ); 28 | } else { 29 | return keccak256( 30 | abi.encodePacked( 31 | "multistack:", activeStackHash, multi.inactiveStackHash, multi.remainingHash 32 | ) 33 | ); 34 | } 35 | } 36 | 37 | function setEmpty( 38 | MultiStack memory multi 39 | ) internal pure { 40 | multi.inactiveStackHash = NO_STACK_HASH; 41 | multi.remainingHash = 0; 42 | } 43 | 44 | function pushNew( 45 | MultiStack memory multi 46 | ) internal pure { 47 | if (multi.inactiveStackHash != NO_STACK_HASH) { 48 | multi.remainingHash = keccak256( 49 | abi.encodePacked("cothread:", multi.inactiveStackHash, multi.remainingHash) 50 | ); 51 | } 52 | multi.inactiveStackHash = 0; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/state/PcArray.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | struct PcArray { 8 | uint32[] inner; 9 | } 10 | 11 | library PcArrayLib { 12 | function get(PcArray memory arr, uint256 index) internal pure returns (uint32) { 13 | return arr.inner[index]; 14 | } 15 | 16 | function set(PcArray memory arr, uint256 index, uint32 val) internal pure { 17 | arr.inner[index] = val; 18 | } 19 | 20 | function length( 21 | PcArray memory arr 22 | ) internal pure returns (uint256) { 23 | return arr.inner.length; 24 | } 25 | 26 | function push(PcArray memory arr, uint32 val) internal pure { 27 | uint32[] memory newInner = new uint32[](arr.inner.length + 1); 28 | for (uint256 i = 0; i < arr.inner.length; i++) { 29 | newInner[i] = arr.inner[i]; 30 | } 31 | newInner[arr.inner.length] = val; 32 | arr.inner = newInner; 33 | } 34 | 35 | function pop( 36 | PcArray memory arr 37 | ) internal pure returns (uint32 popped) { 38 | popped = arr.inner[arr.inner.length - 1]; 39 | uint32[] memory newInner = new uint32[](arr.inner.length - 1); 40 | for (uint256 i = 0; i < newInner.length; i++) { 41 | newInner[i] = arr.inner[i]; 42 | } 43 | arr.inner = newInner; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/state/StackFrame.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2023, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "./Value.sol"; 8 | 9 | struct StackFrame { 10 | Value returnPc; 11 | bytes32 localsMerkleRoot; 12 | uint32 callerModule; 13 | uint32 callerModuleInternals; 14 | } 15 | 16 | struct StackFrameWindow { 17 | StackFrame[] proved; 18 | bytes32 remainingHash; 19 | } 20 | 21 | library StackFrameLib { 22 | using ValueLib for Value; 23 | 24 | function hash( 25 | StackFrame memory frame 26 | ) internal pure returns (bytes32) { 27 | return keccak256( 28 | abi.encodePacked( 29 | "Stack frame:", 30 | frame.returnPc.hash(), 31 | frame.localsMerkleRoot, 32 | frame.callerModule, 33 | frame.callerModuleInternals 34 | ) 35 | ); 36 | } 37 | 38 | function hash( 39 | StackFrameWindow memory window 40 | ) internal pure returns (bytes32 h) { 41 | h = window.remainingHash; 42 | for (uint256 i = 0; i < window.proved.length; i++) { 43 | h = keccak256(abi.encodePacked("Stack frame stack:", hash(window.proved[i]), h)); 44 | } 45 | } 46 | 47 | function peek( 48 | StackFrameWindow memory window 49 | ) internal pure returns (StackFrame memory) { 50 | require(window.proved.length == 1, "BAD_WINDOW_LENGTH"); 51 | return window.proved[0]; 52 | } 53 | 54 | function pop( 55 | StackFrameWindow memory window 56 | ) internal pure returns (StackFrame memory frame) { 57 | require(window.proved.length == 1, "BAD_WINDOW_LENGTH"); 58 | frame = window.proved[0]; 59 | window.proved = new StackFrame[](0); 60 | } 61 | 62 | function push(StackFrameWindow memory window, StackFrame memory frame) internal pure { 63 | StackFrame[] memory newProved = new StackFrame[](window.proved.length + 1); 64 | for (uint256 i = 0; i < window.proved.length; i++) { 65 | newProved[i] = window.proved[i]; 66 | } 67 | newProved[window.proved.length] = frame; 68 | window.proved = newProved; 69 | } 70 | 71 | function overwrite(StackFrameWindow memory window, bytes32 root) internal pure { 72 | window.remainingHash = root; 73 | delete window.proved; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/state/ValueArray.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "./Value.sol"; 8 | 9 | struct ValueArray { 10 | Value[] inner; 11 | } 12 | 13 | library ValueArrayLib { 14 | function get(ValueArray memory arr, uint256 index) internal pure returns (Value memory) { 15 | return arr.inner[index]; 16 | } 17 | 18 | function set(ValueArray memory arr, uint256 index, Value memory val) internal pure { 19 | arr.inner[index] = val; 20 | } 21 | 22 | function length( 23 | ValueArray memory arr 24 | ) internal pure returns (uint256) { 25 | return arr.inner.length; 26 | } 27 | 28 | function push(ValueArray memory arr, Value memory val) internal pure { 29 | Value[] memory newInner = new Value[](arr.inner.length + 1); 30 | for (uint256 i = 0; i < arr.inner.length; i++) { 31 | newInner[i] = arr.inner[i]; 32 | } 33 | newInner[arr.inner.length] = val; 34 | arr.inner = newInner; 35 | } 36 | 37 | function pop( 38 | ValueArray memory arr 39 | ) internal pure returns (Value memory popped) { 40 | popped = arr.inner[arr.inner.length - 1]; 41 | Value[] memory newInner = new Value[](arr.inner.length - 1); 42 | for (uint256 i = 0; i < newInner.length; i++) { 43 | newInner[i] = arr.inner[i]; 44 | } 45 | arr.inner = newInner; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/state/ValueStack.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2023, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "./Value.sol"; 8 | import "./ValueArray.sol"; 9 | 10 | struct ValueStack { 11 | ValueArray proved; 12 | bytes32 remainingHash; 13 | } 14 | 15 | library ValueStackLib { 16 | using ValueLib for Value; 17 | using ValueArrayLib for ValueArray; 18 | 19 | function hash( 20 | ValueStack memory stack 21 | ) internal pure returns (bytes32 h) { 22 | h = stack.remainingHash; 23 | uint256 len = stack.proved.length(); 24 | for (uint256 i = 0; i < len; i++) { 25 | h = keccak256(abi.encodePacked("Value stack:", stack.proved.get(i).hash(), h)); 26 | } 27 | } 28 | 29 | function peek( 30 | ValueStack memory stack 31 | ) internal pure returns (Value memory) { 32 | uint256 len = stack.proved.length(); 33 | return stack.proved.get(len - 1); 34 | } 35 | 36 | function pop( 37 | ValueStack memory stack 38 | ) internal pure returns (Value memory) { 39 | return stack.proved.pop(); 40 | } 41 | 42 | function push(ValueStack memory stack, Value memory val) internal pure { 43 | return stack.proved.push(val); 44 | } 45 | 46 | function overwrite(ValueStack memory stack, bytes32 root) internal pure { 47 | stack.remainingHash = root; 48 | delete stack.proved; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/test-helpers/CryptographyPrimitivesTester.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "../libraries/CryptographyPrimitives.sol"; 8 | 9 | library CryptographyPrimitivesTester { 10 | function keccakF( 11 | uint256[25] memory input 12 | ) public pure returns (uint256[25] memory) { 13 | return CryptographyPrimitives.keccakF(input); 14 | } 15 | 16 | function sha256Block( 17 | bytes32[2] memory inputChunk, 18 | bytes32 hashState 19 | ) public pure returns (bytes32) { 20 | return bytes32( 21 | CryptographyPrimitives.sha256Block( 22 | [uint256(inputChunk[0]), uint256(inputChunk[1])], uint256(hashState) 23 | ) 24 | ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test-helpers/EthVault.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | /** 8 | * Simple contract for testing bridge calls which include calldata 9 | */ 10 | contract EthVault { 11 | uint256 public version = 0; 12 | 13 | function setVersion( 14 | uint256 _version 15 | ) external payable { 16 | version = _version; 17 | } 18 | 19 | function justRevert() external payable { 20 | revert("bye"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test-helpers/InterfaceCompatibilityTester.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | // solhint-disable-next-line compiler-version 6 | pragma solidity >=0.6.9 <0.9.0; 7 | 8 | import "../bridge/IBridge.sol"; 9 | import "../bridge/IOutbox.sol"; 10 | import "../bridge/IInbox.sol"; 11 | import "../bridge/ISequencerInbox.sol"; 12 | -------------------------------------------------------------------------------- /src/test-helpers/MessageTester.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "../bridge/Messages.sol"; 8 | 9 | contract MessageTester { 10 | function messageHash( 11 | uint8 messageType, 12 | address sender, 13 | uint64 blockNumber, 14 | uint64 timestamp, 15 | uint256 inboxSeqNum, 16 | uint256 gasPriceL1, 17 | bytes32 messageDataHash 18 | ) public pure returns (bytes32) { 19 | return Messages.messageHash( 20 | messageType, sender, blockNumber, timestamp, inboxSeqNum, gasPriceL1, messageDataHash 21 | ); 22 | } 23 | 24 | function accumulateInboxMessage(bytes32 inbox, bytes32 message) public pure returns (bytes32) { 25 | return Messages.accumulateInboxMessage(inbox, message); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test-helpers/NoReceiveForwarder.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | /// @notice A call forward that doesnt implement the receive or fallback functions, so cant receive value 5 | contract NoReceiveForwarder { 6 | function forward(address to, bytes calldata data) public payable { 7 | (bool success,) = address(to).call{value: msg.value}(data); 8 | require(success, "call forward failed"); 9 | } 10 | } 11 | 12 | /// @notice A call forward that does implement the receive or fallback functions, so cant receive value 13 | contract ReceivingForwarder { 14 | function forward(address to, bytes calldata data) public payable { 15 | (bool success,) = address(to).call{value: msg.value}(data); 16 | require(success, "call forward failed"); 17 | } 18 | 19 | receive() external payable {} 20 | } 21 | 22 | /// @notice Errors upon construction 23 | contract ConstructorError { 24 | constructor() { 25 | require(false, "test error in constructor"); 26 | } 27 | } 28 | 29 | /// @notice Errors upon construction 30 | contract ConstructorFine { 31 | constructor() { 32 | require(true, "test error in constructor"); 33 | } 34 | 35 | function number() public pure returns (uint256) { 36 | return 0; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test-helpers/RollupMock.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.4; 6 | 7 | contract RollupMock { 8 | event WithdrawTriggered(); 9 | event ZombieTriggered(); 10 | 11 | address public owner; 12 | 13 | constructor( 14 | address _owner 15 | ) { 16 | owner = _owner; 17 | } 18 | 19 | function withdrawStakerFunds() external returns (uint256) { 20 | emit WithdrawTriggered(); 21 | return 0; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test-helpers/TestToken.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 8 | 9 | /** 10 | * Basic ERC20 token 11 | */ 12 | contract TestToken is ERC20 { 13 | constructor( 14 | uint256 initialSupply 15 | ) ERC20("TestToken", "TT") { 16 | _mint(msg.sender, initialSupply); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/test-helpers/ValueArrayTester.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022, Offchain Labs, Inc. 2 | // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "../state/ValueArray.sol"; 8 | 9 | contract ValueArrayTester { 10 | using ValueArrayLib for ValueArray; 11 | 12 | function test() external pure { 13 | ValueArray memory arr = ValueArray(new Value[](2)); 14 | require(arr.length() == 2, "START_LEN"); 15 | arr.set(0, ValueLib.newI32(1)); 16 | arr.set(1, ValueLib.newI32(2)); 17 | arr.push(ValueLib.newI32(3)); 18 | require(arr.length() == 3, "PUSH_LEN"); 19 | for (uint256 i = 0; i < arr.length(); i++) { 20 | Value memory val = arr.get(i); 21 | require(val.valueType == ValueType.I32, "PUSH_VAL_TYPE"); 22 | require(val.contents == i + 1, "PUSH_VAL_CONTENTS"); 23 | } 24 | Value memory popped = arr.pop(); 25 | require(popped.valueType == ValueType.I32, "POP_RET_TYPE"); 26 | require(popped.contents == 3, "POP_RET_CONTENTS"); 27 | require(arr.length() == 2, "POP_LEN"); 28 | for (uint256 i = 0; i < arr.length(); i++) { 29 | Value memory val = arr.get(i); 30 | require(val.valueType == ValueType.I32, "POP_VAL_TYPE"); 31 | require(val.contents == i + 1, "POP_VAL_CONTENTS"); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /test/ERC20Mock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 6 | 7 | // mock class using ERC20 8 | contract ERC20Mock is ERC20 { 9 | constructor( 10 | string memory name, 11 | string memory symbol, 12 | address initialAccount, 13 | uint256 initialBalance 14 | ) payable ERC20(name, symbol) { 15 | _mint(initialAccount, initialBalance); 16 | } 17 | 18 | function mint(address account, uint256 amount) public { 19 | _mint(account, amount); 20 | } 21 | 22 | function burn(address account, uint256 amount) public { 23 | _burn(account, amount); 24 | } 25 | 26 | function transferInternal(address from, address to, uint256 value) public { 27 | _transfer(from, to, value); 28 | } 29 | 30 | function approveInternal(address owner, address spender, uint256 value) public { 31 | _approve(owner, spender, value); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/challengeV2/StateTools.sol: -------------------------------------------------------------------------------- 1 | // Copyright 2023, Offchain Labs, Inc. 2 | // For license information, see https://github.com/offchainlabs/bold/blob/main/LICENSE 3 | // SPDX-License-Identifier: BUSL-1.1 4 | // 5 | pragma solidity ^0.8.17; 6 | 7 | import "forge-std/Test.sol"; 8 | import "../../src/state/GlobalState.sol"; 9 | import "../../src/state/Machine.sol"; 10 | import "../../src/rollup/RollupLib.sol"; 11 | import "./Utils.sol"; 12 | 13 | library StateToolsLib { 14 | using GlobalStateLib for GlobalState; 15 | 16 | function randomState( 17 | Random rand, 18 | uint256 inboxMsgCountProcessed, 19 | bytes32 blockHash, 20 | MachineStatus ms 21 | ) internal returns (AssertionState memory) { 22 | bytes32[2] memory bytes32Vals = [blockHash, rand.hash()]; 23 | uint64[2] memory u64Vals = [uint64(inboxMsgCountProcessed), uint64(uint256(rand.hash()))]; 24 | 25 | GlobalState memory gs = GlobalState({bytes32Vals: bytes32Vals, u64Vals: u64Vals}); 26 | return AssertionState({globalState: gs, machineStatus: ms, endHistoryRoot: bytes32(0)}); 27 | } 28 | 29 | function hash( 30 | AssertionState memory s 31 | ) internal pure returns (bytes32) { 32 | return s.globalState.hash(); 33 | } 34 | 35 | function mockMachineHash( 36 | AssertionState memory s 37 | ) internal pure returns (bytes32) { 38 | return s.globalState.hash(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /test/contract/common/challengeLib.ts: -------------------------------------------------------------------------------- 1 | import { BigNumber } from '@ethersproject/bignumber' 2 | import { solidityKeccak256 } from 'ethers/lib/utils' 3 | 4 | export enum MachineStatus { 5 | RUNNING = 0, 6 | FINISHED = 1, 7 | ERRORED = 2, 8 | } 9 | 10 | export function machineHash(machineStatus: BigNumber, globalStateHash: string) { 11 | const machineStatusNum = machineStatus.toNumber() 12 | if (machineStatusNum === MachineStatus.FINISHED) { 13 | return solidityKeccak256( 14 | ['string', 'bytes32'], 15 | ['Machine finished:', globalStateHash] 16 | ) 17 | } else if (machineStatusNum === MachineStatus.ERRORED) { 18 | return solidityKeccak256( 19 | ['string', 'bytes32'], 20 | ['Machine errored:', globalStateHash] 21 | ) 22 | } else { 23 | console.log(machineStatus.toNumber()) 24 | throw new Error('BAD_BLOCK_STATUS') 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /test/contract/common/globalStateLib.ts: -------------------------------------------------------------------------------- 1 | import { GlobalStateStruct } from '../../../build/types/src/rollup/RollupUserLogic.sol/RollupUserLogic' 2 | import { solidityKeccak256 } from 'ethers/lib/utils' 3 | 4 | export function hash(state: GlobalStateStruct) { 5 | return solidityKeccak256( 6 | ['string', 'bytes32', 'bytes32', 'uint64', 'uint64'], 7 | [ 8 | 'Global state:', 9 | state.bytes32Vals[0], 10 | state.bytes32Vals[1], 11 | state.u64Vals[0], 12 | state.u64Vals[1], 13 | ] 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /test/contract/types.ts: -------------------------------------------------------------------------------- 1 | import { BigNumber } from '@ethersproject/bignumber' 2 | 3 | export type DelayedMsgHeader = { 4 | kind: number 5 | sender: string 6 | blockNumber: number 7 | timestamp: number 8 | totalDelayedMessagesRead: number 9 | baseFee: number 10 | messageDataHash: string 11 | } 12 | 13 | export type DelayedMsg = { 14 | header: DelayedMsgHeader 15 | messageData: string 16 | } 17 | 18 | export type DelayedMsgDelivered = { 19 | delayedMessage: DelayedMsg 20 | delayedAcc: string 21 | delayedCount: number 22 | } 23 | 24 | export type MaxTimeVariation = { 25 | delaySeconds: number 26 | futureSeconds: number 27 | delayBlocks: number 28 | futureBlocks: number 29 | } 30 | 31 | export type DelayConfig = { 32 | threshold: BigNumber 33 | max: number 34 | replenishRateInBasis: number 35 | } 36 | -------------------------------------------------------------------------------- /test/contract/utils.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from 'hardhat' 2 | import { Signer } from '@ethersproject/abstract-signer' 3 | import { getAddress } from '@ethersproject/address' 4 | 5 | const ADDRESS_ALIAS_OFFSET = BigInt( 6 | '0x1111000000000000000000000000000000001111' 7 | ) 8 | const ADDRESS_BIT_LENGTH = 160 9 | const ADDRESS_NIBBLE_LENGTH = ADDRESS_BIT_LENGTH / 4 10 | 11 | export const applyAlias = (addr: string) => { 12 | // we use BigInts in here to allow for proper overflow behaviour 13 | // BigInt.asUintN calculates the correct positive modulus 14 | return getAddress( 15 | '0x' + 16 | BigInt.asUintN(ADDRESS_BIT_LENGTH, BigInt(addr) + ADDRESS_ALIAS_OFFSET) 17 | .toString(16) 18 | .padStart(ADDRESS_NIBBLE_LENGTH, '0') 19 | ) 20 | } 21 | 22 | export async function initializeAccounts(): Promise { 23 | const [account0] = await ethers.getSigners() 24 | const provider = account0.provider! 25 | 26 | const accounts: Signer[] = [account0] 27 | for (let i = 0; i < 9; i++) { 28 | const account = ethers.Wallet.createRandom().connect(provider) 29 | accounts.push(account) 30 | const tx = await account0.sendTransaction({ 31 | value: ethers.utils.parseEther('10000.0'), 32 | to: await account.getAddress(), 33 | }) 34 | await tx.wait() 35 | } 36 | return accounts 37 | } 38 | 39 | export async function tryAdvanceChain( 40 | account: Signer, 41 | blocks: number 42 | ): Promise { 43 | try { 44 | for (let i = 0; i < blocks; i++) { 45 | await ethers.provider.send('evm_mine', []) 46 | } 47 | } catch (e) { 48 | // EVM mine failed. Try advancing the chain by sending txes if the assertion 49 | // is in dev mode and mints blocks when txes are sent 50 | for (let i = 0; i < blocks; i++) { 51 | const tx = await account.sendTransaction({ 52 | value: 0, 53 | to: await account.getAddress(), 54 | }) 55 | await tx.wait() 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /test/foundry/AbsRollupEventInbox.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.4; 3 | 4 | import "forge-std/Test.sol"; 5 | import "../../src/rollup/AbsRollupEventInbox.sol"; 6 | import {IBridge} from "../../src/bridge/IBridge.sol"; 7 | import {IInboxBase} from "../../src/bridge/IInbox.sol"; 8 | 9 | abstract contract AbsRollupEventInboxTest is Test { 10 | IRollupEventInbox public rollupEventInbox; 11 | IBridge public bridge; 12 | 13 | address public rollup = makeAddr("rollup"); 14 | 15 | uint256 public constant MAX_DATA_SIZE = 104_857; 16 | 17 | /* solhint-disable func-name-mixedcase */ 18 | function test_initialize() public { 19 | assertEq(address(rollupEventInbox.bridge()), address(bridge), "Invalid bridge ref"); 20 | assertEq(address(rollupEventInbox.rollup()), rollup, "Invalid rollup ref"); 21 | } 22 | 23 | function test_initialize_revert_AlreadyInit() public { 24 | vm.expectRevert(AlreadyInit.selector); 25 | rollupEventInbox.initialize(bridge); 26 | } 27 | 28 | function test_updateRollupAddress() public { 29 | vm.prank(rollup); 30 | bridge.updateRollupAddress(IOwnable(address(1337))); 31 | vm.mockCall( 32 | address(rollup), 33 | 0, 34 | abi.encodeWithSelector(IOwnable.owner.selector), 35 | abi.encode(address(this)) 36 | ); 37 | rollupEventInbox.updateRollupAddress(); 38 | assertEq(address(rollupEventInbox.rollup()), address(1337), "Invalid rollup"); 39 | } 40 | 41 | function test_updateRollupAddress_revert_NotOwner() public { 42 | vm.mockCall( 43 | address(rollup), 44 | 0, 45 | abi.encodeWithSelector(IOwnable.owner.selector), 46 | abi.encode(address(1337)) 47 | ); 48 | vm.expectRevert(abi.encodeWithSelector(NotOwner.selector, address(this), address(1337))); 49 | rollupEventInbox.updateRollupAddress(); 50 | } 51 | 52 | /** 53 | * 54 | * Event declarations 55 | * 56 | */ 57 | event MessageDelivered( 58 | uint256 indexed messageIndex, 59 | bytes32 indexed beforeInboxAcc, 60 | address inbox, 61 | uint8 kind, 62 | address sender, 63 | bytes32 messageDataHash, 64 | uint256 baseFeeL1, 65 | uint64 timestamp 66 | ); 67 | event InboxMessageDelivered(uint256 indexed messageNum, bytes data); 68 | } 69 | -------------------------------------------------------------------------------- /test/foundry/ExpressLaneBurner.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BUSL-1.1 2 | pragma solidity ^0.8.0; 3 | 4 | import "forge-std/Test.sol"; 5 | import {ERC20BurnableUpgradeable} from 6 | "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol"; 7 | import {Burner} from "../../src/express-lane-auction/Burner.sol"; 8 | import "../../src/express-lane-auction/Errors.sol"; 9 | 10 | contract MockERC20 is ERC20BurnableUpgradeable { 11 | function initialize() public initializer { 12 | __ERC20_init("LANE", "LNE"); 13 | _mint(msg.sender, 1_000_000); 14 | } 15 | } 16 | 17 | contract ExpressLaneBurner is Test { 18 | event Transfer(address indexed from, address indexed to, uint256 value); 19 | 20 | function testBurn() public { 21 | vm.expectRevert(ZeroAddress.selector); 22 | new Burner(address(0)); 23 | 24 | MockERC20 erc20 = new MockERC20(); 25 | erc20.initialize(); 26 | Burner burner = new Burner(address(erc20)); 27 | assertEq(address(burner.token()), address(erc20)); 28 | 29 | erc20.transfer(address(burner), 20); 30 | 31 | uint256 totalSupplyBefore = erc20.totalSupply(); 32 | assertEq(erc20.balanceOf(address(burner)), 20); 33 | 34 | vm.expectEmit(true, true, true, true); 35 | emit Transfer(address(burner), address(0), 20); 36 | vm.prank(vm.addr(137)); 37 | burner.burn(); 38 | 39 | assertEq(totalSupplyBefore - erc20.totalSupply(), 20); 40 | assertEq(erc20.balanceOf(address(burner)), 0); 41 | 42 | // can burn 0 if we want to 43 | vm.expectEmit(true, true, true, true); 44 | emit Transfer(address(burner), address(0), 0); 45 | vm.prank(vm.addr(138)); 46 | burner.burn(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /test/foundry/fee-token-pricers/ConstantExchangeRatePricer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import {IFeeTokenPricer} from "../../../src/bridge/ISequencerInbox.sol"; 5 | 6 | // NOTICE: This contract has not been audited or properly tested. It is for example purposes only 7 | 8 | /// @title A constant price fee token pricer 9 | /// @notice The most simple kind of fee token pricer, does not account for any change in exchange rate 10 | contract ConstantExchangeRatePricer is IFeeTokenPricer { 11 | uint256 immutable exchangeRate; 12 | 13 | constructor( 14 | uint256 _exchangeRate 15 | ) { 16 | exchangeRate = _exchangeRate; 17 | } 18 | 19 | // @inheritdoc IFeeTokenPricer 20 | function getExchangeRate() external view returns (uint256) { 21 | return exchangeRate; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test/foundry/fee-token-pricers/OwnerAdjustableExchangeRatePricer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import {IFeeTokenPricer} from "../../../src/bridge/ISequencerInbox.sol"; 5 | import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; 6 | 7 | /// @title A uniswap twap pricer 8 | /// @notice An example of a type 1 fee token pricer. The owner can adjust the exchange rate at any time 9 | /// to ensure the batch poster is reimbursed an appropriate amount on the child chain 10 | contract OwnerAdjustableExchangeRatePricer is IFeeTokenPricer, Ownable { 11 | uint256 public exchangeRate; 12 | 13 | event ExchangeRateSet(uint256 newExchangeRate); 14 | 15 | constructor( 16 | uint256 initialExchangeRate 17 | ) Ownable() { 18 | exchangeRate = initialExchangeRate; 19 | emit ExchangeRateSet(initialExchangeRate); 20 | } 21 | 22 | function setExchangeRate( 23 | uint256 _exchangeRate 24 | ) external onlyOwner { 25 | exchangeRate = _exchangeRate; 26 | emit ExchangeRateSet(_exchangeRate); 27 | } 28 | 29 | // @inheritdoc IFeeTokenPricer 30 | function getExchangeRate() external view returns (uint256) { 31 | return exchangeRate; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/foundry/fee-token-pricers/uniswap-v2-twap/FixedPoint.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "./FullMath.sol"; 5 | 6 | // Modified from https://github.com/Uniswap/solidity-lib 7 | // DO NOT USE IN PRODUCTION 8 | 9 | // a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format)) 10 | library FixedPoint { 11 | // range: [0, 2**112 - 1] 12 | // resolution: 1 / 2**112 13 | struct uq112x112 { 14 | uint224 _x; 15 | } 16 | 17 | // range: [0, 2**144 - 1] 18 | // resolution: 1 / 2**112 19 | struct uq144x112 { 20 | uint256 _x; 21 | } 22 | 23 | uint8 public constant RESOLUTION = 112; 24 | uint256 public constant Q112 = 0x10000000000000000000000000000; // 2**112 25 | uint256 private constant Q224 = 0x100000000000000000000000000000000000000000000000000000000; // 2**224 26 | uint256 private constant LOWER_MASK = 0xffffffffffffffffffffffffffff; // decimal of UQ*x112 (lower 112 bits) 27 | 28 | // decode a UQ144x112 into a uint144 by truncating after the radix point 29 | function decode144( 30 | uq144x112 memory self 31 | ) internal pure returns (uint144) { 32 | return uint144(self._x >> RESOLUTION); 33 | } 34 | 35 | // multiply a UQ112x112 by a uint, returning a UQ144x112 36 | // reverts on overflow 37 | function mul(uq112x112 memory self, uint256 y) internal pure returns (uq144x112 memory) { 38 | uint256 z = 0; 39 | require(y == 0 || (z = self._x * y) / y == self._x, "FixedPoint::mul: overflow"); 40 | return uq144x112(z); 41 | } 42 | 43 | // returns a UQ112x112 which represents the ratio of the numerator to the denominator 44 | // can be lossy 45 | function fraction( 46 | uint256 numerator, 47 | uint256 denominator 48 | ) internal pure returns (uq112x112 memory) { 49 | require(denominator > 0, "FixedPoint::fraction: division by zero"); 50 | if (numerator == 0) return FixedPoint.uq112x112(0); 51 | 52 | if (numerator <= type(uint144).max) { 53 | uint256 result = (numerator << RESOLUTION) / denominator; 54 | require(result <= type(uint224).max, "FixedPoint::fraction: overflow"); 55 | return uq112x112(uint224(result)); 56 | } else { 57 | uint256 result = FullMath.mulDiv(numerator, Q112, denominator); 58 | require(result <= type(uint224).max, "FixedPoint::fraction: overflow"); 59 | return uq112x112(uint224(result)); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /test/foundry/fee-token-pricers/uniswap-v2-twap/FullMath.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | // Modified from https://github.com/Uniswap/solidity-lib 5 | // DO NOT USE IN PRODUCTION 6 | 7 | library FullMath { 8 | function fullMul(uint256 x, uint256 y) internal pure returns (uint256 l, uint256 h) { 9 | unchecked { 10 | uint256 mm = mulmod(x, y, type(uint256).max); 11 | l = x * y; 12 | h = mm - l; 13 | if (mm < l) h -= 1; 14 | } 15 | } 16 | 17 | function fullDiv(uint256 l, uint256 h, uint256 d) private pure returns (uint256) { 18 | unchecked { 19 | uint256 pow2 = d & (0 - d); 20 | d /= pow2; 21 | l /= pow2; 22 | l += h * ((0 - pow2) / pow2 + 1); 23 | uint256 r = 1; 24 | r *= 2 - d * r; 25 | r *= 2 - d * r; 26 | r *= 2 - d * r; 27 | r *= 2 - d * r; 28 | r *= 2 - d * r; 29 | r *= 2 - d * r; 30 | r *= 2 - d * r; 31 | r *= 2 - d * r; 32 | return l * r; 33 | } 34 | } 35 | 36 | function mulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256) { 37 | unchecked { 38 | (uint256 l, uint256 h) = fullMul(x, y); 39 | 40 | uint256 mm = mulmod(x, y, d); 41 | if (mm > l) h -= 1; 42 | l -= mm; 43 | 44 | if (h == 0) return l / d; 45 | 46 | require(h < d, "FullMath: FULLDIV_OVERFLOW"); 47 | return fullDiv(l, h, d); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /test/foundry/util/NoZeroTransferToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.4; 3 | 4 | import "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetFixedSupply.sol"; 5 | 6 | contract NoZeroTransferToken is ERC20PresetFixedSupply { 7 | constructor( 8 | string memory name_, 9 | string memory symbol_, 10 | uint256 initialSupply, 11 | address owner 12 | ) ERC20PresetFixedSupply(name_, symbol_, initialSupply, owner) {} 13 | 14 | function _transfer(address from, address to, uint256 amount) internal virtual override { 15 | require(amount > 0, "NoZeroTransferToken: zero transfer"); 16 | super._transfer(from, to, amount); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /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( 9 | address logic 10 | ) public returns (address) { 11 | ProxyAdmin pa = new ProxyAdmin(); 12 | return address(new TransparentUpgradeableProxy(address(logic), address(pa), "")); 13 | } 14 | } 15 | 16 | contract Random { 17 | bytes32 seed = bytes32(uint256(0x137)); 18 | 19 | function Bytes32() public returns (bytes32) { 20 | seed = keccak256(abi.encodePacked(seed)); 21 | return seed; 22 | } 23 | 24 | function Bytes( 25 | uint256 length 26 | ) public returns (bytes memory) { 27 | require(length > 0, "Length must be greater than 0"); 28 | bytes memory randomBytes = new bytes(length); 29 | 30 | for (uint256 i = 0; i < length; i++) { 31 | Bytes32(); 32 | randomBytes[i] = bytes1(uint8(uint256(seed) % 256)); 33 | } 34 | 35 | return randomBytes; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /test/prover/proofs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OffchainLabs/nitro-contracts/c32af127fe6a9124316abebbf756609649ede1f5/test/prover/proofs/.gitkeep -------------------------------------------------------------------------------- /test/prover/value-arrays.ts: -------------------------------------------------------------------------------- 1 | import { ethers, run, deployments } from 'hardhat' 2 | 3 | describe('ValueArray', function () { 4 | it('Should pass ValueArrayTester', async function () { 5 | await run('deploy', { tags: 'ValueArrayTester' }) 6 | 7 | const valueArrayTester = await ethers.getContractAt( 8 | 'ValueArrayTester', 9 | ( 10 | await deployments.get('ValueArrayTester') 11 | ).address 12 | ) 13 | 14 | await valueArrayTester.test() 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /test/signatures/BridgeCreator: -------------------------------------------------------------------------------- 1 | 2 | ╭--------------------------------------------------------------------------------------------------------+------------╮ 3 | | Method | Identifier | 4 | +=====================================================================================================================+ 5 | | createBridge(address,address,address,(uint256,uint256,uint256,uint256),(uint64,uint64,uint64),address) | bf2359f7 | 6 | |--------------------------------------------------------------------------------------------------------+------------| 7 | | erc20BasedTemplates() | 76768ab9 | 8 | |--------------------------------------------------------------------------------------------------------+------------| 9 | | ethBasedTemplates() | 11f02227 | 10 | |--------------------------------------------------------------------------------------------------------+------------| 11 | | owner() | 8da5cb5b | 12 | |--------------------------------------------------------------------------------------------------------+------------| 13 | | renounceOwnership() | 715018a6 | 14 | |--------------------------------------------------------------------------------------------------------+------------| 15 | | transferOwnership(address) | f2fde38b | 16 | |--------------------------------------------------------------------------------------------------------+------------| 17 | | updateERC20Templates((address,address,address,address,address,address)) | ceab9410 | 18 | |--------------------------------------------------------------------------------------------------------+------------| 19 | | updateTemplates((address,address,address,address,address,address)) | e83b0e16 | 20 | ╰--------------------------------------------------------------------------------------------------------+------------╯ 21 | 22 | -------------------------------------------------------------------------------- /test/signatures/CacheManager: -------------------------------------------------------------------------------- 1 | 2 | ╭-----------------------------+------------╮ 3 | | Method | Identifier | 4 | +==========================================+ 5 | | cacheSize() | 674a64e0 | 6 | |-----------------------------+------------| 7 | | decay() | 54fac919 | 8 | |-----------------------------+------------| 9 | | entries(uint256) | b30906d4 | 10 | |-----------------------------+------------| 11 | | evictAll() | 5c32e943 | 12 | |-----------------------------+------------| 13 | | evictPrograms(uint256) | cadb43e2 | 14 | |-----------------------------+------------| 15 | | getEntries() | 17be85c3 | 16 | |-----------------------------+------------| 17 | | getMinBid(address) | 32052a9b | 18 | |-----------------------------+------------| 19 | | getMinBid(bytes32) | c565a208 | 20 | |-----------------------------+------------| 21 | | getMinBid(uint64) | d29b303e | 22 | |-----------------------------+------------| 23 | | getSmallestEntries(uint256) | e9c1bc0f | 24 | |-----------------------------+------------| 25 | | initialize(uint64,uint64) | 20f2f345 | 26 | |-----------------------------+------------| 27 | | isPaused() | b187bd26 | 28 | |-----------------------------+------------| 29 | | makeSpace(uint64) | c1c013c4 | 30 | |-----------------------------+------------| 31 | | paused() | 5c975abb | 32 | |-----------------------------+------------| 33 | | placeBid(address) | e4940157 | 34 | |-----------------------------+------------| 35 | | queueSize() | bae6c2ad | 36 | |-----------------------------+------------| 37 | | setCacheSize(uint64) | 2dd4f566 | 38 | |-----------------------------+------------| 39 | | setDecayRate(uint64) | c77ed13e | 40 | |-----------------------------+------------| 41 | | sweepFunds() | a8d6fe04 | 42 | |-----------------------------+------------| 43 | | unpause() | 3f4ba83a | 44 | ╰-----------------------------+------------╯ 45 | 46 | -------------------------------------------------------------------------------- /test/signatures/DeployHelper: -------------------------------------------------------------------------------- 1 | 2 | ╭-----------------------------------------+------------╮ 3 | | Method | Identifier | 4 | +======================================================+ 5 | | ERC1820_DEPLOYER() | 290302ce | 6 | |-----------------------------------------+------------| 7 | | ERC1820_PAYLOAD() | 2e796641 | 8 | |-----------------------------------------+------------| 9 | | ERC1820_VALUE() | db633c3e | 10 | |-----------------------------------------+------------| 11 | | ERC2470_DEPLOYER() | 55e34a6b | 12 | |-----------------------------------------+------------| 13 | | ERC2470_PAYLOAD() | 89cf8ae6 | 14 | |-----------------------------------------+------------| 15 | | ERC2470_VALUE() | 9ed2c6f0 | 16 | |-----------------------------------------+------------| 17 | | NICK_CREATE2_DEPLOYER() | ef77e71a | 18 | |-----------------------------------------+------------| 19 | | NICK_CREATE2_PAYLOAD() | 1b9a680c | 20 | |-----------------------------------------+------------| 21 | | NICK_CREATE2_VALUE() | 4367d652 | 22 | |-----------------------------------------+------------| 23 | | ZOLTU_CREATE2_DEPLOYER() | d3a3faab | 24 | |-----------------------------------------+------------| 25 | | ZOLTU_CREATE2_PAYLOAD() | 75ae22b5 | 26 | |-----------------------------------------+------------| 27 | | ZOLTU_VALUE() | dd0c625a | 28 | |-----------------------------------------+------------| 29 | | getDeploymentTotalCost(address,uint256) | acd7d02a | 30 | |-----------------------------------------+------------| 31 | | perform(address,address,uint256) | d7c641e7 | 32 | ╰-----------------------------------------+------------╯ 33 | 34 | -------------------------------------------------------------------------------- /test/signatures/OneStepProofEntry: -------------------------------------------------------------------------------- 1 | 2 | ╭---------------------------------------------------------------+------------╮ 3 | | Method | Identifier | 4 | +============================================================================+ 5 | | getMachineHash(((bytes32[2],uint64[2]),uint8)) | c39619c4 | 6 | |---------------------------------------------------------------+------------| 7 | | getStartMachineHash(bytes32,bytes32) | 04997be4 | 8 | |---------------------------------------------------------------+------------| 9 | | proveOneStep((uint256,address,bytes32),uint256,bytes32,bytes) | b5112fd2 | 10 | |---------------------------------------------------------------+------------| 11 | | prover0() | 30a5509f | 12 | |---------------------------------------------------------------+------------| 13 | | proverHostIo() | 5f52fd7c | 14 | |---------------------------------------------------------------+------------| 15 | | proverMath() | 66e5d9c3 | 16 | |---------------------------------------------------------------+------------| 17 | | proverMem() | 1f128bc0 | 18 | ╰---------------------------------------------------------------+------------╯ 19 | 20 | -------------------------------------------------------------------------------- /test/signatures/test-sigs.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | output_dir="./test/signatures" 3 | for CONTRACTNAME in Bridge Inbox Outbox RollupCore RollupUserLogic RollupAdminLogic SequencerInbox EdgeChallengeManager ERC20Bridge ERC20Inbox ERC20Outbox BridgeCreator DeployHelper RollupCreator OneStepProofEntry CacheManager 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 -------------------------------------------------------------------------------- /test/storage/CacheManager: -------------------------------------------------------------------------------- 1 | 2 | ╭---------------+-----------------------------+------+--------+-------+-----------------------------------------╮ 3 | | Name | Type | Slot | Offset | Bytes | Contract | 4 | +===============================================================================================================+ 5 | | _initialized | uint8 | 0 | 0 | 1 | src/chain/CacheManager.sol:CacheManager | 6 | |---------------+-----------------------------+------+--------+-------+-----------------------------------------| 7 | | _initializing | bool | 0 | 1 | 1 | src/chain/CacheManager.sol:CacheManager | 8 | |---------------+-----------------------------+------+--------+-------+-----------------------------------------| 9 | | bids | struct MinHeapLib.Heap | 1 | 0 | 32 | src/chain/CacheManager.sol:CacheManager | 10 | |---------------+-----------------------------+------+--------+-------+-----------------------------------------| 11 | | entries | struct CacheManager.Entry[] | 2 | 0 | 32 | src/chain/CacheManager.sol:CacheManager | 12 | |---------------+-----------------------------+------+--------+-------+-----------------------------------------| 13 | | cacheSize | uint64 | 3 | 0 | 8 | src/chain/CacheManager.sol:CacheManager | 14 | |---------------+-----------------------------+------+--------+-------+-----------------------------------------| 15 | | queueSize | uint64 | 3 | 8 | 8 | src/chain/CacheManager.sol:CacheManager | 16 | |---------------+-----------------------------+------+--------+-------+-----------------------------------------| 17 | | decay | uint64 | 3 | 16 | 8 | src/chain/CacheManager.sol:CacheManager | 18 | |---------------+-----------------------------+------+--------+-------+-----------------------------------------| 19 | | isPaused | bool | 3 | 24 | 1 | src/chain/CacheManager.sol:CacheManager | 20 | ╰---------------+-----------------------------+------+--------+-------+-----------------------------------------╯ 21 | 22 | -------------------------------------------------------------------------------- /test/storage/ERC20Inbox: -------------------------------------------------------------------------------- 1 | 2 | ╭------------------+--------------------------+------+--------+-------+--------------------------------------╮ 3 | | Name | Type | Slot | Offset | Bytes | Contract | 4 | +============================================================================================================+ 5 | | _initialized | uint8 | 0 | 0 | 1 | src/bridge/ERC20Inbox.sol:ERC20Inbox | 6 | |------------------+--------------------------+------+--------+-------+--------------------------------------| 7 | | _initializing | bool | 0 | 1 | 1 | src/bridge/ERC20Inbox.sol:ERC20Inbox | 8 | |------------------+--------------------------+------+--------+-------+--------------------------------------| 9 | | __gap | uint256[50] | 1 | 0 | 1600 | src/bridge/ERC20Inbox.sol:ERC20Inbox | 10 | |------------------+--------------------------+------+--------+-------+--------------------------------------| 11 | | _paused | bool | 51 | 0 | 1 | src/bridge/ERC20Inbox.sol:ERC20Inbox | 12 | |------------------+--------------------------+------+--------+-------+--------------------------------------| 13 | | __gap | uint256[49] | 52 | 0 | 1568 | src/bridge/ERC20Inbox.sol:ERC20Inbox | 14 | |------------------+--------------------------+------+--------+-------+--------------------------------------| 15 | | bridge | contract IBridge | 101 | 0 | 20 | src/bridge/ERC20Inbox.sol:ERC20Inbox | 16 | |------------------+--------------------------+------+--------+-------+--------------------------------------| 17 | | sequencerInbox | contract ISequencerInbox | 102 | 0 | 20 | src/bridge/ERC20Inbox.sol:ERC20Inbox | 18 | |------------------+--------------------------+------+--------+-------+--------------------------------------| 19 | | allowListEnabled | bool | 102 | 20 | 1 | src/bridge/ERC20Inbox.sol:ERC20Inbox | 20 | |------------------+--------------------------+------+--------+-------+--------------------------------------| 21 | | isAllowed | mapping(address => bool) | 103 | 0 | 32 | src/bridge/ERC20Inbox.sol:ERC20Inbox | 22 | |------------------+--------------------------+------+--------+-------+--------------------------------------| 23 | | __gap | uint256[47] | 104 | 0 | 1504 | src/bridge/ERC20Inbox.sol:ERC20Inbox | 24 | ╰------------------+--------------------------+------+--------+-------+--------------------------------------╯ 25 | 26 | -------------------------------------------------------------------------------- /test/storage/ERC20Outbox: -------------------------------------------------------------------------------- 1 | 2 | ╭---------+--------------------------------+------+--------+-------+----------------------------------------╮ 3 | | Name | Type | Slot | Offset | Bytes | Contract | 4 | +===========================================================================================================+ 5 | | rollup | address | 0 | 0 | 20 | src/bridge/ERC20Outbox.sol:ERC20Outbox | 6 | |---------+--------------------------------+------+--------+-------+----------------------------------------| 7 | | bridge | contract IBridge | 1 | 0 | 20 | src/bridge/ERC20Outbox.sol:ERC20Outbox | 8 | |---------+--------------------------------+------+--------+-------+----------------------------------------| 9 | | spent | mapping(uint256 => bytes32) | 2 | 0 | 32 | src/bridge/ERC20Outbox.sol:ERC20Outbox | 10 | |---------+--------------------------------+------+--------+-------+----------------------------------------| 11 | | roots | mapping(bytes32 => bytes32) | 3 | 0 | 32 | src/bridge/ERC20Outbox.sol:ERC20Outbox | 12 | |---------+--------------------------------+------+--------+-------+----------------------------------------| 13 | | context | struct AbsOutbox.L2ToL1Context | 4 | 0 | 128 | src/bridge/ERC20Outbox.sol:ERC20Outbox | 14 | |---------+--------------------------------+------+--------+-------+----------------------------------------| 15 | | __gap | uint256[42] | 8 | 0 | 1344 | src/bridge/ERC20Outbox.sol:ERC20Outbox | 16 | ╰---------+--------------------------------+------+--------+-------+----------------------------------------╯ 17 | 18 | -------------------------------------------------------------------------------- /test/storage/Inbox: -------------------------------------------------------------------------------- 1 | 2 | ╭------------------+--------------------------+------+--------+-------+----------------------------╮ 3 | | Name | Type | Slot | Offset | Bytes | Contract | 4 | +==================================================================================================+ 5 | | _initialized | uint8 | 0 | 0 | 1 | src/bridge/Inbox.sol:Inbox | 6 | |------------------+--------------------------+------+--------+-------+----------------------------| 7 | | _initializing | bool | 0 | 1 | 1 | src/bridge/Inbox.sol:Inbox | 8 | |------------------+--------------------------+------+--------+-------+----------------------------| 9 | | __gap | uint256[50] | 1 | 0 | 1600 | src/bridge/Inbox.sol:Inbox | 10 | |------------------+--------------------------+------+--------+-------+----------------------------| 11 | | _paused | bool | 51 | 0 | 1 | src/bridge/Inbox.sol:Inbox | 12 | |------------------+--------------------------+------+--------+-------+----------------------------| 13 | | __gap | uint256[49] | 52 | 0 | 1568 | src/bridge/Inbox.sol:Inbox | 14 | |------------------+--------------------------+------+--------+-------+----------------------------| 15 | | bridge | contract IBridge | 101 | 0 | 20 | src/bridge/Inbox.sol:Inbox | 16 | |------------------+--------------------------+------+--------+-------+----------------------------| 17 | | sequencerInbox | contract ISequencerInbox | 102 | 0 | 20 | src/bridge/Inbox.sol:Inbox | 18 | |------------------+--------------------------+------+--------+-------+----------------------------| 19 | | allowListEnabled | bool | 102 | 20 | 1 | src/bridge/Inbox.sol:Inbox | 20 | |------------------+--------------------------+------+--------+-------+----------------------------| 21 | | isAllowed | mapping(address => bool) | 103 | 0 | 32 | src/bridge/Inbox.sol:Inbox | 22 | |------------------+--------------------------+------+--------+-------+----------------------------| 23 | | __gap | uint256[47] | 104 | 0 | 1504 | src/bridge/Inbox.sol:Inbox | 24 | ╰------------------+--------------------------+------+--------+-------+----------------------------╯ 25 | 26 | -------------------------------------------------------------------------------- /test/storage/OneStepProofEntry: -------------------------------------------------------------------------------- 1 | 2 | ╭--------------+-------------------------+------+--------+-------+-------------------------------------------------╮ 3 | | Name | Type | Slot | Offset | Bytes | Contract | 4 | +==================================================================================================================+ 5 | | prover0 | contract IOneStepProver | 0 | 0 | 20 | src/osp/OneStepProofEntry.sol:OneStepProofEntry | 6 | |--------------+-------------------------+------+--------+-------+-------------------------------------------------| 7 | | proverMem | contract IOneStepProver | 1 | 0 | 20 | src/osp/OneStepProofEntry.sol:OneStepProofEntry | 8 | |--------------+-------------------------+------+--------+-------+-------------------------------------------------| 9 | | proverMath | contract IOneStepProver | 2 | 0 | 20 | src/osp/OneStepProofEntry.sol:OneStepProofEntry | 10 | |--------------+-------------------------+------+--------+-------+-------------------------------------------------| 11 | | proverHostIo | contract IOneStepProver | 3 | 0 | 20 | src/osp/OneStepProofEntry.sol:OneStepProofEntry | 12 | ╰--------------+-------------------------+------+--------+-------+-------------------------------------------------╯ 13 | 14 | -------------------------------------------------------------------------------- /test/storage/Outbox: -------------------------------------------------------------------------------- 1 | 2 | ╭---------+--------------------------------+------+--------+-------+------------------------------╮ 3 | | Name | Type | Slot | Offset | Bytes | Contract | 4 | +=================================================================================================+ 5 | | rollup | address | 0 | 0 | 20 | src/bridge/Outbox.sol:Outbox | 6 | |---------+--------------------------------+------+--------+-------+------------------------------| 7 | | bridge | contract IBridge | 1 | 0 | 20 | src/bridge/Outbox.sol:Outbox | 8 | |---------+--------------------------------+------+--------+-------+------------------------------| 9 | | spent | mapping(uint256 => bytes32) | 2 | 0 | 32 | src/bridge/Outbox.sol:Outbox | 10 | |---------+--------------------------------+------+--------+-------+------------------------------| 11 | | roots | mapping(bytes32 => bytes32) | 3 | 0 | 32 | src/bridge/Outbox.sol:Outbox | 12 | |---------+--------------------------------+------+--------+-------+------------------------------| 13 | | context | struct AbsOutbox.L2ToL1Context | 4 | 0 | 128 | src/bridge/Outbox.sol:Outbox | 14 | |---------+--------------------------------+------+--------+-------+------------------------------| 15 | | __gap | uint256[42] | 8 | 0 | 1344 | src/bridge/Outbox.sol:Outbox | 16 | ╰---------+--------------------------------+------+--------+-------+------------------------------╯ 17 | 18 | -------------------------------------------------------------------------------- /test/storage/test.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | output_dir="./test/storage" 3 | for CONTRACTNAME in Bridge Inbox Outbox RollupCore RollupUserLogic RollupAdminLogic SequencerInbox EdgeChallengeManager ERC20Bridge ERC20Inbox ERC20Outbox OneStepProofEntry CacheManager 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" 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 -------------------------------------------------------------------------------- /test/unused-errors/exceptions.txt: -------------------------------------------------------------------------------- 1 | Custom 2 | Unused 3 | NoTicketWithID 4 | NotCallable 5 | InvalidBlockNumber 6 | ProgramExpired 7 | ProgramInsufficientValue 8 | ProgramKeepaliveTooSoon 9 | ProgramNeedsUpgrade 10 | ProgramNotActivated 11 | ProgramNotWasm 12 | ProgramUpToDate 13 | CallerNotArbOS 14 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2018", 4 | "module": "commonjs", 5 | "strict": true, 6 | "esModuleInterop": true, 7 | "outDir": "dist", 8 | "resolveJsonModule": true, 9 | "allowJs": true 10 | }, 11 | "include": ["./scripts", "./test", "./typechain-types"], 12 | "files": ["./hardhat.config.ts"] 13 | } 14 | -------------------------------------------------------------------------------- /yul/Reader4844.yul: -------------------------------------------------------------------------------- 1 | object "Reader4844" { 2 | code { 3 | datacopy(0, dataoffset("runtime"), datasize("runtime")) 4 | return(0, datasize("runtime")) 5 | } 6 | object "runtime" { 7 | code { 8 | // This contract does not accept callvalue 9 | if callvalue() { revert(0, 0) } 10 | 11 | // Match against the keccak of the ABI function signature needed. 12 | switch shr(0xe0, calldataload(0)) 13 | // bytes4(keccak("getDataHashes()")) 14 | case 0xe83a2d82 { 15 | let i := 0 16 | for { } true { } 17 | { 18 | // DATAHASH opcode has hex value 0x49 19 | let hash := verbatim_1i_1o(hex"49", i) 20 | if iszero(hash) { break } 21 | mstore(add(mul(i, 32), 64), hash) 22 | i := add(i, 1) 23 | } 24 | mstore(0, 32) 25 | mstore(32, i) 26 | return(0, add(mul(i, 32), 64)) 27 | } 28 | // bytes4(keccak("getBlobBaseFee()")) 29 | case 0x1f6d6ef7 { 30 | // BLOBBASEFEE opcode has hex value 0x4a 31 | let blobBasefee := verbatim_0i_1o(hex"4a") 32 | mstore(0, blobBasefee) 33 | return(0, 32) 34 | } 35 | // Unknown selector (revert) 36 | default { revert(0, 0) } 37 | } 38 | } 39 | } 40 | --------------------------------------------------------------------------------