├── .editorconfig ├── .env.example ├── .gitattributes ├── .github ├── CODEOWNERS └── workflows │ ├── build-test-lint-contracts.yml │ ├── dockerhub-build-push.yml │ ├── integration.yml │ ├── push-to-integration-repo.yml │ └── tag-release.yml ├── .gitignore ├── .solcover.js ├── CHANGELOG.md ├── LICENSE.txt ├── README.md ├── bin ├── deploy.js ├── deploy.ts ├── gen_safety_checker_constants.py ├── serve_dump.sh └── take-dump.ts ├── contracts ├── optimistic-ethereum │ ├── OVM │ │ ├── accounts │ │ │ ├── OVM_ECDSAContractAccount.sol │ │ │ └── OVM_ProxyEOA.sol │ │ ├── bridge │ │ │ ├── messaging │ │ │ │ ├── Abs_BaseCrossDomainMessenger.sol │ │ │ │ ├── OVM_L1CrossDomainMessenger.sol │ │ │ │ ├── OVM_L1MultiMessageRelayer.sol │ │ │ │ └── OVM_L2CrossDomainMessenger.sol │ │ │ └── tokens │ │ │ │ ├── Abs_L1TokenGateway.sol │ │ │ │ ├── Abs_L2DepositedToken.sol │ │ │ │ ├── OVM_L1ERC20Gateway.sol │ │ │ │ ├── OVM_L1ETHGateway.sol │ │ │ │ └── OVM_L2DepositedERC20.sol │ │ ├── chain │ │ │ ├── OVM_CanonicalTransactionChain.sol │ │ │ ├── OVM_ChainStorageContainer.sol │ │ │ └── OVM_StateCommitmentChain.sol │ │ ├── execution │ │ │ ├── OVM_ExecutionManager.sol │ │ │ ├── OVM_SafetyChecker.sol │ │ │ ├── OVM_StateManager.sol │ │ │ └── OVM_StateManagerFactory.sol │ │ ├── predeploys │ │ │ ├── ERC1820Registry.sol │ │ │ ├── OVM_DeployerWhitelist.sol │ │ │ ├── OVM_ETH.sol │ │ │ ├── OVM_L1MessageSender.sol │ │ │ ├── OVM_L2ToL1MessagePasser.sol │ │ │ ├── OVM_ProxySequencerEntrypoint.sol │ │ │ └── OVM_SequencerEntrypoint.sol │ │ └── verification │ │ │ ├── Abs_FraudContributor.sol │ │ │ ├── OVM_BondManager.sol │ │ │ ├── OVM_FraudVerifier.sol │ │ │ ├── OVM_StateTransitioner.sol │ │ │ └── OVM_StateTransitionerFactory.sol │ ├── iOVM │ │ ├── accounts │ │ │ └── iOVM_ECDSAContractAccount.sol │ │ ├── bridge │ │ │ ├── messaging │ │ │ │ ├── iAbs_BaseCrossDomainMessenger.sol │ │ │ │ ├── iOVM_L1CrossDomainMessenger.sol │ │ │ │ ├── iOVM_L1MultiMessageRelayer.sol │ │ │ │ └── iOVM_L2CrossDomainMessenger.sol │ │ │ └── tokens │ │ │ │ ├── iOVM_L1ETHGateway.sol │ │ │ │ ├── iOVM_L1TokenGateway.sol │ │ │ │ └── iOVM_L2DepositedToken.sol │ │ ├── chain │ │ │ ├── iOVM_CanonicalTransactionChain.sol │ │ │ ├── iOVM_ChainStorageContainer.sol │ │ │ └── iOVM_StateCommitmentChain.sol │ │ ├── execution │ │ │ ├── iOVM_ExecutionManager.sol │ │ │ ├── iOVM_SafetyChecker.sol │ │ │ ├── iOVM_StateManager.sol │ │ │ └── iOVM_StateManagerFactory.sol │ │ ├── predeploys │ │ │ ├── iOVM_DeployerWhitelist.sol │ │ │ ├── iOVM_ERC20.sol │ │ │ ├── iOVM_L1MessageSender.sol │ │ │ └── iOVM_L2ToL1MessagePasser.sol │ │ └── verification │ │ │ ├── iOVM_BondManager.sol │ │ │ ├── iOVM_FraudVerifier.sol │ │ │ ├── iOVM_StateTransitioner.sol │ │ │ └── iOVM_StateTransitionerFactory.sol │ ├── libraries │ │ ├── bridge │ │ │ └── OVM_CrossDomainEnabled.sol │ │ ├── codec │ │ │ └── Lib_OVMCodec.sol │ │ ├── resolver │ │ │ ├── Lib_AddressManager.sol │ │ │ ├── Lib_AddressResolver.sol │ │ │ ├── Lib_Ownable.sol │ │ │ └── Lib_ResolvedDelegateProxy.sol │ │ ├── rlp │ │ │ ├── Lib_RLPReader.sol │ │ │ └── Lib_RLPWriter.sol │ │ ├── standards │ │ │ ├── IUniswapV2ERC20.sol │ │ │ ├── UniSafeMath.sol │ │ │ └── UniswapV2ERC20.sol │ │ ├── trie │ │ │ ├── Lib_MerkleTrie.sol │ │ │ └── Lib_SecureMerkleTrie.sol │ │ ├── utils │ │ │ ├── Lib_Bytes32Utils.sol │ │ │ ├── Lib_BytesUtils.sol │ │ │ ├── Lib_ECDSAUtils.sol │ │ │ ├── Lib_ErrorUtils.sol │ │ │ ├── Lib_EthUtils.sol │ │ │ ├── Lib_Math.sol │ │ │ ├── Lib_MerkleTree.sol │ │ │ ├── Lib_ReentrancyGuard.sol │ │ │ └── Lib_RingBuffer.sol │ │ └── wrappers │ │ │ ├── Lib_SafeExecutionManagerWrapper.sol │ │ │ └── Lib_SafeMathWrapper.sol │ └── mockOVM │ │ ├── accounts │ │ └── mockOVM_ECDSAContractAccount.sol │ │ ├── bridge │ │ ├── mockOVM_CrossDomainMessenger.sol │ │ └── mockOVM_GenericCrossDomainMessenger.sol │ │ └── verification │ │ └── mockOVM_BondManager.sol ├── test-helpers │ ├── Helper_GasMeasurer.sol │ ├── Helper_ModifiableStorage.sol │ ├── Helper_PrecompileCaller.sol │ ├── Helper_SimpleProxy.sol │ ├── Helper_TestRunner.sol │ ├── Mock_FraudVerifier.sol │ └── TestERC20.sol └── test-libraries │ ├── codec │ └── TestLib_OVMCodec.sol │ ├── rlp │ ├── TestLib_RLPReader.sol │ └── TestLib_RLPWriter.sol │ ├── trie │ ├── TestLib_MerkleTrie.sol │ └── TestLib_SecureMerkleTrie.sol │ └── utils │ ├── TestLib_Bytes32Utils.sol │ ├── TestLib_BytesUtils.sol │ ├── TestLib_ECDSAUtils.sol │ ├── TestLib_EthUtils.sol │ ├── TestLib_MerkleTree.sol │ └── TestLib_RingBuffer.sol ├── deploy ├── 000-Lib_AddressManager.deploy.ts ├── 001-OVM_ChainStorageContainer_ctc_batches.deploy.ts ├── 002-OVM_ChainStorageContainer_ctc_queue.deploy.ts ├── 003-OVM_ChainStorageContainer_scc_batches.deploy.ts ├── 004-OVM_CanonicalTransactionChain.deploy.ts ├── 005-OVM_StateCommitmentChain.deploy.ts ├── 006-mockOVM_BondManager.deploy.ts ├── 007-OVM_L1CrossDomainMessenger.deploy.ts ├── 008-Proxy__OVM_L1CrossDomainMessenger.deploy.ts ├── 009-OVM_ExecutionManager.deploy.ts ├── 010-OVM_FraudVerifer.deploy.ts ├── 011-OVM_StateManagerFactory.deploy.ts ├── 012-OVM_StateTransitionerFactory.deploy.ts ├── 013-OVM_SafetyChecker.deploy.ts ├── 014-OVM_L1MultiMessageRelayer.deploy.ts ├── 015-OVM_L1ETHGateway.deploy.ts ├── 016-Proxy__OVM_L1ETHGateway.deploy.ts └── 017-finalize.ts ├── hardhat.config.ts ├── hh ├── index.ts └── tasks │ └── task-deploy.ts ├── package.json ├── prettier-config.json ├── src ├── contract-defs.ts ├── contract-deployment │ ├── config.ts │ ├── deploy.ts │ └── index.ts ├── contract-dumps.ts ├── hardhat-deploy-ethers.ts ├── index.ts └── predeploys.ts ├── test ├── contracts │ ├── OVM │ │ ├── accounts │ │ │ ├── OVM_ECDSAContractAccount.spec.ts │ │ │ └── OVM_ProxyEOA.spec.ts │ │ ├── bridge │ │ │ ├── assets │ │ │ │ ├── OVM_L1ERC20Gateway.spec.ts │ │ │ │ ├── OVM_L1ETHGateway.spec.ts │ │ │ │ └── OVM_L2DepositedERC20.spec.ts │ │ │ └── base │ │ │ │ ├── OVM_L1CrossDomainMessenger.spec.ts │ │ │ │ ├── OVM_L1MultiMessageRelayer.ts │ │ │ │ └── OVM_L2CrossDomainMessenger.spec.ts │ │ ├── chain │ │ │ ├── OVM_CanonicalTransactionChain.gas.spec.ts │ │ │ ├── OVM_CanonicalTransactionChain.spec.ts │ │ │ └── OVM_StateCommitmentChain.spec.ts │ │ ├── execution │ │ │ ├── OVM_ExecutionManager.gas-spec.ts │ │ │ ├── OVM_ExecutionManager │ │ │ │ ├── context-opcodes.spec.ts │ │ │ │ ├── nuisance-gas.spec.ts │ │ │ │ ├── ovmCALL.spec.ts │ │ │ │ ├── ovmCREATE.spec.ts │ │ │ │ ├── ovmCREATEEOA.spec.ts │ │ │ │ ├── ovmDELEGATECALL.spec.ts │ │ │ │ ├── ovmREVERT.spec.ts │ │ │ │ ├── ovmSLOAD.spec.ts │ │ │ │ ├── ovmSTATICCALL.spec.ts │ │ │ │ └── run.spec.ts │ │ │ ├── OVM_SafetyChecker.spec.ts │ │ │ ├── OVM_StateManager.gas-spec.ts │ │ │ └── OVM_StateManager.spec.ts │ │ ├── precompiles │ │ │ ├── OVM_L1MessageSender.spec.ts │ │ │ ├── OVM_L2ToL1MessagePasser.spec.ts │ │ │ ├── OVM_ProxySequencerEntrypoint.spec.ts │ │ │ └── OVM_SequencerEntrypoint.spec.ts │ │ └── verification │ │ │ ├── OVM_BondManager.spec.ts │ │ │ ├── OVM_FraudVerifier.spec.ts │ │ │ ├── OVM_StateTransitioner.spec.ts │ │ │ └── OVM_StateTransitionerFactory.spec.ts │ ├── libraries │ │ ├── codec │ │ │ └── Lib_OVMCodec.spec.ts │ │ ├── rlp │ │ │ ├── Lib_RLPReader.spec.ts │ │ │ └── Lib_RLPWriter.spec.ts │ │ ├── trie │ │ │ ├── Lib_MerkleTrie.spec.ts │ │ │ └── Lib_SecureMerkleTrie.spec.ts │ │ └── utils │ │ │ ├── Lib_Bytes32Utils.spec.ts │ │ │ ├── Lib_BytesUtils.spec.ts │ │ │ ├── Lib_ECDSAUtils.spec.ts │ │ │ ├── Lib_EthUtils.spec.ts │ │ │ └── Lib_MerkleTree.spec.ts │ └── mockOVM │ │ └── verification │ │ └── mockOVM_BondManager.spec.ts ├── data │ ├── index.ts │ └── json │ │ ├── create2.test.json │ │ ├── libraries │ │ ├── codec │ │ │ └── Lib_OVMCodec.test.json │ │ ├── rlp │ │ │ ├── Lib_RLPReader.test.json │ │ │ └── Lib_RLPWriter.test.json │ │ ├── trie │ │ │ └── Lib_MerkleTrie.test.json │ │ └── utils │ │ │ ├── Lib_Bytes32Utils.test.json │ │ │ ├── Lib_BytesUtils.test.json │ │ │ └── Lib_ECDSAUtils.test.json │ │ └── safety-checker.test.json ├── helpers │ ├── codec │ │ ├── bridge.ts │ │ ├── encoding.ts │ │ ├── index.ts │ │ └── revert-flags.ts │ ├── constants.ts │ ├── dummy │ │ ├── accounts.ts │ │ ├── batches.ts │ │ ├── bytecode.ts │ │ ├── bytes32.ts │ │ ├── context.ts │ │ ├── index.ts │ │ └── transactions.ts │ ├── gas │ │ ├── gas.ts │ │ └── index.ts │ ├── index.ts │ ├── resolver │ │ ├── address-manager.ts │ │ └── index.ts │ ├── test-runner │ │ ├── index.ts │ │ ├── json-test-runner.ts │ │ ├── test-runner.ts │ │ └── test.types.ts │ ├── trie │ │ ├── index.ts │ │ └── trie-test-generator.ts │ ├── types │ │ ├── index.ts │ │ └── ovm-types.ts │ └── utils │ │ ├── custom-deployer.ts │ │ ├── eth-time.ts │ │ ├── index.ts │ │ └── sol-utils.ts └── setup.ts ├── tsconfig.json ├── tslint.json └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | # defaults 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | indent_size = 2 8 | indent_style = space 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | [*.sol] 13 | indent_size = 4 14 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | # name of the network to deploy to e.g., kovan or mainnet 2 | CONTRACTS_TARGET_NETWORK= 3 | 4 | # private key for the account that will execute the deploy 5 | CONTRACTS_DEPLOYER_KEY= 6 | 7 | # rpc url for the node that will receive deploy transactions 8 | CONTRACTS_RPC_URL= 9 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity 2 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @smartcontracts @ben-chain @maurelian 2 | -------------------------------------------------------------------------------- /.github/workflows/build-test-lint-contracts.yml: -------------------------------------------------------------------------------- 1 | name: CI - contracts 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | build-test-lint: 13 | name: Run Contracts Test Suite on Node ${{matrix.node}} 14 | runs-on: ubuntu-latest 15 | 16 | strategy: 17 | matrix: 18 | node: [ '10', '12', '14' ] 19 | 20 | steps: 21 | - uses: actions/checkout@v2 22 | 23 | - name: Setup node ${{ matrix.node }} 24 | uses: actions/setup-node@v1 25 | with: 26 | node-version: ${{ matrix.node }} 27 | 28 | # START DEPENDENCY CACHING 29 | - name: Cache root deps 30 | uses: actions/cache@v1 31 | id: cache_base 32 | with: 33 | path: node_modules 34 | key: ${{ runner.os }}-${{ matrix.node }}-${{ hashFiles('package.json') }} 35 | 36 | # END DEPENDENCY CACHING 37 | 38 | - name: Install Dependencies 39 | run: yarn install 40 | 41 | - name: Lint 42 | run: yarn lint:check 43 | 44 | - name: Build 45 | run: | 46 | yarn clean 47 | yarn build 48 | 49 | - name: Test 50 | run: yarn test 51 | -------------------------------------------------------------------------------- /.github/workflows/dockerhub-build-push.yml: -------------------------------------------------------------------------------- 1 | name: Build & Push to DockerHub 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - testnet 8 | - uat 9 | 10 | jobs: 11 | build: 12 | name: Build & Push to DockerHub 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | 18 | - uses: webfactory/ssh-agent@v0.4.1 19 | with: 20 | ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY_READ }} 21 | 22 | - name: Login to DockerHub Registry 23 | run: echo ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} | docker login -u ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME}} --password-stdin 24 | 25 | - name: Build and push Deployer image to DockerHub 26 | run: | 27 | git clone https://github.com/ethereum-optimism/docker.git \ 28 | $HOME/docker 29 | cd $HOME/docker 30 | BRANCH=${GITHUB_REF##*/} 31 | ./build.sh -s deployer -b $BRANCH 32 | if [ $BRANCH == 'master' ]; then 33 | docker push ethereumoptimism/deployer:latest 34 | elif [[ $BRANCH == 'uat' || $BRANCH == 'testnet' ]]; then 35 | docker push ethereumoptimism/deployer:$BRANCH 36 | fi 37 | - name: Logout of DockerHub 38 | run: docker logout 39 | -------------------------------------------------------------------------------- /.github/workflows/integration.yml: -------------------------------------------------------------------------------- 1 | name: Setup & Run Integration Test Suite 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | build: 13 | name: Setup & Run Integration Tests 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v2 18 | 19 | - name: Build 20 | run: | 21 | git clone https://github.com/ethereum-optimism/optimism-integration.git \ 22 | $HOME/optimism-integration 23 | cd $HOME/optimism-integration 24 | sed -i -Ee's#git@github.com:([^/]*)/(.*).git#https://github.com/\1/\2.git#' .gitmodules 25 | git submodule init 26 | git submodule update 27 | if [ -z $GITHUB_HEAD_REF ]; then 28 | GITHUB_HEAD_REF=${GITHUB_REF##*/} 29 | fi 30 | GIT_COMMIT=$(git rev-parse HEAD | head -c 8) 31 | REMOTE=${{ github.event.pull_request.head.repo.html_url }} 32 | echo "optimism-integration $GIT_COMMIT" 33 | if [ -z $REMOTE ]; then 34 | ./docker/build.sh -s deployer -b $GITHUB_HEAD_REF 35 | else 36 | ./docker/build.sh -s deployer -b $GITHUB_HEAD_REF -r $REMOTE 37 | fi 38 | 39 | - name: Test 40 | run: | 41 | cd $HOME/optimism-integration 42 | DEPLOYER_TAG=$GITHUB_HEAD_REF ./test.sh 43 | -------------------------------------------------------------------------------- /.github/workflows/push-to-integration-repo.yml: -------------------------------------------------------------------------------- 1 | name: Update submodules in integration repo 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | run: 10 | name: Update submodules 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | 16 | - uses: webfactory/ssh-agent@v0.4.1 17 | with: 18 | ssh-private-key: ${{ secrets.INTEGRATION_PUSH_ACTION }} 19 | 20 | - name: Clone repo 21 | run: | 22 | git clone git@github.com:ethereum-optimism/optimism-integration.git $HOME/optimism-integration 23 | cd $HOME/optimism-integration 24 | git submodule init && git submodule update 25 | REPO=$(echo $GITHUB_REPOSITORY | cut -d '/' -f2) 26 | cd $HOME/optimism-integration/$REPO 27 | git pull origin master 28 | 29 | - name: Commit 30 | run: | 31 | git config --global user.email "action@github.com" 32 | git config --global user.name "GitHub Action" 33 | cd $HOME/optimism-integration 34 | REPO=$(echo $GITHUB_REPOSITORY | cut -d '/' -f2) 35 | SHORT=$(echo $GITHUB_SHA | head -c 8) 36 | git add $REPO 37 | git commit -m "submodule bump: $REPO $SHORT" 38 | git push origin master 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | artifacts/ 3 | artifacts-ovm/ 4 | cache/ 5 | cache-ovm/ 6 | yarn-error.log 7 | build/ 8 | .DS_STORE 9 | 10 | # Coverage output 11 | coverage/ 12 | coverage.json 13 | 14 | # Environment variables 15 | .env 16 | -------------------------------------------------------------------------------- /.solcover.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | skipFiles: [ 3 | './test-helpers', 4 | './test-libraries', 5 | './optimistic-ethereum/mockOVM' 6 | ], 7 | mocha: { 8 | grep: "@skip-on-coverage", 9 | invert: true 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## v0.1.11 4 | - cleanup: ECDSAContractAccount 5 | - cleanup: Proxy_EOA 6 | - cleanup: StateManagerFactory 7 | - cleanup: Bytes32Utils 8 | - cleanup: Minor cleanup to state manager 9 | - cleanup: SafetyChecker 10 | - Remove gas estimators from gateway interface 11 | - Add ERC1820 Registry as a precompile 12 | - dev: Remove usage of custom concat function in Solidity 13 | - Fix revert string generated by EM wrapper 14 | - Update OVM_L1ERC20Gateway.sol 15 | - Move OVM_BondManager test into the right location 16 | 17 | ## v0.1.10 18 | Adds extensible ERC20Gateway and Improve CI. 19 | 20 | - dev: Apply linting to all test files 21 | - Test gas consumption of EM.run() 22 | - Extensible deposit withdraw 23 | - Update OVM_L2DepositedERC20.sol 24 | - Commit state dumps to regenesis repo for new tags 25 | - Update OVM_ChainStorageContainer.sol 26 | - Update OVM_ECDSAContractAccount.sol 27 | - Update OVM_CanonicalTransactionChain.sol 28 | - Reset Context on invalid gaslimit 29 | - [Fix] CI on merge 30 | - [Fix] Run integration tests in forked context 31 | 32 | ## v0.1.9 33 | 34 | Standardized ETH and ERC20 Gateways. 35 | 36 | - Add ETH deposit contract. 37 | - Add standard deposit/withdrawal interfaces. 38 | 39 | ## v0.1.5 40 | 41 | Various cleanup and maintenance tasks. 42 | 43 | - Improving comments and some names (#211) 44 | - Add descriptive comments above the contract declaration for all 'non-abstract contracts' (#200) 45 | - Add generic mock xdomain messenger (#209) 46 | - Move everything over to hardhat (#208) 47 | - Add comment to document v argument (#199) 48 | - Add security related comments (#191) 49 | 50 | ## v0.1.4 51 | 52 | Fix single contract redeployment & state dump script for 53 | mainnet. 54 | 55 | ## v0.1.3 56 | 57 | Add events to fraud proof initialization and finalization. 58 | 59 | ## v0.1.2 60 | 61 | Npm publish integrity. 62 | 63 | ## v0.1.1 64 | 65 | Audit fixes, deployment fixes & final parameterization. 66 | 67 | - Add build mainnet command to package.json (#186) 68 | - revert chain ID 422 -> 420 (#185) 69 | - add `AddressSet` event (#184) 70 | - Add mint & burn to L2 ETH (#178) 71 | - Wait for deploy transactions (#180) 72 | - Final Parameterization of Constants (#176) 73 | - re-enable monotonicity tests (#177) 74 | - make ovmSETNONCE notStatic (#179) 75 | - Add reentry protection to ExecutionManager.run() (#175) 76 | - Add nonReentrant to `relayMessage()` (#172) 77 | - ctc: public getters, remove dead variable (#174) 78 | - fix tainted memory bug in `Lib_BytesUtils.slice` (#171) 79 | 80 | ## v0.1.0 81 | 82 | Initial Release 83 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright 2020 Optimism 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **[DEPRECATED]** This repository is now deprecated in favour of the new development [monorepo](https://github.com/ethereum-optimism/optimism-monorepo). 2 | 3 | # Optimistic Ethereum Smart Contracts 4 | 5 | `@eth-optimism/contracts` contains the various Solidity smart contracts used within the Optimistic Ethereum system. 6 | Some of these contracts are deployed on Ethereum ("Layer 1"), while others are meant to be deployed to Optimistic Ethereum ("Layer 2"). 7 | 8 | Within each contract file you'll find a comment that lists: 9 | 1. The compiler with which a contract is intended to be compiled, `solc` or `optimistic-solc`. 10 | 2. The network upon to which the contract will be deployed, `OVM` or `EVM`. 11 | 12 | A more detailed overview of these contracts can be found on the [community hub](http://community.optimism.io/docs/protocol/protocol.html#system-overview). 13 | 14 | 15 | 16 | ## Usage (npm) 17 | If your development stack is based on Node/npm: 18 | 19 | ```shell 20 | npm install @eth-optimism/contracts 21 | ``` 22 | 23 | Within your contracts: 24 | 25 | ```solidity 26 | import { SomeContract } from "@eth-optimism/contracts/SomeContract.sol"; 27 | ``` 28 | 29 | ## Guide for Developers 30 | ### Setup 31 | Install the following: 32 | - [`Node.js` (14+)](https://nodejs.org/en/) 33 | - [`npm`](https://www.npmjs.com/get-npm) 34 | - [`yarn`](https://classic.yarnpkg.com/en/docs/install/) 35 | 36 | Clone the repo: 37 | 38 | ```shell 39 | git clone https://github.com/ethereum-optimism/contracts.git 40 | cd contracts 41 | ``` 42 | 43 | Install `npm` packages: 44 | ```shell 45 | yarn install 46 | ``` 47 | 48 | ### Running Tests 49 | Tests are executed via `yarn`: 50 | ```shell 51 | yarn test 52 | ``` 53 | 54 | Run specific tests by giving a path to the file you want to run: 55 | ```shell 56 | yarn test ./test/path/to/my/test.spec.ts 57 | ``` 58 | 59 | ### Measuring test coverage: 60 | ```shell 61 | yarn test-coverage 62 | ``` 63 | 64 | The output is most easily viewable by opening the html file in your browser: 65 | ```shell 66 | open ./coverage/index.html 67 | ``` 68 | 69 | ### Compiling and Building 70 | Easiest way is to run the primary build script: 71 | ```shell 72 | yarn build 73 | ``` 74 | 75 | Running the full build command will perform the following actions: 76 | 1. `build:contracts` - Compile all Solidity contracts with both the EVM and OVM compilers. 77 | 2. `build:typescript` - Builds the typescript files that are used to export utilities into js. 78 | 3. `build:copy` - Copies various other files into the build folder. 79 | 4. `build:dump` - Generates a genesis state from the contracts that L2 geth will use. 80 | 5. `build:typechain` - Generates [TypeChain](https://github.com/ethereum-ts/TypeChain) artifacts. 81 | 82 | You can also build specific components as follows: 83 | ```shell 84 | yarn build:contracts 85 | ``` 86 | 87 | ## Security 88 | Please refer to our [Security Policy](https://github.com/ethereum-optimism/.github/security/policy) for information about how to disclose security issues with this code. 89 | -------------------------------------------------------------------------------- /bin/deploy.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const path = require('path') 4 | const { spawn } = require('child_process') 5 | const dirtree = require('directory-tree') 6 | 7 | const main = async () => { 8 | const task = spawn(path.join(__dirname, 'deploy.ts')) 9 | 10 | await new Promise((resolve) => { 11 | task.on('exit', () => { 12 | resolve() 13 | }) 14 | }) 15 | 16 | // Stuff below this line is currently required for CI to work properly. We probably want to 17 | // update our CI so this is no longer necessary. But I'm adding it for backwards compat so we can 18 | // get the hardhat-deploy stuff merged. Woot. 19 | const nicknames = { 20 | 'Lib_AddressManager': 'AddressManager', 21 | 'mockOVM_BondManager': 'OVM_BondManager' 22 | } 23 | 24 | const contracts = dirtree( 25 | path.resolve(__dirname, `../deployments/custom`) 26 | ).children.filter((child) => { 27 | return child.extension === '.json' 28 | }).reduce((contracts, child) => { 29 | const contractName = child.name.replace('.json', '') 30 | const artifact = require(path.resolve(__dirname, `../deployments/custom/${child.name}`)) 31 | contracts[nicknames[contractName] || contractName] = artifact.address 32 | return contracts 33 | }, {}) 34 | 35 | // We *must* console.log here because CI will pipe the output of this script into an 36 | // addresses.json file. Also something we should probably remove. 37 | console.log(JSON.stringify(contracts, null, 2)) 38 | } 39 | 40 | main() 41 | .then(() => process.exit(0)) 42 | .catch((error) => { 43 | console.log( 44 | JSON.stringify({ error: error.message, stack: error.stack }, null, 2) 45 | ) 46 | process.exit(1) 47 | }) 48 | -------------------------------------------------------------------------------- /bin/deploy.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ts-node-script 2 | 3 | import { Wallet } from 'ethers' 4 | 5 | // Ensures that all relevant environment vars are properly set. These lines *must* come before the 6 | // hardhat import because importing will load the config (which relies on these vars). Necessary 7 | // because CI currently uses different var names than the ones we've chosen here. 8 | // TODO: Update CI so that we don't have to do this anymore. 9 | process.env.HARDHAT_NETWORK = 'custom' // "custom" here is an arbitrary name. only used for CI. 10 | process.env.CONTRACTS_TARGET_NETWORK = 'custom' 11 | process.env.CONTRACTS_DEPLOYER_KEY = process.env.DEPLOYER_PRIVATE_KEY 12 | process.env.CONTRACTS_RPC_URL = 13 | process.env.L1_NODE_WEB3_URL || 'http://127.0.0.1:8545' 14 | 15 | import hre from 'hardhat' 16 | 17 | const main = async () => { 18 | const sequencer = new Wallet(process.env.SEQUENCER_PRIVATE_KEY) 19 | const deployer = new Wallet(process.env.DEPLOYER_PRIVATE_KEY) 20 | 21 | await hre.run('deploy', { 22 | l1BlockTimeSeconds: process.env.BLOCK_TIME_SECONDS, 23 | ctcForceInclusionPeriodSeconds: process.env.FORCE_INCLUSION_PERIOD_SECONDS, 24 | ctcMaxTransactionGasLimit: process.env.MAX_TRANSACTION_GAS_LIMIT, 25 | emMinTransactionGasLimit: process.env.MIN_TRANSACTION_GAS_LIMIT, 26 | emMaxtransactionGasLimit: process.env.MAX_TRANSACTION_GAS_LIMIT, 27 | emMaxGasPerQueuePerEpoch: process.env.MAX_GAS_PER_QUEUE_PER_EPOCH, 28 | emSecondsPerEpoch: process.env.SECONDS_PER_EPOCH, 29 | emOvmChainId: process.env.CHAIN_ID, 30 | sccFraudProofWindow: parseInt(process.env.FRAUD_PROOF_WINDOW_SECONDS, 10), 31 | sccSequencerPublishWindow: process.env.SEQUENCER_PUBLISH_WINDOW_SECONDS, 32 | ovmSequencerAddress: sequencer.address, 33 | ovmProposerAddress: sequencer.address, 34 | ovmRelayerAddress: sequencer.address, 35 | ovmAddressManagerOwner: deployer.address, 36 | }) 37 | } 38 | 39 | main() 40 | .then(() => process.exit(0)) 41 | .catch((error) => { 42 | console.log( 43 | JSON.stringify({ error: error.message, stack: error.stack }, null, 2) 44 | ) 45 | process.exit(1) 46 | }) 47 | -------------------------------------------------------------------------------- /bin/gen_safety_checker_constants.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # pip3 install pyevmasm 3 | from pyevmasm import instruction_tables 4 | 5 | #print(instruction_tables.keys()) 6 | 7 | def asm(x): 8 | return [instruction_tables['istanbul'][i].opcode for i in x] 9 | 10 | push_opcodes = asm(["PUSH%d" % i for i in range(1,33)]) 11 | stop_opcodes = asm(["STOP", "JUMP", "RETURN", "INVALID"]) 12 | caller_opcodes = asm(["CALLER"]) 13 | blacklist_ops = set([ 14 | "ADDRESS", "BALANCE", "BLOCKHASH", 15 | "CALL", "CALLCODE", "CHAINID", "COINBASE", 16 | "CREATE", "CREATE2", "DELEGATECALL", "DIFFICULTY", 17 | "EXTCODESIZE", "EXTCODECOPY", "EXTCODEHASH", 18 | "GASLIMIT", "GASPRICE", "NUMBER", 19 | "ORIGIN", "REVERT", "SELFBALANCE", "SELFDESTRUCT", 20 | "SLOAD", "SSTORE", "STATICCALL", "TIMESTAMP"]) 21 | whitelist_opcodes = [] 22 | for x in instruction_tables['istanbul']: 23 | if x.name not in blacklist_ops: 24 | whitelist_opcodes.append(x.opcode) 25 | 26 | pushmask = 0 27 | for x in push_opcodes: 28 | pushmask |= 1 << x 29 | 30 | stopmask = 0 31 | for x in stop_opcodes: 32 | stopmask |= 1 << x 33 | 34 | stoplist = [0]*256 35 | procmask = 0 36 | for i in range(256): 37 | if i in whitelist_opcodes and \ 38 | i not in push_opcodes and \ 39 | i not in stop_opcodes and \ 40 | i not in caller_opcodes: 41 | # can skip this opcode 42 | stoplist[i] = 1 43 | else: 44 | procmask |= 1 << i 45 | 46 | # PUSH1 through PUSH4, can't skip in slow 47 | for i in range(0x60, 0x64): 48 | stoplist[i] = i-0x5e 49 | rr = "uint256[8] memory opcodeSkippableBytes = [\n" 50 | for i in range(0, 0x100, 0x20): 51 | ret = "uint256(0x" 52 | for j in range(i, i+0x20, 1): 53 | ret += ("%02X" % stoplist[j]) 54 | rr += ret+"),\n" 55 | 56 | rr = rr[:-2] + "];" 57 | 58 | print(rr) 59 | print("// Mask to gate opcode specific cases") 60 | print("uint256 opcodeGateMask = ~uint256(0x%x);" % procmask) 61 | print("// Halting opcodes") 62 | print("uint256 opcodeHaltingMask = ~uint256(0x%x);" % stopmask) 63 | print("// PUSH opcodes") 64 | print("uint256 opcodePushMask = ~uint256(0x%x);" % pushmask) 65 | 66 | -------------------------------------------------------------------------------- /bin/serve_dump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Run this script to serve the latest state dump from 4 | # an http server. This is useful to serve the state dump 5 | # to a local instance of the sequencer/verifier during 6 | # development. The state dump can be found at 7 | # `GET /state-dump.latest.json` 8 | 9 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" > /dev/null && pwd )" 10 | 11 | PYTHON=${PYTHON:-python} 12 | HOST=${HOST:-0.0.0.0} 13 | PORT=${PORT:-8081} 14 | DIRECTORY=$DIR/../build/dumps 15 | 16 | if [ ! command -v $PYTHON&>/dev/null ]; then 17 | echo "Please install python" 18 | exit 1 19 | fi 20 | 21 | VERSION=$($PYTHON --version 2>&1 \ 22 | | cut -d ' ' -f2 \ 23 | | sed -Ee's#([^/]).([^/]).([^/])#\1#') 24 | 25 | 26 | if [[ $VERSION == 3 ]]; then 27 | $PYTHON -m http.server \ 28 | --bind $HOST $PORT \ 29 | --directory $DIRECTORY 30 | else 31 | ( 32 | echo "Serving HTTP on $HOST port $PORT" 33 | cd $DIRECTORY 34 | $PYTHON -c \ 35 | 'import BaseHTTPServer as bhs, SimpleHTTPServer as shs; bhs.HTTPServer(("'$HOST'", '"$PORT"'), shs.SimpleHTTPRequestHandler).serve_forever()' 36 | ) 37 | fi 38 | -------------------------------------------------------------------------------- /bin/take-dump.ts: -------------------------------------------------------------------------------- 1 | /* External Imports */ 2 | import * as fs from 'fs' 3 | import * as path from 'path' 4 | import * as mkdirp from 'mkdirp' 5 | 6 | const env = process.env 7 | const CHAIN_ID = env.CHAIN_ID || '420' 8 | 9 | /* Internal Imports */ 10 | import { makeStateDump } from '../src/contract-dumps' 11 | import { RollupDeployConfig } from '../src/contract-deployment' 12 | ;(async () => { 13 | const outdir = path.resolve(__dirname, '../build/dumps') 14 | const outfile = path.join(outdir, 'state-dump.latest.json') 15 | mkdirp.sync(outdir) 16 | 17 | const config = { 18 | ovmGlobalContext: { 19 | ovmCHAINID: parseInt(CHAIN_ID, 10), 20 | }, 21 | } 22 | 23 | const dump = await makeStateDump(config as RollupDeployConfig) 24 | fs.writeFileSync(outfile, JSON.stringify(dump, null, 4)) 25 | })() 26 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/OVM/accounts/OVM_ProxyEOA.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /* Library Imports */ 5 | import { Lib_Bytes32Utils } from "../../libraries/utils/Lib_Bytes32Utils.sol"; 6 | import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol"; 7 | import { Lib_ECDSAUtils } from "../../libraries/utils/Lib_ECDSAUtils.sol"; 8 | import { Lib_SafeExecutionManagerWrapper } from "../../libraries/wrappers/Lib_SafeExecutionManagerWrapper.sol"; 9 | 10 | /** 11 | * @title OVM_ProxyEOA 12 | * @dev The Proxy EOA contract uses a delegate call to execute the logic in an implementation contract. 13 | * In combination with the logic implemented in the ECDSA Contract Account, this enables a form of upgradable 14 | * 'account abstraction' on layer 2. 15 | * 16 | * Compiler used: solc 17 | * Runtime target: OVM 18 | */ 19 | contract OVM_ProxyEOA { 20 | 21 | /************* 22 | * Constants * 23 | *************/ 24 | 25 | bytes32 constant IMPLEMENTATION_KEY = 0xdeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddead; 26 | 27 | 28 | /*************** 29 | * Constructor * 30 | ***************/ 31 | 32 | /** 33 | * @param _implementation Address of the initial implementation contract. 34 | */ 35 | constructor( 36 | address _implementation 37 | ) 38 | { 39 | _setImplementation(_implementation); 40 | } 41 | 42 | 43 | /********************* 44 | * Fallback Function * 45 | *********************/ 46 | 47 | fallback() 48 | external 49 | { 50 | (bool success, bytes memory returndata) = Lib_SafeExecutionManagerWrapper.safeDELEGATECALL( 51 | gasleft(), 52 | getImplementation(), 53 | msg.data 54 | ); 55 | 56 | if (success) { 57 | assembly { 58 | return(add(returndata, 0x20), mload(returndata)) 59 | } 60 | } else { 61 | Lib_SafeExecutionManagerWrapper.safeREVERT( 62 | string(returndata) 63 | ); 64 | } 65 | } 66 | 67 | 68 | /******************** 69 | * Public Functions * 70 | ********************/ 71 | 72 | /** 73 | * Changes the implementation address. 74 | * @param _implementation New implementation address. 75 | */ 76 | function upgrade( 77 | address _implementation 78 | ) 79 | external 80 | { 81 | Lib_SafeExecutionManagerWrapper.safeREQUIRE( 82 | Lib_SafeExecutionManagerWrapper.safeADDRESS() == Lib_SafeExecutionManagerWrapper.safeCALLER(), 83 | "EOAs can only upgrade their own EOA implementation" 84 | ); 85 | 86 | _setImplementation(_implementation); 87 | } 88 | 89 | /** 90 | * Gets the address of the current implementation. 91 | * @return Current implementation address. 92 | */ 93 | function getImplementation() 94 | public 95 | returns ( 96 | address 97 | ) 98 | { 99 | return Lib_Bytes32Utils.toAddress( 100 | Lib_SafeExecutionManagerWrapper.safeSLOAD( 101 | IMPLEMENTATION_KEY 102 | ) 103 | ); 104 | } 105 | 106 | 107 | /********************** 108 | * Internal Functions * 109 | **********************/ 110 | 111 | function _setImplementation( 112 | address _implementation 113 | ) 114 | internal 115 | { 116 | Lib_SafeExecutionManagerWrapper.safeSSTORE( 117 | IMPLEMENTATION_KEY, 118 | Lib_Bytes32Utils.fromAddress(_implementation) 119 | ); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/OVM/bridge/messaging/OVM_L1MultiMessageRelayer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // @unsupported: ovm 3 | pragma solidity >0.5.0 <0.8.0; 4 | pragma experimental ABIEncoderV2; 5 | /* Interface Imports */ 6 | import { iOVM_L1CrossDomainMessenger } from "../../../iOVM/bridge/messaging/iOVM_L1CrossDomainMessenger.sol"; 7 | import { iOVM_L1MultiMessageRelayer } from "../../../iOVM/bridge/messaging/iOVM_L1MultiMessageRelayer.sol"; 8 | 9 | /* Contract Imports */ 10 | import { Lib_AddressResolver } from "../../../libraries/resolver/Lib_AddressResolver.sol"; 11 | 12 | 13 | /** 14 | * @title OVM_L1MultiMessageRelayer 15 | * @dev The L1 Multi-Message Relayer contract is a gas efficiency optimization which enables the 16 | * relayer to submit multiple messages in a single transaction to be relayed by the L1 Cross Domain 17 | * Message Sender. 18 | * 19 | * Compiler used: solc 20 | * Runtime target: EVM 21 | */ 22 | contract OVM_L1MultiMessageRelayer is iOVM_L1MultiMessageRelayer, Lib_AddressResolver { 23 | 24 | /*************** 25 | * Constructor * 26 | ***************/ 27 | constructor( 28 | address _libAddressManager 29 | ) 30 | Lib_AddressResolver(_libAddressManager) 31 | {} 32 | 33 | /********************** 34 | * Function Modifiers * 35 | **********************/ 36 | 37 | modifier onlyBatchRelayer() { 38 | require( 39 | msg.sender == resolve("OVM_L2BatchMessageRelayer"), 40 | "OVM_L1MultiMessageRelayer: Function can only be called by the OVM_L2BatchMessageRelayer" 41 | ); 42 | _; 43 | } 44 | 45 | /******************** 46 | * Public Functions * 47 | ********************/ 48 | 49 | /** 50 | * @notice Forwards multiple cross domain messages to the L1 Cross Domain Messenger for relaying 51 | * @param _messages An array of L2 to L1 messages 52 | */ 53 | function batchRelayMessages(L2ToL1Message[] calldata _messages) 54 | override 55 | external 56 | onlyBatchRelayer 57 | { 58 | iOVM_L1CrossDomainMessenger messenger = iOVM_L1CrossDomainMessenger(resolve("Proxy__OVM_L1CrossDomainMessenger")); 59 | for (uint256 i = 0; i < _messages.length; i++) { 60 | L2ToL1Message memory message = _messages[i]; 61 | messenger.relayMessage( 62 | message.target, 63 | message.sender, 64 | message.message, 65 | message.messageNonce, 66 | message.proof 67 | ); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/OVM/bridge/tokens/OVM_L1ERC20Gateway.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // @unsupported: ovm 3 | pragma solidity >0.5.0 <0.8.0; 4 | pragma experimental ABIEncoderV2; 5 | 6 | /* Interface Imports */ 7 | import { iOVM_L1TokenGateway } from "../../../iOVM/bridge/tokens/iOVM_L1TokenGateway.sol"; 8 | import { Abs_L1TokenGateway } from "./Abs_L1TokenGateway.sol"; 9 | import { iOVM_ERC20 } from "../../../iOVM/predeploys/iOVM_ERC20.sol"; 10 | 11 | /** 12 | * @title OVM_L1ERC20Gateway 13 | * @dev The L1 ERC20 Gateway is a contract which stores deposited L1 funds that are in use on L2. 14 | * It synchronizes a corresponding L2 ERC20 Gateway, informing it of deposits, and listening to it 15 | * for newly finalized withdrawals. 16 | * 17 | * NOTE: This contract extends Abs_L1TokenGateway, which is where we 18 | * takes care of most of the initialization and the cross-chain logic. 19 | * If you are looking to implement your own deposit/withdrawal contracts, you 20 | * may also want to extend the abstract contract in a similar manner. 21 | * 22 | * Compiler used: solc 23 | * Runtime target: EVM 24 | */ 25 | contract OVM_L1ERC20Gateway is Abs_L1TokenGateway { 26 | 27 | /******************************** 28 | * External Contract References * 29 | ********************************/ 30 | 31 | iOVM_ERC20 public l1ERC20; 32 | 33 | /*************** 34 | * Constructor * 35 | ***************/ 36 | 37 | /** 38 | * @param _l1ERC20 L1 ERC20 address this contract stores deposits for 39 | * @param _l2DepositedERC20 L2 Gateway address on the chain being deposited into 40 | */ 41 | constructor( 42 | iOVM_ERC20 _l1ERC20, 43 | address _l2DepositedERC20, 44 | address _l1messenger 45 | ) 46 | Abs_L1TokenGateway( 47 | _l2DepositedERC20, 48 | _l1messenger 49 | ) 50 | { 51 | l1ERC20 = _l1ERC20; 52 | } 53 | 54 | 55 | /************** 56 | * Accounting * 57 | **************/ 58 | 59 | /** 60 | * @dev When a deposit is initiated on L1, the L1 Gateway 61 | * transfers the funds to itself for future withdrawals 62 | * 63 | * @param _from L1 address ETH is being deposited from 64 | * param _to L2 address that the ETH is being deposited to 65 | * @param _amount Amount of ERC20 to send 66 | */ 67 | function _handleInitiateDeposit( 68 | address _from, 69 | address, // _to, 70 | uint256 _amount 71 | ) 72 | internal 73 | override 74 | { 75 | // Hold on to the newly deposited funds 76 | l1ERC20.transferFrom( 77 | _from, 78 | address(this), 79 | _amount 80 | ); 81 | } 82 | 83 | /** 84 | * @dev When a withdrawal is finalized on L1, the L1 Gateway 85 | * transfers the funds to the withdrawer 86 | * 87 | * @param _to L1 address that the ERC20 is being withdrawn to 88 | * @param _amount Amount of ERC20 to send 89 | */ 90 | function _handleFinalizeWithdrawal( 91 | address _to, 92 | uint _amount 93 | ) 94 | internal 95 | override 96 | { 97 | // Transfer withdrawn funds out to withdrawer 98 | l1ERC20.transfer(_to, _amount); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/OVM/bridge/tokens/OVM_L2DepositedERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | /* Interface Imports */ 6 | import { iOVM_L1TokenGateway } from "../../../iOVM/bridge/tokens/iOVM_L1TokenGateway.sol"; 7 | 8 | /* Contract Imports */ 9 | import { UniswapV2ERC20 } from "../../../libraries/standards/UniswapV2ERC20.sol"; 10 | 11 | /* Library Imports */ 12 | import { Abs_L2DepositedToken } from "./Abs_L2DepositedToken.sol"; 13 | 14 | /** 15 | * @title OVM_L2DepositedERC20 16 | * @dev The L2 Deposited ERC20 is an ERC20 implementation which represents L1 assets deposited into L2. 17 | * This contract mints new tokens when it hears about deposits into the L1 ERC20 gateway. 18 | * This contract also burns the tokens intended for withdrawal, informing the L1 gateway to release L1 funds. 19 | * 20 | * NOTE: This contract implements the Abs_L2DepositedToken contract using Uniswap's ERC20 as the implementation. 21 | * Alternative implementations can be used in this similar manner. 22 | * 23 | * Compiler used: optimistic-solc 24 | * Runtime target: OVM 25 | */ 26 | contract OVM_L2DepositedERC20 is Abs_L2DepositedToken, UniswapV2ERC20 { 27 | 28 | /*************** 29 | * Constructor * 30 | ***************/ 31 | 32 | /** 33 | * @param _l2CrossDomainMessenger Cross-domain messenger used by this contract. 34 | * @param _name ERC20 name 35 | * @param _symbol ERC20 symbol 36 | */ 37 | constructor( 38 | address _l2CrossDomainMessenger, 39 | string memory _name, 40 | string memory _symbol 41 | ) 42 | Abs_L2DepositedToken(_l2CrossDomainMessenger) 43 | UniswapV2ERC20(_name, _symbol) 44 | {} 45 | 46 | // When a withdrawal is initiated, we burn the withdrawer's funds to prevent subsequent L2 usage. 47 | function _handleInitiateWithdrawal( 48 | address, // _to, 49 | uint _amount 50 | ) 51 | internal 52 | override 53 | { 54 | _burn(msg.sender, _amount); 55 | } 56 | 57 | // When a deposit is finalized, we credit the account on L2 with the same amount of tokens. 58 | function _handleFinalizeDeposit( 59 | address _to, 60 | uint _amount 61 | ) 62 | internal 63 | override 64 | { 65 | _mint(_to, _amount); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/OVM/execution/OVM_StateManagerFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /* Interface Imports */ 5 | import { iOVM_StateManager } from "../../iOVM/execution/iOVM_StateManager.sol"; 6 | import { iOVM_StateManagerFactory } from "../../iOVM/execution/iOVM_StateManagerFactory.sol"; 7 | 8 | /* Contract Imports */ 9 | import { OVM_StateManager } from "./OVM_StateManager.sol"; 10 | 11 | /** 12 | * @title OVM_StateManagerFactory 13 | * @dev The State Manager Factory is called by a State Transitioner's init code, to create a new 14 | * State Manager for use in the Fraud Verification process. 15 | * 16 | * Compiler used: solc 17 | * Runtime target: EVM 18 | */ 19 | contract OVM_StateManagerFactory is iOVM_StateManagerFactory { 20 | 21 | /******************** 22 | * Public Functions * 23 | ********************/ 24 | 25 | /** 26 | * Creates a new OVM_StateManager 27 | * @param _owner Owner of the created contract. 28 | * @return New OVM_StateManager instance. 29 | */ 30 | function create( 31 | address _owner 32 | ) 33 | override 34 | public 35 | returns ( 36 | iOVM_StateManager 37 | ) 38 | { 39 | return new OVM_StateManager(_owner); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/OVM/predeploys/OVM_ETH.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /* Library Imports */ 5 | import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol"; 6 | 7 | /* Interface Imports */ 8 | import { iOVM_L1TokenGateway } from "../../iOVM/bridge/tokens/iOVM_L1TokenGateway.sol"; 9 | 10 | /* Contract Imports */ 11 | import { OVM_L2DepositedERC20 } from "../bridge/tokens/OVM_L2DepositedERC20.sol"; 12 | 13 | /** 14 | * @title OVM_ETH 15 | * @dev The ETH predeploy provides an ERC20 interface for ETH deposited to Layer 2. Note that 16 | * unlike on Layer 1, Layer 2 accounts do not have a balance field. 17 | * 18 | * Compiler used: optimistic-solc 19 | * Runtime target: OVM 20 | */ 21 | contract OVM_ETH is OVM_L2DepositedERC20 { 22 | constructor( 23 | address _l2CrossDomainMessenger, 24 | address _l1ETHGateway 25 | ) 26 | OVM_L2DepositedERC20( 27 | _l2CrossDomainMessenger, 28 | "Ether", 29 | "ETH" 30 | ) 31 | { 32 | init(iOVM_L1TokenGateway(_l1ETHGateway)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/OVM/predeploys/OVM_L1MessageSender.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /* Interface Imports */ 5 | import { iOVM_L1MessageSender } from "../../iOVM/predeploys/iOVM_L1MessageSender.sol"; 6 | import { iOVM_ExecutionManager } from "../../iOVM/execution/iOVM_ExecutionManager.sol"; 7 | 8 | /** 9 | * @title OVM_L1MessageSender 10 | * @dev The L1MessageSender is a predeploy contract running on L2. During the execution of cross 11 | * domain transaction from L1 to L2, it returns the address of the L1 account (either an EOA or 12 | * contract) which sent the message to L2 via the Canonical Transaction Chain's `enqueue()` 13 | * function. 14 | * 15 | * This contract exclusively serves as a getter for the ovmL1TXORIGIN operation. This is necessary 16 | * because there is no corresponding operation in the EVM which the the optimistic solidity compiler 17 | * can be replaced with a call to the ExecutionManager's ovmL1TXORIGIN() function. 18 | * 19 | * 20 | * Compiler used: solc 21 | * Runtime target: OVM 22 | */ 23 | contract OVM_L1MessageSender is iOVM_L1MessageSender { 24 | 25 | /******************** 26 | * Public Functions * 27 | ********************/ 28 | 29 | /** 30 | * @return _l1MessageSender L1 message sender address (msg.sender). 31 | */ 32 | function getL1MessageSender() 33 | override 34 | public 35 | view 36 | returns ( 37 | address _l1MessageSender 38 | ) 39 | { 40 | // Note that on L2 msg.sender (ie. evmCALLER) will always be the Execution Manager 41 | return iOVM_ExecutionManager(msg.sender).ovmL1TXORIGIN(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/OVM/predeploys/OVM_L2ToL1MessagePasser.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /* Interface Imports */ 5 | import { iOVM_L2ToL1MessagePasser } from "../../iOVM/predeploys/iOVM_L2ToL1MessagePasser.sol"; 6 | 7 | /** 8 | * @title OVM_L2ToL1MessagePasser 9 | * @dev The L2 to L1 Message Passer is a utility contract which facilitate an L1 proof of the 10 | * of a message on L2. The L1 Cross Domain Messenger performs this proof in its 11 | * _verifyStorageProof function, which verifies the existence of the transaction hash in this 12 | * contract's `sentMessages` mapping. 13 | * 14 | * Compiler used: solc 15 | * Runtime target: EVM 16 | */ 17 | contract OVM_L2ToL1MessagePasser is iOVM_L2ToL1MessagePasser { 18 | 19 | /********************** 20 | * Contract Variables * 21 | **********************/ 22 | 23 | mapping (bytes32 => bool) public sentMessages; 24 | 25 | 26 | /******************** 27 | * Public Functions * 28 | ********************/ 29 | 30 | /** 31 | * Passes a message to L1. 32 | * @param _message Message to pass to L1. 33 | */ 34 | function passMessageToL1( 35 | bytes memory _message 36 | ) 37 | override 38 | public 39 | { 40 | // Note: although this function is public, only messages sent from the OVM_L2CrossDomainMessenger 41 | // will be relayed by the OVM_L1CrossDomainMessenger. This is enforced by a check in 42 | // OVM_L1CrossDomainMessenger._verifyStorageProof(). 43 | sentMessages[keccak256( 44 | abi.encodePacked( 45 | _message, 46 | msg.sender 47 | ) 48 | )] = true; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/OVM/predeploys/OVM_ProxySequencerEntrypoint.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /* Library Imports */ 5 | import { Lib_SafeExecutionManagerWrapper } from "../../libraries/wrappers/Lib_SafeExecutionManagerWrapper.sol"; 6 | 7 | /** 8 | * @title OVM_ProxySequencerEntrypoint 9 | * @dev The Proxy Sequencer Entrypoint is a predeployed proxy to the implementation of the 10 | * Sequencer Entrypoint. This will enable the Optimism team to upgrade the Sequencer Entrypoint 11 | * contract. 12 | * 13 | * Compiler used: solc 14 | * Runtime target: OVM 15 | */ 16 | contract OVM_ProxySequencerEntrypoint { 17 | 18 | /********************* 19 | * Fallback Function * 20 | *********************/ 21 | 22 | fallback() 23 | external 24 | { 25 | Lib_SafeExecutionManagerWrapper.safeDELEGATECALL( 26 | gasleft(), 27 | _getImplementation(), 28 | msg.data 29 | ); 30 | } 31 | 32 | 33 | /******************** 34 | * Public Functions * 35 | ********************/ 36 | 37 | function init( 38 | address _implementation, 39 | address _owner 40 | ) 41 | external 42 | { 43 | Lib_SafeExecutionManagerWrapper.safeREQUIRE( 44 | _getOwner() == address(0), 45 | "ProxySequencerEntrypoint has already been inited" 46 | ); 47 | _setOwner(_owner); 48 | _setImplementation(_implementation); 49 | } 50 | 51 | function upgrade( 52 | address _implementation 53 | ) 54 | external 55 | { 56 | Lib_SafeExecutionManagerWrapper.safeREQUIRE( 57 | _getOwner() == Lib_SafeExecutionManagerWrapper.safeCALLER(), 58 | "Only owner can upgrade the Entrypoint" 59 | ); 60 | 61 | _setImplementation(_implementation); 62 | } 63 | 64 | 65 | /********************** 66 | * Internal Functions * 67 | **********************/ 68 | 69 | function _setImplementation( 70 | address _implementation 71 | ) 72 | internal 73 | { 74 | Lib_SafeExecutionManagerWrapper.safeSSTORE( 75 | bytes32(uint256(0)), 76 | bytes32(uint256(uint160(_implementation))) 77 | ); 78 | } 79 | 80 | function _getImplementation() 81 | internal 82 | returns ( 83 | address _implementation 84 | ) 85 | { 86 | return address(uint160(uint256( 87 | Lib_SafeExecutionManagerWrapper.safeSLOAD( 88 | bytes32(uint256(0)) 89 | ) 90 | ))); 91 | } 92 | 93 | function _setOwner( 94 | address _owner 95 | ) 96 | internal 97 | { 98 | Lib_SafeExecutionManagerWrapper.safeSSTORE( 99 | bytes32(uint256(1)), 100 | bytes32(uint256(uint160(_owner))) 101 | ); 102 | } 103 | 104 | function _getOwner() 105 | internal 106 | returns ( 107 | address _owner 108 | ) 109 | { 110 | return address(uint160(uint256( 111 | Lib_SafeExecutionManagerWrapper.safeSLOAD( 112 | bytes32(uint256(1)) 113 | ) 114 | ))); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/OVM/verification/Abs_FraudContributor.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | import { iOVM_BondManager } from "../../iOVM/verification/iOVM_BondManager.sol"; 5 | import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol"; 6 | 7 | /// Minimal contract to be inherited by contracts consumed by users that provide 8 | /// data for fraud proofs 9 | abstract contract Abs_FraudContributor is Lib_AddressResolver { 10 | /// Decorate your functions with this modifier to store how much total gas was 11 | /// consumed by the sender, to reward users fairly 12 | modifier contributesToFraudProof(bytes32 preStateRoot, bytes32 txHash) { 13 | uint256 startGas = gasleft(); 14 | _; 15 | uint256 gasSpent = startGas - gasleft(); 16 | iOVM_BondManager(resolve('OVM_BondManager')).recordGasSpent(preStateRoot, txHash, msg.sender, gasSpent); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/OVM/verification/OVM_StateTransitionerFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // @unsupported: ovm 3 | pragma solidity >0.5.0 <0.8.0; 4 | 5 | /* Library Imports */ 6 | import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol"; 7 | 8 | /* Interface Imports */ 9 | import { iOVM_StateTransitioner } from "../../iOVM/verification/iOVM_StateTransitioner.sol"; 10 | import { iOVM_StateTransitionerFactory } from "../../iOVM/verification/iOVM_StateTransitionerFactory.sol"; 11 | import { iOVM_FraudVerifier } from "../../iOVM/verification/iOVM_FraudVerifier.sol"; 12 | 13 | /* Contract Imports */ 14 | import { OVM_StateTransitioner } from "./OVM_StateTransitioner.sol"; 15 | 16 | /** 17 | * @title OVM_StateTransitionerFactory 18 | * @dev The State Transitioner Factory is used by the Fraud Verifier to create a new State 19 | * Transitioner during the initialization of a fraud proof. 20 | * 21 | * Compiler used: solc 22 | * Runtime target: EVM 23 | */ 24 | contract OVM_StateTransitionerFactory is iOVM_StateTransitionerFactory, Lib_AddressResolver { 25 | 26 | /*************** 27 | * Constructor * 28 | ***************/ 29 | 30 | constructor( 31 | address _libAddressManager 32 | ) 33 | Lib_AddressResolver(_libAddressManager) 34 | {} 35 | 36 | 37 | /******************** 38 | * Public Functions * 39 | ********************/ 40 | 41 | /** 42 | * Creates a new OVM_StateTransitioner 43 | * @param _libAddressManager Address of the Address Manager. 44 | * @param _stateTransitionIndex Index of the state transition being verified. 45 | * @param _preStateRoot State root before the transition was executed. 46 | * @param _transactionHash Hash of the executed transaction. 47 | * @return New OVM_StateTransitioner instance. 48 | */ 49 | function create( 50 | address _libAddressManager, 51 | uint256 _stateTransitionIndex, 52 | bytes32 _preStateRoot, 53 | bytes32 _transactionHash 54 | ) 55 | override 56 | public 57 | returns ( 58 | iOVM_StateTransitioner 59 | ) 60 | { 61 | require( 62 | msg.sender == resolve("OVM_FraudVerifier"), 63 | "Create can only be done by the OVM_FraudVerifier." 64 | ); 65 | 66 | return new OVM_StateTransitioner( 67 | _libAddressManager, 68 | _stateTransitionIndex, 69 | _preStateRoot, 70 | _transactionHash 71 | ); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/iOVM/accounts/iOVM_ECDSAContractAccount.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | /* Library Imports */ 6 | import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol"; 7 | 8 | /** 9 | * @title iOVM_ECDSAContractAccount 10 | */ 11 | interface iOVM_ECDSAContractAccount { 12 | 13 | /******************** 14 | * Public Functions * 15 | ********************/ 16 | 17 | function execute( 18 | bytes memory _transaction, 19 | Lib_OVMCodec.EOASignatureType _signatureType, 20 | uint8 _v, 21 | bytes32 _r, 22 | bytes32 _s 23 | ) external returns (bool _success, bytes memory _returndata); 24 | } 25 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/iOVM/bridge/messaging/iAbs_BaseCrossDomainMessenger.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | /** 6 | * @title iAbs_BaseCrossDomainMessenger 7 | */ 8 | interface iAbs_BaseCrossDomainMessenger { 9 | 10 | /********** 11 | * Events * 12 | **********/ 13 | event SentMessage(bytes message); 14 | event RelayedMessage(bytes32 msgHash); 15 | 16 | /********************** 17 | * Contract Variables * 18 | **********************/ 19 | function xDomainMessageSender() external view returns (address); 20 | 21 | /******************** 22 | * Public Functions * 23 | ********************/ 24 | 25 | /** 26 | * Sends a cross domain message to the target messenger. 27 | * @param _target Target contract address. 28 | * @param _message Message to send to the target. 29 | * @param _gasLimit Gas limit for the provided message. 30 | */ 31 | function sendMessage( 32 | address _target, 33 | bytes calldata _message, 34 | uint32 _gasLimit 35 | ) external; 36 | } 37 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_L1CrossDomainMessenger.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | /* Library Imports */ 6 | import { Lib_OVMCodec } from "../../../libraries/codec/Lib_OVMCodec.sol"; 7 | 8 | /* Interface Imports */ 9 | import { iAbs_BaseCrossDomainMessenger } from "./iAbs_BaseCrossDomainMessenger.sol"; 10 | 11 | /** 12 | * @title iOVM_L1CrossDomainMessenger 13 | */ 14 | interface iOVM_L1CrossDomainMessenger is iAbs_BaseCrossDomainMessenger { 15 | 16 | /******************* 17 | * Data Structures * 18 | *******************/ 19 | 20 | struct L2MessageInclusionProof { 21 | bytes32 stateRoot; 22 | Lib_OVMCodec.ChainBatchHeader stateRootBatchHeader; 23 | Lib_OVMCodec.ChainInclusionProof stateRootProof; 24 | bytes stateTrieWitness; 25 | bytes storageTrieWitness; 26 | } 27 | 28 | 29 | /******************** 30 | * Public Functions * 31 | ********************/ 32 | 33 | /** 34 | * Relays a cross domain message to a contract. 35 | * @param _target Target contract address. 36 | * @param _sender Message sender address. 37 | * @param _message Message to send to the target. 38 | * @param _messageNonce Nonce for the provided message. 39 | * @param _proof Inclusion proof for the given message. 40 | */ 41 | function relayMessage( 42 | address _target, 43 | address _sender, 44 | bytes memory _message, 45 | uint256 _messageNonce, 46 | L2MessageInclusionProof memory _proof 47 | ) external; 48 | 49 | /** 50 | * Replays a cross domain message to the target messenger. 51 | * @param _target Target contract address. 52 | * @param _sender Original sender address. 53 | * @param _message Message to send to the target. 54 | * @param _messageNonce Nonce for the provided message. 55 | * @param _gasLimit Gas limit for the provided message. 56 | */ 57 | function replayMessage( 58 | address _target, 59 | address _sender, 60 | bytes memory _message, 61 | uint256 _messageNonce, 62 | uint32 _gasLimit 63 | ) external; 64 | } 65 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_L1MultiMessageRelayer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | /* Interface Imports */ 6 | import { iOVM_L1CrossDomainMessenger } from "../../../iOVM/bridge/messaging/iOVM_L1CrossDomainMessenger.sol"; 7 | interface iOVM_L1MultiMessageRelayer { 8 | 9 | struct L2ToL1Message { 10 | address target; 11 | address sender; 12 | bytes message; 13 | uint256 messageNonce; 14 | iOVM_L1CrossDomainMessenger.L2MessageInclusionProof proof; 15 | } 16 | 17 | function batchRelayMessages(L2ToL1Message[] calldata _messages) external; 18 | } 19 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_L2CrossDomainMessenger.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | /* Interface Imports */ 6 | import { iAbs_BaseCrossDomainMessenger } from "./iAbs_BaseCrossDomainMessenger.sol"; 7 | 8 | /** 9 | * @title iOVM_L2CrossDomainMessenger 10 | */ 11 | interface iOVM_L2CrossDomainMessenger is iAbs_BaseCrossDomainMessenger { 12 | 13 | /******************** 14 | * Public Functions * 15 | ********************/ 16 | 17 | /** 18 | * Relays a cross domain message to a contract. 19 | * @param _target Target contract address. 20 | * @param _sender Message sender address. 21 | * @param _message Message to send to the target. 22 | * @param _messageNonce Nonce for the provided message. 23 | */ 24 | function relayMessage( 25 | address _target, 26 | address _sender, 27 | bytes memory _message, 28 | uint256 _messageNonce 29 | ) external; 30 | } 31 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/iOVM/bridge/tokens/iOVM_L1ETHGateway.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | /** 6 | * @title iOVM_L1ETHGateway 7 | */ 8 | interface iOVM_L1ETHGateway { 9 | 10 | /********** 11 | * Events * 12 | **********/ 13 | 14 | event DepositInitiated( 15 | address indexed _from, 16 | address _to, 17 | uint256 _amount 18 | ); 19 | 20 | event WithdrawalFinalized( 21 | address indexed _to, 22 | uint256 _amount 23 | ); 24 | 25 | /******************** 26 | * Public Functions * 27 | ********************/ 28 | 29 | function deposit() 30 | external 31 | payable; 32 | 33 | function depositTo( 34 | address _to 35 | ) 36 | external 37 | payable; 38 | 39 | /************************* 40 | * Cross-chain Functions * 41 | *************************/ 42 | 43 | function finalizeWithdrawal( 44 | address _to, 45 | uint _amount 46 | ) 47 | external; 48 | 49 | function getFinalizeDepositL2Gas() 50 | external 51 | view 52 | returns( 53 | uint32 54 | ); 55 | } 56 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/iOVM/bridge/tokens/iOVM_L1TokenGateway.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | /** 6 | * @title iOVM_L1TokenGateway 7 | */ 8 | interface iOVM_L1TokenGateway { 9 | 10 | /********** 11 | * Events * 12 | **********/ 13 | 14 | event DepositInitiated( 15 | address indexed _from, 16 | address _to, 17 | uint256 _amount 18 | ); 19 | 20 | event WithdrawalFinalized( 21 | address indexed _to, 22 | uint256 _amount 23 | ); 24 | 25 | 26 | /******************** 27 | * Public Functions * 28 | ********************/ 29 | 30 | function deposit( 31 | uint _amount 32 | ) 33 | external; 34 | 35 | function depositTo( 36 | address _to, 37 | uint _amount 38 | ) 39 | external; 40 | 41 | 42 | /************************* 43 | * Cross-chain Functions * 44 | *************************/ 45 | 46 | function finalizeWithdrawal( 47 | address _to, 48 | uint _amount 49 | ) 50 | external; 51 | } 52 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/iOVM/bridge/tokens/iOVM_L2DepositedToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | /** 6 | * @title iOVM_L2DepositedToken 7 | */ 8 | interface iOVM_L2DepositedToken { 9 | 10 | /********** 11 | * Events * 12 | **********/ 13 | 14 | event WithdrawalInitiated( 15 | address indexed _from, 16 | address _to, 17 | uint256 _amount 18 | ); 19 | 20 | event DepositFinalized( 21 | address indexed _to, 22 | uint256 _amount 23 | ); 24 | 25 | 26 | /******************** 27 | * Public Functions * 28 | ********************/ 29 | 30 | function withdraw( 31 | uint _amount 32 | ) 33 | external; 34 | 35 | function withdrawTo( 36 | address _to, 37 | uint _amount 38 | ) 39 | external; 40 | 41 | 42 | /************************* 43 | * Cross-chain Functions * 44 | *************************/ 45 | 46 | function finalizeDeposit( 47 | address _to, 48 | uint _amount 49 | ) 50 | external; 51 | } 52 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/iOVM/chain/iOVM_ChainStorageContainer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /** 5 | * @title iOVM_ChainStorageContainer 6 | */ 7 | interface iOVM_ChainStorageContainer { 8 | 9 | /******************** 10 | * Public Functions * 11 | ********************/ 12 | 13 | /** 14 | * Sets the container's global metadata field. We're using `bytes27` here because we use five 15 | * bytes to maintain the length of the underlying data structure, meaning we have an extra 16 | * 27 bytes to store arbitrary data. 17 | * @param _globalMetadata New global metadata to set. 18 | */ 19 | function setGlobalMetadata( 20 | bytes27 _globalMetadata 21 | ) 22 | external; 23 | 24 | /** 25 | * Retrieves the container's global metadata field. 26 | * @return Container global metadata field. 27 | */ 28 | function getGlobalMetadata() 29 | external 30 | view 31 | returns ( 32 | bytes27 33 | ); 34 | 35 | /** 36 | * Retrieves the number of objects stored in the container. 37 | * @return Number of objects in the container. 38 | */ 39 | function length() 40 | external 41 | view 42 | returns ( 43 | uint256 44 | ); 45 | 46 | /** 47 | * Pushes an object into the container. 48 | * @param _object A 32 byte value to insert into the container. 49 | */ 50 | function push( 51 | bytes32 _object 52 | ) 53 | external; 54 | 55 | /** 56 | * Pushes an object into the container. Function allows setting the global metadata since 57 | * we'll need to touch the "length" storage slot anyway, which also contains the global 58 | * metadata (it's an optimization). 59 | * @param _object A 32 byte value to insert into the container. 60 | * @param _globalMetadata New global metadata for the container. 61 | */ 62 | function push( 63 | bytes32 _object, 64 | bytes27 _globalMetadata 65 | ) 66 | external; 67 | 68 | /** 69 | * Retrieves an object from the container. 70 | * @param _index Index of the particular object to access. 71 | * @return 32 byte object value. 72 | */ 73 | function get( 74 | uint256 _index 75 | ) 76 | external 77 | view 78 | returns ( 79 | bytes32 80 | ); 81 | 82 | /** 83 | * Removes all objects after and including a given index. 84 | * @param _index Object index to delete from. 85 | */ 86 | function deleteElementsAfterInclusive( 87 | uint256 _index 88 | ) 89 | external; 90 | 91 | /** 92 | * Removes all objects after and including a given index. Also allows setting the global 93 | * metadata field. 94 | * @param _index Object index to delete from. 95 | * @param _globalMetadata New global metadata for the container. 96 | */ 97 | function deleteElementsAfterInclusive( 98 | uint256 _index, 99 | bytes27 _globalMetadata 100 | ) 101 | external; 102 | 103 | /** 104 | * Marks an index as overwritable, meaing the underlying buffer can start to write values over 105 | * any objects before and including the given index. 106 | */ 107 | function setNextOverwritableIndex( 108 | uint256 _index 109 | ) 110 | external; 111 | } 112 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/iOVM/chain/iOVM_StateCommitmentChain.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | /* Library Imports */ 6 | import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol"; 7 | 8 | /** 9 | * @title iOVM_StateCommitmentChain 10 | */ 11 | interface iOVM_StateCommitmentChain { 12 | 13 | /********** 14 | * Events * 15 | **********/ 16 | 17 | event StateBatchAppended( 18 | uint256 indexed _batchIndex, 19 | bytes32 _batchRoot, 20 | uint256 _batchSize, 21 | uint256 _prevTotalElements, 22 | bytes _extraData 23 | ); 24 | 25 | event StateBatchDeleted( 26 | uint256 indexed _batchIndex, 27 | bytes32 _batchRoot 28 | ); 29 | 30 | 31 | /******************** 32 | * Public Functions * 33 | ********************/ 34 | 35 | /** 36 | * Retrieves the total number of elements submitted. 37 | * @return _totalElements Total submitted elements. 38 | */ 39 | function getTotalElements() 40 | external 41 | view 42 | returns ( 43 | uint256 _totalElements 44 | ); 45 | 46 | /** 47 | * Retrieves the total number of batches submitted. 48 | * @return _totalBatches Total submitted batches. 49 | */ 50 | function getTotalBatches() 51 | external 52 | view 53 | returns ( 54 | uint256 _totalBatches 55 | ); 56 | 57 | /** 58 | * Retrieves the timestamp of the last batch submitted by the sequencer. 59 | * @return _lastSequencerTimestamp Last sequencer batch timestamp. 60 | */ 61 | function getLastSequencerTimestamp() 62 | external 63 | view 64 | returns ( 65 | uint256 _lastSequencerTimestamp 66 | ); 67 | 68 | /** 69 | * Appends a batch of state roots to the chain. 70 | * @param _batch Batch of state roots. 71 | * @param _shouldStartAtElement Index of the element at which this batch should start. 72 | */ 73 | function appendStateBatch( 74 | bytes32[] calldata _batch, 75 | uint256 _shouldStartAtElement 76 | ) 77 | external; 78 | 79 | /** 80 | * Deletes all state roots after (and including) a given batch. 81 | * @param _batchHeader Header of the batch to start deleting from. 82 | */ 83 | function deleteStateBatch( 84 | Lib_OVMCodec.ChainBatchHeader memory _batchHeader 85 | ) 86 | external; 87 | 88 | /** 89 | * Verifies a batch inclusion proof. 90 | * @param _element Hash of the element to verify a proof for. 91 | * @param _batchHeader Header of the batch in which the element was included. 92 | * @param _proof Merkle inclusion proof for the element. 93 | */ 94 | function verifyStateCommitment( 95 | bytes32 _element, 96 | Lib_OVMCodec.ChainBatchHeader memory _batchHeader, 97 | Lib_OVMCodec.ChainInclusionProof memory _proof 98 | ) 99 | external 100 | view 101 | returns ( 102 | bool _verified 103 | ); 104 | 105 | /** 106 | * Checks whether a given batch is still inside its fraud proof window. 107 | * @param _batchHeader Header of the batch to check. 108 | * @return _inside Whether or not the batch is inside the fraud proof window. 109 | */ 110 | function insideFraudProofWindow( 111 | Lib_OVMCodec.ChainBatchHeader memory _batchHeader 112 | ) 113 | external 114 | view 115 | returns ( 116 | bool _inside 117 | ); 118 | } 119 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/iOVM/execution/iOVM_SafetyChecker.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /** 5 | * @title iOVM_SafetyChecker 6 | */ 7 | interface iOVM_SafetyChecker { 8 | 9 | /******************** 10 | * Public Functions * 11 | ********************/ 12 | 13 | function isBytecodeSafe(bytes calldata _bytecode) external pure returns (bool); 14 | } 15 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/iOVM/execution/iOVM_StateManagerFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /* Contract Imports */ 5 | import { iOVM_StateManager } from "./iOVM_StateManager.sol"; 6 | 7 | /** 8 | * @title iOVM_StateManagerFactory 9 | */ 10 | interface iOVM_StateManagerFactory { 11 | 12 | /*************************************** 13 | * Public Functions: Contract Creation * 14 | ***************************************/ 15 | 16 | function create( 17 | address _owner 18 | ) 19 | external 20 | returns ( 21 | iOVM_StateManager _ovmStateManager 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/iOVM/predeploys/iOVM_DeployerWhitelist.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /** 5 | * @title iOVM_DeployerWhitelist 6 | */ 7 | interface iOVM_DeployerWhitelist { 8 | 9 | /******************** 10 | * Public Functions * 11 | ********************/ 12 | 13 | function initialize(address _owner, bool _allowArbitraryDeployment) external; 14 | function getOwner() external returns (address _owner); 15 | function setWhitelistedDeployer(address _deployer, bool _isWhitelisted) external; 16 | function setOwner(address _newOwner) external; 17 | function setAllowArbitraryDeployment(bool _allowArbitraryDeployment) external; 18 | function enableArbitraryContractDeployment() external; 19 | function isDeployerAllowed(address _deployer) external returns (bool _allowed); 20 | } 21 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/iOVM/predeploys/iOVM_ERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /** 5 | * @title iOVM_ERC20 6 | */ 7 | interface iOVM_ERC20 { 8 | /* This is a slight change to the ERC20 base standard. 9 | function totalSupply() constant returns (uint256 supply); 10 | is replaced with: 11 | uint256 public totalSupply; 12 | This automatically creates a getter function for the totalSupply. 13 | This is moved to the base contract since public getter functions are not 14 | currently recognised as an implementation of the matching abstract 15 | function by the compiler. 16 | */ 17 | /// total amount of tokens 18 | function totalSupply() external view returns (uint256); 19 | 20 | /// @param _owner The address from which the balance will be retrieved 21 | /// @return balance The balance 22 | function balanceOf(address _owner) external view returns (uint256 balance); 23 | 24 | /// @notice send `_value` token to `_to` from `msg.sender` 25 | /// @param _to The address of the recipient 26 | /// @param _value The amount of token to be transferred 27 | /// @return success Whether the transfer was successful or not 28 | function transfer(address _to, uint256 _value) external returns (bool success); 29 | 30 | /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from` 31 | /// @param _from The address of the sender 32 | /// @param _to The address of the recipient 33 | /// @param _value The amount of token to be transferred 34 | /// @return success Whether the transfer was successful or not 35 | function transferFrom(address _from, address _to, uint256 _value) external returns (bool success); 36 | 37 | /// @notice `msg.sender` approves `_spender` to spend `_value` tokens 38 | /// @param _spender The address of the account able to transfer the tokens 39 | /// @param _value The amount of tokens to be approved for transfer 40 | /// @return success Whether the approval was successful or not 41 | function approve(address _spender, uint256 _value) external returns (bool success); 42 | 43 | /// @param _owner The address of the account owning tokens 44 | /// @param _spender The address of the account able to transfer the tokens 45 | /// @return remaining Amount of remaining tokens allowed to spent 46 | function allowance(address _owner, address _spender) external view returns (uint256 remaining); 47 | 48 | // solhint-disable-next-line no-simple-event-func-name 49 | event Transfer(address indexed _from, address indexed _to, uint256 _value); 50 | event Approval(address indexed _owner, address indexed _spender, uint256 _value); 51 | event Mint(address indexed _account, uint256 _amount); 52 | event Burn(address indexed _account, uint256 _amount); 53 | } 54 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/iOVM/predeploys/iOVM_L1MessageSender.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /** 5 | * @title iOVM_L1MessageSender 6 | */ 7 | interface iOVM_L1MessageSender { 8 | 9 | /******************** 10 | * Public Functions * 11 | ********************/ 12 | 13 | function getL1MessageSender() external view returns (address _l1MessageSender); 14 | } 15 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/iOVM/predeploys/iOVM_L2ToL1MessagePasser.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /** 5 | * @title iOVM_L2ToL1MessagePasser 6 | */ 7 | interface iOVM_L2ToL1MessagePasser { 8 | 9 | /********** 10 | * Events * 11 | **********/ 12 | 13 | event L2ToL1Message( 14 | uint256 _nonce, 15 | address _sender, 16 | bytes _data 17 | ); 18 | 19 | 20 | /******************** 21 | * Public Functions * 22 | ********************/ 23 | 24 | function passMessageToL1(bytes calldata _message) external; 25 | } 26 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/iOVM/verification/iOVM_FraudVerifier.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | /* Library Imports */ 6 | import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol"; 7 | 8 | /* Interface Imports */ 9 | import { iOVM_StateTransitioner } from "./iOVM_StateTransitioner.sol"; 10 | 11 | /** 12 | * @title iOVM_FraudVerifier 13 | */ 14 | interface iOVM_FraudVerifier { 15 | 16 | /********** 17 | * Events * 18 | **********/ 19 | 20 | event FraudProofInitialized( 21 | bytes32 _preStateRoot, 22 | uint256 _preStateRootIndex, 23 | bytes32 _transactionHash, 24 | address _who 25 | ); 26 | 27 | event FraudProofFinalized( 28 | bytes32 _preStateRoot, 29 | uint256 _preStateRootIndex, 30 | bytes32 _transactionHash, 31 | address _who 32 | ); 33 | 34 | 35 | /*************************************** 36 | * Public Functions: Transition Status * 37 | ***************************************/ 38 | 39 | function getStateTransitioner(bytes32 _preStateRoot, bytes32 _txHash) external view returns (iOVM_StateTransitioner _transitioner); 40 | 41 | 42 | /**************************************** 43 | * Public Functions: Fraud Verification * 44 | ****************************************/ 45 | 46 | function initializeFraudVerification( 47 | bytes32 _preStateRoot, 48 | Lib_OVMCodec.ChainBatchHeader calldata _preStateRootBatchHeader, 49 | Lib_OVMCodec.ChainInclusionProof calldata _preStateRootProof, 50 | Lib_OVMCodec.Transaction calldata _transaction, 51 | Lib_OVMCodec.TransactionChainElement calldata _txChainElement, 52 | Lib_OVMCodec.ChainBatchHeader calldata _transactionBatchHeader, 53 | Lib_OVMCodec.ChainInclusionProof calldata _transactionProof 54 | ) external; 55 | 56 | function finalizeFraudVerification( 57 | bytes32 _preStateRoot, 58 | Lib_OVMCodec.ChainBatchHeader calldata _preStateRootBatchHeader, 59 | Lib_OVMCodec.ChainInclusionProof calldata _preStateRootProof, 60 | bytes32 _txHash, 61 | bytes32 _postStateRoot, 62 | Lib_OVMCodec.ChainBatchHeader calldata _postStateRootBatchHeader, 63 | Lib_OVMCodec.ChainInclusionProof calldata _postStateRootProof 64 | ) external; 65 | } 66 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/iOVM/verification/iOVM_StateTransitioner.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | /* Library Imports */ 6 | import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol"; 7 | 8 | /** 9 | * @title iOVM_StateTransitioner 10 | */ 11 | interface iOVM_StateTransitioner { 12 | 13 | /********** 14 | * Events * 15 | **********/ 16 | 17 | event AccountCommitted( 18 | address _address 19 | ); 20 | 21 | event ContractStorageCommitted( 22 | address _address, 23 | bytes32 _key 24 | ); 25 | 26 | 27 | /********************************** 28 | * Public Functions: State Access * 29 | **********************************/ 30 | 31 | function getPreStateRoot() external view returns (bytes32 _preStateRoot); 32 | function getPostStateRoot() external view returns (bytes32 _postStateRoot); 33 | function isComplete() external view returns (bool _complete); 34 | 35 | 36 | /*********************************** 37 | * Public Functions: Pre-Execution * 38 | ***********************************/ 39 | 40 | function proveContractState( 41 | address _ovmContractAddress, 42 | address _ethContractAddress, 43 | bytes calldata _stateTrieWitness 44 | ) external; 45 | 46 | function proveStorageSlot( 47 | address _ovmContractAddress, 48 | bytes32 _key, 49 | bytes calldata _storageTrieWitness 50 | ) external; 51 | 52 | 53 | /******************************* 54 | * Public Functions: Execution * 55 | *******************************/ 56 | 57 | function applyTransaction( 58 | Lib_OVMCodec.Transaction calldata _transaction 59 | ) external; 60 | 61 | 62 | /************************************ 63 | * Public Functions: Post-Execution * 64 | ************************************/ 65 | 66 | function commitContractState( 67 | address _ovmContractAddress, 68 | bytes calldata _stateTrieWitness 69 | ) external; 70 | 71 | function commitStorageSlot( 72 | address _ovmContractAddress, 73 | bytes32 _key, 74 | bytes calldata _storageTrieWitness 75 | ) external; 76 | 77 | 78 | /********************************** 79 | * Public Functions: Finalization * 80 | **********************************/ 81 | 82 | function completeTransition() external; 83 | } 84 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/iOVM/verification/iOVM_StateTransitionerFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /* Contract Imports */ 5 | import { iOVM_StateTransitioner } from "./iOVM_StateTransitioner.sol"; 6 | 7 | /** 8 | * @title iOVM_StateTransitionerFactory 9 | */ 10 | interface iOVM_StateTransitionerFactory { 11 | 12 | /*************************************** 13 | * Public Functions: Contract Creation * 14 | ***************************************/ 15 | 16 | function create( 17 | address _proxyManager, 18 | uint256 _stateTransitionIndex, 19 | bytes32 _preStateRoot, 20 | bytes32 _transactionHash 21 | ) 22 | external 23 | returns ( 24 | iOVM_StateTransitioner _ovmStateTransitioner 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/libraries/bridge/OVM_CrossDomainEnabled.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | /* Interface Imports */ 4 | import { iAbs_BaseCrossDomainMessenger } from "../../iOVM/bridge/messaging/iAbs_BaseCrossDomainMessenger.sol"; 5 | 6 | /** 7 | * @title OVM_CrossDomainEnabled 8 | * @dev Helper contract for contracts performing cross-domain communications 9 | * 10 | * Compiler used: defined by inheriting contract 11 | * Runtime target: defined by inheriting contract 12 | */ 13 | contract OVM_CrossDomainEnabled { 14 | // Messenger contract used to send and recieve messages from the other domain. 15 | address public messenger; 16 | 17 | /*************** 18 | * Constructor * 19 | ***************/ 20 | constructor( 21 | address _messenger 22 | ) { 23 | messenger = _messenger; 24 | } 25 | 26 | /********************** 27 | * Function Modifiers * 28 | **********************/ 29 | 30 | /** 31 | * @notice Enforces that the modified function is only callable by a specific cross-domain account. 32 | * @param _sourceDomainAccount The only account on the originating domain which is authenticated to call this function. 33 | */ 34 | modifier onlyFromCrossDomainAccount( 35 | address _sourceDomainAccount 36 | ) { 37 | require( 38 | msg.sender == address(getCrossDomainMessenger()), 39 | "OVM_XCHAIN: messenger contract unauthenticated" 40 | ); 41 | 42 | require( 43 | getCrossDomainMessenger().xDomainMessageSender() == _sourceDomainAccount, 44 | "OVM_XCHAIN: wrong sender of cross-domain message" 45 | ); 46 | 47 | _; 48 | } 49 | 50 | /********************** 51 | * Internal Functions * 52 | **********************/ 53 | 54 | /** 55 | * @notice Gets the messenger, usually from storage. This function is exposed in case a child contract needs to override. 56 | * @return The address of the cross-domain messenger contract which should be used. 57 | */ 58 | function getCrossDomainMessenger() 59 | internal 60 | virtual 61 | returns( 62 | iAbs_BaseCrossDomainMessenger 63 | ) 64 | { 65 | return iAbs_BaseCrossDomainMessenger(messenger); 66 | } 67 | 68 | /** 69 | * @notice Sends a message to an account on another domain 70 | * @param _crossDomainTarget The intended recipient on the destination domain 71 | * @param _data The data to send to the target (usually calldata to a function with `onlyFromCrossDomainAccount()`) 72 | * @param _gasLimit The gasLimit for the receipt of the message on the target domain. 73 | */ 74 | function sendCrossDomainMessage( 75 | address _crossDomainTarget, 76 | bytes memory _data, 77 | uint32 _gasLimit 78 | ) internal { 79 | getCrossDomainMessenger().sendMessage(_crossDomainTarget, _data, _gasLimit); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/libraries/resolver/Lib_AddressManager.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /* Contract Imports */ 5 | import { Ownable } from "./Lib_Ownable.sol"; 6 | 7 | /** 8 | * @title Lib_AddressManager 9 | */ 10 | contract Lib_AddressManager is Ownable { 11 | 12 | /********** 13 | * Events * 14 | **********/ 15 | 16 | event AddressSet( 17 | string _name, 18 | address _newAddress 19 | ); 20 | 21 | 22 | /************* 23 | * Variables * 24 | *************/ 25 | 26 | mapping (bytes32 => address) private addresses; 27 | 28 | 29 | /******************** 30 | * Public Functions * 31 | ********************/ 32 | 33 | /** 34 | * Changes the address associated with a particular name. 35 | * @param _name String name to associate an address with. 36 | * @param _address Address to associate with the name. 37 | */ 38 | function setAddress( 39 | string memory _name, 40 | address _address 41 | ) 42 | public 43 | onlyOwner 44 | { 45 | addresses[_getNameHash(_name)] = _address; 46 | 47 | emit AddressSet( 48 | _name, 49 | _address 50 | ); 51 | } 52 | 53 | /** 54 | * Retrieves the address associated with a given name. 55 | * @param _name Name to retrieve an address for. 56 | * @return Address associated with the given name. 57 | */ 58 | function getAddress( 59 | string memory _name 60 | ) 61 | public 62 | view 63 | returns ( 64 | address 65 | ) 66 | { 67 | return addresses[_getNameHash(_name)]; 68 | } 69 | 70 | 71 | /********************** 72 | * Internal Functions * 73 | **********************/ 74 | 75 | /** 76 | * Computes the hash of a name. 77 | * @param _name Name to compute a hash for. 78 | * @return Hash of the given name. 79 | */ 80 | function _getNameHash( 81 | string memory _name 82 | ) 83 | internal 84 | pure 85 | returns ( 86 | bytes32 87 | ) 88 | { 89 | return keccak256(abi.encodePacked(_name)); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/libraries/resolver/Lib_AddressResolver.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /* Library Imports */ 5 | import { Lib_AddressManager } from "./Lib_AddressManager.sol"; 6 | 7 | /** 8 | * @title Lib_AddressResolver 9 | */ 10 | abstract contract Lib_AddressResolver { 11 | 12 | /************* 13 | * Variables * 14 | *************/ 15 | 16 | Lib_AddressManager public libAddressManager; 17 | 18 | 19 | /*************** 20 | * Constructor * 21 | ***************/ 22 | 23 | /** 24 | * @param _libAddressManager Address of the Lib_AddressManager. 25 | */ 26 | constructor( 27 | address _libAddressManager 28 | ) { 29 | libAddressManager = Lib_AddressManager(_libAddressManager); 30 | } 31 | 32 | 33 | /******************** 34 | * Public Functions * 35 | ********************/ 36 | 37 | /** 38 | * Resolves the address associated with a given name. 39 | * @param _name Name to resolve an address for. 40 | * @return Address associated with the given name. 41 | */ 42 | function resolve( 43 | string memory _name 44 | ) 45 | public 46 | view 47 | returns ( 48 | address 49 | ) 50 | { 51 | return libAddressManager.getAddress(_name); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/libraries/resolver/Lib_Ownable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /** 5 | * @title Ownable 6 | * @dev Adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol 7 | */ 8 | abstract contract Ownable { 9 | 10 | /************* 11 | * Variables * 12 | *************/ 13 | 14 | address public owner; 15 | 16 | 17 | /********** 18 | * Events * 19 | **********/ 20 | 21 | event OwnershipTransferred( 22 | address indexed previousOwner, 23 | address indexed newOwner 24 | ); 25 | 26 | 27 | /*************** 28 | * Constructor * 29 | ***************/ 30 | 31 | constructor() { 32 | owner = msg.sender; 33 | emit OwnershipTransferred(address(0), owner); 34 | } 35 | 36 | 37 | /********************** 38 | * Function Modifiers * 39 | **********************/ 40 | 41 | modifier onlyOwner() { 42 | require( 43 | owner == msg.sender, 44 | "Ownable: caller is not the owner" 45 | ); 46 | _; 47 | } 48 | 49 | 50 | /******************** 51 | * Public Functions * 52 | ********************/ 53 | 54 | /** 55 | * Sets the owner of this contract to the zero address, effectively renouncing ownership 56 | * completely. Can only be called by the current owner of this contract. 57 | */ 58 | function renounceOwnership() 59 | public 60 | virtual 61 | onlyOwner 62 | { 63 | emit OwnershipTransferred(owner, address(0)); 64 | owner = address(0); 65 | } 66 | 67 | /** 68 | * Transfers ownership of this contract to a new address. Can only be called by the current 69 | * owner of this contract. 70 | * @param _newOwner Address of the new contract owner. 71 | */ 72 | function transferOwnership( 73 | address _newOwner 74 | ) 75 | public 76 | virtual 77 | onlyOwner 78 | { 79 | require( 80 | _newOwner != address(0), 81 | "Ownable: new owner cannot be the zero address" 82 | ); 83 | 84 | emit OwnershipTransferred(owner, _newOwner); 85 | owner = _newOwner; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/libraries/resolver/Lib_ResolvedDelegateProxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /* Library Imports */ 5 | import { Lib_AddressManager } from "./Lib_AddressManager.sol"; 6 | 7 | /** 8 | * @title Lib_ResolvedDelegateProxy 9 | */ 10 | contract Lib_ResolvedDelegateProxy { 11 | 12 | /************* 13 | * Variables * 14 | *************/ 15 | 16 | // Using mappings to store fields to avoid overwriting storage slots in the 17 | // implementation contract. For example, instead of storing these fields at 18 | // storage slot `0` & `1`, they are stored at `keccak256(key + slot)`. 19 | // See: https://solidity.readthedocs.io/en/v0.7.0/internals/layout_in_storage.html 20 | // NOTE: Do not use this code in your own contract system. 21 | // There is a known flaw in this contract, and we will remove it from the repository 22 | // in the near future. Due to the very limited way that we are using it, this flaw is 23 | // not an issue in our system. 24 | mapping (address => string) private implementationName; 25 | mapping (address => Lib_AddressManager) private addressManager; 26 | 27 | 28 | /*************** 29 | * Constructor * 30 | ***************/ 31 | 32 | /** 33 | * @param _libAddressManager Address of the Lib_AddressManager. 34 | * @param _implementationName implementationName of the contract to proxy to. 35 | */ 36 | constructor( 37 | address _libAddressManager, 38 | string memory _implementationName 39 | ) 40 | { 41 | addressManager[address(this)] = Lib_AddressManager(_libAddressManager); 42 | implementationName[address(this)] = _implementationName; 43 | } 44 | 45 | 46 | /********************* 47 | * Fallback Function * 48 | *********************/ 49 | 50 | fallback() 51 | external 52 | payable 53 | { 54 | address target = addressManager[address(this)].getAddress( 55 | (implementationName[address(this)]) 56 | ); 57 | 58 | require( 59 | target != address(0), 60 | "Target address must be initialized." 61 | ); 62 | 63 | (bool success, bytes memory returndata) = target.delegatecall(msg.data); 64 | 65 | if (success == true) { 66 | assembly { 67 | return(add(returndata, 0x20), mload(returndata)) 68 | } 69 | } else { 70 | assembly { 71 | revert(add(returndata, 0x20), mload(returndata)) 72 | } 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/libraries/standards/IUniswapV2ERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.5.16 <0.8.0; 3 | 4 | interface IUniswapV2ERC20 { 5 | event Approval(address indexed owner, address indexed spender, uint value); 6 | event Transfer(address indexed from, address indexed to, uint value); 7 | 8 | function name() external view returns (string memory); 9 | function symbol() external view returns (string memory); 10 | function decimals() external view returns (uint8); 11 | function totalSupply() external view returns (uint); 12 | function balanceOf(address owner) external view returns (uint); 13 | function allowance(address owner, address spender) external view returns (uint); 14 | 15 | function approve(address spender, uint value) external returns (bool); 16 | function transfer(address to, uint value) external returns (bool); 17 | function transferFrom(address from, address to, uint value) external returns (bool); 18 | 19 | function DOMAIN_SEPARATOR() external view returns (bytes32); 20 | function PERMIT_TYPEHASH() external pure returns (bytes32); 21 | function nonces(address owner) external view returns (uint); 22 | 23 | function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; 24 | } 25 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/libraries/standards/UniSafeMath.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.5.16 <0.8.0; 3 | 4 | // a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math) 5 | 6 | library UniSafeMath { 7 | function add(uint x, uint y) internal pure returns (uint z) { 8 | require((z = x + y) >= x, 'ds-math-add-overflow'); 9 | } 10 | 11 | function sub(uint x, uint y) internal pure returns (uint z) { 12 | require((z = x - y) <= x, 'ds-math-sub-underflow'); 13 | } 14 | 15 | function mul(uint x, uint y) internal pure returns (uint z) { 16 | require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/libraries/utils/Lib_Bytes32Utils.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /** 5 | * @title Lib_Byte32Utils 6 | */ 7 | library Lib_Bytes32Utils { 8 | 9 | /********************** 10 | * Internal Functions * 11 | **********************/ 12 | 13 | /** 14 | * Converts a bytes32 value to a boolean. Anything non-zero will be converted to "true." 15 | * @param _in Input bytes32 value. 16 | * @return Bytes32 as a boolean. 17 | */ 18 | function toBool( 19 | bytes32 _in 20 | ) 21 | internal 22 | pure 23 | returns ( 24 | bool 25 | ) 26 | { 27 | return _in != 0; 28 | } 29 | 30 | /** 31 | * Converts a boolean to a bytes32 value. 32 | * @param _in Input boolean value. 33 | * @return Boolean as a bytes32. 34 | */ 35 | function fromBool( 36 | bool _in 37 | ) 38 | internal 39 | pure 40 | returns ( 41 | bytes32 42 | ) 43 | { 44 | return bytes32(uint256(_in ? 1 : 0)); 45 | } 46 | 47 | /** 48 | * Converts a bytes32 value to an address. Takes the *last* 20 bytes. 49 | * @param _in Input bytes32 value. 50 | * @return Bytes32 as an address. 51 | */ 52 | function toAddress( 53 | bytes32 _in 54 | ) 55 | internal 56 | pure 57 | returns ( 58 | address 59 | ) 60 | { 61 | return address(uint160(uint256(_in))); 62 | } 63 | 64 | /** 65 | * Converts an address to a bytes32. 66 | * @param _in Input address value. 67 | * @return Address as a bytes32. 68 | */ 69 | function fromAddress( 70 | address _in 71 | ) 72 | internal 73 | pure 74 | returns ( 75 | bytes32 76 | ) 77 | { 78 | return bytes32(uint256(_in)); 79 | } 80 | 81 | /** 82 | * Removes the leading zeros from a bytes32 value and returns a new (smaller) bytes value. 83 | * @param _in Input bytes32 value. 84 | * @return Bytes32 without any leading zeros. 85 | */ 86 | function removeLeadingZeros( 87 | bytes32 _in 88 | ) 89 | internal 90 | pure 91 | returns ( 92 | bytes memory 93 | ) 94 | { 95 | bytes memory out; 96 | 97 | assembly { 98 | // Figure out how many leading zero bytes to remove. 99 | let shift := 0 100 | for { let i := 0 } and(lt(i, 32), eq(byte(i, _in), 0)) { i := add(i, 1) } { 101 | shift := add(shift, 1) 102 | } 103 | 104 | // Reserve some space for our output and fix the free memory pointer. 105 | out := mload(0x40) 106 | mstore(0x40, add(out, 0x40)) 107 | 108 | // Shift the value and store it into the output bytes. 109 | mstore(add(out, 0x20), shl(mul(shift, 8), _in)) 110 | 111 | // Store the new size (with leading zero bytes removed) in the output byte size. 112 | mstore(out, sub(32, shift)) 113 | } 114 | 115 | return out; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/libraries/utils/Lib_ECDSAUtils.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /** 5 | * @title Lib_ECDSAUtils 6 | */ 7 | library Lib_ECDSAUtils { 8 | 9 | /************************************** 10 | * Internal Functions: ECDSA Recovery * 11 | **************************************/ 12 | 13 | /** 14 | * Recovers a signed address given a message and signature. 15 | * @param _message Message that was originally signed. 16 | * @param _isEthSignedMessage Whether or not the user used the `Ethereum Signed Message` prefix. 17 | * @param _v Signature `v` parameter. 18 | * @param _r Signature `r` parameter. 19 | * @param _s Signature `s` parameter. 20 | * @return _sender Signer address. 21 | */ 22 | function recover( 23 | bytes memory _message, 24 | bool _isEthSignedMessage, 25 | uint8 _v, 26 | bytes32 _r, 27 | bytes32 _s 28 | ) 29 | internal 30 | pure 31 | returns ( 32 | address _sender 33 | ) 34 | { 35 | bytes32 messageHash = getMessageHash(_message, _isEthSignedMessage); 36 | 37 | return ecrecover( 38 | messageHash, 39 | _v + 27, 40 | _r, 41 | _s 42 | ); 43 | } 44 | 45 | function getMessageHash( 46 | bytes memory _message, 47 | bool _isEthSignedMessage 48 | ) 49 | internal 50 | pure 51 | returns (bytes32) { 52 | if (_isEthSignedMessage) { 53 | return getEthSignedMessageHash(_message); 54 | } 55 | return getNativeMessageHash(_message); 56 | } 57 | 58 | 59 | /************************************* 60 | * Private Functions: ECDSA Recovery * 61 | *************************************/ 62 | 63 | /** 64 | * Gets the native message hash (simple keccak256) for a message. 65 | * @param _message Message to hash. 66 | * @return _messageHash Native message hash. 67 | */ 68 | function getNativeMessageHash( 69 | bytes memory _message 70 | ) 71 | private 72 | pure 73 | returns ( 74 | bytes32 _messageHash 75 | ) 76 | { 77 | return keccak256(_message); 78 | } 79 | 80 | /** 81 | * Gets the hash of a message with the `Ethereum Signed Message` prefix. 82 | * @param _message Message to hash. 83 | * @return _messageHash Prefixed message hash. 84 | */ 85 | function getEthSignedMessageHash( 86 | bytes memory _message 87 | ) 88 | private 89 | pure 90 | returns ( 91 | bytes32 _messageHash 92 | ) 93 | { 94 | bytes memory prefix = "\x19Ethereum Signed Message:\n32"; 95 | bytes32 messageHash = keccak256(_message); 96 | return keccak256(abi.encodePacked(prefix, messageHash)); 97 | } 98 | } -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/libraries/utils/Lib_ErrorUtils.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | /** 6 | * @title Lib_ErrorUtils 7 | */ 8 | library Lib_ErrorUtils { 9 | 10 | /********************** 11 | * Internal Functions * 12 | **********************/ 13 | 14 | /** 15 | * Encodes an error string into raw solidity-style revert data. 16 | * (i.e. ascii bytes, prefixed with bytes4(keccak("Error(string))")) 17 | * Ref: https://docs.soliditylang.org/en/v0.8.2/control-structures.html?highlight=Error(string)#panic-via-assert-and-error-via-require 18 | * @param _reason Reason for the reversion. 19 | * @return Standard solidity revert data for the given reason. 20 | */ 21 | function encodeRevertString( 22 | string memory _reason 23 | ) 24 | internal 25 | pure 26 | returns ( 27 | bytes memory 28 | ) 29 | { 30 | return abi.encodeWithSignature( 31 | "Error(string)", 32 | _reason 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/libraries/utils/Lib_Math.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /** 5 | * @title Lib_Math 6 | */ 7 | library Lib_Math { 8 | 9 | /********************** 10 | * Internal Functions * 11 | **********************/ 12 | 13 | /** 14 | * Calculates the minumum of two numbers. 15 | * @param _x First number to compare. 16 | * @param _y Second number to compare. 17 | * @return Lesser of the two numbers. 18 | */ 19 | function min( 20 | uint256 _x, 21 | uint256 _y 22 | ) 23 | internal 24 | pure 25 | returns ( 26 | uint256 27 | ) 28 | { 29 | if (_x < _y) { 30 | return _x; 31 | } 32 | 33 | return _y; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/libraries/utils/Lib_ReentrancyGuard.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /** 5 | * @dev Contract module that helps prevent reentrant calls to a function. 6 | * 7 | * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier 8 | * available, which can be applied to functions to make sure there are no nested 9 | * (reentrant) calls to them. 10 | * 11 | * Note that because there is a single `nonReentrant` guard, functions marked as 12 | * `nonReentrant` may not call one another. This can be worked around by making 13 | * those functions `private`, and then adding `external` `nonReentrant` entry 14 | * points to them. 15 | * 16 | * TIP: If you would like to learn more about reentrancy and alternative ways 17 | * to protect against it, check out our blog post 18 | * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. 19 | */ 20 | abstract contract Lib_ReentrancyGuard { 21 | // Booleans are more expensive than uint256 or any type that takes up a full 22 | // word because each write operation emits an extra SLOAD to first read the 23 | // slot's contents, replace the bits taken up by the boolean, and then write 24 | // back. This is the compiler's defense against contract upgrades and 25 | // pointer aliasing, and it cannot be disabled. 26 | 27 | // The values being non-zero value makes deployment a bit more expensive, 28 | // but in exchange the refund on every call to nonReentrant will be lower in 29 | // amount. Since refunds are capped to a percentage of the total 30 | // transaction's gas, it is best to keep them low in cases like this one, to 31 | // increase the likelihood of the full refund coming into effect. 32 | uint256 private constant _NOT_ENTERED = 1; 33 | uint256 private constant _ENTERED = 2; 34 | 35 | uint256 private _status; 36 | 37 | constructor () { 38 | _status = _NOT_ENTERED; 39 | } 40 | 41 | /** 42 | * @dev Prevents a contract from calling itself, directly or indirectly. 43 | * Calling a `nonReentrant` function from another `nonReentrant` 44 | * function is not supported. It is possible to prevent this from happening 45 | * by making the `nonReentrant` function external, and make it call a 46 | * `private` function that does the actual work. 47 | */ 48 | modifier nonReentrant() { 49 | // On the first call to nonReentrant, _notEntered will be true 50 | require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); 51 | 52 | // Any calls to nonReentrant after this point will fail 53 | _status = _ENTERED; 54 | 55 | _; 56 | 57 | // By storing the original value once again, a refund is triggered (see 58 | // https://eips.ethereum.org/EIPS/eip-2200) 59 | _status = _NOT_ENTERED; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/mockOVM/accounts/mockOVM_ECDSAContractAccount.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | /* Interface Imports */ 6 | import { iOVM_ECDSAContractAccount } from "../../iOVM/accounts/iOVM_ECDSAContractAccount.sol"; 7 | 8 | /* Library Imports */ 9 | import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol"; 10 | import { Lib_ECDSAUtils } from "../../libraries/utils/Lib_ECDSAUtils.sol"; 11 | import { Lib_SafeExecutionManagerWrapper } from "../../libraries/wrappers/Lib_SafeExecutionManagerWrapper.sol"; 12 | 13 | /** 14 | * @title mockOVM_ECDSAContractAccount 15 | */ 16 | contract mockOVM_ECDSAContractAccount is iOVM_ECDSAContractAccount { 17 | 18 | /******************** 19 | * Public Functions * 20 | ********************/ 21 | 22 | /** 23 | * Executes a signed transaction. 24 | * @param _transaction Signed EOA transaction. 25 | * @param _signatureType Hashing scheme used for the transaction (e.g., ETH signed message). 26 | * param _v Signature `v` parameter. 27 | * param _r Signature `r` parameter. 28 | * param _s Signature `s` parameter. 29 | * @return _success Whether or not the call returned (rather than reverted). 30 | * @return _returndata Data returned by the call. 31 | */ 32 | function execute( 33 | bytes memory _transaction, 34 | Lib_OVMCodec.EOASignatureType _signatureType, 35 | uint8, // _v, 36 | bytes32, // _r, 37 | bytes32 // _s 38 | ) 39 | override 40 | public 41 | returns ( 42 | bool _success, 43 | bytes memory _returndata 44 | ) 45 | { 46 | bool isEthSign = _signatureType == Lib_OVMCodec.EOASignatureType.ETH_SIGNED_MESSAGE; 47 | Lib_OVMCodec.EIP155Transaction memory decodedTx = Lib_OVMCodec.decodeEIP155Transaction(_transaction, isEthSign); 48 | 49 | // Need to make sure that the transaction nonce is right. 50 | Lib_SafeExecutionManagerWrapper.safeREQUIRE( 51 | decodedTx.nonce == Lib_SafeExecutionManagerWrapper.safeGETNONCE(), 52 | "Transaction nonce does not match the expected nonce." 53 | ); 54 | 55 | // Contract creations are signalled by sending a transaction to the zero address. 56 | if (decodedTx.to == address(0)) { 57 | (address created, ) = Lib_SafeExecutionManagerWrapper.safeCREATE( 58 | decodedTx.gasLimit, 59 | decodedTx.data 60 | ); 61 | 62 | // If the created address is the ZERO_ADDRESS then we know the deployment failed, though not why 63 | return (created != address(0), abi.encode(created)); 64 | } else { 65 | // We only want to bump the nonce for `ovmCALL` because `ovmCREATE` automatically bumps 66 | // the nonce of the calling account. Normally an EOA would bump the nonce for both 67 | // cases, but since this is a contract we'd end up bumping the nonce twice. 68 | Lib_SafeExecutionManagerWrapper.safeINCREMENTNONCE(); 69 | 70 | return Lib_SafeExecutionManagerWrapper.safeCALL( 71 | decodedTx.gasLimit, 72 | decodedTx.to, 73 | decodedTx.data 74 | ); 75 | } 76 | } 77 | 78 | function qall( 79 | uint256 _gasLimit, 80 | address _to, 81 | bytes memory _data 82 | ) 83 | public 84 | returns ( 85 | bool _success, 86 | bytes memory _returndata 87 | ) 88 | { 89 | return Lib_SafeExecutionManagerWrapper.safeCALL( 90 | _gasLimit, 91 | _to, 92 | _data 93 | ); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/mockOVM/bridge/mockOVM_GenericCrossDomainMessenger.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | /** 6 | * @title mockOVM_GenericCrossDomainMessenger 7 | * @dev An experimental alternative mock for local testing. 8 | */ 9 | contract mockOVM_GenericCrossDomainMessenger { 10 | address public xDomainMessageSender; 11 | 12 | event SentMessage( 13 | address _sender, 14 | address _target, 15 | bytes _message, 16 | uint256 _gasLimit 17 | ); 18 | 19 | function sendMessage( 20 | address _target, 21 | bytes memory _message, 22 | uint32 _gasLimit 23 | ) 24 | public 25 | { 26 | emit SentMessage( 27 | msg.sender, 28 | _target, 29 | _message, 30 | _gasLimit 31 | ); 32 | } 33 | 34 | function relayMessage( 35 | address _sender, 36 | address _target, 37 | bytes memory _message, 38 | uint256 _gasLimit 39 | ) 40 | public 41 | { 42 | xDomainMessageSender = _sender; 43 | (bool success, ) = _target.call{gas: _gasLimit}(_message); 44 | require(success, "Cross-domain message call reverted. Did you set your gas limit high enough?"); 45 | xDomainMessageSender = address(0); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /contracts/optimistic-ethereum/mockOVM/verification/mockOVM_BondManager.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /* Interface Imports */ 5 | import { iOVM_BondManager } from "../../iOVM/verification/iOVM_BondManager.sol"; 6 | 7 | /* Contract Imports */ 8 | import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol"; 9 | 10 | /** 11 | * @title mockOVM_BondManager 12 | */ 13 | contract mockOVM_BondManager is iOVM_BondManager, Lib_AddressResolver { 14 | constructor( 15 | address _libAddressManager 16 | ) 17 | Lib_AddressResolver(_libAddressManager) 18 | {} 19 | 20 | function recordGasSpent( 21 | bytes32 _preStateRoot, 22 | bytes32 _txHash, 23 | address _who, 24 | uint256 _gasSpent 25 | ) 26 | override 27 | public 28 | {} 29 | 30 | function finalize( 31 | bytes32 _preStateRoot, 32 | address _publisher, 33 | uint256 _timestamp 34 | ) 35 | override 36 | public 37 | {} 38 | 39 | function deposit() 40 | override 41 | public 42 | {} 43 | 44 | function startWithdrawal() 45 | override 46 | public 47 | {} 48 | 49 | function finalizeWithdrawal() 50 | override 51 | public 52 | {} 53 | 54 | function claim( 55 | address _who 56 | ) 57 | override 58 | public 59 | {} 60 | 61 | function isCollateralized( 62 | address _who 63 | ) 64 | override 65 | public 66 | view 67 | returns ( 68 | bool 69 | ) 70 | { 71 | // Only authenticate sequencer to submit state root batches. 72 | return _who == resolve("OVM_Proposer"); 73 | } 74 | 75 | function getGasSpent( 76 | bytes32, // _preStateRoot, 77 | address // _who 78 | ) 79 | override 80 | public 81 | pure 82 | returns ( 83 | uint256 84 | ) 85 | { 86 | return 0; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /contracts/test-helpers/Helper_GasMeasurer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | // SPDX-License-Identifier: MIT 3 | pragma solidity >0.5.0 <0.8.0; 4 | 5 | contract Helper_GasMeasurer { 6 | function measureCallGas( 7 | address _target, 8 | bytes memory _data 9 | ) 10 | public 11 | returns ( uint256 ) 12 | { 13 | uint256 gasBefore; 14 | uint256 gasAfter; 15 | 16 | uint256 calldataStart; 17 | uint256 calldataLength; 18 | assembly { 19 | calldataStart := add(_data,0x20) 20 | calldataLength := mload(_data) 21 | } 22 | 23 | bool success; 24 | assembly { 25 | gasBefore := gas() 26 | success := call(gas(), _target, 0, calldataStart, calldataLength, 0, 0) 27 | gasAfter := gas() 28 | } 29 | require(success, "Call failed, but calls we want to measure gas for should succeed!"); 30 | 31 | return gasBefore - gasAfter; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /contracts/test-helpers/Helper_ModifiableStorage.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | contract Helper_ModifiableStorage { 5 | mapping (address => address) private target; 6 | 7 | constructor( 8 | address _target 9 | ) 10 | { 11 | target[address(this)] = _target; 12 | } 13 | 14 | fallback() 15 | external 16 | { 17 | (bool success, bytes memory returndata) = target[address(this)].delegatecall(msg.data); 18 | 19 | if (success) { 20 | assembly { 21 | return(add(returndata, 0x20), mload(returndata)) 22 | } 23 | } else { 24 | assembly { 25 | revert(add(returndata, 0x20), mload(returndata)) 26 | } 27 | } 28 | } 29 | 30 | function __setStorageSlot( 31 | bytes32 _key, 32 | bytes32 _value 33 | ) 34 | public 35 | { 36 | assembly { 37 | sstore(_key, _value) 38 | } 39 | } 40 | 41 | function __getStorageSlot( 42 | bytes32 _key 43 | ) 44 | public 45 | view 46 | returns ( 47 | bytes32 _value 48 | ) 49 | { 50 | bytes32 value; 51 | assembly { 52 | value := sload(_key) 53 | } 54 | return value; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /contracts/test-helpers/Helper_PrecompileCaller.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | import { Helper_SimpleProxy } from "./Helper_SimpleProxy.sol"; 5 | 6 | contract Helper_PredeployCaller is Helper_SimpleProxy { 7 | function callPredeploy( 8 | address _predeploy, 9 | bytes memory _data 10 | ) 11 | public 12 | { 13 | if (msg.sender == owner) { 14 | makeExternalCall(_predeploy, _data); 15 | } else { 16 | makeExternalCall(target, msg.data); 17 | } 18 | } 19 | 20 | function callPredeployAbi( 21 | address _predeploy, 22 | bytes memory _data 23 | ) 24 | public 25 | returns ( 26 | bytes memory 27 | ) 28 | { 29 | 30 | bool success; 31 | bytes memory returndata; 32 | if (msg.sender == owner) { 33 | (success, returndata) = _predeploy.call(_data); 34 | } else { 35 | (success, returndata) = target.call(msg.data); 36 | } 37 | require(success, "Predeploy call reverted"); 38 | return returndata; 39 | } 40 | 41 | function getL1MessageSender( 42 | address _predeploy, 43 | bytes memory _data 44 | ) 45 | public 46 | returns ( 47 | address 48 | ) 49 | { 50 | callPredeploy(_predeploy, _data); 51 | return address(0); // unused: silence compiler 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /contracts/test-helpers/Helper_SimpleProxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | contract Helper_SimpleProxy { 5 | address internal owner; 6 | address internal target; 7 | 8 | constructor() 9 | { 10 | owner = msg.sender; 11 | } 12 | 13 | fallback() 14 | external 15 | { 16 | makeExternalCall(target, msg.data); 17 | } 18 | 19 | function setTarget( 20 | address _target 21 | ) 22 | public 23 | { 24 | if (msg.sender == owner) { 25 | target = _target; 26 | } else { 27 | makeExternalCall(target, msg.data); 28 | } 29 | } 30 | 31 | function makeExternalCall( 32 | address _target, 33 | bytes memory _calldata 34 | ) 35 | internal 36 | { 37 | (bool success, bytes memory returndata) = _target.call(_calldata); 38 | 39 | if (success) { 40 | assembly { 41 | return(add(returndata, 0x20), mload(returndata)) 42 | } 43 | } else { 44 | assembly { 45 | revert(add(returndata, 0x20), mload(returndata)) 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /contracts/test-helpers/Mock_FraudVerifier.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | import { OVM_BondManager } from "./../optimistic-ethereum/OVM/verification/OVM_BondManager.sol"; 5 | 6 | contract Mock_FraudVerifier { 7 | OVM_BondManager bondManager; 8 | 9 | mapping (bytes32 => address) transitioners; 10 | 11 | function setBondManager(OVM_BondManager _bondManager) public { 12 | bondManager = _bondManager; 13 | } 14 | 15 | function setStateTransitioner(bytes32 preStateRoot, bytes32 txHash, address addr) public { 16 | transitioners[keccak256(abi.encodePacked(preStateRoot, txHash))] = addr; 17 | } 18 | 19 | function getStateTransitioner( 20 | bytes32 _preStateRoot, 21 | bytes32 _txHash 22 | ) 23 | public 24 | view 25 | returns ( 26 | address 27 | ) 28 | { 29 | return transitioners[keccak256(abi.encodePacked(_preStateRoot, _txHash))]; 30 | } 31 | 32 | function finalize(bytes32 _preStateRoot, address publisher, uint256 timestamp) public { 33 | bondManager.finalize(_preStateRoot, publisher, timestamp); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /contracts/test-helpers/TestERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | // a test ERC20 token with an open mint function 5 | contract TestERC20 { 6 | using SafeMath for uint; 7 | 8 | string public constant name = 'Test'; 9 | string public constant symbol = 'TST'; 10 | uint8 public constant decimals = 18; 11 | uint256 public totalSupply; 12 | mapping(address => uint) public balanceOf; 13 | mapping(address => mapping(address => uint)) public allowance; 14 | 15 | event Approval(address indexed owner, address indexed spender, uint256 value); 16 | event Transfer(address indexed from, address indexed to, uint256 value); 17 | 18 | constructor() {} 19 | 20 | function mint(address to, uint256 value) public { 21 | totalSupply = totalSupply.add(value); 22 | balanceOf[to] = balanceOf[to].add(value); 23 | emit Transfer(address(0), to, value); 24 | } 25 | 26 | function _approve(address owner, address spender, uint256 value) private { 27 | allowance[owner][spender] = value; 28 | emit Approval(owner, spender, value); 29 | } 30 | 31 | function _transfer(address from, address to, uint256 value) private { 32 | balanceOf[from] = balanceOf[from].sub(value); 33 | balanceOf[to] = balanceOf[to].add(value); 34 | emit Transfer(from, to, value); 35 | } 36 | 37 | function approve(address spender, uint256 value) external returns (bool) { 38 | _approve(msg.sender, spender, value); 39 | return true; 40 | } 41 | 42 | function transfer(address to, uint256 value) external returns (bool) { 43 | _transfer(msg.sender, to, value); 44 | return true; 45 | } 46 | 47 | function transferFrom(address from, address to, uint256 value) external returns (bool) { 48 | if (allowance[from][msg.sender] != uint(-1)) { 49 | allowance[from][msg.sender] = allowance[from][msg.sender].sub(value); 50 | } 51 | _transfer(from, to, value); 52 | return true; 53 | } 54 | } 55 | 56 | library SafeMath { 57 | function add(uint256 x, uint256 y) internal pure returns (uint256 z) { 58 | require((z = x + y) >= x, 'ds-math-add-overflow'); 59 | } 60 | 61 | function sub(uint256 x, uint256 y) internal pure returns (uint256 z) { 62 | require((z = x - y) <= x, 'ds-math-sub-underflow'); 63 | } 64 | 65 | function mul(uint256 x, uint256 y) internal pure returns (uint256 z) { 66 | require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow'); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /contracts/test-libraries/codec/TestLib_OVMCodec.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | /* Library Imports */ 6 | import { Lib_OVMCodec } from "../../optimistic-ethereum/libraries/codec/Lib_OVMCodec.sol"; 7 | 8 | /** 9 | * @title TestLib_OVMCodec 10 | */ 11 | contract TestLib_OVMCodec { 12 | 13 | function decodeEIP155Transaction( 14 | bytes memory _transaction, 15 | bool _isEthSignedMessage 16 | ) 17 | public 18 | pure 19 | returns ( 20 | Lib_OVMCodec.EIP155Transaction memory _decoded 21 | ) 22 | { 23 | return Lib_OVMCodec.decodeEIP155Transaction(_transaction, _isEthSignedMessage); 24 | } 25 | 26 | function encodeTransaction( 27 | Lib_OVMCodec.Transaction memory _transaction 28 | ) 29 | public 30 | pure 31 | returns ( 32 | bytes memory _encoded 33 | ) 34 | { 35 | return Lib_OVMCodec.encodeTransaction(_transaction); 36 | } 37 | 38 | function hashTransaction( 39 | Lib_OVMCodec.Transaction memory _transaction 40 | ) 41 | public 42 | pure 43 | returns ( 44 | bytes32 _hash 45 | ) 46 | { 47 | return Lib_OVMCodec.hashTransaction(_transaction); 48 | } 49 | 50 | function decompressEIP155Transaction( 51 | bytes memory _transaction 52 | ) 53 | public 54 | returns ( 55 | Lib_OVMCodec.EIP155Transaction memory _decompressed 56 | ) 57 | { 58 | return Lib_OVMCodec.decompressEIP155Transaction(_transaction); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /contracts/test-libraries/rlp/TestLib_RLPReader.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | /* Library Imports */ 6 | import { Lib_RLPReader } from "../../optimistic-ethereum/libraries/rlp/Lib_RLPReader.sol"; 7 | 8 | /** 9 | * @title TestLib_RLPReader 10 | */ 11 | contract TestLib_RLPReader { 12 | 13 | function readList( 14 | bytes memory _in 15 | ) 16 | public 17 | pure 18 | returns ( 19 | bytes[] memory 20 | ) 21 | { 22 | Lib_RLPReader.RLPItem[] memory decoded = Lib_RLPReader.readList(_in); 23 | bytes[] memory out = new bytes[](decoded.length); 24 | for (uint256 i = 0; i < out.length; i++) { 25 | out[i] = Lib_RLPReader.readRawBytes(decoded[i]); 26 | } 27 | return out; 28 | } 29 | 30 | function readString( 31 | bytes memory _in 32 | ) 33 | public 34 | pure 35 | returns ( 36 | string memory 37 | ) 38 | { 39 | return Lib_RLPReader.readString(_in); 40 | } 41 | 42 | function readBytes( 43 | bytes memory _in 44 | ) 45 | public 46 | pure 47 | returns ( 48 | bytes memory 49 | ) 50 | { 51 | return Lib_RLPReader.readBytes(_in); 52 | } 53 | 54 | function readBytes32( 55 | bytes memory _in 56 | ) 57 | public 58 | pure 59 | returns ( 60 | bytes32 61 | ) 62 | { 63 | return Lib_RLPReader.readBytes32(_in); 64 | } 65 | 66 | function readUint256( 67 | bytes memory _in 68 | ) 69 | public 70 | pure 71 | returns ( 72 | uint256 73 | ) 74 | { 75 | return Lib_RLPReader.readUint256(_in); 76 | } 77 | 78 | function readBool( 79 | bytes memory _in 80 | ) 81 | public 82 | pure 83 | returns ( 84 | bool 85 | ) 86 | { 87 | return Lib_RLPReader.readBool(_in); 88 | } 89 | 90 | function readAddress( 91 | bytes memory _in 92 | ) 93 | public 94 | pure 95 | returns ( 96 | address 97 | ) 98 | { 99 | return Lib_RLPReader.readAddress(_in); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /contracts/test-libraries/rlp/TestLib_RLPWriter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | /* Library Imports */ 6 | import { Lib_RLPWriter } from "../../optimistic-ethereum/libraries/rlp/Lib_RLPWriter.sol"; 7 | import { TestERC20 } from "../../test-helpers/TestERC20.sol"; 8 | 9 | /** 10 | * @title TestLib_RLPWriter 11 | */ 12 | contract TestLib_RLPWriter { 13 | 14 | function writeBytes( 15 | bytes memory _in 16 | ) 17 | public 18 | pure 19 | returns ( 20 | bytes memory _out 21 | ) 22 | { 23 | return Lib_RLPWriter.writeBytes(_in); 24 | } 25 | 26 | function writeList( 27 | bytes[] memory _in 28 | ) 29 | public 30 | pure 31 | returns ( 32 | bytes memory _out 33 | ) 34 | { 35 | return Lib_RLPWriter.writeList(_in); 36 | } 37 | 38 | function writeString( 39 | string memory _in 40 | ) 41 | public 42 | pure 43 | returns ( 44 | bytes memory _out 45 | ) 46 | { 47 | return Lib_RLPWriter.writeString(_in); 48 | } 49 | 50 | function writeAddress( 51 | address _in 52 | ) 53 | public 54 | pure 55 | returns ( 56 | bytes memory _out 57 | ) 58 | { 59 | return Lib_RLPWriter.writeAddress(_in); 60 | } 61 | 62 | function writeUint( 63 | uint256 _in 64 | ) 65 | public 66 | pure 67 | returns ( 68 | bytes memory _out 69 | ) 70 | { 71 | return Lib_RLPWriter.writeUint(_in); 72 | } 73 | 74 | function writeBool( 75 | bool _in 76 | ) 77 | public 78 | pure 79 | returns ( 80 | bytes memory _out 81 | ) 82 | { 83 | return Lib_RLPWriter.writeBool(_in); 84 | } 85 | 86 | function writeAddressWithTaintedMemory( 87 | address _in 88 | ) 89 | public 90 | returns ( 91 | bytes memory _out 92 | ) 93 | { 94 | new TestERC20(); 95 | return Lib_RLPWriter.writeAddress(_in); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /contracts/test-libraries/trie/TestLib_MerkleTrie.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /* Library Imports */ 5 | import { Lib_MerkleTrie } from "../../optimistic-ethereum/libraries/trie/Lib_MerkleTrie.sol"; 6 | 7 | /** 8 | * @title TestLib_MerkleTrie 9 | */ 10 | contract TestLib_MerkleTrie { 11 | 12 | function verifyInclusionProof( 13 | bytes memory _key, 14 | bytes memory _value, 15 | bytes memory _proof, 16 | bytes32 _root 17 | ) 18 | public 19 | pure 20 | returns ( 21 | bool 22 | ) 23 | { 24 | return Lib_MerkleTrie.verifyInclusionProof( 25 | _key, 26 | _value, 27 | _proof, 28 | _root 29 | ); 30 | } 31 | 32 | function verifyExclusionProof( 33 | bytes memory _key, 34 | bytes memory _proof, 35 | bytes32 _root 36 | ) 37 | public 38 | pure 39 | returns ( 40 | bool 41 | ) 42 | { 43 | return Lib_MerkleTrie.verifyExclusionProof( 44 | _key, 45 | _proof, 46 | _root 47 | ); 48 | } 49 | 50 | function update( 51 | bytes memory _key, 52 | bytes memory _value, 53 | bytes memory _proof, 54 | bytes32 _root 55 | ) 56 | public 57 | pure 58 | returns ( 59 | bytes32 60 | ) 61 | { 62 | return Lib_MerkleTrie.update( 63 | _key, 64 | _value, 65 | _proof, 66 | _root 67 | ); 68 | } 69 | 70 | function get( 71 | bytes memory _key, 72 | bytes memory _proof, 73 | bytes32 _root 74 | ) 75 | public 76 | pure 77 | returns ( 78 | bool, 79 | bytes memory 80 | ) 81 | { 82 | return Lib_MerkleTrie.get( 83 | _key, 84 | _proof, 85 | _root 86 | ); 87 | } 88 | 89 | function getSingleNodeRootHash( 90 | bytes memory _key, 91 | bytes memory _value 92 | ) 93 | public 94 | pure 95 | returns ( 96 | bytes32 97 | ) 98 | { 99 | return Lib_MerkleTrie.getSingleNodeRootHash( 100 | _key, 101 | _value 102 | ); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /contracts/test-libraries/trie/TestLib_SecureMerkleTrie.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | /* Library Imports */ 6 | import { Lib_SecureMerkleTrie } from "../../optimistic-ethereum/libraries/trie/Lib_SecureMerkleTrie.sol"; 7 | 8 | /** 9 | * @title TestLib_SecureMerkleTrie 10 | */ 11 | contract TestLib_SecureMerkleTrie { 12 | 13 | function verifyInclusionProof( 14 | bytes memory _key, 15 | bytes memory _value, 16 | bytes memory _proof, 17 | bytes32 _root 18 | ) 19 | public 20 | pure 21 | returns ( 22 | bool 23 | ) 24 | { 25 | return Lib_SecureMerkleTrie.verifyInclusionProof( 26 | _key, 27 | _value, 28 | _proof, 29 | _root 30 | ); 31 | } 32 | 33 | function verifyExclusionProof( 34 | bytes memory _key, 35 | bytes memory _proof, 36 | bytes32 _root 37 | ) 38 | public 39 | pure 40 | returns ( 41 | bool 42 | ) 43 | { 44 | return Lib_SecureMerkleTrie.verifyExclusionProof( 45 | _key, 46 | _proof, 47 | _root 48 | ); 49 | } 50 | 51 | function update( 52 | bytes memory _key, 53 | bytes memory _value, 54 | bytes memory _proof, 55 | bytes32 _root 56 | ) 57 | public 58 | pure 59 | returns ( 60 | bytes32 61 | ) 62 | { 63 | return Lib_SecureMerkleTrie.update( 64 | _key, 65 | _value, 66 | _proof, 67 | _root 68 | ); 69 | } 70 | 71 | function get( 72 | bytes memory _key, 73 | bytes memory _proof, 74 | bytes32 _root 75 | ) 76 | public 77 | pure 78 | returns ( 79 | bool, 80 | bytes memory 81 | ) 82 | { 83 | return Lib_SecureMerkleTrie.get( 84 | _key, 85 | _proof, 86 | _root 87 | ); 88 | } 89 | 90 | function getSingleNodeRootHash( 91 | bytes memory _key, 92 | bytes memory _value 93 | ) 94 | public 95 | pure 96 | returns ( 97 | bytes32 98 | ) 99 | { 100 | return Lib_SecureMerkleTrie.getSingleNodeRootHash( 101 | _key, 102 | _value 103 | ); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /contracts/test-libraries/utils/TestLib_Bytes32Utils.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /* Library Imports */ 5 | import { Lib_Bytes32Utils } from "../../optimistic-ethereum/libraries/utils/Lib_Bytes32Utils.sol"; 6 | 7 | /** 8 | * @title TestLib_Byte32Utils 9 | */ 10 | contract TestLib_Bytes32Utils { 11 | 12 | function toBool( 13 | bytes32 _in 14 | ) 15 | public 16 | pure 17 | returns ( 18 | bool _out 19 | ) 20 | { 21 | return Lib_Bytes32Utils.toBool(_in); 22 | } 23 | 24 | function fromBool( 25 | bool _in 26 | ) 27 | public 28 | pure 29 | returns ( 30 | bytes32 _out 31 | ) 32 | { 33 | return Lib_Bytes32Utils.fromBool(_in); 34 | } 35 | 36 | function toAddress( 37 | bytes32 _in 38 | ) 39 | public 40 | pure 41 | returns ( 42 | address _out 43 | ) 44 | { 45 | return Lib_Bytes32Utils.toAddress(_in); 46 | } 47 | 48 | function fromAddress( 49 | address _in 50 | ) 51 | public 52 | pure 53 | returns ( 54 | bytes32 _out 55 | ) 56 | { 57 | return Lib_Bytes32Utils.fromAddress(_in); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /contracts/test-libraries/utils/TestLib_BytesUtils.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | /* Library Imports */ 6 | import { Lib_BytesUtils } from "../../optimistic-ethereum/libraries/utils/Lib_BytesUtils.sol"; 7 | import { TestERC20 } from "../../test-helpers/TestERC20.sol"; 8 | 9 | /** 10 | * @title TestLib_BytesUtils 11 | */ 12 | contract TestLib_BytesUtils { 13 | 14 | function concat( 15 | bytes memory _preBytes, 16 | bytes memory _postBytes 17 | ) 18 | public 19 | pure 20 | returns (bytes memory) 21 | { 22 | return abi.encodePacked( 23 | _preBytes, 24 | _postBytes 25 | ); 26 | } 27 | 28 | function slice( 29 | bytes memory _bytes, 30 | uint256 _start, 31 | uint256 _length 32 | ) 33 | public 34 | pure 35 | returns (bytes memory) 36 | { 37 | return Lib_BytesUtils.slice( 38 | _bytes, 39 | _start, 40 | _length 41 | ); 42 | } 43 | 44 | function toBytes32( 45 | bytes memory _bytes 46 | ) 47 | public 48 | pure 49 | returns (bytes32) 50 | { 51 | return Lib_BytesUtils.toBytes32( 52 | _bytes 53 | ); 54 | } 55 | 56 | function toUint256( 57 | bytes memory _bytes 58 | ) 59 | public 60 | pure 61 | returns (uint256) 62 | { 63 | return Lib_BytesUtils.toUint256( 64 | _bytes 65 | ); 66 | } 67 | 68 | function toNibbles( 69 | bytes memory _bytes 70 | ) 71 | public 72 | pure 73 | returns (bytes memory) 74 | { 75 | return Lib_BytesUtils.toNibbles( 76 | _bytes 77 | ); 78 | } 79 | 80 | function fromNibbles( 81 | bytes memory _bytes 82 | ) 83 | public 84 | pure 85 | returns (bytes memory) 86 | { 87 | return Lib_BytesUtils.fromNibbles( 88 | _bytes 89 | ); 90 | } 91 | 92 | function equal( 93 | bytes memory _bytes, 94 | bytes memory _other 95 | ) 96 | public 97 | pure 98 | returns (bool) 99 | { 100 | return Lib_BytesUtils.equal( 101 | _bytes, 102 | _other 103 | ); 104 | } 105 | 106 | function sliceWithTaintedMemory( 107 | bytes memory _bytes, 108 | uint256 _start, 109 | uint256 _length 110 | ) 111 | public 112 | returns (bytes memory) 113 | { 114 | new TestERC20(); 115 | return Lib_BytesUtils.slice( 116 | _bytes, 117 | _start, 118 | _length 119 | ); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /contracts/test-libraries/utils/TestLib_ECDSAUtils.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | 4 | /* Library Imports */ 5 | import { Lib_ECDSAUtils } from "../../optimistic-ethereum/libraries/utils/Lib_ECDSAUtils.sol"; 6 | 7 | /** 8 | * @title TestLib_ECDSAUtils 9 | */ 10 | contract TestLib_ECDSAUtils { 11 | 12 | function recover( 13 | bytes memory _message, 14 | bool _isEthSignedMessage, 15 | uint8 _v, 16 | bytes32 _r, 17 | bytes32 _s 18 | ) 19 | public 20 | pure 21 | returns ( 22 | address _sender 23 | ) 24 | { 25 | return Lib_ECDSAUtils.recover( 26 | _message, 27 | _isEthSignedMessage, 28 | _v, 29 | _r, 30 | _s 31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /contracts/test-libraries/utils/TestLib_EthUtils.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // @unsupported: ovm 3 | pragma solidity >0.5.0 <0.8.0; 4 | pragma experimental ABIEncoderV2; 5 | 6 | /* Library Imports */ 7 | import { Lib_EthUtils } from "../../optimistic-ethereum/libraries/utils/Lib_EthUtils.sol"; 8 | 9 | /** 10 | * @title TestLib_EthUtils 11 | */ 12 | contract TestLib_EthUtils { 13 | 14 | function getCode( 15 | address _address, 16 | uint256 _offset, 17 | uint256 _length 18 | ) 19 | public 20 | view 21 | returns ( 22 | bytes memory _code 23 | ) 24 | { 25 | return Lib_EthUtils.getCode( 26 | _address, 27 | _offset, 28 | _length 29 | ); 30 | } 31 | 32 | function getCode( 33 | address _address 34 | ) 35 | public 36 | view 37 | returns ( 38 | bytes memory _code 39 | ) 40 | { 41 | return Lib_EthUtils.getCode( 42 | _address 43 | ); 44 | } 45 | 46 | function getCodeSize( 47 | address _address 48 | ) 49 | public 50 | view 51 | returns ( 52 | uint256 _codeSize 53 | ) 54 | { 55 | return Lib_EthUtils.getCodeSize( 56 | _address 57 | ); 58 | } 59 | 60 | function getCodeHash( 61 | address _address 62 | ) 63 | public 64 | view 65 | returns ( 66 | bytes32 _codeHash 67 | ) 68 | { 69 | return Lib_EthUtils.getCodeHash( 70 | _address 71 | ); 72 | } 73 | 74 | function createContract( 75 | bytes memory _code 76 | ) 77 | public 78 | returns ( 79 | address _created 80 | ) 81 | { 82 | return Lib_EthUtils.createContract( 83 | _code 84 | ); 85 | } 86 | 87 | function getAddressForCREATE( 88 | address _creator, 89 | uint256 _nonce 90 | ) 91 | public 92 | pure 93 | returns ( 94 | address _address 95 | ) 96 | { 97 | return Lib_EthUtils.getAddressForCREATE( 98 | _creator, 99 | _nonce 100 | ); 101 | } 102 | 103 | function getAddressForCREATE2( 104 | address _creator, 105 | bytes memory _bytecode, 106 | bytes32 _salt 107 | ) 108 | public 109 | pure 110 | returns (address _address) 111 | { 112 | return Lib_EthUtils.getAddressForCREATE2( 113 | _creator, 114 | _bytecode, 115 | _salt 116 | ); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /contracts/test-libraries/utils/TestLib_MerkleTree.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | /* Library Imports */ 6 | import { Lib_MerkleTree } from "../../optimistic-ethereum/libraries/utils/Lib_MerkleTree.sol"; 7 | 8 | /** 9 | * @title TestLib_MerkleTree 10 | */ 11 | contract TestLib_MerkleTree { 12 | 13 | function getMerkleRoot( 14 | bytes32[] memory _elements 15 | ) 16 | public 17 | pure 18 | returns ( 19 | bytes32 20 | ) 21 | { 22 | return Lib_MerkleTree.getMerkleRoot( 23 | _elements 24 | ); 25 | } 26 | 27 | function verify( 28 | bytes32 _root, 29 | bytes32 _leaf, 30 | uint256 _index, 31 | bytes32[] memory _siblings, 32 | uint256 _totalLeaves 33 | ) 34 | public 35 | pure 36 | returns ( 37 | bool 38 | ) 39 | { 40 | return Lib_MerkleTree.verify( 41 | _root, 42 | _leaf, 43 | _index, 44 | _siblings, 45 | _totalLeaves 46 | ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /contracts/test-libraries/utils/TestLib_RingBuffer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >0.5.0 <0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | /* Library Imports */ 6 | import { Lib_RingBuffer } from "../../optimistic-ethereum/libraries/utils/Lib_RingBuffer.sol"; 7 | 8 | /** 9 | * @title TestLib_RingBuffer 10 | */ 11 | contract TestLib_RingBuffer { 12 | using Lib_RingBuffer for Lib_RingBuffer.RingBuffer; 13 | 14 | Lib_RingBuffer.RingBuffer internal buf; 15 | 16 | function push( 17 | bytes32 _value, 18 | bytes27 _extraData 19 | ) 20 | public 21 | { 22 | buf.push( 23 | _value, 24 | _extraData 25 | ); 26 | } 27 | 28 | function get( 29 | uint256 _index 30 | ) 31 | public 32 | view 33 | returns ( 34 | bytes32 35 | ) 36 | { 37 | return buf.get(_index); 38 | } 39 | 40 | function deleteElementsAfterInclusive( 41 | uint40 _index, 42 | bytes27 _extraData 43 | ) 44 | internal 45 | { 46 | return buf.deleteElementsAfterInclusive( 47 | _index, 48 | _extraData 49 | ); 50 | } 51 | 52 | function getLength() 53 | internal 54 | view 55 | returns ( 56 | uint40 57 | ) 58 | { 59 | return buf.getLength(); 60 | } 61 | 62 | function getExtraData() 63 | internal 64 | view 65 | returns ( 66 | bytes27 67 | ) 68 | { 69 | return buf.getExtraData(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /deploy/000-Lib_AddressManager.deploy.ts: -------------------------------------------------------------------------------- 1 | /* Imports: External */ 2 | import { DeployFunction } from 'hardhat-deploy/dist/types' 3 | 4 | /* Imports: Internal */ 5 | import { registerAddress } from '../src/hardhat-deploy-ethers' 6 | import { predeploys } from '../src/predeploys' 7 | 8 | const deployFn: DeployFunction = async (hre) => { 9 | const { deploy } = hre.deployments 10 | const { deployer } = await hre.getNamedAccounts() 11 | 12 | await deploy('Lib_AddressManager', { 13 | from: deployer, 14 | args: [], 15 | log: true, 16 | }) 17 | 18 | await registerAddress({ 19 | hre, 20 | name: 'OVM_L2CrossDomainMessenger', 21 | address: predeploys.OVM_L2CrossDomainMessenger, 22 | }) 23 | 24 | await registerAddress({ 25 | hre, 26 | name: 'OVM_DecompressionPrecompileAddress', 27 | address: predeploys.OVM_SequencerEntrypoint, 28 | }) 29 | 30 | await registerAddress({ 31 | hre, 32 | name: 'OVM_Sequencer', 33 | address: (hre as any).deployConfig.ovmSequencerAddress, 34 | }) 35 | 36 | await registerAddress({ 37 | hre, 38 | name: 'OVM_Proposer', 39 | address: (hre as any).deployConfig.ovmProposerAddress, 40 | }) 41 | 42 | await registerAddress({ 43 | hre, 44 | name: 'OVM_L2BatchMessageRelayer', 45 | address: (hre as any).deployConfig.ovmRelayerAddress, 46 | }) 47 | } 48 | 49 | deployFn.tags = ['Lib_AddressManager', 'required'] 50 | 51 | export default deployFn 52 | -------------------------------------------------------------------------------- /deploy/001-OVM_ChainStorageContainer_ctc_batches.deploy.ts: -------------------------------------------------------------------------------- 1 | /* Imports: External */ 2 | import { DeployFunction } from 'hardhat-deploy/dist/types' 3 | 4 | /* Imports: Internal */ 5 | import { 6 | deployAndRegister, 7 | getDeployedContract, 8 | } from '../src/hardhat-deploy-ethers' 9 | 10 | const deployFn: DeployFunction = async (hre) => { 11 | const Lib_AddressManager = await getDeployedContract( 12 | hre, 13 | 'Lib_AddressManager' 14 | ) 15 | 16 | await deployAndRegister({ 17 | hre, 18 | name: 'OVM_ChainStorageContainer:CTC:batches', 19 | contract: 'OVM_ChainStorageContainer', 20 | args: [Lib_AddressManager.address, 'OVM_CanonicalTransactionChain'], 21 | }) 22 | } 23 | 24 | deployFn.dependencies = ['Lib_AddressManager'] 25 | deployFn.tags = ['OVM_ChainStorageContainer_ctc_batches'] 26 | 27 | export default deployFn 28 | -------------------------------------------------------------------------------- /deploy/002-OVM_ChainStorageContainer_ctc_queue.deploy.ts: -------------------------------------------------------------------------------- 1 | /* Imports: External */ 2 | import { DeployFunction } from 'hardhat-deploy/dist/types' 3 | 4 | /* Imports: Internal */ 5 | import { 6 | deployAndRegister, 7 | getDeployedContract, 8 | } from '../src/hardhat-deploy-ethers' 9 | 10 | const deployFn: DeployFunction = async (hre) => { 11 | const Lib_AddressManager = await getDeployedContract( 12 | hre, 13 | 'Lib_AddressManager' 14 | ) 15 | 16 | await deployAndRegister({ 17 | hre, 18 | name: 'OVM_ChainStorageContainer:CTC:queue', 19 | contract: 'OVM_ChainStorageContainer', 20 | args: [Lib_AddressManager.address, 'OVM_CanonicalTransactionChain'], 21 | }) 22 | } 23 | 24 | deployFn.dependencies = ['Lib_AddressManager'] 25 | deployFn.tags = ['OVM_ChainStorageContainer_ctc_queue'] 26 | 27 | export default deployFn 28 | -------------------------------------------------------------------------------- /deploy/003-OVM_ChainStorageContainer_scc_batches.deploy.ts: -------------------------------------------------------------------------------- 1 | /* Imports: External */ 2 | import { DeployFunction } from 'hardhat-deploy/dist/types' 3 | 4 | /* Imports: Internal */ 5 | import { 6 | deployAndRegister, 7 | getDeployedContract, 8 | } from '../src/hardhat-deploy-ethers' 9 | 10 | const deployFn: DeployFunction = async (hre) => { 11 | const Lib_AddressManager = await getDeployedContract( 12 | hre, 13 | 'Lib_AddressManager' 14 | ) 15 | 16 | await deployAndRegister({ 17 | hre, 18 | name: 'OVM_ChainStorageContainer:SCC:batches', 19 | contract: 'OVM_ChainStorageContainer', 20 | args: [Lib_AddressManager.address, 'OVM_StateCommitmentChain'], 21 | }) 22 | } 23 | 24 | deployFn.dependencies = ['Lib_AddressManager'] 25 | deployFn.tags = ['OVM_ChainStorageContainer_scc_batches'] 26 | 27 | export default deployFn 28 | -------------------------------------------------------------------------------- /deploy/004-OVM_CanonicalTransactionChain.deploy.ts: -------------------------------------------------------------------------------- 1 | /* Imports: External */ 2 | import { DeployFunction } from 'hardhat-deploy/dist/types' 3 | 4 | /* Imports: Internal */ 5 | import { 6 | deployAndRegister, 7 | getDeployedContract, 8 | } from '../src/hardhat-deploy-ethers' 9 | 10 | const deployFn: DeployFunction = async (hre) => { 11 | const Lib_AddressManager = await getDeployedContract( 12 | hre, 13 | 'Lib_AddressManager' 14 | ) 15 | 16 | await deployAndRegister({ 17 | hre, 18 | name: 'OVM_CanonicalTransactionChain', 19 | args: [ 20 | Lib_AddressManager.address, 21 | (hre as any).deployConfig.ctcForceInclusionPeriodSeconds, 22 | (hre as any).deployConfig.ctcForceInclusionPeriodBlocks, 23 | (hre as any).deployConfig.ctcMaxTransactionGasLimit, 24 | ], 25 | }) 26 | } 27 | 28 | deployFn.dependencies = ['Lib_AddressManager'] 29 | deployFn.tags = ['OVM_CanonicalTransactionChain'] 30 | 31 | export default deployFn 32 | -------------------------------------------------------------------------------- /deploy/005-OVM_StateCommitmentChain.deploy.ts: -------------------------------------------------------------------------------- 1 | /* Imports: External */ 2 | import { DeployFunction } from 'hardhat-deploy/dist/types' 3 | 4 | /* Imports: Internal */ 5 | import { 6 | deployAndRegister, 7 | getDeployedContract, 8 | } from '../src/hardhat-deploy-ethers' 9 | 10 | const deployFn: DeployFunction = async (hre) => { 11 | const Lib_AddressManager = await getDeployedContract( 12 | hre, 13 | 'Lib_AddressManager' 14 | ) 15 | 16 | await deployAndRegister({ 17 | hre, 18 | name: 'OVM_StateCommitmentChain', 19 | args: [ 20 | Lib_AddressManager.address, 21 | (hre as any).deployConfig.sccFraudProofWindow, 22 | (hre as any).deployConfig.sccSequencerPublishWindow, 23 | ], 24 | }) 25 | } 26 | 27 | deployFn.dependencies = ['Lib_AddressManager'] 28 | deployFn.tags = ['OVM_StateCommitmentChain'] 29 | 30 | export default deployFn 31 | -------------------------------------------------------------------------------- /deploy/006-mockOVM_BondManager.deploy.ts: -------------------------------------------------------------------------------- 1 | /* Imports: External */ 2 | import { DeployFunction } from 'hardhat-deploy/dist/types' 3 | 4 | /* Imports: Internal */ 5 | import { getDeployedContract } from '../src/hardhat-deploy-ethers' 6 | 7 | const deployFn: DeployFunction = async (hre) => { 8 | const { deploy } = hre.deployments 9 | const { deployer } = await hre.getNamedAccounts() 10 | 11 | const Lib_AddressManager = await getDeployedContract( 12 | hre, 13 | 'Lib_AddressManager', 14 | { 15 | signerOrProvider: deployer, 16 | } 17 | ) 18 | 19 | const result = await deploy('mockOVM_BondManager', { 20 | from: deployer, 21 | args: [Lib_AddressManager.address], 22 | log: true, 23 | }) 24 | 25 | if (!result.newlyDeployed) { 26 | return 27 | } 28 | 29 | await Lib_AddressManager.setAddress('OVM_BondManager', result.address) 30 | } 31 | 32 | deployFn.dependencies = ['Lib_AddressManager'] 33 | deployFn.tags = ['mockOVM_BondManager'] 34 | 35 | export default deployFn 36 | -------------------------------------------------------------------------------- /deploy/007-OVM_L1CrossDomainMessenger.deploy.ts: -------------------------------------------------------------------------------- 1 | /* Imports: External */ 2 | import { DeployFunction } from 'hardhat-deploy/dist/types' 3 | 4 | /* Imports: Internal */ 5 | import { getDeployedContract } from '../src/hardhat-deploy-ethers' 6 | 7 | const deployFn: DeployFunction = async (hre) => { 8 | const { deploy } = hre.deployments 9 | const { deployer } = await hre.getNamedAccounts() 10 | 11 | const Lib_AddressManager = await getDeployedContract( 12 | hre, 13 | 'Lib_AddressManager', 14 | { 15 | signerOrProvider: deployer, 16 | } 17 | ) 18 | 19 | const result = await deploy('OVM_L1CrossDomainMessenger', { 20 | from: deployer, 21 | args: [], 22 | log: true, 23 | }) 24 | 25 | if (!result.newlyDeployed) { 26 | return 27 | } 28 | 29 | const OVM_L1CrossDomainMessenger = await getDeployedContract( 30 | hre, 31 | 'OVM_L1CrossDomainMessenger', 32 | { 33 | signerOrProvider: deployer, 34 | } 35 | ) 36 | 37 | // NOTE: this initialization is *not* technically required (we only need to initialize the proxy) 38 | // but it feels safer to initialize this anyway. Otherwise someone else could come along and 39 | // initialize this. 40 | await OVM_L1CrossDomainMessenger.initialize(Lib_AddressManager.address) 41 | 42 | const libAddressManager = await OVM_L1CrossDomainMessenger.libAddressManager() 43 | if (libAddressManager !== Lib_AddressManager.address) { 44 | throw new Error( 45 | `\n**FATAL ERROR. THIS SHOULD NEVER HAPPEN. CHECK YOUR DEPLOYMENT.**:\n` + 46 | `OVM_L1CrossDomainMessenger could not be succesfully initialized.\n` + 47 | `Attempted to set Lib_AddressManager to: ${Lib_AddressManager.address}\n` + 48 | `Actual address after initialization: ${libAddressManager}\n` + 49 | `This could indicate a compromised deployment.` 50 | ) 51 | } 52 | 53 | await Lib_AddressManager.setAddress( 54 | 'OVM_L1CrossDomainMessenger', 55 | result.address 56 | ) 57 | } 58 | 59 | deployFn.dependencies = ['Lib_AddressManager'] 60 | deployFn.tags = ['OVM_L1CrossDomainMessenger'] 61 | 62 | export default deployFn 63 | -------------------------------------------------------------------------------- /deploy/008-Proxy__OVM_L1CrossDomainMessenger.deploy.ts: -------------------------------------------------------------------------------- 1 | /* Imports: External */ 2 | import { DeployFunction } from 'hardhat-deploy/dist/types' 3 | 4 | /* Imports: Internal */ 5 | import { getDeployedContract } from '../src/hardhat-deploy-ethers' 6 | 7 | const deployFn: DeployFunction = async (hre) => { 8 | const { deploy } = hre.deployments 9 | const { deployer } = await hre.getNamedAccounts() 10 | 11 | const Lib_AddressManager = await getDeployedContract( 12 | hre, 13 | 'Lib_AddressManager', 14 | { 15 | signerOrProvider: deployer, 16 | } 17 | ) 18 | 19 | const result = await deploy('Proxy__OVM_L1CrossDomainMessenger', { 20 | contract: 'Lib_ResolvedDelegateProxy', 21 | from: deployer, 22 | args: [Lib_AddressManager.address, 'OVM_L1CrossDomainMessenger'], 23 | log: true, 24 | }) 25 | 26 | if (!result.newlyDeployed) { 27 | return 28 | } 29 | 30 | const Proxy__OVM_L1CrossDomainMessenger = await getDeployedContract( 31 | hre, 32 | 'Proxy__OVM_L1CrossDomainMessenger', 33 | { 34 | signerOrProvider: deployer, 35 | iface: 'OVM_L1CrossDomainMessenger', 36 | } 37 | ) 38 | 39 | await Proxy__OVM_L1CrossDomainMessenger.initialize(Lib_AddressManager.address) 40 | 41 | const libAddressManager = await Proxy__OVM_L1CrossDomainMessenger.libAddressManager() 42 | if (libAddressManager !== Lib_AddressManager.address) { 43 | throw new Error( 44 | `\n**FATAL ERROR. THIS SHOULD NEVER HAPPEN. CHECK YOUR DEPLOYMENT.**:\n` + 45 | `Proxy__OVM_L1CrossDomainMessenger could not be succesfully initialized.\n` + 46 | `Attempted to set Lib_AddressManager to: ${Lib_AddressManager.address}\n` + 47 | `Actual address after initialization: ${libAddressManager}\n` + 48 | `This could indicate a compromised deployment.` 49 | ) 50 | } 51 | 52 | await Lib_AddressManager.setAddress( 53 | 'Proxy__OVM_L1CrossDomainMessenger', 54 | result.address 55 | ) 56 | } 57 | 58 | deployFn.dependencies = ['Lib_AddressManager', 'OVM_L1CrossDomainMessenger'] 59 | deployFn.tags = ['Proxy__OVM_L1CrossDomainMessenger'] 60 | 61 | export default deployFn 62 | -------------------------------------------------------------------------------- /deploy/009-OVM_ExecutionManager.deploy.ts: -------------------------------------------------------------------------------- 1 | /* Imports: External */ 2 | import { DeployFunction } from 'hardhat-deploy/dist/types' 3 | 4 | /* Imports: Internal */ 5 | import { 6 | deployAndRegister, 7 | getDeployedContract, 8 | } from '../src/hardhat-deploy-ethers' 9 | 10 | const deployFn: DeployFunction = async (hre) => { 11 | const Lib_AddressManager = await getDeployedContract( 12 | hre, 13 | 'Lib_AddressManager' 14 | ) 15 | 16 | await deployAndRegister({ 17 | hre, 18 | name: 'OVM_ExecutionManager', 19 | args: [ 20 | Lib_AddressManager.address, 21 | { 22 | minTransactionGasLimit: (hre as any).deployConfig 23 | .emMinTransactionGasLimit, 24 | maxTransactionGasLimit: (hre as any).deployConfig 25 | .emMaxTransactionGasLimit, 26 | maxGasPerQueuePerEpoch: (hre as any).deployConfig 27 | .emMaxGasPerQueuePerEpoch, 28 | secondsPerEpoch: (hre as any).deployConfig.emSecondsPerEpoch, 29 | }, 30 | { 31 | ovmCHAINID: (hre as any).deployConfig.emOvmChainId, 32 | }, 33 | ], 34 | }) 35 | } 36 | 37 | deployFn.dependencies = ['Lib_AddressManager'] 38 | deployFn.tags = ['OVM_ExecutionManager'] 39 | 40 | export default deployFn 41 | -------------------------------------------------------------------------------- /deploy/010-OVM_FraudVerifer.deploy.ts: -------------------------------------------------------------------------------- 1 | /* Imports: External */ 2 | import { DeployFunction } from 'hardhat-deploy/dist/types' 3 | 4 | /* Imports: Internal */ 5 | import { 6 | deployAndRegister, 7 | getDeployedContract, 8 | } from '../src/hardhat-deploy-ethers' 9 | 10 | const deployFn: DeployFunction = async (hre) => { 11 | const Lib_AddressManager = await getDeployedContract( 12 | hre, 13 | 'Lib_AddressManager' 14 | ) 15 | 16 | await deployAndRegister({ 17 | hre, 18 | name: 'OVM_FraudVerifier', 19 | args: [Lib_AddressManager.address], 20 | }) 21 | } 22 | 23 | deployFn.dependencies = ['Lib_AddressManager'] 24 | deployFn.tags = ['OVM_FraudVerifier'] 25 | 26 | export default deployFn 27 | -------------------------------------------------------------------------------- /deploy/011-OVM_StateManagerFactory.deploy.ts: -------------------------------------------------------------------------------- 1 | /* Imports: External */ 2 | import { DeployFunction } from 'hardhat-deploy/dist/types' 3 | 4 | /* Imports: Internal */ 5 | import { deployAndRegister } from '../src/hardhat-deploy-ethers' 6 | 7 | const deployFn: DeployFunction = async (hre) => { 8 | await deployAndRegister({ 9 | hre, 10 | name: 'OVM_StateManagerFactory', 11 | args: [], 12 | }) 13 | } 14 | 15 | deployFn.tags = ['OVM_FraudVerifier'] 16 | 17 | export default deployFn 18 | -------------------------------------------------------------------------------- /deploy/012-OVM_StateTransitionerFactory.deploy.ts: -------------------------------------------------------------------------------- 1 | /* Imports: External */ 2 | import { DeployFunction } from 'hardhat-deploy/dist/types' 3 | 4 | /* Imports: Internal */ 5 | import { 6 | deployAndRegister, 7 | getDeployedContract, 8 | } from '../src/hardhat-deploy-ethers' 9 | 10 | const deployFn: DeployFunction = async (hre) => { 11 | const Lib_AddressManager = await getDeployedContract( 12 | hre, 13 | 'Lib_AddressManager' 14 | ) 15 | 16 | await deployAndRegister({ 17 | hre, 18 | name: 'OVM_StateTransitionerFactory', 19 | args: [Lib_AddressManager.address], 20 | }) 21 | } 22 | 23 | deployFn.dependencies = ['Lib_AddressManager'] 24 | deployFn.tags = ['OVM_StateTransitionerFactory'] 25 | 26 | export default deployFn 27 | -------------------------------------------------------------------------------- /deploy/013-OVM_SafetyChecker.deploy.ts: -------------------------------------------------------------------------------- 1 | /* Imports: External */ 2 | import { DeployFunction } from 'hardhat-deploy/dist/types' 3 | 4 | /* Imports: Internal */ 5 | import { deployAndRegister } from '../src/hardhat-deploy-ethers' 6 | 7 | const deployFn: DeployFunction = async (hre) => { 8 | await deployAndRegister({ 9 | hre, 10 | name: 'OVM_SafetyChecker', 11 | args: [], 12 | }) 13 | } 14 | 15 | deployFn.tags = ['OVM_SafetyChecker'] 16 | 17 | export default deployFn 18 | -------------------------------------------------------------------------------- /deploy/014-OVM_L1MultiMessageRelayer.deploy.ts: -------------------------------------------------------------------------------- 1 | /* Imports: External */ 2 | import { DeployFunction } from 'hardhat-deploy/dist/types' 3 | 4 | /* Imports: Internal */ 5 | import { 6 | deployAndRegister, 7 | getDeployedContract, 8 | } from '../src/hardhat-deploy-ethers' 9 | 10 | const deployFn: DeployFunction = async (hre) => { 11 | const Lib_AddressManager = await getDeployedContract( 12 | hre, 13 | 'Lib_AddressManager' 14 | ) 15 | 16 | await deployAndRegister({ 17 | hre, 18 | name: 'OVM_L1MultiMessageRelayer', 19 | args: [Lib_AddressManager.address], 20 | }) 21 | } 22 | 23 | deployFn.dependencies = ['Lib_AddressManager'] 24 | deployFn.tags = ['OVM_L1MultiMessageRelayer'] 25 | 26 | export default deployFn 27 | -------------------------------------------------------------------------------- /deploy/015-OVM_L1ETHGateway.deploy.ts: -------------------------------------------------------------------------------- 1 | /* Imports: External */ 2 | import { DeployFunction } from 'hardhat-deploy/dist/types' 3 | 4 | /* Imports: Internal */ 5 | import { getDeployedContract } from '../src/hardhat-deploy-ethers' 6 | import { predeploys } from '../src/predeploys' 7 | 8 | const deployFn: DeployFunction = async (hre) => { 9 | const { deploy } = hre.deployments 10 | const { deployer } = await hre.getNamedAccounts() 11 | 12 | const Lib_AddressManager = await getDeployedContract( 13 | hre, 14 | 'Lib_AddressManager', 15 | { 16 | signerOrProvider: deployer, 17 | } 18 | ) 19 | 20 | const result = await deploy('OVM_L1ETHGateway', { 21 | from: deployer, 22 | args: [], 23 | log: true, 24 | }) 25 | 26 | if (!result.newlyDeployed) { 27 | return 28 | } 29 | 30 | const OVM_L1ETHGateway = await getDeployedContract(hre, 'OVM_L1ETHGateway', { 31 | signerOrProvider: deployer, 32 | }) 33 | 34 | // NOTE: this initialization is *not* technically required (we only need to initialize the proxy) 35 | // but it feels safer to initialize this anyway. Otherwise someone else could come along and 36 | // initialize this. 37 | await OVM_L1ETHGateway.initialize( 38 | Lib_AddressManager.address, 39 | predeploys.OVM_ETH 40 | ) 41 | 42 | const libAddressManager = await OVM_L1ETHGateway.libAddressManager() 43 | if (libAddressManager !== Lib_AddressManager.address) { 44 | throw new Error( 45 | `\n**FATAL ERROR. THIS SHOULD NEVER HAPPEN. CHECK YOUR DEPLOYMENT.**:\n` + 46 | `OVM_L1ETHGateway could not be succesfully initialized.\n` + 47 | `Attempted to set Lib_AddressManager to: ${Lib_AddressManager.address}\n` + 48 | `Actual address after initialization: ${libAddressManager}\n` + 49 | `This could indicate a compromised deployment.` 50 | ) 51 | } 52 | 53 | await Lib_AddressManager.setAddress('OVM_L1ETHGateway', result.address) 54 | } 55 | 56 | deployFn.dependencies = ['Lib_AddressManager'] 57 | deployFn.tags = ['OVM_L1ETHGateway'] 58 | 59 | export default deployFn 60 | -------------------------------------------------------------------------------- /deploy/016-Proxy__OVM_L1ETHGateway.deploy.ts: -------------------------------------------------------------------------------- 1 | /* Imports: External */ 2 | import { DeployFunction } from 'hardhat-deploy/dist/types' 3 | 4 | /* Imports: Internal */ 5 | import { getDeployedContract } from '../src/hardhat-deploy-ethers' 6 | import { predeploys } from '../src/predeploys' 7 | 8 | const deployFn: DeployFunction = async (hre) => { 9 | const { deploy } = hre.deployments 10 | const { deployer } = await hre.getNamedAccounts() 11 | 12 | const Lib_AddressManager = await getDeployedContract( 13 | hre, 14 | 'Lib_AddressManager', 15 | { 16 | signerOrProvider: deployer, 17 | } 18 | ) 19 | 20 | const result = await deploy('Proxy__OVM_L1ETHGateway', { 21 | contract: 'Lib_ResolvedDelegateProxy', 22 | from: deployer, 23 | args: [Lib_AddressManager.address, 'OVM_L1ETHGateway'], 24 | log: true, 25 | }) 26 | 27 | if (!result.newlyDeployed) { 28 | return 29 | } 30 | 31 | const Proxy__OVM_L1ETHGateway = await getDeployedContract( 32 | hre, 33 | 'Proxy__OVM_L1ETHGateway', 34 | { 35 | signerOrProvider: deployer, 36 | iface: 'OVM_L1ETHGateway', 37 | } 38 | ) 39 | 40 | await Proxy__OVM_L1ETHGateway.initialize( 41 | Lib_AddressManager.address, 42 | predeploys.OVM_ETH 43 | ) 44 | 45 | const libAddressManager = await Proxy__OVM_L1ETHGateway.libAddressManager() 46 | if (libAddressManager !== Lib_AddressManager.address) { 47 | throw new Error( 48 | `\n**FATAL ERROR. THIS SHOULD NEVER HAPPEN. CHECK YOUR DEPLOYMENT.**:\n` + 49 | `Proxy__OVM_L1ETHGateway could not be succesfully initialized.\n` + 50 | `Attempted to set Lib_AddressManager to: ${Lib_AddressManager.address}\n` + 51 | `Actual address after initialization: ${libAddressManager}\n` + 52 | `This could indicate a compromised deployment.` 53 | ) 54 | } 55 | 56 | await Lib_AddressManager.setAddress('Proxy__OVM_L1ETHGateway', result.address) 57 | } 58 | 59 | deployFn.dependencies = ['Lib_AddressManager', 'OVM_L1ETHGateway'] 60 | deployFn.tags = ['Proxy__OVM_L1ETHGateway'] 61 | 62 | export default deployFn 63 | -------------------------------------------------------------------------------- /deploy/017-finalize.ts: -------------------------------------------------------------------------------- 1 | /* Imports: External */ 2 | import { DeployFunction } from 'hardhat-deploy/dist/types' 3 | 4 | /* Imports: Internal */ 5 | import { getDeployedContract } from '../src/hardhat-deploy-ethers' 6 | 7 | const deployFn: DeployFunction = async (hre) => { 8 | const { deployer } = await hre.getNamedAccounts() 9 | const Lib_AddressManager = await getDeployedContract( 10 | hre, 11 | 'Lib_AddressManager', 12 | { 13 | signerOrProvider: deployer, 14 | } 15 | ) 16 | 17 | const owner = (hre as any).deployConfig.ovmAddressManagerOwner 18 | const remoteOwner = await Lib_AddressManager.owner() 19 | if (remoteOwner === owner) { 20 | console.log( 21 | `✓ Not changing owner of Lib_AddressManager because it's already correctly set` 22 | ) 23 | return 24 | } 25 | 26 | console.log(`Transferring ownership of Lib_AddressManager to ${owner}...`) 27 | const tx = await Lib_AddressManager.transferOwnership(owner) 28 | await tx.wait() 29 | 30 | const newRemoteOwner = await Lib_AddressManager.owner() 31 | if (newRemoteOwner !== owner) { 32 | throw new Error( 33 | `\n**FATAL ERROR. THIS SHOULD NEVER HAPPEN. CHECK YOUR DEPLOYMENT.**:\n` + 34 | `Could not transfer ownership of Lib_AddressManager.\n` + 35 | `Attempted to set owner of Lib_AddressManager to: ${owner}\n` + 36 | `Actual owner after transaction: ${newRemoteOwner}\n` + 37 | `This could indicate a compromised deployment.` 38 | ) 39 | } 40 | 41 | console.log(`✓ Set owner of Lib_AddressManager to: ${owner}`) 42 | } 43 | 44 | deployFn.dependencies = ['Lib_AddressManager'] 45 | deployFn.tags = ['finalize'] 46 | 47 | export default deployFn 48 | -------------------------------------------------------------------------------- /hardhat.config.ts: -------------------------------------------------------------------------------- 1 | import { HardhatUserConfig } from 'hardhat/types' 2 | import 'solidity-coverage' 3 | import * as dotenv from 'dotenv' 4 | 5 | import { 6 | DEFAULT_ACCOUNTS_HARDHAT, 7 | RUN_OVM_TEST_GAS, 8 | } from './test/helpers/constants' 9 | 10 | // Hardhat plugins 11 | import '@nomiclabs/hardhat-ethers' 12 | import '@nomiclabs/hardhat-waffle' 13 | import 'hardhat-deploy' 14 | import '@typechain/hardhat' 15 | import '@eth-optimism/plugins/hardhat/compiler' 16 | import './hh' 17 | 18 | // Load environment variables from .env 19 | dotenv.config() 20 | 21 | const config: HardhatUserConfig = { 22 | networks: { 23 | hardhat: { 24 | accounts: DEFAULT_ACCOUNTS_HARDHAT, 25 | blockGasLimit: RUN_OVM_TEST_GAS * 2, 26 | live: false, 27 | saveDeployments: false, 28 | tags: ['local'], 29 | }, 30 | }, 31 | mocha: { 32 | timeout: 50000, 33 | }, 34 | solidity: { 35 | version: '0.7.6', 36 | settings: { 37 | optimizer: { enabled: true, runs: 200 }, 38 | metadata: { 39 | bytecodeHash: 'none', 40 | }, 41 | outputSelection: { 42 | '*': { 43 | '*': ['storageLayout'], 44 | }, 45 | }, 46 | }, 47 | }, 48 | typechain: { 49 | outDir: 'build/types', 50 | target: 'ethers-v5', 51 | }, 52 | paths: { 53 | deploy: './deploy', 54 | deployments: './deployments', 55 | }, 56 | namedAccounts: { 57 | deployer: { 58 | default: 0, 59 | }, 60 | }, 61 | } 62 | 63 | if ( 64 | process.env.CONTRACTS_TARGET_NETWORK && 65 | process.env.CONTRACTS_DEPLOYER_KEY && 66 | process.env.CONTRACTS_RPC_URL 67 | ) { 68 | config.networks[process.env.CONTRACTS_TARGET_NETWORK] = { 69 | accounts: [process.env.CONTRACTS_DEPLOYER_KEY], 70 | url: process.env.CONTRACTS_RPC_URL, 71 | live: true, 72 | saveDeployments: true, 73 | tags: [process.env.CONTRACTS_TARGET_NETWORK], 74 | } 75 | } 76 | 77 | export default config 78 | -------------------------------------------------------------------------------- /hh/index.ts: -------------------------------------------------------------------------------- 1 | import './tasks/task-deploy' 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@eth-optimism/contracts", 3 | "version": "0.2.0", 4 | "main": "build/src/index.js", 5 | "files": [ 6 | "build/**/*.js", 7 | "build/contracts/*", 8 | "build/dumps/*json", 9 | "build/artifacts/**/*.json", 10 | "build/artifacts-ovm/**/*.json", 11 | "build/types/**/*.ts" 12 | ], 13 | "author": "Optimism PBC", 14 | "license": "MIT", 15 | "scripts": { 16 | "all": "yarn clean && yarn build && yarn test && yarn lint:fix && yarn lint", 17 | "build": "yarn build:contracts && yarn build:contracts:ovm && yarn build:typescript && yarn build:copy && yarn build:dump && yarn build:typechain", 18 | "build:kovan": "yarn build:contracts && yarn build:typescript && yarn build:copy && CHAIN_ID=69 yarn build:dump && yarn build:typechain", 19 | "build:mainnet": "yarn build:contracts && yarn build:typescript && yarn build:copy && CHAIN_ID=10 yarn build:dump && yarn build:typechain", 20 | "build:typescript": "tsc -p .", 21 | "build:contracts": "hardhat compile --show-stack-traces", 22 | "build:contracts:ovm": "TARGET=ovm hardhat compile --show-stack-traces", 23 | "build:dump": "ts-node \"bin/take-dump.ts\"", 24 | "build:copy": "yarn build:copy:artifacts && yarn build:copy:artifacts:ovm && yarn build:copy:contracts", 25 | "build:copy:artifacts": "copyfiles -u 1 \"artifacts/**/*.json\" \"build/artifacts\"", 26 | "build:copy:artifacts:ovm": "copyfiles -u 1 \"artifacts-ovm/**/*.json\" \"build/artifacts-ovm\"", 27 | "build:copy:contracts": "copyfiles -u 2 \"contracts/optimistic-ethereum/**/*.sol\" \"build/contracts\"", 28 | "build:typechain": "hardhat typechain", 29 | "test": "yarn test:contracts", 30 | "test:contracts": "hardhat test --show-stack-traces", 31 | "test:gas": "hardhat test \"test/contracts/OVM/execution/OVM_StateManager.gas-spec.ts\" --no-compile --show-stack-traces", 32 | "test:coverage": "NODE_OPTIONS=--max_old_space_size=8192 hardhat coverage", 33 | "lint": "yarn lint:fix && yarn lint:check", 34 | "lint:check": "tslint --format stylish --project .", 35 | "lint:fix": "prettier --config prettier-config.json --write \"hardhat.config.ts\" \"{src,test,hh,deploy,bin}/**/*.ts\"", 36 | "clean": "rm -rf ./build ./artifacts ./artifacts-ovm ./cache ./cache-ovm", 37 | "deploy": "./bin/deploy.js", 38 | "serve": "./bin/serve_dump.sh" 39 | }, 40 | "peerDependencies": { 41 | "ethers": "^5.0.0" 42 | }, 43 | "dependencies": { 44 | "@eth-optimism/core-utils": "^0.1.10", 45 | "@ethersproject/abstract-provider": "^5.0.8", 46 | "@ethersproject/contracts": "^5.0.5", 47 | "@ethersproject/hardware-wallets": "^5.0.8", 48 | "@openzeppelin/contracts": "^3.3.0", 49 | "ganache-core": "^2.13.2", 50 | "glob": "^7.1.6" 51 | }, 52 | "devDependencies": { 53 | "@eth-optimism/dev": "^1.1.1", 54 | "@eth-optimism/plugins": "1.0.0-alpha.2", 55 | "@eth-optimism/smock": "1.0.0-alpha.6", 56 | "@ethersproject/abstract-signer": "^5.0.14", 57 | "@nomiclabs/hardhat-ethers": "^2.0.1", 58 | "@nomiclabs/hardhat-waffle": "^2.0.1", 59 | "@typechain/ethers-v5": "1.0.0", 60 | "@typechain/hardhat": "^1.0.1", 61 | "@types/glob": "^7.1.3", 62 | "@types/lodash": "^4.14.161", 63 | "buffer-xor": "^2.0.2", 64 | "chai": "^4.3.1", 65 | "copyfiles": "^2.3.0", 66 | "directory-tree": "^2.2.7", 67 | "dotenv": "^8.2.0", 68 | "ethereum-waffle": "^3.3.0", 69 | "ethers": "^5.0.31", 70 | "hardhat": "^2.0.8", 71 | "hardhat-deploy": "^0.7.0-beta.50", 72 | "lodash": "^4.17.20", 73 | "merkle-patricia-tree": "^4.0.0", 74 | "merkletreejs": "^0.2.12", 75 | "mkdirp": "^1.0.4", 76 | "mocha": "^8.3.0", 77 | "random-bytes-seed": "^1.0.3", 78 | "rlp": "^2.2.6", 79 | "solidity-coverage": "^0.7.16", 80 | "ts-generator": "0.0.8", 81 | "typechain": "2.0.0" 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /prettier-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/prettierrc", 3 | "trailingComma": "es5", 4 | "tabWidth": 2, 5 | "semi": false, 6 | "singleQuote": true, 7 | "arrowParens": "always" 8 | } 9 | -------------------------------------------------------------------------------- /src/contract-defs.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path' 2 | import * as glob from 'glob' 3 | import { ethers, ContractFactory, Signer } from 'ethers' 4 | import { Interface } from 'ethers/lib/utils' 5 | 6 | export const getContractDefinition = (name: string, ovm?: boolean): any => { 7 | const match = glob.sync( 8 | path.resolve(__dirname, `../artifacts${ovm ? '-ovm' : ''}`) + 9 | `/**/${name}.json` 10 | ) 11 | 12 | if (match.length > 0) { 13 | return require(match[0]) 14 | } else { 15 | throw new Error(`Unable to find artifact for contract: ${name}`) 16 | } 17 | } 18 | 19 | export const getContractInterface = ( 20 | name: string, 21 | ovm?: boolean 22 | ): Interface => { 23 | const definition = getContractDefinition(name, ovm) 24 | return new ethers.utils.Interface(definition.abi) 25 | } 26 | 27 | export const getContractFactory = ( 28 | name: string, 29 | signer?: Signer, 30 | ovm?: boolean 31 | ): ContractFactory => { 32 | const definition = getContractDefinition(name, ovm) 33 | const contractInterface = getContractInterface(name, ovm) 34 | return new ContractFactory(contractInterface, definition.bytecode, signer) 35 | } 36 | -------------------------------------------------------------------------------- /src/contract-deployment/deploy.ts: -------------------------------------------------------------------------------- 1 | /* External Imports */ 2 | import { Contract } from 'ethers' 3 | 4 | /* Internal Imports */ 5 | import { RollupDeployConfig, makeContractDeployConfig } from './config' 6 | import { getContractFactory } from '../contract-defs' 7 | 8 | export interface DeployResult { 9 | AddressManager: Contract 10 | failedDeployments: string[] 11 | contracts: { 12 | [name: string]: Contract 13 | } 14 | } 15 | 16 | export const deploy = async ( 17 | config: RollupDeployConfig 18 | ): Promise => { 19 | let AddressManager: Contract 20 | 21 | if (config.addressManager) { 22 | // console.log(`Connecting to existing address manager.`) //console.logs currently break our deployer 23 | AddressManager = getContractFactory( 24 | 'Lib_AddressManager', 25 | config.deploymentSigner 26 | ).attach(config.addressManager) 27 | } else { 28 | // console.log( 29 | // `Address manager wasn't provided, so we're deploying a new one.` 30 | // ) //console.logs currently break our deployer 31 | AddressManager = await getContractFactory( 32 | 'Lib_AddressManager', 33 | config.deploymentSigner 34 | ).deploy() 35 | if (config.waitForReceipts) { 36 | await AddressManager.deployTransaction.wait() 37 | } 38 | } 39 | 40 | const contractDeployConfig = await makeContractDeployConfig( 41 | config, 42 | AddressManager 43 | ) 44 | 45 | const failedDeployments: string[] = [] 46 | const contracts: { 47 | [name: string]: Contract 48 | } = {} 49 | 50 | for (const [name, contractDeployParameters] of Object.entries( 51 | contractDeployConfig 52 | )) { 53 | if (config.dependencies && !config.dependencies.includes(name)) { 54 | continue 55 | } 56 | 57 | try { 58 | contracts[name] = await contractDeployParameters.factory 59 | .connect(config.deploymentSigner) 60 | .deploy( 61 | ...(contractDeployParameters.params || []), 62 | config.deployOverrides 63 | ) 64 | if (config.waitForReceipts) { 65 | await contracts[name].deployTransaction.wait() 66 | } 67 | const res = await AddressManager.setAddress(name, contracts[name].address) 68 | if (config.waitForReceipts) { 69 | await res.wait() 70 | } 71 | } catch (err) { 72 | console.error(`Error deploying ${name}: ${err}`) 73 | failedDeployments.push(name) 74 | } 75 | } 76 | 77 | for (const [name, contractDeployParameters] of Object.entries( 78 | contractDeployConfig 79 | )) { 80 | if (config.dependencies && !config.dependencies.includes(name)) { 81 | continue 82 | } 83 | 84 | if (contractDeployParameters.afterDeploy) { 85 | await contractDeployParameters.afterDeploy(contracts) 86 | } 87 | } 88 | 89 | return { 90 | AddressManager, 91 | failedDeployments, 92 | contracts, 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/contract-deployment/index.ts: -------------------------------------------------------------------------------- 1 | export { RollupDeployConfig } from './config' 2 | export { deploy } from './deploy' 3 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './contract-defs' 2 | export { getLatestStateDump, StateDump } from './contract-dumps' 3 | export * from './contract-deployment' 4 | -------------------------------------------------------------------------------- /src/predeploys.ts: -------------------------------------------------------------------------------- 1 | export const predeploys = { 2 | OVM_L2ToL1MessagePasser: '0x4200000000000000000000000000000000000000', 3 | OVM_L1MessageSender: '0x4200000000000000000000000000000000000001', 4 | OVM_DeployerWhitelist: '0x4200000000000000000000000000000000000002', 5 | OVM_ECDSAContractAccount: '0x4200000000000000000000000000000000000003', 6 | OVM_ProxySequencerEntrypoint: '0x4200000000000000000000000000000000000004', 7 | OVM_SequencerEntrypoint: '0x4200000000000000000000000000000000000005', 8 | OVM_ETH: '0x4200000000000000000000000000000000000006', 9 | OVM_L2CrossDomainMessenger: '0x4200000000000000000000000000000000000007', 10 | Lib_AddressManager: '0x4200000000000000000000000000000000000008', 11 | ERC1820Registry: '0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24', 12 | } 13 | -------------------------------------------------------------------------------- /test/contracts/OVM/execution/OVM_ExecutionManager/context-opcodes.spec.ts: -------------------------------------------------------------------------------- 1 | /* Internal Imports */ 2 | import { 3 | ExecutionManagerTestRunner, 4 | TestDefinition, 5 | NON_NULL_BYTES32, 6 | OVM_TX_GAS_LIMIT, 7 | } from '../../../../helpers' 8 | 9 | const globalContext = { 10 | ovmCHAINID: 420, 11 | } 12 | 13 | const transactionContext = { 14 | ovmTIMESTAMP: 12341234, 15 | ovmNUMBER: 13371337, 16 | ovmGASLIMIT: 45674567, 17 | ovmTXGASLIMIT: 78907890, 18 | ovmL1QUEUEORIGIN: 1, 19 | ovmL1TXORIGIN: '0x1234123412341234123412341234123412341234', 20 | } 21 | 22 | const messageContext = { 23 | ovmCALLER: '0x6789678967896789678967896789678967896789', 24 | ovmADDRESS: '0x4567456745674567456745674567456745674567', 25 | } 26 | 27 | const test_contextOpcodes: TestDefinition = { 28 | name: 'unit tests for basic getter opcodes', 29 | preState: { 30 | ExecutionManager: { 31 | ovmStateManager: '$OVM_STATE_MANAGER', 32 | ovmSafetyChecker: '$OVM_SAFETY_CHECKER', 33 | messageRecord: { 34 | nuisanceGasLeft: OVM_TX_GAS_LIMIT, 35 | }, 36 | globalContext, 37 | transactionContext, 38 | messageContext, 39 | }, 40 | StateManager: { 41 | owner: '$OVM_EXECUTION_MANAGER', 42 | accounts: { 43 | $DUMMY_OVM_ADDRESS_1: { 44 | codeHash: NON_NULL_BYTES32, 45 | ethAddress: '$OVM_CALL_HELPER', 46 | }, 47 | }, 48 | }, 49 | }, 50 | parameters: [ 51 | // TODO: re-enable when we can unwrap tests' ovmCALL 52 | // { 53 | // name: 'gets ovmCALLER', 54 | // steps: [ 55 | // { 56 | // functionName: 'ovmCALLER', 57 | // expectedReturnValue: messageContext.ovmCALLER 58 | // } 59 | // ], 60 | // }, 61 | // { 62 | // name: 'gets ovmADDRESS', 63 | // steps: [ 64 | // { 65 | // functionName: 'ovmADDRESS', 66 | // expectedReturnValue: messageContext.ovmADDRESS 67 | // } 68 | // ], 69 | // }, 70 | { 71 | name: 'gets ovmTIMESTAMP', 72 | steps: [ 73 | { 74 | functionName: 'ovmTIMESTAMP', 75 | expectedReturnValue: transactionContext.ovmTIMESTAMP, 76 | }, 77 | ], 78 | }, 79 | { 80 | name: 'gets ovmNUMBER', 81 | steps: [ 82 | { 83 | functionName: 'ovmNUMBER', 84 | expectedReturnValue: transactionContext.ovmNUMBER, 85 | }, 86 | ], 87 | }, 88 | { 89 | name: 'gets ovmGASLIMIT', 90 | steps: [ 91 | { 92 | functionName: 'ovmGASLIMIT', 93 | expectedReturnValue: transactionContext.ovmGASLIMIT, 94 | }, 95 | ], 96 | }, 97 | { 98 | name: 'gets ovmL1QUEUEORIGIN', 99 | steps: [ 100 | { 101 | functionName: 'ovmL1QUEUEORIGIN', 102 | expectedReturnValue: transactionContext.ovmL1QUEUEORIGIN, 103 | }, 104 | ], 105 | }, 106 | { 107 | name: 'gets ovmL1TXORIGIN', 108 | steps: [ 109 | { 110 | functionName: 'ovmL1TXORIGIN', 111 | expectedReturnValue: transactionContext.ovmL1TXORIGIN, 112 | }, 113 | ], 114 | }, 115 | { 116 | name: 'gets ovmCHAINID', 117 | steps: [ 118 | { 119 | functionName: 'ovmCHAINID', 120 | expectedReturnValue: globalContext.ovmCHAINID, 121 | }, 122 | ], 123 | }, 124 | ], 125 | } 126 | 127 | const runner = new ExecutionManagerTestRunner() 128 | runner.run(test_contextOpcodes) 129 | -------------------------------------------------------------------------------- /test/contracts/OVM/execution/OVM_ExecutionManager/ovmREVERT.spec.ts: -------------------------------------------------------------------------------- 1 | /* Internal Imports */ 2 | import { 3 | ExecutionManagerTestRunner, 4 | TestDefinition, 5 | OVM_TX_GAS_LIMIT, 6 | NON_NULL_BYTES32, 7 | REVERT_FLAGS, 8 | } from '../../../../helpers' 9 | 10 | const test_ovmREVERT: TestDefinition = { 11 | name: 'Basic tests for ovmREVERT', 12 | preState: { 13 | ExecutionManager: { 14 | ovmStateManager: '$OVM_STATE_MANAGER', 15 | ovmSafetyChecker: '$OVM_SAFETY_CHECKER', 16 | messageRecord: { 17 | nuisanceGasLeft: OVM_TX_GAS_LIMIT, 18 | }, 19 | }, 20 | StateManager: { 21 | owner: '$OVM_EXECUTION_MANAGER', 22 | accounts: { 23 | $DUMMY_OVM_ADDRESS_1: { 24 | codeHash: NON_NULL_BYTES32, 25 | ethAddress: '$OVM_CALL_HELPER', 26 | }, 27 | }, 28 | }, 29 | }, 30 | parameters: [ 31 | { 32 | name: 'ovmCALL => ovmREVERT', 33 | steps: [ 34 | { 35 | functionName: 'ovmCALL', 36 | functionParams: { 37 | gasLimit: OVM_TX_GAS_LIMIT / 2, 38 | target: '$DUMMY_OVM_ADDRESS_1', 39 | subSteps: [ 40 | { 41 | functionName: 'ovmREVERT', 42 | revertData: '0xdeadbeef', 43 | expectedReturnStatus: false, 44 | expectedReturnValue: { 45 | flag: REVERT_FLAGS.INTENTIONAL_REVERT, 46 | data: '0xdeadbeef', 47 | nuisanceGasLeft: OVM_TX_GAS_LIMIT / 2, 48 | ovmGasRefund: 0, 49 | }, 50 | }, 51 | ], 52 | }, 53 | expectedReturnStatus: false, 54 | expectedReturnValue: '0xdeadbeef', 55 | }, 56 | ], 57 | }, 58 | // TODO: fix this. only way to do it is manually set up and call ovmREVERT directly inside a context which mirrors that during creation. 59 | // { 60 | // name: "ovmREVERT inside ovmCREATE ?", 61 | // parameters: [ 62 | // { 63 | // steps: [ 64 | // { 65 | // functionName: "ovmCALL", 66 | // functionParams: [ 67 | // GAS_LIMIT / 2, 68 | // "$DUMMY_OVM_ADDRESS_1", 69 | // [ 70 | // { 71 | // functionName: "ovmCREATE", 72 | // functionParams: [ 73 | // USELESS_BYTECODE, 74 | // false, // "create will be successful?" 75 | // [ 76 | // { 77 | // functionName: "ovmREVERT", 78 | // functionParams: [ "0xdeadbeef" ], 79 | // expectedReturnStatus: false, 80 | // expectedReturnValues: [ "0x00" ] // no return values for reversion in constructor 81 | // }, 82 | // // TODO: check internally flagged storage here 83 | // ] 84 | // ], 85 | // expectedReturnStatus: true, 86 | // expectedReturnValues: [ CREATED_CONTRACT_1 ] 87 | // } 88 | // ], 89 | // ], 90 | // expectedReturnStatus: true, 91 | // expectedReturnValues: [] 92 | // } 93 | // ] 94 | // } 95 | // ] 96 | // } 97 | ], 98 | } 99 | 100 | const runner = new ExecutionManagerTestRunner() 101 | runner.run(test_ovmREVERT) 102 | -------------------------------------------------------------------------------- /test/contracts/OVM/execution/OVM_ExecutionManager/ovmSLOAD.spec.ts: -------------------------------------------------------------------------------- 1 | /* External Imports */ 2 | import { ethers } from 'ethers' 3 | 4 | /* Internal Imports */ 5 | import { 6 | ExecutionManagerTestRunner, 7 | TestDefinition, 8 | OVM_TX_GAS_LIMIT, 9 | NON_NULL_BYTES32, 10 | getStorageXOR, 11 | } from '../../../../helpers' 12 | 13 | const test_ovmSLOAD: TestDefinition = { 14 | name: 'Basic tests for ovmSLOAD', 15 | preState: { 16 | ExecutionManager: { 17 | ovmStateManager: '$OVM_STATE_MANAGER', 18 | ovmSafetyChecker: '$OVM_SAFETY_CHECKER', 19 | messageRecord: { 20 | nuisanceGasLeft: OVM_TX_GAS_LIMIT, 21 | }, 22 | }, 23 | StateManager: { 24 | owner: '$OVM_EXECUTION_MANAGER', 25 | accounts: { 26 | $DUMMY_OVM_ADDRESS_1: { 27 | codeHash: NON_NULL_BYTES32, 28 | ethAddress: '$OVM_CALL_HELPER', 29 | }, 30 | $DUMMY_OVM_ADDRESS_2: { 31 | codeHash: NON_NULL_BYTES32, 32 | ethAddress: '$OVM_CALL_HELPER', 33 | }, 34 | }, 35 | contractStorage: { 36 | $DUMMY_OVM_ADDRESS_1: { 37 | [NON_NULL_BYTES32]: getStorageXOR(ethers.constants.HashZero), 38 | }, 39 | }, 40 | verifiedContractStorage: { 41 | $DUMMY_OVM_ADDRESS_1: { 42 | [NON_NULL_BYTES32]: true, 43 | }, 44 | }, 45 | }, 46 | }, 47 | parameters: [ 48 | { 49 | name: 'ovmCALL => ovmSLOAD', 50 | steps: [ 51 | { 52 | functionName: 'ovmCALL', 53 | functionParams: { 54 | gasLimit: OVM_TX_GAS_LIMIT, 55 | target: '$DUMMY_OVM_ADDRESS_1', 56 | subSteps: [ 57 | { 58 | functionName: 'ovmSLOAD', 59 | functionParams: { 60 | key: NON_NULL_BYTES32, 61 | }, 62 | expectedReturnStatus: true, 63 | expectedReturnValue: ethers.constants.HashZero, 64 | }, 65 | ], 66 | }, 67 | expectedReturnStatus: true, 68 | }, 69 | ], 70 | }, 71 | ], 72 | } 73 | 74 | const runner = new ExecutionManagerTestRunner() 75 | runner.run(test_ovmSLOAD) 76 | -------------------------------------------------------------------------------- /test/contracts/OVM/execution/OVM_SafetyChecker.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from '../../../setup' 2 | 3 | /* External Imports */ 4 | import { ethers } from 'hardhat' 5 | import { Contract } from 'ethers' 6 | 7 | /* Internal Imports */ 8 | import { SAFETY_CHECKER_TEST_JSON } from '../../../data' 9 | 10 | describe('OVM_SafetyChecker', () => { 11 | let OVM_SafetyChecker: Contract 12 | before(async () => { 13 | const Factory__OVM_SafetyChecker = await ethers.getContractFactory( 14 | 'OVM_SafetyChecker' 15 | ) 16 | 17 | OVM_SafetyChecker = await Factory__OVM_SafetyChecker.deploy() 18 | }) 19 | 20 | describe('isBytecodeSafe()', () => { 21 | for (const testName of Object.keys(SAFETY_CHECKER_TEST_JSON)) { 22 | const test = SAFETY_CHECKER_TEST_JSON[testName] 23 | it(`should correctly classify: ${testName}`, async () => { 24 | expect(await OVM_SafetyChecker.isBytecodeSafe(test.in)).to.equal( 25 | test.out 26 | ) 27 | }) 28 | } 29 | }) 30 | }) 31 | -------------------------------------------------------------------------------- /test/contracts/OVM/precompiles/OVM_L1MessageSender.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from '../../../setup' 2 | 3 | /* External Imports */ 4 | import { ethers } from 'hardhat' 5 | import { ContractFactory, Contract } from 'ethers' 6 | import { MockContract, smockit } from '@eth-optimism/smock' 7 | import { NON_ZERO_ADDRESS } from '../../../helpers/constants' 8 | 9 | const callPredeployStatic = async ( 10 | Helper_PredeployCaller: Contract, 11 | predeploy: Contract, 12 | functionName: string, 13 | functionParams?: any[] 14 | ): Promise => { 15 | return Helper_PredeployCaller.callStatic[functionName]( 16 | predeploy.address, 17 | predeploy.interface.encodeFunctionData(functionName, functionParams || []) 18 | ) 19 | } 20 | 21 | describe('OVM_L1MessageSender', () => { 22 | let Mock__OVM_ExecutionManager: MockContract 23 | before(async () => { 24 | Mock__OVM_ExecutionManager = await smockit( 25 | await ethers.getContractFactory('OVM_ExecutionManager') 26 | ) 27 | }) 28 | 29 | let Helper_PredeployCaller: Contract 30 | before(async () => { 31 | Helper_PredeployCaller = await ( 32 | await ethers.getContractFactory('Helper_PredeployCaller') 33 | ).deploy() 34 | 35 | Helper_PredeployCaller.setTarget(Mock__OVM_ExecutionManager.address) 36 | }) 37 | 38 | let Factory__OVM_L1MessageSender: ContractFactory 39 | before(async () => { 40 | Factory__OVM_L1MessageSender = await ethers.getContractFactory( 41 | 'OVM_L1MessageSender' 42 | ) 43 | }) 44 | 45 | let OVM_L1MessageSender: Contract 46 | beforeEach(async () => { 47 | OVM_L1MessageSender = await Factory__OVM_L1MessageSender.deploy() 48 | }) 49 | 50 | describe('getL1MessageSender', () => { 51 | before(async () => { 52 | Mock__OVM_ExecutionManager.smocked.ovmL1TXORIGIN.will.return.with( 53 | NON_ZERO_ADDRESS 54 | ) 55 | }) 56 | 57 | it('should return the L1 message sender', async () => { 58 | expect( 59 | await callPredeployStatic( 60 | Helper_PredeployCaller, 61 | OVM_L1MessageSender, 62 | 'getL1MessageSender' 63 | ) 64 | ).to.equal(NON_ZERO_ADDRESS) 65 | }) 66 | }) 67 | }) 68 | -------------------------------------------------------------------------------- /test/contracts/OVM/precompiles/OVM_L2ToL1MessagePasser.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from '../../../setup' 2 | 3 | /* External Imports */ 4 | import { ethers } from 'hardhat' 5 | import { ContractFactory, Contract } from 'ethers' 6 | import { MockContract, smockit } from '@eth-optimism/smock' 7 | import { remove0x } from '@eth-optimism/core-utils' 8 | import { keccak256 } from 'ethers/lib/utils' 9 | 10 | /* Internal Imports */ 11 | import { NON_ZERO_ADDRESS } from '../../../helpers/constants' 12 | 13 | const ELEMENT_TEST_SIZES = [1, 2, 4, 8, 16] 14 | 15 | const callPredeploy = async ( 16 | Helper_PredeployCaller: Contract, 17 | predeploy: Contract, 18 | functionName: string, 19 | functionParams?: any[] 20 | ): Promise => { 21 | return Helper_PredeployCaller.callPredeploy( 22 | predeploy.address, 23 | predeploy.interface.encodeFunctionData(functionName, functionParams || []) 24 | ) 25 | } 26 | 27 | describe('OVM_L2ToL1MessagePasser', () => { 28 | let Mock__OVM_ExecutionManager: MockContract 29 | before(async () => { 30 | Mock__OVM_ExecutionManager = await smockit( 31 | await ethers.getContractFactory('OVM_ExecutionManager') 32 | ) 33 | }) 34 | 35 | let Helper_PredeployCaller: Contract 36 | before(async () => { 37 | Helper_PredeployCaller = await ( 38 | await ethers.getContractFactory('Helper_PredeployCaller') 39 | ).deploy() 40 | 41 | Helper_PredeployCaller.setTarget(Mock__OVM_ExecutionManager.address) 42 | }) 43 | 44 | let Factory__OVM_L2ToL1MessagePasser: ContractFactory 45 | before(async () => { 46 | Factory__OVM_L2ToL1MessagePasser = await ethers.getContractFactory( 47 | 'OVM_L2ToL1MessagePasser' 48 | ) 49 | }) 50 | 51 | let OVM_L2ToL1MessagePasser: Contract 52 | beforeEach(async () => { 53 | OVM_L2ToL1MessagePasser = await Factory__OVM_L2ToL1MessagePasser.deploy() 54 | }) 55 | 56 | describe('passMessageToL1', () => { 57 | before(async () => { 58 | Mock__OVM_ExecutionManager.smocked.ovmCALLER.will.return.with( 59 | NON_ZERO_ADDRESS 60 | ) 61 | }) 62 | 63 | for (const size of ELEMENT_TEST_SIZES) { 64 | it(`should be able to pass ${size} messages`, async () => { 65 | for (let i = 0; i < size; i++) { 66 | const message = '0x' + '12' + '34'.repeat(i) 67 | 68 | await callPredeploy( 69 | Helper_PredeployCaller, 70 | OVM_L2ToL1MessagePasser, 71 | 'passMessageToL1', 72 | [message] 73 | ) 74 | 75 | expect( 76 | await OVM_L2ToL1MessagePasser.sentMessages( 77 | keccak256(message + remove0x(Helper_PredeployCaller.address)) 78 | ) 79 | ).to.equal(true) 80 | } 81 | }) 82 | } 83 | }) 84 | }) 85 | -------------------------------------------------------------------------------- /test/contracts/OVM/verification/OVM_StateTransitionerFactory.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from '../../../setup' 2 | 3 | /* External Imports */ 4 | import { ethers } from 'hardhat' 5 | import { ContractFactory, Contract, constants, Signer } from 'ethers' 6 | import { MockContract, smockit } from '@eth-optimism/smock' 7 | 8 | /* Internal Imports */ 9 | import { 10 | makeAddressManager, 11 | DUMMY_OVM_TRANSACTIONS, 12 | hashTransaction, 13 | } from '../../../helpers' 14 | 15 | const DUMMY_HASH = hashTransaction(DUMMY_OVM_TRANSACTIONS[0]) 16 | 17 | describe('OVM_StateTransitionerFactory', () => { 18 | let signer1: Signer 19 | before(async () => { 20 | ;[signer1] = await ethers.getSigners() 21 | }) 22 | 23 | let AddressManager: Contract 24 | before(async () => { 25 | AddressManager = await makeAddressManager() 26 | }) 27 | 28 | let Factory__OVM_StateTransitionerFactory: ContractFactory 29 | before(async () => { 30 | Factory__OVM_StateTransitionerFactory = await ethers.getContractFactory( 31 | 'OVM_StateTransitionerFactory' 32 | ) 33 | }) 34 | 35 | let OVM_StateTransitionerFactory: Contract 36 | let Mock__OVM_StateManagerFactory: MockContract 37 | beforeEach(async () => { 38 | OVM_StateTransitionerFactory = await Factory__OVM_StateTransitionerFactory.deploy( 39 | AddressManager.address 40 | ) 41 | 42 | Mock__OVM_StateManagerFactory = await smockit('OVM_StateManagerFactory') 43 | Mock__OVM_StateManagerFactory.smocked.create.will.return.with( 44 | ethers.constants.AddressZero 45 | ) 46 | 47 | await AddressManager.setAddress( 48 | 'OVM_StateManagerFactory', 49 | Mock__OVM_StateManagerFactory.address 50 | ) 51 | }) 52 | 53 | describe('create', () => { 54 | describe('when the sender is not the OVM_FraudVerifier', () => { 55 | beforeEach(async () => { 56 | await AddressManager.setAddress( 57 | 'OVM_FraudVerifier', 58 | constants.AddressZero 59 | ) 60 | }) 61 | 62 | it('should revert', async () => { 63 | await expect( 64 | OVM_StateTransitionerFactory.create( 65 | AddressManager.address, 66 | ethers.constants.HashZero, 67 | ethers.constants.HashZero, 68 | DUMMY_HASH 69 | ) 70 | ).to.be.revertedWith( 71 | 'Create can only be done by the OVM_FraudVerifier.' 72 | ) 73 | }) 74 | }) 75 | 76 | describe('when the sender is the OVM_FraudVerifier', () => { 77 | beforeEach(async () => { 78 | await AddressManager.setAddress( 79 | 'OVM_FraudVerifier', 80 | await signer1.getAddress() 81 | ) 82 | }) 83 | 84 | it('should not revert', async () => { 85 | await expect( 86 | OVM_StateTransitionerFactory.connect(signer1).create( 87 | AddressManager.address, 88 | ethers.constants.HashZero, 89 | ethers.constants.HashZero, 90 | DUMMY_HASH 91 | ) 92 | ).to.not.be.reverted 93 | }) 94 | }) 95 | }) 96 | }) 97 | -------------------------------------------------------------------------------- /test/contracts/libraries/codec/Lib_OVMCodec.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-empty */ 2 | import '../../../setup' 3 | 4 | /* Internal Imports */ 5 | import { Lib_OVMCodec_TEST_JSON } from '../../../data' 6 | import { runJsonTest } from '../../../helpers' 7 | 8 | describe.skip('Lib_OVMCodec', () => { 9 | describe('JSON tests', () => { 10 | runJsonTest('TestLib_OVMCodec', Lib_OVMCodec_TEST_JSON) 11 | }) 12 | }) 13 | -------------------------------------------------------------------------------- /test/contracts/libraries/rlp/Lib_RLPReader.spec.ts: -------------------------------------------------------------------------------- 1 | /* Internal Imports */ 2 | import { Lib_RLPReader_TEST_JSON } from '../../../data' 3 | import { runJsonTest } from '../../../helpers' 4 | 5 | describe('Lib_RLPReader', () => { 6 | describe('JSON tests', () => { 7 | runJsonTest('TestLib_RLPReader', Lib_RLPReader_TEST_JSON) 8 | }) 9 | }) 10 | -------------------------------------------------------------------------------- /test/contracts/libraries/rlp/Lib_RLPWriter.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-empty */ 2 | import { expect } from '../../../setup' 3 | 4 | /* External Imports */ 5 | import { ethers } from 'hardhat' 6 | import { Contract } from 'ethers' 7 | 8 | /* Internal Imports */ 9 | import { Lib_RLPWriter_TEST_JSON } from '../../../data' 10 | 11 | const encode = async (Lib_RLPWriter: Contract, input: any): Promise => { 12 | if (Array.isArray(input)) { 13 | const elements = await Promise.all( 14 | input.map(async (el) => { 15 | return encode(Lib_RLPWriter, el) 16 | }) 17 | ) 18 | 19 | return Lib_RLPWriter.writeList(elements) 20 | } else if (Number.isInteger(input)) { 21 | return Lib_RLPWriter.writeUint(input) 22 | } else { 23 | return Lib_RLPWriter.writeString(input) 24 | } 25 | } 26 | 27 | describe('Lib_RLPWriter', () => { 28 | let Lib_RLPWriter: Contract 29 | before(async () => { 30 | Lib_RLPWriter = await ( 31 | await ethers.getContractFactory('TestLib_RLPWriter') 32 | ).deploy() 33 | }) 34 | 35 | describe('Official Ethereum RLP Tests', () => { 36 | for (const [key, test] of Object.entries(Lib_RLPWriter_TEST_JSON)) { 37 | it(`should properly encode: ${key}`, async () => { 38 | expect(await encode(Lib_RLPWriter, test.in)).to.equal(test.out) 39 | }) 40 | } 41 | }) 42 | 43 | describe('Use of library with other memory-modifying operations', () => { 44 | it('should allow creation of a contract beforehand and still work', async () => { 45 | const randomAddress = '0x1234123412341234123412341234123412341234' 46 | const rlpEncodedRandomAddress = 47 | '0x941234123412341234123412341234123412341234' 48 | const encoded = await Lib_RLPWriter.callStatic.writeAddressWithTaintedMemory( 49 | randomAddress 50 | ) 51 | expect(encoded).to.eq(rlpEncodedRandomAddress) 52 | }) 53 | }) 54 | }) 55 | -------------------------------------------------------------------------------- /test/contracts/libraries/utils/Lib_Bytes32Utils.spec.ts: -------------------------------------------------------------------------------- 1 | /* Internal Imports */ 2 | import { Lib_Bytes32Utils_TEST_JSON } from '../../../data' 3 | import { runJsonTest } from '../../../helpers' 4 | 5 | describe('Lib_Bytes32Utils', () => { 6 | describe('JSON tests', () => { 7 | runJsonTest('TestLib_Bytes32Utils', Lib_Bytes32Utils_TEST_JSON) 8 | }) 9 | }) 10 | -------------------------------------------------------------------------------- /test/contracts/libraries/utils/Lib_BytesUtils.spec.ts: -------------------------------------------------------------------------------- 1 | /* Internal Imports */ 2 | import { Lib_BytesUtils_TEST_JSON } from '../../../data' 3 | import { runJsonTest } from '../../../helpers' 4 | 5 | /* External Imports */ 6 | import { ethers } from 'hardhat' 7 | import { Contract } from 'ethers' 8 | import { expect } from '../../../setup' 9 | 10 | describe('Lib_BytesUtils', () => { 11 | describe('JSON tests', () => { 12 | runJsonTest('TestLib_BytesUtils', Lib_BytesUtils_TEST_JSON) 13 | }) 14 | 15 | describe('Use of library with other memory-modifying operations', () => { 16 | let TestLib_BytesUtils: Contract 17 | before(async () => { 18 | TestLib_BytesUtils = await ( 19 | await ethers.getContractFactory('TestLib_BytesUtils') 20 | ).deploy() 21 | }) 22 | 23 | it('should allow creation of a contract beforehand and still work', async () => { 24 | const slice = await TestLib_BytesUtils.callStatic.sliceWithTaintedMemory( 25 | '0x123412341234', 26 | 0, 27 | 0 28 | ) 29 | expect(slice).to.eq('0x') 30 | }) 31 | }) 32 | }) 33 | -------------------------------------------------------------------------------- /test/contracts/libraries/utils/Lib_ECDSAUtils.spec.ts: -------------------------------------------------------------------------------- 1 | /* Internal Imports */ 2 | import { Lib_ECDSAUtils_TEST_JSON } from '../../../data' 3 | import { runJsonTest } from '../../../helpers' 4 | 5 | describe('Lib_ECDSAUtils', () => { 6 | describe('JSON tests', () => { 7 | runJsonTest('TestLib_ECDSAUtils', Lib_ECDSAUtils_TEST_JSON) 8 | }) 9 | }) 10 | -------------------------------------------------------------------------------- /test/contracts/mockOVM/verification/mockOVM_BondManager.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from '../../../setup' 2 | 3 | /* External Imports */ 4 | import { ethers } from 'hardhat' 5 | import { Signer, Contract } from 'ethers' 6 | 7 | /* Internal Imports */ 8 | import { makeAddressManager } from '../../../helpers' 9 | 10 | describe('mockOVM_BondManager', () => { 11 | let sequencer: Signer 12 | let nonSequencer: Signer 13 | before(async () => { 14 | ;[sequencer, nonSequencer] = await ethers.getSigners() 15 | }) 16 | 17 | let AddressManager: Contract 18 | before(async () => { 19 | AddressManager = await makeAddressManager() 20 | }) 21 | 22 | let mockOVM_BondManager: Contract 23 | before(async () => { 24 | mockOVM_BondManager = await ( 25 | await ethers.getContractFactory('mockOVM_BondManager') 26 | ).deploy(AddressManager.address) 27 | 28 | AddressManager.setAddress('OVM_Proposer', await sequencer.getAddress()) 29 | }) 30 | 31 | describe('isCollateralized', () => { 32 | it('should return true for OVM_Proposer', async () => { 33 | expect( 34 | await mockOVM_BondManager.isCollateralized(await sequencer.getAddress()) 35 | ).to.equal(true) 36 | }) 37 | 38 | it('should return false for non-sequencer', async () => { 39 | expect( 40 | await mockOVM_BondManager.isCollateralized( 41 | await nonSequencer.getAddress() 42 | ) 43 | ).to.equal(false) 44 | }) 45 | }) 46 | }) 47 | -------------------------------------------------------------------------------- /test/data/index.ts: -------------------------------------------------------------------------------- 1 | export { tests as Lib_RLPWriter_TEST_JSON } from './json/libraries/rlp/Lib_RLPWriter.test.json' 2 | export { tests as Lib_RLPReader_TEST_JSON } from './json/libraries/rlp/Lib_RLPReader.test.json' 3 | export { tests as Lib_Bytes32Utils_TEST_JSON } from './json/libraries/utils/Lib_Bytes32Utils.test.json' 4 | export { tests as Lib_BytesUtils_TEST_JSON } from './json/libraries/utils/Lib_BytesUtils.test.json' 5 | export { tests as Lib_ECDSAUtils_TEST_JSON } from './json/libraries/utils/Lib_ECDSAUtils.test.json' 6 | export { tests as Lib_MerkleTrie_TEST_JSON } from './json/libraries/trie/Lib_MerkleTrie.test.json' 7 | export { tests as Lib_OVMCodec_TEST_JSON } from './json/libraries/codec/Lib_OVMCodec.test.json' 8 | export { tests as CREATE2_TEST_JSON } from './json/create2.test.json' 9 | export { tests as SAFETY_CHECKER_TEST_JSON } from './json/safety-checker.test.json' 10 | -------------------------------------------------------------------------------- /test/data/json/libraries/codec/Lib_OVMCodec.test.json: -------------------------------------------------------------------------------- 1 | { 2 | "tests": { 3 | "decompressEIP155Transaction": { 4 | "decompression": { 5 | "in": [ 6 | "0x0001f4000064000064121212121212121212121212121212121212121299999999999999999999" 7 | ], 8 | "out": [ 9 | [ 10 | 100, 11 | 100000000, 12 | 500, 13 | "0x1212121212121212121212121212121212121212", 14 | 0, 15 | "0x99999999999999999999", 16 | 420 17 | ] 18 | ] 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test/data/json/libraries/utils/Lib_Bytes32Utils.test.json: -------------------------------------------------------------------------------- 1 | { 2 | "tests": { 3 | "toBool": { 4 | "input bytes32 of 0": { 5 | "in": ["0x0000000000000000000000000000000000000000000000000000000000000000"], 6 | "out": [false] 7 | }, 8 | "input bytes32 of 1": { 9 | "in": ["0x0000000000000000000000000000000000000000000000000000000000000001"], 10 | "out": [true] 11 | }, 12 | "input bytes32 > 1": { 13 | "in": ["0x1212121212121212121212121212121212121212121212121212121212121212"], 14 | "out": [true] 15 | }, 16 | "input bytes32 > 1, last byte 0": { 17 | "in": ["0x1212121212121212121212121212121212121212121212121212121212121200"], 18 | "out": [true] 19 | } 20 | }, 21 | "fromBool": { 22 | "input false": { 23 | "in": [false], 24 | "out": ["0x0000000000000000000000000000000000000000000000000000000000000000"] 25 | }, 26 | "input true": { 27 | "in": [true], 28 | "out": ["0x0000000000000000000000000000000000000000000000000000000000000001"] 29 | } 30 | }, 31 | "toAddress": { 32 | "input bytes32 address": { 33 | "in": ["0x0000000000000000000000001212121212121212121212121212121212121212"], 34 | "out": ["0x1212121212121212121212121212121212121212"] 35 | }, 36 | "input full bytes32": { 37 | "in": ["0x1212121212121212121212121212121212121212121212121212121212121212"], 38 | "out": ["0x1212121212121212121212121212121212121212"] 39 | } 40 | }, 41 | "fromAddress": { 42 | "input address": { 43 | "in": ["0x1212121212121212121212121212121212121212"], 44 | "out": ["0x0000000000000000000000001212121212121212121212121212121212121212"] 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /test/helpers/codec/bridge.ts: -------------------------------------------------------------------------------- 1 | import { getContractInterface } from '../../../src/contract-defs' 2 | 3 | export const getXDomainCalldata = ( 4 | sender: string, 5 | target: string, 6 | message: string, 7 | messageNonce: number 8 | ): string => { 9 | return getContractInterface( 10 | 'OVM_L2CrossDomainMessenger' 11 | ).encodeFunctionData('relayMessage', [target, sender, message, messageNonce]) 12 | } 13 | -------------------------------------------------------------------------------- /test/helpers/codec/index.ts: -------------------------------------------------------------------------------- 1 | export * from './revert-flags' 2 | export * from './encoding' 3 | export * from './bridge' 4 | -------------------------------------------------------------------------------- /test/helpers/codec/revert-flags.ts: -------------------------------------------------------------------------------- 1 | /* External Imports */ 2 | import { ethers } from 'hardhat' 3 | 4 | export const encodeRevertData = ( 5 | flag: number, 6 | data: string = '0x', 7 | nuisanceGasLeft: number = 0, 8 | ovmGasRefund: number = 0 9 | ): string => { 10 | const abiEncoded: string = ethers.utils.defaultAbiCoder.encode( 11 | ['uint256', 'uint256', 'uint256', 'bytes'], 12 | [flag, nuisanceGasLeft, ovmGasRefund, data] 13 | ) 14 | return abiEncoded 15 | } 16 | 17 | export const decodeRevertData = (revertData: string): any => { 18 | const decoded = ethers.utils.defaultAbiCoder.decode( 19 | ['uint256', 'uint256', 'uint256', 'bytes'], 20 | revertData 21 | ) 22 | 23 | return ( 24 | '[revertFlag:' + 25 | Object.keys(REVERT_FLAGS)[decoded[0]] + 26 | ', nuisanceGasLeft:' + 27 | decoded[1] + 28 | ', ovmGasRefund: ' + 29 | decoded[2] + 30 | ', data: ' + 31 | decoded[3] + 32 | ']' 33 | ) 34 | } 35 | 36 | export const REVERT_FLAGS = { 37 | OUT_OF_GAS: 0, 38 | INTENTIONAL_REVERT: 1, 39 | EXCEEDS_NUISANCE_GAS: 2, 40 | INVALID_STATE_ACCESS: 3, 41 | UNSAFE_BYTECODE: 4, 42 | CREATE_COLLISION: 5, 43 | STATIC_VIOLATION: 6, 44 | CREATOR_NOT_ALLOWED: 7, 45 | } 46 | -------------------------------------------------------------------------------- /test/helpers/constants.ts: -------------------------------------------------------------------------------- 1 | /* External Imports */ 2 | import { ethers } from 'ethers' 3 | import { defaultAccounts } from 'ethereum-waffle' 4 | import { fromHexString, toHexString } from '@eth-optimism/core-utils' 5 | import xor from 'buffer-xor' 6 | 7 | /* Internal Imports */ 8 | import { getContractDefinition } from '../../src' 9 | 10 | export const DEFAULT_ACCOUNTS = defaultAccounts 11 | export const DEFAULT_ACCOUNTS_HARDHAT = defaultAccounts.map((account) => { 12 | return { 13 | balance: ethers.BigNumber.from(account.balance).toHexString(), 14 | privateKey: account.secretKey, 15 | } 16 | }) 17 | 18 | export const OVM_TX_GAS_LIMIT = 10_000_000 19 | export const RUN_OVM_TEST_GAS = 20_000_000 20 | export const FORCE_INCLUSION_PERIOD_SECONDS = 600 21 | export const FORCE_INCLUSION_PERIOD_BLOCKS = 600 / 12 22 | 23 | export const NON_NULL_BYTES32 = 24 | '0x1111111111111111111111111111111111111111111111111111111111111111' 25 | export const NON_ZERO_ADDRESS = '0x1111111111111111111111111111111111111111' 26 | 27 | export const VERIFIED_EMPTY_CONTRACT_HASH = 28 | '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' 29 | 30 | export const STORAGE_XOR_VALUE = 31 | '0xFEEDFACECAFEBEEFFEEDFACECAFEBEEFFEEDFACECAFEBEEFFEEDFACECAFEBEEF' 32 | 33 | export const NUISANCE_GAS_COSTS = { 34 | NUISANCE_GAS_SLOAD: 20000, 35 | NUISANCE_GAS_SSTORE: 20000, 36 | MIN_NUISANCE_GAS_PER_CONTRACT: 30000, 37 | NUISANCE_GAS_PER_CONTRACT_BYTE: 100, 38 | MIN_GAS_FOR_INVALID_STATE_ACCESS: 30000, 39 | } 40 | 41 | let len 42 | // This is hacky, but `hardhat compile` evaluates this file for some reason. 43 | // Feels better to have something hacky then a constant we have to keep re-hardcoding. 44 | try { 45 | len = fromHexString( 46 | getContractDefinition('Helper_TestRunner').deployedBytecode 47 | ).byteLength 48 | /* tslint:disable:no-empty */ 49 | } catch {} 50 | 51 | export const Helper_TestRunner_BYTELEN = len 52 | 53 | export const STORAGE_XOR = 54 | '0xfeedfacecafebeeffeedfacecafebeeffeedfacecafebeeffeedfacecafebeef' 55 | export const getStorageXOR = (key: string): string => { 56 | return toHexString(xor(fromHexString(key), fromHexString(STORAGE_XOR))) 57 | } 58 | 59 | export const EMPTY_ACCOUNT_CODE_HASH = 60 | '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' 61 | export const KECCAK_256_NULL = 62 | '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' 63 | -------------------------------------------------------------------------------- /test/helpers/dummy/accounts.ts: -------------------------------------------------------------------------------- 1 | /* External Imports */ 2 | import { BigNumber, constants } from 'ethers' 3 | 4 | /* Internal Imports */ 5 | import { DUMMY_BYTES32 } from './bytes32' 6 | import { NON_ZERO_ADDRESS } from '../constants' 7 | import { OVMAccount } from '../types/ovm-types' 8 | 9 | export const DUMMY_ACCOUNTS: Array<{ 10 | address: string 11 | data: OVMAccount 12 | }> = [ 13 | { 14 | address: '0x1212121212121212121212121212121212121212', 15 | data: { 16 | nonce: BigNumber.from(123), 17 | balance: BigNumber.from(456), 18 | storageRoot: DUMMY_BYTES32[0], 19 | codeHash: DUMMY_BYTES32[1], 20 | ethAddress: constants.AddressZero, 21 | }, 22 | }, 23 | { 24 | address: '0x2121212121212121212121212121212121212121', 25 | data: { 26 | nonce: BigNumber.from(321), 27 | balance: BigNumber.from(654), 28 | storageRoot: DUMMY_BYTES32[2], 29 | codeHash: DUMMY_BYTES32[3], 30 | ethAddress: NON_ZERO_ADDRESS, 31 | }, 32 | }, 33 | ] 34 | -------------------------------------------------------------------------------- /test/helpers/dummy/batches.ts: -------------------------------------------------------------------------------- 1 | import { NON_ZERO_ADDRESS } from '../constants' 2 | import { ethers } from 'hardhat' 3 | 4 | export const DUMMY_BATCH_HEADERS = [ 5 | { 6 | batchIndex: 0, 7 | batchRoot: ethers.constants.HashZero, 8 | batchSize: 0, 9 | prevTotalElements: 0, 10 | extraData: ethers.utils.defaultAbiCoder.encode( 11 | ['uint256', 'address'], 12 | [ethers.constants.HashZero, NON_ZERO_ADDRESS] 13 | ), 14 | }, 15 | { 16 | batchIndex: 1, 17 | batchRoot: ethers.constants.HashZero, 18 | batchSize: 0, 19 | prevTotalElements: 0, 20 | extraData: ethers.utils.defaultAbiCoder.encode( 21 | ['uint256', 'address'], 22 | [ethers.constants.HashZero, NON_ZERO_ADDRESS] 23 | ), 24 | }, 25 | ] 26 | 27 | export const DUMMY_BATCH_PROOFS = [ 28 | { 29 | index: 0, 30 | siblings: [ethers.constants.HashZero], 31 | }, 32 | { 33 | index: 1, 34 | siblings: [ethers.constants.HashZero], 35 | }, 36 | ] 37 | -------------------------------------------------------------------------------- /test/helpers/dummy/bytecode.ts: -------------------------------------------------------------------------------- 1 | /* External Imports */ 2 | import { keccak256 } from 'ethers/lib/utils' 3 | 4 | export const DUMMY_BYTECODE = '0x123412341234' 5 | export const DUMMY_BYTECODE_BYTELEN = 6 6 | export const UNSAFE_BYTECODE = '0x6069606955' 7 | export const DUMMY_BYTECODE_HASH = keccak256(DUMMY_BYTECODE) 8 | -------------------------------------------------------------------------------- /test/helpers/dummy/bytes32.ts: -------------------------------------------------------------------------------- 1 | /* External Imports */ 2 | import { ethers } from 'ethers' 3 | 4 | export const DUMMY_BYTES32: string[] = Array.from( 5 | { 6 | length: 10, 7 | }, 8 | (_, i) => { 9 | return ethers.utils.keccak256(`0x0${i}`) 10 | } 11 | ) 12 | -------------------------------------------------------------------------------- /test/helpers/dummy/context.ts: -------------------------------------------------------------------------------- 1 | /* Internal Imports */ 2 | import { NON_ZERO_ADDRESS } from '../constants' 3 | 4 | export const DUMMY_CONTEXT = { 5 | GLOBAL: { 6 | ovmCHAINID: 11, 7 | }, 8 | TRANSACTION: { 9 | ovmORIGIN: NON_ZERO_ADDRESS, 10 | ovmTIMESTAMP: 22, 11 | ovmGASLIMIT: 33, 12 | ovmTXGASLIMIT: 44, 13 | ovmQUEUEORIGIN: 55, 14 | }, 15 | MESSAGE: { 16 | ovmCALLER: NON_ZERO_ADDRESS, 17 | ovmADDRESS: NON_ZERO_ADDRESS, 18 | ovmSTATICCTX: true, 19 | }, 20 | } 21 | -------------------------------------------------------------------------------- /test/helpers/dummy/index.ts: -------------------------------------------------------------------------------- 1 | export * from './accounts' 2 | export * from './bytes32' 3 | export * from './context' 4 | export * from './bytecode' 5 | export * from './batches' 6 | export * from './transactions' 7 | -------------------------------------------------------------------------------- /test/helpers/dummy/transactions.ts: -------------------------------------------------------------------------------- 1 | import { constants, ethers } from 'ethers' 2 | 3 | export interface Transaction { 4 | timestamp: number 5 | blockNumber: number 6 | l1QueueOrigin: number 7 | l1TxOrigin: string 8 | entrypoint: string 9 | gasLimit: number 10 | data: string 11 | } 12 | 13 | export const DUMMY_OVM_TRANSACTIONS: Array = [ 14 | ...Array(10).keys(), 15 | ].map((i) => { 16 | return { 17 | timestamp: i, 18 | blockNumber: 0, 19 | l1QueueOrigin: 0, 20 | l1TxOrigin: constants.AddressZero, 21 | entrypoint: constants.AddressZero, 22 | gasLimit: 0, 23 | data: ethers.constants.HashZero, 24 | } 25 | }) 26 | 27 | export const hashTransaction = ({ 28 | timestamp, 29 | blockNumber, 30 | l1QueueOrigin, 31 | l1TxOrigin, 32 | entrypoint, 33 | gasLimit, 34 | data, 35 | }: Transaction): string => { 36 | return ethers.utils.solidityKeccak256( 37 | ['uint256', 'uint256', 'uint8', 'address', 'address', 'uint256', 'bytes'], 38 | [ 39 | timestamp, 40 | blockNumber, 41 | l1QueueOrigin, 42 | l1TxOrigin, 43 | entrypoint, 44 | gasLimit, 45 | data, 46 | ] 47 | ) 48 | } 49 | -------------------------------------------------------------------------------- /test/helpers/gas/gas.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from 'hardhat' 2 | import { Contract, Signer } from 'ethers' 3 | 4 | export class GasMeasurement { 5 | GasMeasurementContract: Contract 6 | 7 | public async init(wallet: Signer) { 8 | this.GasMeasurementContract = await ( 9 | await (await ethers.getContractFactory('Helper_GasMeasurer')).deploy() 10 | ).connect(wallet) 11 | } 12 | 13 | public async getGasCost( 14 | targetContract: Contract, 15 | methodName: string, 16 | methodArgs: Array = [] 17 | ): Promise { 18 | const gasCost: number = await this.GasMeasurementContract.callStatic.measureCallGas( 19 | targetContract.address, 20 | targetContract.interface.encodeFunctionData(methodName, methodArgs) 21 | ) 22 | 23 | return gasCost 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test/helpers/gas/index.ts: -------------------------------------------------------------------------------- 1 | export * from './gas' 2 | -------------------------------------------------------------------------------- /test/helpers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './dummy' 2 | export * from './types' 3 | export * from './constants' 4 | export * from './resolver' 5 | export * from './utils' 6 | export * from './codec' 7 | export * from './test-runner' 8 | export * from './trie' 9 | export * from './gas' 10 | -------------------------------------------------------------------------------- /test/helpers/resolver/address-manager.ts: -------------------------------------------------------------------------------- 1 | /* External Imports */ 2 | import { ethers } from 'hardhat' 3 | import { Contract } from 'ethers' 4 | 5 | export const setProxyTarget = async ( 6 | AddressManager: Contract, 7 | name: string, 8 | target: Contract 9 | ): Promise => { 10 | const SimpleProxy: Contract = await ( 11 | await ethers.getContractFactory('Helper_SimpleProxy') 12 | ).deploy() 13 | 14 | await SimpleProxy.setTarget(target.address) 15 | await AddressManager.setAddress(name, SimpleProxy.address) 16 | } 17 | 18 | export const makeAddressManager = async (): Promise => { 19 | return (await ethers.getContractFactory('Lib_AddressManager')).deploy() 20 | } 21 | -------------------------------------------------------------------------------- /test/helpers/resolver/index.ts: -------------------------------------------------------------------------------- 1 | export * from './address-manager' 2 | -------------------------------------------------------------------------------- /test/helpers/test-runner/index.ts: -------------------------------------------------------------------------------- 1 | export * from './test-runner' 2 | export * from './test.types' 3 | export * from './json-test-runner' 4 | -------------------------------------------------------------------------------- /test/helpers/test-runner/json-test-runner.ts: -------------------------------------------------------------------------------- 1 | import { expect } from '../../setup' 2 | 3 | /* External Imports */ 4 | import { ethers } from 'hardhat' 5 | import { Contract, BigNumber } from 'ethers' 6 | 7 | const bigNumberify = (arr) => { 8 | return arr.map((el: any) => { 9 | if (typeof el === 'number') { 10 | return BigNumber.from(el) 11 | } else if (Array.isArray(el)) { 12 | return bigNumberify(el) 13 | } else { 14 | return el 15 | } 16 | }) 17 | } 18 | 19 | export const runJsonTest = (contractName: string, json: any): void => { 20 | let contract: Contract 21 | before(async () => { 22 | contract = await (await ethers.getContractFactory(contractName)).deploy() 23 | }) 24 | 25 | for (const [functionName, functionTests] of Object.entries(json)) { 26 | describe(functionName, () => { 27 | for (const [key, test] of Object.entries(functionTests)) { 28 | it(`should run test: ${key}`, async () => { 29 | if (test.revert) { 30 | await expect(contract.functions[functionName](...test.in)).to.be 31 | .reverted 32 | } else { 33 | expect( 34 | await contract.functions[functionName](...test.in) 35 | ).to.deep.equal(bigNumberify(test.out)) 36 | } 37 | }) 38 | } 39 | }) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /test/helpers/trie/index.ts: -------------------------------------------------------------------------------- 1 | export * from './trie-test-generator' 2 | -------------------------------------------------------------------------------- /test/helpers/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ovm-types' 2 | -------------------------------------------------------------------------------- /test/helpers/types/ovm-types.ts: -------------------------------------------------------------------------------- 1 | /* External Imports */ 2 | import { BigNumber } from 'ethers' 3 | 4 | export interface OVMAccount { 5 | nonce: number | BigNumber 6 | balance: number | BigNumber 7 | storageRoot: string 8 | codeHash: string 9 | ethAddress: string 10 | } 11 | -------------------------------------------------------------------------------- /test/helpers/utils/custom-deployer.ts: -------------------------------------------------------------------------------- 1 | /* External Imports */ 2 | import { Signer } from 'ethers' 3 | import { toHexString } from '@eth-optimism/core-utils' 4 | 5 | export const deployContractCode = async ( 6 | code: string, 7 | signer: Signer, 8 | gasLimit: number 9 | ): Promise => { 10 | // "Magic" prefix to be prepended to the contract code. Contains a series of opcodes that will 11 | // copy the given code into memory and return it, thereby storing at the contract address. 12 | const prefix = '0x600D380380600D6000396000f3' 13 | const deployCode = prefix + toHexString(code).slice(2) 14 | 15 | const response = await signer.sendTransaction({ 16 | to: null, 17 | data: deployCode, 18 | gasLimit, 19 | }) 20 | 21 | const result = await response.wait() 22 | return result.contractAddress 23 | } 24 | -------------------------------------------------------------------------------- /test/helpers/utils/eth-time.ts: -------------------------------------------------------------------------------- 1 | export const getEthTime = async (provider: any): Promise => { 2 | return (await provider.getBlock('latest')).timestamp 3 | } 4 | 5 | export const setEthTime = async ( 6 | provider: any, 7 | time: number 8 | ): Promise => { 9 | await provider.send('evm_setNextBlockTimestamp', [time]) 10 | } 11 | 12 | export const increaseEthTime = async ( 13 | provider: any, 14 | amount: number 15 | ): Promise => { 16 | await setEthTime(provider, (await getEthTime(provider)) + amount) 17 | await mineBlock(provider) 18 | } 19 | 20 | export const mineBlock = async ( 21 | provider: any, 22 | timestamp?: number 23 | ): Promise => { 24 | await provider.send('evm_mine', timestamp ? [timestamp] : []) 25 | } 26 | 27 | export const getBlockTime = async ( 28 | provider: any, 29 | block?: number 30 | ): Promise => { 31 | await mineBlock(provider) 32 | if (!!block) { 33 | block = await getNextBlockNumber(provider) 34 | } 35 | return (await provider.getBlock(block)).timestamp 36 | } 37 | 38 | export const getNextBlockNumber = async (provider: any): Promise => { 39 | return (await provider.getBlock('latest')).number + 1 40 | } 41 | -------------------------------------------------------------------------------- /test/helpers/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './eth-time' 2 | export * from './sol-utils' 3 | export * from './custom-deployer' 4 | -------------------------------------------------------------------------------- /test/helpers/utils/sol-utils.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from 'ethers' 2 | 3 | const errorABI = new ethers.utils.Interface([ 4 | { 5 | type: 'function', 6 | inputs: [ 7 | { 8 | type: 'string', 9 | }, 10 | ], 11 | name: 'Error', 12 | stateMutability: 'pure', 13 | }, 14 | ]) 15 | 16 | export const decodeSolidityError = (err: string): string => { 17 | return errorABI.decodeFunctionData('Error', err)[0] 18 | } 19 | 20 | export const encodeSolidityError = (message: string): string => { 21 | return errorABI.encodeFunctionData('Error', [message]) 22 | } 23 | -------------------------------------------------------------------------------- /test/setup.ts: -------------------------------------------------------------------------------- 1 | /* External Imports */ 2 | import chai = require('chai') 3 | import Mocha from 'mocha' 4 | import { solidity } from 'ethereum-waffle' 5 | 6 | chai.use(solidity) 7 | const should = chai.should() 8 | const expect = chai.expect 9 | 10 | export { should, expect, Mocha } 11 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es2017", 5 | "declaration": true, 6 | "noImplicitAny": false, 7 | "noUnusedLocals": true, 8 | "removeComments": true, 9 | "noLib": false, 10 | "emitDecoratorMetadata": true, 11 | "experimentalDecorators": true, 12 | "sourceMap": true, 13 | "outDir": "./build", 14 | "baseUrl": "./", 15 | "resolveJsonModule": true, 16 | "esModuleInterop": true, 17 | "lib": [ 18 | "es7" 19 | ], 20 | "typeRoots": [ 21 | "node_modules/@types" 22 | ] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@eth-optimism/dev/tslint.json", 3 | "rules": { 4 | "array-type": false, 5 | "class-name": false, 6 | "prefer-conditional-expression": false 7 | } 8 | } 9 | --------------------------------------------------------------------------------