Commit 8674d465 authored by Mark Tyneway's avatar Mark Tyneway Committed by GitHub

Merge pull request #3033 from ethereum-optimism/develop

Develop -> Master PR
parents 975d77c3 79ca7e1a
---
'@eth-optimism/contracts-bedrock': patch
---
Clean up BytesUtils
---
'@eth-optimism/foundry': patch
---
Bump foundry to 3c49efe58ca4bdeec4729490501da06914446405
---
'@eth-optimism/contracts-bedrock': patch
---
Updates CrossDomainMessenger.baseGas to more accurately reflect gas costs
---
'@eth-optimism/contracts-bedrock': patch
---
Cleans up natspec in MerkleTrie and SecureMerkleTrie contracts
---
'@eth-optimism/ci-builder': minor
---
Fix unbound variable in check_changed script
This now uses -z to check if a variable is unbound instead of -n.
This should fix the error when the script is being ran on develop.
---
'@eth-optimism/contracts-bedrock': patch
---
Cleans up various compiler warnings
---
'@eth-optimism/contracts-bedrock': patch
---
Minor cleanups to initialization and semver for L1 contracts
---
'@eth-optimism/contracts-bedrock': patch
---
Clears most contract linting warnings
---
'@eth-optimism/fault-detector': patch
---
Properly handle connection failures for L2 node
...@@ -139,7 +139,7 @@ jobs: ...@@ -139,7 +139,7 @@ jobs:
name: gas snapshot name: gas snapshot
command: | command: |
forge --version forge --version
forge snapshot --check forge snapshot --check || exit 0
working_directory: packages/contracts-bedrock working_directory: packages/contracts-bedrock
- run: - run:
name: storage snapshot name: storage snapshot
......
...@@ -11,7 +11,7 @@ jobs: ...@@ -11,7 +11,7 @@ jobs:
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Install Dependencies - name: Install Dependencies
uses: yarn run: yarn
- name: Changeset Status - name: Changeset Status
run: npx changeset status run: npx changeset status
...@@ -27,8 +27,6 @@ jobs: ...@@ -27,8 +27,6 @@ jobs:
batch-submitter-service: ${{ steps.packages.outputs.batch-submitter-service }} batch-submitter-service: ${{ steps.packages.outputs.batch-submitter-service }}
indexer: ${{ steps.packages.outputs.indexer }} indexer: ${{ steps.packages.outputs.indexer }}
teleportr: ${{ steps.packages.outputs.teleportr }} teleportr: ${{ steps.packages.outputs.teleportr }}
go-builder: ${{ steps.packages.outputs.go-builder }}
js-builder: ${{ steps.packages.outputs.js-builder }}
ci-builder: ${{ steps.packages.outputs.ci-builder }} ci-builder: ${{ steps.packages.outputs.ci-builder }}
foundry: ${{ steps.packages.outputs.foundry }} foundry: ${{ steps.packages.outputs.foundry }}
...@@ -159,58 +157,6 @@ jobs: ...@@ -159,58 +157,6 @@ jobs:
push: true push: true
tags: ethereumoptimism/hardhat-node:${{ needs.release.outputs.gas-oracle }},ethereumoptimism/hardhat-node:latest tags: ethereumoptimism/hardhat-node:${{ needs.release.outputs.gas-oracle }},ethereumoptimism/hardhat-node:latest
go-builder:
name: Publish go-builder ${{ needs.release.outputs.go-builder }}
needs: release
if: needs.release.outputs.go-builder != ''
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Publish go-builder
uses: docker/build-push-action@v2
with:
context: .
file: ./ops/docker/go-builder/Dockerfile
push: true
tags: ethereumoptimism/go-builder:${{ needs.release.outputs.go-builder }},ethereumoptimism/go-builder:latest
js-builder:
name: Publish js-builder ${{ needs.release.outputs.js-builder }}
needs: release
if: needs.release.outputs.js-builder != ''
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Publish js-builder
uses: docker/build-push-action@v2
with:
context: .
file: ./ops/docker/js-builder/Dockerfile
push: true
tags: ethereumoptimism/js-builder:${{ needs.release.outputs.js-builder }},ethereumoptimism/js-builder:latest
ci-builder: ci-builder:
name: Publish ci-builder ${{ needs.release.outputs.ci-builder }} name: Publish ci-builder ${{ needs.release.outputs.ci-builder }}
needs: release needs: release
......
...@@ -39,7 +39,7 @@ type HashingOutputRootProof struct { ...@@ -39,7 +39,7 @@ type HashingOutputRootProof struct {
// OptimismPortalMetaData contains all meta data concerning the OptimismPortal contract. // OptimismPortalMetaData contains all meta data concerning the OptimismPortal contract.
var OptimismPortalMetaData = &bind.MetaData{ var OptimismPortalMetaData = &bind.MetaData{
ABI: "[{\"inputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"_l2Oracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_finalizationPeriodSeconds\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mint\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"gasLimit\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isCreation\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"TransactionDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"withdrawalHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"WithdrawalFinalized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BASE_FEE_MAX_CHANGE_DENOMINATOR\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ELASTICITY_MULTIPLIER\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FINALIZATION_PERIOD_SECONDS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"INITIAL_BASE_FEE\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_ORACLE\",\"outputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAJOR_VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_RESOURCE_LIMIT\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINIMUM_BASE_FEE\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINOR_VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PATCH_VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TARGET_RESOURCE_LIMIT\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"depositTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"withdrawerStorageRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"latestBlockhash\",\"type\":\"bytes32\"}],\"internalType\":\"structHashing.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"_withdrawalProof\",\"type\":\"bytes\"}],\"name\":\"finalizeWithdrawalTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"finalizedWithdrawals\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"name\":\"isOutputFinalized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Sender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"params\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"prevBaseFee\",\"type\":\"uint128\"},{\"internalType\":\"uint64\",\"name\":\"prevBoughtGas\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"prevBlockNum\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", ABI: "[{\"inputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"_l2Oracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_finalizationPeriodSeconds\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mint\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"gasLimit\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isCreation\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"TransactionDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"withdrawalHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"WithdrawalFinalized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BASE_FEE_MAX_CHANGE_DENOMINATOR\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ELASTICITY_MULTIPLIER\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FINALIZATION_PERIOD_SECONDS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"INITIAL_BASE_FEE\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_ORACLE\",\"outputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAJOR_VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_RESOURCE_LIMIT\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINIMUM_BASE_FEE\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINOR_VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PATCH_VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TARGET_RESOURCE_LIMIT\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"depositTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"withdrawerStorageRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"latestBlockhash\",\"type\":\"bytes32\"}],\"internalType\":\"structHashing.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"_withdrawalProof\",\"type\":\"bytes\"}],\"name\":\"finalizeWithdrawalTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"finalizedWithdrawals\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"name\":\"isOutputFinalized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Sender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"params\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"prevBaseFee\",\"type\":\"uint128\"},{\"internalType\":\"uint64\",\"name\":\"prevBoughtGas\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"prevBlockNum\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]",
Bin: "0x6101206040523480156200001257600080fd5b5060405162003f2b38038062003f2b833981016040819052620000359162000285565b60008060016200007460408051606081018252633b9aca0080825260006020830152436001600160401b031691909201819052600160c01b0217600155565b60809290925260a05260c0526001600160a01b0382166101005260e08190526200009d620000a5565b5050620002c1565b6000620000b3600162000164565b90508015620000cc576000805461ff0019166101001790555b603380546001600160a01b03191661dead1790556200011a60408051606081018252633b9aca0080825260006020830152436001600160401b031691909201819052600160c01b0217600155565b801562000161576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b60008054610100900460ff1615620001fd578160ff1660011480156200019d57506200019b306200027660201b620014801760201c565b155b620001f55760405162461bcd60e51b815260206004820152602e602482015260008051602062003f0b83398151915260448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b506000919050565b60005460ff8084169116106200025c5760405162461bcd60e51b815260206004820152602e602482015260008051602062003f0b83398151915260448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620001ec565b506000805460ff191660ff92909216919091179055600190565b6001600160a01b03163b151590565b600080604083850312156200029957600080fd5b82516001600160a01b0381168114620002b157600080fd5b6020939093015192949293505050565b60805160a05160c05160e05161010051613bd4620003376000396000818161016a0152818161099101528181610a0801528181610a9b01528181610b6d0152610f0a01526000818161044c01528181610c1f0152610f8d0152600061023b01526000610327015260006104800152613bd46000f3fe60806040526004361061012c5760003560e01c8063a14238e7116100a5578063cff0ab9611610074578063eecf1c3611610059578063eecf1c3614610427578063f4daa2911461043a578063f786becd1461046e57600080fd5b8063cff0ab9614610373578063e9e05c421461041457600080fd5b8063a14238e7146102e5578063c8b9153114610315578063ca3e99ba14610349578063cd7c97891461035e57600080fd5b80636bf2606a116100fc5780638129fc1c116100e15780638129fc1c1461028d578063867ead13146102a25780639bf62d82146102b857600080fd5b80636bf2606a146102295780636dbffb781461025d57600080fd5b80621c2ff61461015857806313620abd146101b657806364b79208146101ef5780636bb0291e1461021457600080fd5b36610153576101513334620186a06000604051806020016040528060008152506104a2565b005b600080fd5b34801561016457600080fd5b5061018c7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101c257600080fd5b506101ce633b9aca0081565b6040516fffffffffffffffffffffffffffffffff90911681526020016101ad565b3480156101fb57600080fd5b50610206627a120081565b6040519081526020016101ad565b34801561022057600080fd5b50610206600481565b34801561023557600080fd5b506102067f000000000000000000000000000000000000000000000000000000000000000081565b34801561026957600080fd5b5061027d6102783660046132bd565b610948565b60405190151581526020016101ad565b34801561029957600080fd5b50610151610c56565b3480156102ae57600080fd5b5061020661271081565b3480156102c457600080fd5b5060335461018c9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156102f157600080fd5b5061027d6103003660046132bd565b60346020526000908152604090205460ff1681565b34801561032157600080fd5b506102067f000000000000000000000000000000000000000000000000000000000000000081565b34801561035557600080fd5b50610206610d78565b34801561036a57600080fd5b50610206600881565b34801561037f57600080fd5b506001546103db906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101ad565b610151610422366004613378565b6104a2565b6101516104353660046134c2565b610d89565b34801561044657600080fd5b506102067f000000000000000000000000000000000000000000000000000000000000000081565b34801561047a57600080fd5b506102067f000000000000000000000000000000000000000000000000000000000000000081565b8260005a905083156105595773ffffffffffffffffffffffffffffffffffffffff87161561055957604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b3332811461057a575033731111000000000000000000000000000000001111015b8773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f0195348a8a8a8a6040516105df95949392919061362d565b60405180910390a35060015460009061061e907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643613693565b905080156107a75760006106366004627a12006136d9565b6001546106619190700100000000000000000000000000000000900467ffffffffffffffff16613741565b9050600060086106756004627a12006136d9565b6001546106959085906fffffffffffffffffffffffffffffffff166137b5565b61069f91906136d9565b6106a991906136d9565b6001549091506000906106f5906106df906106d79085906fffffffffffffffffffffffffffffffff16613871565b61271061149c565b6fffffffffffffffffffffffffffffffff6114b7565b90506001841115610768576107656106df670de0b6b3a764000061075161071d6008836136d9565b61072f90670de0b6b3a7640000613741565b61073a60018a613693565b61074c90670de0b6b3a76400006138e5565b6114c6565b61075b90856137b5565b6106d791906136d9565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b600180548491906010906107da908490700100000000000000000000000000000000900467ffffffffffffffff16613922565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550627a1200600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff1613156108b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603c60248201527f4f7074696d69736d506f7274616c3a2063616e6e6f7420627579206d6f72652060448201527f676173207468616e20617661696c61626c6520676173206c696d6974000000006064820152608401610550565b6001546000906108e2906fffffffffffffffffffffffffffffffff1667ffffffffffffffff861661394e565b6fffffffffffffffffffffffffffffffff169050600061090648633b9aca006114f7565b6109109083613986565b905060005a61091f9086613693565b90508082111561093b5761093b6109368284613693565b611507565b5050505050505050505050565b6040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101829052600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae557906024016040805180830381865afa1580156109d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109fb919061399a565b8051909150610c1d5760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663529933df6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a9591906139e9565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16634ab65d736040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b2891906139e9565b905084811115610b3d57506000949350505050565b600082610b4a8388613693565b610b549190613a02565b905073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663a25ae557610b9c8386613693565b610ba69089613a16565b6040518263ffffffff1660e01b8152600401610bc491815260200190565b6040805180830381865afa158015610be0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c04919061399a565b8051909450610c195750600095945050505050565b5050505b7f00000000000000000000000000000000000000000000000000000000000000008160200151610c4d9190613a16565b42119392505050565b6000610c626001611535565b90508015610c9757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603380547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055610d1260408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b8015610d7557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b610d866004627a12006136d9565b81565b60335473ffffffffffffffffffffffffffffffffffffffff1661dead14610e32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e006064820152608401610550565b73ffffffffffffffffffffffffffffffffffffffff8916301415610ed8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e7472616374006064820152608401610550565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae557906024016040805180830381865afa158015610f65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f89919061399a565b90507f00000000000000000000000000000000000000000000000000000000000000008160200151610fbb9190613a16565b4211611049576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4f7074696d69736d506f7274616c3a2070726f706f73616c206973206e6f742060448201527f7965742066696e616c697a6564000000000000000000000000000000000000006064820152608401610550565b61106061105b36869003860186613a2e565b6116c0565b8151146110ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f6600000000000000000000000000000000000000000000006064820152608401610550565b60006111358d8d8d8d8d8d8d8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061171c92505050565b905061117c81866040013586868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061175b92505050565b611208576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610550565b60008181526034602052604090205460ff16156112a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610550565b600081815260346020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556112ea614e208a613a16565b5a1015611379576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a20696e73756666696369656e742067617360448201527f20746f2066696e616c697a65207769746864726177616c0000000000000000006064820152608401610550565b603380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8e16179055604080516020601f8a01819004810282018101909252888152600091611402918e918d918f918691908f908f908190840183828082843760009201919091525061182492505050565b50603380547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915082907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b9061146890841515815260200190565b60405180910390a25050505050505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6000818312156114ac57816114ae565b825b90505b92915050565b60008183126114ac57816114ae565b60006114ae670de0b6b3a7640000836114de866118af565b6114e891906137b5565b6114f291906136d9565b611af3565b6000818310156114ac57816114ae565b6000805a90505b825a61151a9083613693565b10156115305761152982613a94565b915061150e565b505050565b60008054610100900460ff16156115ec578160ff1660011480156115585750303b155b6115e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610550565b506000919050565b60005460ff808416911610611683576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610550565b50600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff92909216919091179055600190565b919050565b600081600001518260200151836040015184606001516040516020016116ff949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b600086868686868660405160200161173996959493929190613acd565b6040516020818303038152906040528051906020012090509695505050505050565b604080516020810185905260009181018290528190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506118199101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f01000000000000000000000000000000000000000000000000000000000000006020830152908587611d32565b9150505b9392505050565b6000606060008060008661ffff1667ffffffffffffffff81111561184a5761184a6132fa565b6040519080825280601f01601f191660200182016040528015611874576020820181803683370190505b5090506000808751602089018b8e8ef191503d925086831115611895578692505b828152826000602083013e90999098509650505050505050565b600080821361191a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610550565b6000606061192784611d56565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c18213611b2457506000919050565b680755bf798b4a1bf1e58212611b96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610550565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b600080611d3e86611e2c565b9050611d4c81868686611e5e565b9695505050505050565b6000808211611dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610550565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b60608180519060200120604051602001611e4891815260200190565b6040516020818303038152906040529050919050565b6000806000611e6e878686611e9b565b91509150818015611e9057508051602080830191909120875191880191909120145b979650505050505050565b600060606000611eaa85611f90565b90506000806000611ebc848a8961208b565b81519295509093509150158080611ed05750815b611f36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e0000000000006044820152606401610550565b600081611f525760405180602001604052806000815250611f7e565b611f7e86611f61600188613693565b81518110611f7157611f71613b24565b60200260200101516125a8565b919b919a509098505050505050505050565b60606000611f9d836125d2565b90506000815167ffffffffffffffff811115611fbb57611fbb6132fa565b60405190808252806020026020018201604052801561200057816020015b6040805180820190915260608082526020820152815260200190600190039081611fd95790505b50905060005b825181101561208357600061203384838151811061202657612026613b24565b6020026020010151612605565b9050604051806040016040528082815260200161204f836125d2565b81525083838151811061206457612064613b24565b602002602001018190525050808061207b90613a94565b915050612006565b509392505050565b6000606081808061209b876126af565b905060008690506000806120c2604051806040016040528060608152602001606081525090565b60005b8c51811015612564578c81815181106120e0576120e0613b24565b6020026020010151915082846120f69190613a16565b9350612103600188613a16565b9650836121815781518051602090910120851461217c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f496e76616c696420726f6f7420686173680000000000000000000000000000006044820152606401610550565b612272565b8151516020116121fd5781518051602090910120851461217c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c206861736800000000006044820152606401610550565b8461220b8360000151612832565b14612272576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f646520686173680000000000006044820152606401610550565b61227e60106001613a16565b82602001515114156122f757855184141561229857612564565b60008685815181106122ac576122ac613b24565b602001015160f81c60f81b60f81c9050600083602001518260ff16815181106122d7576122d7613b24565b602002602001015190506122ea8161285a565b9650600194505050612552565b600282602001515114156124f057600061231083612890565b905060008160008151811061232757612327613b24565b016020015160f81c9050600061233e600283613b53565b612349906002613b75565b9050600061235a848360ff166128b4565b905060006123688b8a6128b4565b9050600061237683836128ea565b905060ff85166002148061238d575060ff85166003145b156123e3578083511480156123a25750808251145b156123b4576123b1818b613a16565b99505b507f80000000000000000000000000000000000000000000000000000000000000009950612564945050505050565b60ff851615806123f6575060ff85166001145b15612468578251811461243257507f80000000000000000000000000000000000000000000000000000000000000009950612564945050505050565b612459886020015160018151811061244c5761244c613b24565b602002602001015161285a565b9a509750612552945050505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e2060448201527f70726566697800000000000000000000000000000000000000000000000000006064820152608401610550565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e0000006044820152606401610550565b8061255c81613a94565b9150506120c5565b507f800000000000000000000000000000000000000000000000000000000000000084148661259387866128b4565b909e909d50909b509950505050505050505050565b602081015180516060916114b1916125c290600190613693565b8151811061202657612026613b24565b6040805180820182526000808252602091820152815180830190925282518252808301908201526060906114b190612996565b6060600080600061261585612bc9565b91945092509050600081600181111561263057612630613b98565b14612697576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e00000000000000006044820152606401610550565b6126a685602001518484612fd0565b95945050505050565b60606000825160026126c191906138e5565b67ffffffffffffffff8111156126d9576126d96132fa565b6040519080825280601f01601f191660200182016040528015612703576020820181803683370190505b50905060005b835181101561282b57600484828151811061272657612726613b24565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c8261275b8360026138e5565b8151811061276b5761276b613b24565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060108482815181106127ae576127ae613b24565b01602001516127c0919060f81c613b53565b60f81b826127cf8360026138e5565b6127da906001613a16565b815181106127ea576127ea613b24565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508061282381613a94565b915050612709565b5092915050565b600060208251101561284657506020015190565b818060200190518101906114b191906139e9565b6000606060208360000151101561287b57612874836130af565b9050612887565b61288483612605565b90505b61181d81612832565b60606114b16128af836020015160008151811061202657612026613b24565b6126af565b6060825182106128d357506040805160208101909152600081526114b1565b6114ae83838486516128e59190613693565b6130ba565b6000805b8084511180156128fe5750808351115b801561297f575082818151811061291757612917613b24565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191684828151811061295657612956613b24565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156114ae578061298e81613a94565b9150506128ee565b60606000806129a484612bc9565b919350909150600190508160018111156129c0576129c0613b98565b14612a27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e0000000000000000006044820152606401610550565b6040805160208082526104208201909252600091816020015b6040805180820190915260008082526020820152815260200190600190039081612a405790505090506000835b8651811015612bbe5760208210612b06576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201527f7374206c656e6774682e000000000000000000000000000000000000000000006064820152608401610550565b600080612b436040518060400160405280858c60000151612b279190613693565b8152602001858c60200151612b3c9190613a16565b9052612bc9565b509150915060405180604001604052808383612b5f9190613a16565b8152602001848b60200151612b749190613a16565b815250858581518110612b8957612b89613b24565b6020908102919091010152612b9f600185613a16565b9350612bab8183613a16565b612bb59084613a16565b92505050612a6d565b508152949350505050565b600080600080846000015111612c3b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e00000000000000006044820152606401610550565b6020840151805160001a607f8111612c60576000600160009450945094505050612fc9565b60b78111612cf6576000612c75608083613693565b905080876000015111612ce4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e000000000000006044820152606401610550565b60019550935060009250612fc9915050565b60bf8111612e19576000612d0b60b783613693565b905080876000015111612d7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e006044820152606401610550565b600183015160208290036101000a9004612d948183613a16565b885111612dfd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e00000000000000006044820152606401610550565b612e08826001613a16565b9650945060009350612fc992505050565b60f78111612eae576000612e2e60c083613693565b905080876000015111612e9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e0000000000000000006044820152606401610550565b600195509350849250612fc9915050565b6000612ebb60f783613693565b905080876000015111612f2a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e0000006044820152606401610550565b600183015160208290036101000a9004612f448183613a16565b885111612fad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f496e76616c696420524c50206c6f6e67206c6973742e000000000000000000006044820152606401610550565b612fb8826001613a16565b9650945060019350612fc992505050565b9193909250565b606060008267ffffffffffffffff811115612fed57612fed6132fa565b6040519080825280601f01601f191660200182016040528015613017576020820181803683370190505b50905080516000141561302b57905061181d565b60006130378587613a16565b90506020820160005b61304b602087613986565b8110156130825782518252613061602084613a16565b925061306e602083613a16565b91508061307a81613a94565b915050613040565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b60606114b1826132a7565b6060816130c881601f613a16565b1015613130576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610550565b8261313b8382613a16565b10156131a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610550565b6131ad8284613a16565b84511015613217576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610550565b606082158015613236576040519150600082526020820160405261329e565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561326f578051835260209283019201613257565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60606114b1826020015160008460000151612fd0565b6000602082840312156132cf57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff811681146116bb57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613370576133706132fa565b604052919050565b600080600080600060a0868803121561339057600080fd5b613399866132d6565b94506020808701359450604087013567ffffffffffffffff80821682146133bf57600080fd5b90945060608801359081151582146133d657600080fd5b909350608088013590808211156133ec57600080fd5b818901915089601f83011261340057600080fd5b813581811115613412576134126132fa565b613442847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613329565b91508082528a8482850101111561345857600080fd5b80848401858401376000848284010152508093505050509295509295909350565b60008083601f84011261348b57600080fd5b50813567ffffffffffffffff8111156134a357600080fd5b6020830191508360208285010111156134bb57600080fd5b9250929050565b60008060008060008060008060008060006101808c8e0312156134e457600080fd5b8b359a506134f460208d016132d6565b995061350260408d016132d6565b985060608c0135975060808c0135965067ffffffffffffffff60a08d0135111561352b57600080fd5b61353b8d60a08e01358e01613479565b909650945060c08c0135935060808c8e037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2001121561357957600080fd5b60e08c01925067ffffffffffffffff6101608d0135111561359957600080fd5b6135aa8d6101608e01358e01613479565b81935080925050509295989b509295989b9093969950565b6000815180845260005b818110156135e8576020818501810151868301820152016135cc565b818111156135fa576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b85815284602082015267ffffffffffffffff84166040820152821515606082015260a060808201526000611e9060a08301846135c2565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156136a5576136a5613664565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826136e8576136e86136aa565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561373c5761373c613664565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561377b5761377b613664565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156137af576137af613664565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156137f6576137f6613664565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561383157613831613664565b6000871292508782058712848416161561384d5761384d613664565b8785058712818416161561386357613863613664565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156138ab576138ab613664565b827f80000000000000000000000000000000000000000000000000000000000000000384128116156138df576138df613664565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561391d5761391d613664565b500290565b600067ffffffffffffffff80831681851680830382111561394557613945613664565b01949350505050565b60006fffffffffffffffffffffffffffffffff8083168185168183048111821515161561397d5761397d613664565b02949350505050565b600082613995576139956136aa565b500490565b6000604082840312156139ac57600080fd5b6040516040810181811067ffffffffffffffff821117156139cf576139cf6132fa565b604052825181526020928301519281019290925250919050565b6000602082840312156139fb57600080fd5b5051919050565b600082613a1157613a116136aa565b500690565b60008219821115613a2957613a29613664565b500190565b600060808284031215613a4057600080fd5b6040516080810181811067ffffffffffffffff82111715613a6357613a636132fa565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613ac657613ac6613664565b5060010190565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152613b1860c08301846135c2565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff831680613b6657613b666136aa565b8060ff84160691505092915050565b600060ff821660ff841680821015613b8f57613b8f613664565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080a000a496e697469616c697a61626c653a20636f6e747261637420697320616c726561", Bin: "0x6101206040523480156200001257600080fd5b5060405162004005380380620040058339810160408190526200003591620002bc565b6000608081905260a052600160c0526001600160a01b0382166101005260e08190526200006162000069565b5050620002f8565b6000620000776001620000f8565b9050801562000090576000805461ff0019166101001790555b603380546001600160a01b03191661dead179055620000ae6200020a565b8015620000f5576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b60008054610100900460ff161562000191578160ff1660011480156200013157506200012f30620002ad60201b620014391760201c565b155b620001895760405162461bcd60e51b815260206004820152602e602482015260008051602062003fe583398151915260448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b506000919050565b60005460ff808416911610620001f05760405162461bcd60e51b815260206004820152602e602482015260008051602062003fe583398151915260448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840162000180565b506000805460ff191660ff92909216919091179055600190565b600054610100900460ff16620002775760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840162000180565b60408051606081018252633b9aca0080825260006020830152436001600160401b031691909201819052600160c01b0217600155565b6001600160a01b03163b151590565b60008060408385031215620002d057600080fd5b82516001600160a01b0381168114620002e857600080fd5b6020939093015192949293505050565b60805160a05160c05160e05161010051613c776200036e6000396000818161016a0152818161099101528181610a0801528181610a9b01528181610b6d0152610ec301526000818161044c01528181610c1f0152610f460152600061023b01526000610327015260006104800152613c776000f3fe60806040526004361061012c5760003560e01c8063a14238e7116100a5578063cff0ab9611610074578063eecf1c3611610059578063eecf1c3614610427578063f4daa2911461043a578063f786becd1461046e57600080fd5b8063cff0ab9614610373578063e9e05c421461041457600080fd5b8063a14238e7146102e5578063c8b9153114610315578063ca3e99ba14610349578063cd7c97891461035e57600080fd5b80636bf2606a116100fc5780638129fc1c116100e15780638129fc1c1461028d578063867ead13146102a25780639bf62d82146102b857600080fd5b80636bf2606a146102295780636dbffb781461025d57600080fd5b80621c2ff61461015857806313620abd146101b657806364b79208146101ef5780636bb0291e1461021457600080fd5b36610153576101513334620186a06000604051806020016040528060008152506104a2565b005b600080fd5b34801561016457600080fd5b5061018c7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101c257600080fd5b506101ce633b9aca0081565b6040516fffffffffffffffffffffffffffffffff90911681526020016101ad565b3480156101fb57600080fd5b50610206627a120081565b6040519081526020016101ad565b34801561022057600080fd5b50610206600481565b34801561023557600080fd5b506102067f000000000000000000000000000000000000000000000000000000000000000081565b34801561026957600080fd5b5061027d61027836600461331b565b610948565b60405190151581526020016101ad565b34801561029957600080fd5b50610151610c56565b3480156102ae57600080fd5b5061020661271081565b3480156102c457600080fd5b5060335461018c9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156102f157600080fd5b5061027d61030036600461331b565b60346020526000908152604090205460ff1681565b34801561032157600080fd5b506102067f000000000000000000000000000000000000000000000000000000000000000081565b34801561035557600080fd5b50610206610d31565b34801561036a57600080fd5b50610206600881565b34801561037f57600080fd5b506001546103db906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101ad565b6101516104223660046133d6565b6104a2565b610151610435366004613520565b610d42565b34801561044657600080fd5b506102067f000000000000000000000000000000000000000000000000000000000000000081565b34801561047a57600080fd5b506102067f000000000000000000000000000000000000000000000000000000000000000081565b8260005a905083156105595773ffffffffffffffffffffffffffffffffffffffff87161561055957604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b3332811461057a575033731111000000000000000000000000000000001111015b8773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f0195348a8a8a8a6040516105df95949392919061368b565b60405180910390a35060015460009061061e907801000000000000000000000000000000000000000000000000900467ffffffffffffffff16436136f1565b905080156107a75760006106366004627a1200613737565b6001546106619190700100000000000000000000000000000000900467ffffffffffffffff1661379f565b9050600060086106756004627a1200613737565b6001546106959085906fffffffffffffffffffffffffffffffff16613813565b61069f9190613737565b6106a99190613737565b6001549091506000906106f5906106df906106d79085906fffffffffffffffffffffffffffffffff166138cf565b612710611455565b6fffffffffffffffffffffffffffffffff611470565b90506001841115610768576107656106df670de0b6b3a764000061075161071d600883613737565b61072f90670de0b6b3a764000061379f565b61073a60018a6136f1565b61074c90670de0b6b3a7640000613943565b61147f565b61075b9085613813565b6106d79190613737565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b600180548491906010906107da908490700100000000000000000000000000000000900467ffffffffffffffff16613980565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550627a1200600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff1613156108b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603c60248201527f4f7074696d69736d506f7274616c3a2063616e6e6f7420627579206d6f72652060448201527f676173207468616e20617661696c61626c6520676173206c696d6974000000006064820152608401610550565b6001546000906108e2906fffffffffffffffffffffffffffffffff1667ffffffffffffffff86166139ac565b6fffffffffffffffffffffffffffffffff169050600061090648633b9aca006114b0565b61091090836139e4565b905060005a61091f90866136f1565b90508082111561093b5761093b61093682846136f1565b6114c0565b5050505050505050505050565b6040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101829052600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae557906024016040805180830381865afa1580156109d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109fb91906139f8565b8051909150610c1d5760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663529933df6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a959190613a47565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16634ab65d736040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b289190613a47565b905084811115610b3d57506000949350505050565b600082610b4a83886136f1565b610b549190613a60565b905073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663a25ae557610b9c83866136f1565b610ba69089613a74565b6040518263ffffffff1660e01b8152600401610bc491815260200190565b6040805180830381865afa158015610be0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c0491906139f8565b8051909450610c195750600095945050505050565b5050505b7f00000000000000000000000000000000000000000000000000000000000000008160200151610c4d9190613a74565b42119392505050565b6000610c6260016114ee565b90508015610c9757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603380547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055610ccb611679565b8015610d2e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b610d3f6004627a1200613737565b81565b60335473ffffffffffffffffffffffffffffffffffffffff1661dead14610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e006064820152608401610550565b73ffffffffffffffffffffffffffffffffffffffff8916301415610e91576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e7472616374006064820152608401610550565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae557906024016040805180830381865afa158015610f1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4291906139f8565b90507f00000000000000000000000000000000000000000000000000000000000000008160200151610f749190613a74565b4211611002576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4f7074696d69736d506f7274616c3a2070726f706f73616c206973206e6f742060448201527f7965742066696e616c697a6564000000000000000000000000000000000000006064820152608401610550565b61101961101436869003860186613a8c565b61175c565b8151146110a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f6600000000000000000000000000000000000000000000006064820152608401610550565b60006110ee8d8d8d8d8d8d8d8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117b892505050565b905061113581866040013586868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117f792505050565b6111c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610550565b60008181526034602052604090205460ff1615611260576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610550565b600081815260346020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556112a3614e208a613a74565b5a1015611332576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a20696e73756666696369656e742067617360448201527f20746f2066696e616c697a65207769746864726177616c0000000000000000006064820152608401610550565b603380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8e16179055604080516020601f8a018190048102820181019092528881526000916113bb918e918d918f918691908f908f90819084018382808284376000920191909152506118c092505050565b50603380547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915082907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b9061142190841515815260200190565b60405180910390a25050505050505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6000818312156114655781611467565b825b90505b92915050565b60008183126114655781611467565b6000611467670de0b6b3a7640000836114978661194b565b6114a19190613813565b6114ab9190613737565b611b8f565b6000818310156114655781611467565b6000805a90505b825a6114d390836136f1565b10156114e9576114e282613af2565b91506114c7565b505050565b60008054610100900460ff16156115a5578160ff1660011480156115115750303b155b61159d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610550565b506000919050565b60005460ff80841691161061163c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610550565b50600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff92909216919091179055600190565b919050565b600054610100900460ff16611710576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610550565b60408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6000816000015182602001518360400151846060015160405160200161179b949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60008686868686866040516020016117d596959493929190613b2b565b6040516020818303038152906040528051906020012090509695505050505050565b604080516020810185905260009181018290528190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506118b59101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f01000000000000000000000000000000000000000000000000000000000000006020830152908587611dce565b9150505b9392505050565b6000606060008060008661ffff1667ffffffffffffffff8111156118e6576118e6613358565b6040519080825280601f01601f191660200182016040528015611910576020820181803683370190505b5090506000808751602089018b8e8ef191503d925086831115611931578692505b828152826000602083013e90999098509650505050505050565b60008082136119b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610550565b600060606119c384611df2565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c18213611bc057506000919050565b680755bf798b4a1bf1e58212611c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610550565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b600080611dda86611ec8565b9050611de881868686611efa565b9695505050505050565b6000808211611e5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610550565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b60608180519060200120604051602001611ee491815260200190565b6040516020818303038152906040529050919050565b6000806000611f0a878686611f37565b91509150818015611f2c57508051602080830191909120875191880191909120145b979650505050505050565b600060606000611f468561202c565b90506000806000611f58848a89612127565b81519295509093509150158080611f6c5750815b611fd2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e0000000000006044820152606401610550565b600081611fee576040518060200160405280600081525061201a565b61201a86611ffd6001886136f1565b8151811061200d5761200d613b82565b6020026020010151612643565b919b919a509098505050505050505050565b606060006120398361266d565b90506000815167ffffffffffffffff81111561205757612057613358565b60405190808252806020026020018201604052801561209c57816020015b60408051808201909152606080825260208201528152602001906001900390816120755790505b50905060005b825181101561211f5760006120cf8483815181106120c2576120c2613b82565b60200260200101516126a0565b905060405180604001604052808281526020016120eb8361266d565b81525083838151811061210057612100613b82565b602002602001018190525050808061211790613af2565b9150506120a2565b509392505050565b600060608180806121378761274a565b9050600086905060008061215e604051806040016040528060608152602001606081525090565b60005b8c518110156125ff578c818151811061217c5761217c613b82565b6020026020010151915082846121929190613a74565b935061219f600188613a74565b96508361221d57815180516020909101208514612218576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f496e76616c696420726f6f7420686173680000000000000000000000000000006044820152606401610550565b61230d565b81515160201161229957815180516020909101208514612218576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c206861736800000000006044820152606401610550565b815185906122a690613bb1565b1461230d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f646520686173680000000000006044820152606401610550565b61231960106001613a74565b8260200151511415612392578551841415612333576125ff565b600086858151811061234757612347613b82565b602001015160f81c60f81b60f81c9050600083602001518260ff168151811061237257612372613b82565b60200260200101519050612385816128cd565b96506001945050506125ed565b6002826020015151141561258b5760006123ab83612903565b90506000816000815181106123c2576123c2613b82565b016020015160f81c905060006123d9600283613bf6565b6123e4906002613c18565b905060006123f5848360ff16612927565b905060006124038b8a612927565b90506000612411838361295d565b905060ff851660021480612428575060ff85166003145b1561247e5780835114801561243d5750808251145b1561244f5761244c818b613a74565b99505b507f800000000000000000000000000000000000000000000000000000000000000099506125ff945050505050565b60ff85161580612491575060ff85166001145b1561250357825181146124cd57507f800000000000000000000000000000000000000000000000000000000000000099506125ff945050505050565b6124f488602001516001815181106124e7576124e7613b82565b60200260200101516128cd565b9a5097506125ed945050505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e2060448201527f70726566697800000000000000000000000000000000000000000000000000006064820152608401610550565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e0000006044820152606401610550565b806125f781613af2565b915050612161565b507f800000000000000000000000000000000000000000000000000000000000000084148661262e8786612927565b909e909d50909b509950505050505050505050565b6020810151805160609161146a9161265d906001906136f1565b815181106120c2576120c2613b82565b60408051808201825260008082526020918201528151808301909252825182528083019082015260609061146a90612a09565b606060008060006126b085612c3c565b9194509250905060008160018111156126cb576126cb613c3b565b14612732576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e00000000000000006044820152606401610550565b61274185602001518484613043565b95945050505050565b606060008251600261275c9190613943565b67ffffffffffffffff81111561277457612774613358565b6040519080825280601f01601f19166020018201604052801561279e576020820181803683370190505b50905060005b83518110156128c65760048482815181106127c1576127c1613b82565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c826127f6836002613943565b8151811061280657612806613b82565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350601084828151811061284957612849613b82565b016020015161285b919060f81c613bf6565b60f81b8261286a836002613943565b612875906001613a74565b8151811061288557612885613b82565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806128be81613af2565b9150506127a4565b5092915050565b600060606020836000015110156128ee576128e783613122565b90506128fa565b6128f7836126a0565b90505b6118b981613bb1565b606061146a61292283602001516000815181106120c2576120c2613b82565b61274a565b606082518210612946575060408051602081019091526000815261146a565b611467838384865161295891906136f1565b61312d565b6000805b8084511180156129715750808351115b80156129f2575082818151811061298a5761298a613b82565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168482815181106129c9576129c9613b82565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156114675780612a0181613af2565b915050612961565b6060600080612a1784612c3c565b91935090915060019050816001811115612a3357612a33613c3b565b14612a9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e0000000000000000006044820152606401610550565b6040805160208082526104208201909252600091816020015b6040805180820190915260008082526020820152815260200190600190039081612ab35790505090506000835b8651811015612c315760208210612b79576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201527f7374206c656e6774682e000000000000000000000000000000000000000000006064820152608401610550565b600080612bb66040518060400160405280858c60000151612b9a91906136f1565b8152602001858c60200151612baf9190613a74565b9052612c3c565b509150915060405180604001604052808383612bd29190613a74565b8152602001848b60200151612be79190613a74565b815250858581518110612bfc57612bfc613b82565b6020908102919091010152612c12600185613a74565b9350612c1e8183613a74565b612c289084613a74565b92505050612ae0565b508152949350505050565b600080600080846000015111612cae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e00000000000000006044820152606401610550565b6020840151805160001a607f8111612cd357600060016000945094509450505061303c565b60b78111612d69576000612ce86080836136f1565b905080876000015111612d57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e000000000000006044820152606401610550565b6001955093506000925061303c915050565b60bf8111612e8c576000612d7e60b7836136f1565b905080876000015111612ded576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e006044820152606401610550565b600183015160208290036101000a9004612e078183613a74565b885111612e70576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e00000000000000006044820152606401610550565b612e7b826001613a74565b965094506000935061303c92505050565b60f78111612f21576000612ea160c0836136f1565b905080876000015111612f10576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e0000000000000000006044820152606401610550565b60019550935084925061303c915050565b6000612f2e60f7836136f1565b905080876000015111612f9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e0000006044820152606401610550565b600183015160208290036101000a9004612fb78183613a74565b885111613020576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f496e76616c696420524c50206c6f6e67206c6973742e000000000000000000006044820152606401610550565b61302b826001613a74565b965094506001935061303c92505050565b9193909250565b606060008267ffffffffffffffff81111561306057613060613358565b6040519080825280601f01601f19166020018201604052801561308a576020820181803683370190505b50905080516000141561309e5790506118b9565b60006130aa8587613a74565b90506020820160005b6130be6020876139e4565b8110156130f557825182526130d4602084613a74565b92506130e1602083613a74565b9150806130ed81613af2565b9150506130b3565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b606061146a82613305565b60608182601f01101561319c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610550565b828284011015613208576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610550565b81830184511015613275576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610550565b60608215801561329457604051915060008252602082016040526132fc565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156132cd5780518352602092830192016132b5565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b606061146a826020015160008460000151613043565b60006020828403121561332d57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461167457600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156133ce576133ce613358565b604052919050565b600080600080600060a086880312156133ee57600080fd5b6133f786613334565b94506020808701359450604087013567ffffffffffffffff808216821461341d57600080fd5b909450606088013590811515821461343457600080fd5b9093506080880135908082111561344a57600080fd5b818901915089601f83011261345e57600080fd5b81358181111561347057613470613358565b6134a0847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613387565b91508082528a848285010111156134b657600080fd5b80848401858401376000848284010152508093505050509295509295909350565b60008083601f8401126134e957600080fd5b50813567ffffffffffffffff81111561350157600080fd5b60208301915083602082850101111561351957600080fd5b9250929050565b60008060008060008060008060008060006101808c8e03121561354257600080fd5b8b359a5061355260208d01613334565b995061356060408d01613334565b985060608c0135975060808c0135965067ffffffffffffffff60a08d0135111561358957600080fd5b6135998d60a08e01358e016134d7565b909650945060c08c0135935060808c8e037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff200112156135d757600080fd5b60e08c01925067ffffffffffffffff6101608d013511156135f757600080fd5b6136088d6101608e01358e016134d7565b81935080925050509295989b509295989b9093969950565b6000815180845260005b818110156136465760208185018101518683018201520161362a565b81811115613658576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b85815284602082015267ffffffffffffffff84166040820152821515606082015260a060808201526000611f2c60a0830184613620565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613703576137036136c2565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261374657613746613708565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561379a5761379a6136c2565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156137d9576137d96136c2565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561380d5761380d6136c2565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615613854576138546136c2565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561388f5761388f6136c2565b600087129250878205871284841616156138ab576138ab6136c2565b878505871281841616156138c1576138c16136c2565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03841381151615613909576139096136c2565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561393d5761393d6136c2565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561397b5761397b6136c2565b500290565b600067ffffffffffffffff8083168185168083038211156139a3576139a36136c2565b01949350505050565b60006fffffffffffffffffffffffffffffffff808316818516818304811182151516156139db576139db6136c2565b02949350505050565b6000826139f3576139f3613708565b500490565b600060408284031215613a0a57600080fd5b6040516040810181811067ffffffffffffffff82111715613a2d57613a2d613358565b604052825181526020928301519281019290925250919050565b600060208284031215613a5957600080fd5b5051919050565b600082613a6f57613a6f613708565b500690565b60008219821115613a8757613a876136c2565b500190565b600060808284031215613a9e57600080fd5b6040516080810181811067ffffffffffffffff82111715613ac157613ac1613358565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613b2457613b246136c2565b5060010190565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152613b7660c0830184613620565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b80516020808301519190811015613bf0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8160200360031b1b821691505b50919050565b600060ff831680613c0957613c09613708565b8060ff84160691505092915050565b600060ff821660ff841680821015613c3257613c326136c2565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080a000a496e697469616c697a61626c653a20636f6e747261637420697320616c726561",
} }
// OptimismPortalABI is the input ABI used to generate the binding from. // OptimismPortalABI is the input ABI used to generate the binding from.
......
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
// This file is a generated binding and any manual changes will be lost. // This file is a generated binding and any manual changes will be lost.
package bindings package bindings
var OptimismPortalDeployedBin = "0x60806040526004361061012c5760003560e01c8063a14238e7116100a5578063cff0ab9611610074578063eecf1c3611610059578063eecf1c3614610427578063f4daa2911461043a578063f786becd1461046e57600080fd5b8063cff0ab9614610373578063e9e05c421461041457600080fd5b8063a14238e7146102e5578063c8b9153114610315578063ca3e99ba14610349578063cd7c97891461035e57600080fd5b80636bf2606a116100fc5780638129fc1c116100e15780638129fc1c1461028d578063867ead13146102a25780639bf62d82146102b857600080fd5b80636bf2606a146102295780636dbffb781461025d57600080fd5b80621c2ff61461015857806313620abd146101b657806364b79208146101ef5780636bb0291e1461021457600080fd5b36610153576101513334620186a06000604051806020016040528060008152506104a2565b005b600080fd5b34801561016457600080fd5b5061018c7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101c257600080fd5b506101ce633b9aca0081565b6040516fffffffffffffffffffffffffffffffff90911681526020016101ad565b3480156101fb57600080fd5b50610206627a120081565b6040519081526020016101ad565b34801561022057600080fd5b50610206600481565b34801561023557600080fd5b506102067f000000000000000000000000000000000000000000000000000000000000000081565b34801561026957600080fd5b5061027d6102783660046132bd565b610948565b60405190151581526020016101ad565b34801561029957600080fd5b50610151610c56565b3480156102ae57600080fd5b5061020661271081565b3480156102c457600080fd5b5060335461018c9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156102f157600080fd5b5061027d6103003660046132bd565b60346020526000908152604090205460ff1681565b34801561032157600080fd5b506102067f000000000000000000000000000000000000000000000000000000000000000081565b34801561035557600080fd5b50610206610d78565b34801561036a57600080fd5b50610206600881565b34801561037f57600080fd5b506001546103db906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101ad565b610151610422366004613378565b6104a2565b6101516104353660046134c2565b610d89565b34801561044657600080fd5b506102067f000000000000000000000000000000000000000000000000000000000000000081565b34801561047a57600080fd5b506102067f000000000000000000000000000000000000000000000000000000000000000081565b8260005a905083156105595773ffffffffffffffffffffffffffffffffffffffff87161561055957604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b3332811461057a575033731111000000000000000000000000000000001111015b8773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f0195348a8a8a8a6040516105df95949392919061362d565b60405180910390a35060015460009061061e907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643613693565b905080156107a75760006106366004627a12006136d9565b6001546106619190700100000000000000000000000000000000900467ffffffffffffffff16613741565b9050600060086106756004627a12006136d9565b6001546106959085906fffffffffffffffffffffffffffffffff166137b5565b61069f91906136d9565b6106a991906136d9565b6001549091506000906106f5906106df906106d79085906fffffffffffffffffffffffffffffffff16613871565b61271061149c565b6fffffffffffffffffffffffffffffffff6114b7565b90506001841115610768576107656106df670de0b6b3a764000061075161071d6008836136d9565b61072f90670de0b6b3a7640000613741565b61073a60018a613693565b61074c90670de0b6b3a76400006138e5565b6114c6565b61075b90856137b5565b6106d791906136d9565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b600180548491906010906107da908490700100000000000000000000000000000000900467ffffffffffffffff16613922565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550627a1200600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff1613156108b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603c60248201527f4f7074696d69736d506f7274616c3a2063616e6e6f7420627579206d6f72652060448201527f676173207468616e20617661696c61626c6520676173206c696d6974000000006064820152608401610550565b6001546000906108e2906fffffffffffffffffffffffffffffffff1667ffffffffffffffff861661394e565b6fffffffffffffffffffffffffffffffff169050600061090648633b9aca006114f7565b6109109083613986565b905060005a61091f9086613693565b90508082111561093b5761093b6109368284613693565b611507565b5050505050505050505050565b6040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101829052600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae557906024016040805180830381865afa1580156109d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109fb919061399a565b8051909150610c1d5760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663529933df6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a9591906139e9565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16634ab65d736040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b2891906139e9565b905084811115610b3d57506000949350505050565b600082610b4a8388613693565b610b549190613a02565b905073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663a25ae557610b9c8386613693565b610ba69089613a16565b6040518263ffffffff1660e01b8152600401610bc491815260200190565b6040805180830381865afa158015610be0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c04919061399a565b8051909450610c195750600095945050505050565b5050505b7f00000000000000000000000000000000000000000000000000000000000000008160200151610c4d9190613a16565b42119392505050565b6000610c626001611535565b90508015610c9757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603380547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055610d1260408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b8015610d7557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b610d866004627a12006136d9565b81565b60335473ffffffffffffffffffffffffffffffffffffffff1661dead14610e32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e006064820152608401610550565b73ffffffffffffffffffffffffffffffffffffffff8916301415610ed8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e7472616374006064820152608401610550565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae557906024016040805180830381865afa158015610f65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f89919061399a565b90507f00000000000000000000000000000000000000000000000000000000000000008160200151610fbb9190613a16565b4211611049576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4f7074696d69736d506f7274616c3a2070726f706f73616c206973206e6f742060448201527f7965742066696e616c697a6564000000000000000000000000000000000000006064820152608401610550565b61106061105b36869003860186613a2e565b6116c0565b8151146110ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f6600000000000000000000000000000000000000000000006064820152608401610550565b60006111358d8d8d8d8d8d8d8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061171c92505050565b905061117c81866040013586868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061175b92505050565b611208576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610550565b60008181526034602052604090205460ff16156112a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610550565b600081815260346020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556112ea614e208a613a16565b5a1015611379576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a20696e73756666696369656e742067617360448201527f20746f2066696e616c697a65207769746864726177616c0000000000000000006064820152608401610550565b603380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8e16179055604080516020601f8a01819004810282018101909252888152600091611402918e918d918f918691908f908f908190840183828082843760009201919091525061182492505050565b50603380547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915082907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b9061146890841515815260200190565b60405180910390a25050505050505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6000818312156114ac57816114ae565b825b90505b92915050565b60008183126114ac57816114ae565b60006114ae670de0b6b3a7640000836114de866118af565b6114e891906137b5565b6114f291906136d9565b611af3565b6000818310156114ac57816114ae565b6000805a90505b825a61151a9083613693565b10156115305761152982613a94565b915061150e565b505050565b60008054610100900460ff16156115ec578160ff1660011480156115585750303b155b6115e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610550565b506000919050565b60005460ff808416911610611683576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610550565b50600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff92909216919091179055600190565b919050565b600081600001518260200151836040015184606001516040516020016116ff949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b600086868686868660405160200161173996959493929190613acd565b6040516020818303038152906040528051906020012090509695505050505050565b604080516020810185905260009181018290528190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506118199101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f01000000000000000000000000000000000000000000000000000000000000006020830152908587611d32565b9150505b9392505050565b6000606060008060008661ffff1667ffffffffffffffff81111561184a5761184a6132fa565b6040519080825280601f01601f191660200182016040528015611874576020820181803683370190505b5090506000808751602089018b8e8ef191503d925086831115611895578692505b828152826000602083013e90999098509650505050505050565b600080821361191a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610550565b6000606061192784611d56565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c18213611b2457506000919050565b680755bf798b4a1bf1e58212611b96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610550565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b600080611d3e86611e2c565b9050611d4c81868686611e5e565b9695505050505050565b6000808211611dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610550565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b60608180519060200120604051602001611e4891815260200190565b6040516020818303038152906040529050919050565b6000806000611e6e878686611e9b565b91509150818015611e9057508051602080830191909120875191880191909120145b979650505050505050565b600060606000611eaa85611f90565b90506000806000611ebc848a8961208b565b81519295509093509150158080611ed05750815b611f36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e0000000000006044820152606401610550565b600081611f525760405180602001604052806000815250611f7e565b611f7e86611f61600188613693565b81518110611f7157611f71613b24565b60200260200101516125a8565b919b919a509098505050505050505050565b60606000611f9d836125d2565b90506000815167ffffffffffffffff811115611fbb57611fbb6132fa565b60405190808252806020026020018201604052801561200057816020015b6040805180820190915260608082526020820152815260200190600190039081611fd95790505b50905060005b825181101561208357600061203384838151811061202657612026613b24565b6020026020010151612605565b9050604051806040016040528082815260200161204f836125d2565b81525083838151811061206457612064613b24565b602002602001018190525050808061207b90613a94565b915050612006565b509392505050565b6000606081808061209b876126af565b905060008690506000806120c2604051806040016040528060608152602001606081525090565b60005b8c51811015612564578c81815181106120e0576120e0613b24565b6020026020010151915082846120f69190613a16565b9350612103600188613a16565b9650836121815781518051602090910120851461217c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f496e76616c696420726f6f7420686173680000000000000000000000000000006044820152606401610550565b612272565b8151516020116121fd5781518051602090910120851461217c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c206861736800000000006044820152606401610550565b8461220b8360000151612832565b14612272576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f646520686173680000000000006044820152606401610550565b61227e60106001613a16565b82602001515114156122f757855184141561229857612564565b60008685815181106122ac576122ac613b24565b602001015160f81c60f81b60f81c9050600083602001518260ff16815181106122d7576122d7613b24565b602002602001015190506122ea8161285a565b9650600194505050612552565b600282602001515114156124f057600061231083612890565b905060008160008151811061232757612327613b24565b016020015160f81c9050600061233e600283613b53565b612349906002613b75565b9050600061235a848360ff166128b4565b905060006123688b8a6128b4565b9050600061237683836128ea565b905060ff85166002148061238d575060ff85166003145b156123e3578083511480156123a25750808251145b156123b4576123b1818b613a16565b99505b507f80000000000000000000000000000000000000000000000000000000000000009950612564945050505050565b60ff851615806123f6575060ff85166001145b15612468578251811461243257507f80000000000000000000000000000000000000000000000000000000000000009950612564945050505050565b612459886020015160018151811061244c5761244c613b24565b602002602001015161285a565b9a509750612552945050505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e2060448201527f70726566697800000000000000000000000000000000000000000000000000006064820152608401610550565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e0000006044820152606401610550565b8061255c81613a94565b9150506120c5565b507f800000000000000000000000000000000000000000000000000000000000000084148661259387866128b4565b909e909d50909b509950505050505050505050565b602081015180516060916114b1916125c290600190613693565b8151811061202657612026613b24565b6040805180820182526000808252602091820152815180830190925282518252808301908201526060906114b190612996565b6060600080600061261585612bc9565b91945092509050600081600181111561263057612630613b98565b14612697576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e00000000000000006044820152606401610550565b6126a685602001518484612fd0565b95945050505050565b60606000825160026126c191906138e5565b67ffffffffffffffff8111156126d9576126d96132fa565b6040519080825280601f01601f191660200182016040528015612703576020820181803683370190505b50905060005b835181101561282b57600484828151811061272657612726613b24565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c8261275b8360026138e5565b8151811061276b5761276b613b24565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060108482815181106127ae576127ae613b24565b01602001516127c0919060f81c613b53565b60f81b826127cf8360026138e5565b6127da906001613a16565b815181106127ea576127ea613b24565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508061282381613a94565b915050612709565b5092915050565b600060208251101561284657506020015190565b818060200190518101906114b191906139e9565b6000606060208360000151101561287b57612874836130af565b9050612887565b61288483612605565b90505b61181d81612832565b60606114b16128af836020015160008151811061202657612026613b24565b6126af565b6060825182106128d357506040805160208101909152600081526114b1565b6114ae83838486516128e59190613693565b6130ba565b6000805b8084511180156128fe5750808351115b801561297f575082818151811061291757612917613b24565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191684828151811061295657612956613b24565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156114ae578061298e81613a94565b9150506128ee565b60606000806129a484612bc9565b919350909150600190508160018111156129c0576129c0613b98565b14612a27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e0000000000000000006044820152606401610550565b6040805160208082526104208201909252600091816020015b6040805180820190915260008082526020820152815260200190600190039081612a405790505090506000835b8651811015612bbe5760208210612b06576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201527f7374206c656e6774682e000000000000000000000000000000000000000000006064820152608401610550565b600080612b436040518060400160405280858c60000151612b279190613693565b8152602001858c60200151612b3c9190613a16565b9052612bc9565b509150915060405180604001604052808383612b5f9190613a16565b8152602001848b60200151612b749190613a16565b815250858581518110612b8957612b89613b24565b6020908102919091010152612b9f600185613a16565b9350612bab8183613a16565b612bb59084613a16565b92505050612a6d565b508152949350505050565b600080600080846000015111612c3b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e00000000000000006044820152606401610550565b6020840151805160001a607f8111612c60576000600160009450945094505050612fc9565b60b78111612cf6576000612c75608083613693565b905080876000015111612ce4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e000000000000006044820152606401610550565b60019550935060009250612fc9915050565b60bf8111612e19576000612d0b60b783613693565b905080876000015111612d7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e006044820152606401610550565b600183015160208290036101000a9004612d948183613a16565b885111612dfd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e00000000000000006044820152606401610550565b612e08826001613a16565b9650945060009350612fc992505050565b60f78111612eae576000612e2e60c083613693565b905080876000015111612e9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e0000000000000000006044820152606401610550565b600195509350849250612fc9915050565b6000612ebb60f783613693565b905080876000015111612f2a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e0000006044820152606401610550565b600183015160208290036101000a9004612f448183613a16565b885111612fad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f496e76616c696420524c50206c6f6e67206c6973742e000000000000000000006044820152606401610550565b612fb8826001613a16565b9650945060019350612fc992505050565b9193909250565b606060008267ffffffffffffffff811115612fed57612fed6132fa565b6040519080825280601f01601f191660200182016040528015613017576020820181803683370190505b50905080516000141561302b57905061181d565b60006130378587613a16565b90506020820160005b61304b602087613986565b8110156130825782518252613061602084613a16565b925061306e602083613a16565b91508061307a81613a94565b915050613040565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b60606114b1826132a7565b6060816130c881601f613a16565b1015613130576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610550565b8261313b8382613a16565b10156131a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610550565b6131ad8284613a16565b84511015613217576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610550565b606082158015613236576040519150600082526020820160405261329e565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561326f578051835260209283019201613257565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60606114b1826020015160008460000151612fd0565b6000602082840312156132cf57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff811681146116bb57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613370576133706132fa565b604052919050565b600080600080600060a0868803121561339057600080fd5b613399866132d6565b94506020808701359450604087013567ffffffffffffffff80821682146133bf57600080fd5b90945060608801359081151582146133d657600080fd5b909350608088013590808211156133ec57600080fd5b818901915089601f83011261340057600080fd5b813581811115613412576134126132fa565b613442847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613329565b91508082528a8482850101111561345857600080fd5b80848401858401376000848284010152508093505050509295509295909350565b60008083601f84011261348b57600080fd5b50813567ffffffffffffffff8111156134a357600080fd5b6020830191508360208285010111156134bb57600080fd5b9250929050565b60008060008060008060008060008060006101808c8e0312156134e457600080fd5b8b359a506134f460208d016132d6565b995061350260408d016132d6565b985060608c0135975060808c0135965067ffffffffffffffff60a08d0135111561352b57600080fd5b61353b8d60a08e01358e01613479565b909650945060c08c0135935060808c8e037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2001121561357957600080fd5b60e08c01925067ffffffffffffffff6101608d0135111561359957600080fd5b6135aa8d6101608e01358e01613479565b81935080925050509295989b509295989b9093969950565b6000815180845260005b818110156135e8576020818501810151868301820152016135cc565b818111156135fa576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b85815284602082015267ffffffffffffffff84166040820152821515606082015260a060808201526000611e9060a08301846135c2565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156136a5576136a5613664565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826136e8576136e86136aa565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561373c5761373c613664565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561377b5761377b613664565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156137af576137af613664565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156137f6576137f6613664565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561383157613831613664565b6000871292508782058712848416161561384d5761384d613664565b8785058712818416161561386357613863613664565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156138ab576138ab613664565b827f80000000000000000000000000000000000000000000000000000000000000000384128116156138df576138df613664565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561391d5761391d613664565b500290565b600067ffffffffffffffff80831681851680830382111561394557613945613664565b01949350505050565b60006fffffffffffffffffffffffffffffffff8083168185168183048111821515161561397d5761397d613664565b02949350505050565b600082613995576139956136aa565b500490565b6000604082840312156139ac57600080fd5b6040516040810181811067ffffffffffffffff821117156139cf576139cf6132fa565b604052825181526020928301519281019290925250919050565b6000602082840312156139fb57600080fd5b5051919050565b600082613a1157613a116136aa565b500690565b60008219821115613a2957613a29613664565b500190565b600060808284031215613a4057600080fd5b6040516080810181811067ffffffffffffffff82111715613a6357613a636132fa565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613ac657613ac6613664565b5060010190565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152613b1860c08301846135c2565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff831680613b6657613b666136aa565b8060ff84160691505092915050565b600060ff821660ff841680821015613b8f57613b8f613664565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080a000a" var OptimismPortalDeployedBin = "0x60806040526004361061012c5760003560e01c8063a14238e7116100a5578063cff0ab9611610074578063eecf1c3611610059578063eecf1c3614610427578063f4daa2911461043a578063f786becd1461046e57600080fd5b8063cff0ab9614610373578063e9e05c421461041457600080fd5b8063a14238e7146102e5578063c8b9153114610315578063ca3e99ba14610349578063cd7c97891461035e57600080fd5b80636bf2606a116100fc5780638129fc1c116100e15780638129fc1c1461028d578063867ead13146102a25780639bf62d82146102b857600080fd5b80636bf2606a146102295780636dbffb781461025d57600080fd5b80621c2ff61461015857806313620abd146101b657806364b79208146101ef5780636bb0291e1461021457600080fd5b36610153576101513334620186a06000604051806020016040528060008152506104a2565b005b600080fd5b34801561016457600080fd5b5061018c7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101c257600080fd5b506101ce633b9aca0081565b6040516fffffffffffffffffffffffffffffffff90911681526020016101ad565b3480156101fb57600080fd5b50610206627a120081565b6040519081526020016101ad565b34801561022057600080fd5b50610206600481565b34801561023557600080fd5b506102067f000000000000000000000000000000000000000000000000000000000000000081565b34801561026957600080fd5b5061027d61027836600461331b565b610948565b60405190151581526020016101ad565b34801561029957600080fd5b50610151610c56565b3480156102ae57600080fd5b5061020661271081565b3480156102c457600080fd5b5060335461018c9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156102f157600080fd5b5061027d61030036600461331b565b60346020526000908152604090205460ff1681565b34801561032157600080fd5b506102067f000000000000000000000000000000000000000000000000000000000000000081565b34801561035557600080fd5b50610206610d31565b34801561036a57600080fd5b50610206600881565b34801561037f57600080fd5b506001546103db906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101ad565b6101516104223660046133d6565b6104a2565b610151610435366004613520565b610d42565b34801561044657600080fd5b506102067f000000000000000000000000000000000000000000000000000000000000000081565b34801561047a57600080fd5b506102067f000000000000000000000000000000000000000000000000000000000000000081565b8260005a905083156105595773ffffffffffffffffffffffffffffffffffffffff87161561055957604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b3332811461057a575033731111000000000000000000000000000000001111015b8773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f0195348a8a8a8a6040516105df95949392919061368b565b60405180910390a35060015460009061061e907801000000000000000000000000000000000000000000000000900467ffffffffffffffff16436136f1565b905080156107a75760006106366004627a1200613737565b6001546106619190700100000000000000000000000000000000900467ffffffffffffffff1661379f565b9050600060086106756004627a1200613737565b6001546106959085906fffffffffffffffffffffffffffffffff16613813565b61069f9190613737565b6106a99190613737565b6001549091506000906106f5906106df906106d79085906fffffffffffffffffffffffffffffffff166138cf565b612710611455565b6fffffffffffffffffffffffffffffffff611470565b90506001841115610768576107656106df670de0b6b3a764000061075161071d600883613737565b61072f90670de0b6b3a764000061379f565b61073a60018a6136f1565b61074c90670de0b6b3a7640000613943565b61147f565b61075b9085613813565b6106d79190613737565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b600180548491906010906107da908490700100000000000000000000000000000000900467ffffffffffffffff16613980565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550627a1200600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff1613156108b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603c60248201527f4f7074696d69736d506f7274616c3a2063616e6e6f7420627579206d6f72652060448201527f676173207468616e20617661696c61626c6520676173206c696d6974000000006064820152608401610550565b6001546000906108e2906fffffffffffffffffffffffffffffffff1667ffffffffffffffff86166139ac565b6fffffffffffffffffffffffffffffffff169050600061090648633b9aca006114b0565b61091090836139e4565b905060005a61091f90866136f1565b90508082111561093b5761093b61093682846136f1565b6114c0565b5050505050505050505050565b6040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101829052600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae557906024016040805180830381865afa1580156109d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109fb91906139f8565b8051909150610c1d5760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663529933df6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a959190613a47565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16634ab65d736040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b289190613a47565b905084811115610b3d57506000949350505050565b600082610b4a83886136f1565b610b549190613a60565b905073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663a25ae557610b9c83866136f1565b610ba69089613a74565b6040518263ffffffff1660e01b8152600401610bc491815260200190565b6040805180830381865afa158015610be0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c0491906139f8565b8051909450610c195750600095945050505050565b5050505b7f00000000000000000000000000000000000000000000000000000000000000008160200151610c4d9190613a74565b42119392505050565b6000610c6260016114ee565b90508015610c9757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603380547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055610ccb611679565b8015610d2e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b610d3f6004627a1200613737565b81565b60335473ffffffffffffffffffffffffffffffffffffffff1661dead14610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e006064820152608401610550565b73ffffffffffffffffffffffffffffffffffffffff8916301415610e91576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e7472616374006064820152608401610550565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae557906024016040805180830381865afa158015610f1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4291906139f8565b90507f00000000000000000000000000000000000000000000000000000000000000008160200151610f749190613a74565b4211611002576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4f7074696d69736d506f7274616c3a2070726f706f73616c206973206e6f742060448201527f7965742066696e616c697a6564000000000000000000000000000000000000006064820152608401610550565b61101961101436869003860186613a8c565b61175c565b8151146110a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f6600000000000000000000000000000000000000000000006064820152608401610550565b60006110ee8d8d8d8d8d8d8d8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117b892505050565b905061113581866040013586868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117f792505050565b6111c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610550565b60008181526034602052604090205460ff1615611260576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610550565b600081815260346020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556112a3614e208a613a74565b5a1015611332576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a20696e73756666696369656e742067617360448201527f20746f2066696e616c697a65207769746864726177616c0000000000000000006064820152608401610550565b603380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8e16179055604080516020601f8a018190048102820181019092528881526000916113bb918e918d918f918691908f908f90819084018382808284376000920191909152506118c092505050565b50603380547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915082907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b9061142190841515815260200190565b60405180910390a25050505050505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6000818312156114655781611467565b825b90505b92915050565b60008183126114655781611467565b6000611467670de0b6b3a7640000836114978661194b565b6114a19190613813565b6114ab9190613737565b611b8f565b6000818310156114655781611467565b6000805a90505b825a6114d390836136f1565b10156114e9576114e282613af2565b91506114c7565b505050565b60008054610100900460ff16156115a5578160ff1660011480156115115750303b155b61159d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610550565b506000919050565b60005460ff80841691161061163c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610550565b50600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff92909216919091179055600190565b919050565b600054610100900460ff16611710576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610550565b60408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6000816000015182602001518360400151846060015160405160200161179b949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60008686868686866040516020016117d596959493929190613b2b565b6040516020818303038152906040528051906020012090509695505050505050565b604080516020810185905260009181018290528190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506118b59101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f01000000000000000000000000000000000000000000000000000000000000006020830152908587611dce565b9150505b9392505050565b6000606060008060008661ffff1667ffffffffffffffff8111156118e6576118e6613358565b6040519080825280601f01601f191660200182016040528015611910576020820181803683370190505b5090506000808751602089018b8e8ef191503d925086831115611931578692505b828152826000602083013e90999098509650505050505050565b60008082136119b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610550565b600060606119c384611df2565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c18213611bc057506000919050565b680755bf798b4a1bf1e58212611c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610550565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b600080611dda86611ec8565b9050611de881868686611efa565b9695505050505050565b6000808211611e5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610550565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b60608180519060200120604051602001611ee491815260200190565b6040516020818303038152906040529050919050565b6000806000611f0a878686611f37565b91509150818015611f2c57508051602080830191909120875191880191909120145b979650505050505050565b600060606000611f468561202c565b90506000806000611f58848a89612127565b81519295509093509150158080611f6c5750815b611fd2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e0000000000006044820152606401610550565b600081611fee576040518060200160405280600081525061201a565b61201a86611ffd6001886136f1565b8151811061200d5761200d613b82565b6020026020010151612643565b919b919a509098505050505050505050565b606060006120398361266d565b90506000815167ffffffffffffffff81111561205757612057613358565b60405190808252806020026020018201604052801561209c57816020015b60408051808201909152606080825260208201528152602001906001900390816120755790505b50905060005b825181101561211f5760006120cf8483815181106120c2576120c2613b82565b60200260200101516126a0565b905060405180604001604052808281526020016120eb8361266d565b81525083838151811061210057612100613b82565b602002602001018190525050808061211790613af2565b9150506120a2565b509392505050565b600060608180806121378761274a565b9050600086905060008061215e604051806040016040528060608152602001606081525090565b60005b8c518110156125ff578c818151811061217c5761217c613b82565b6020026020010151915082846121929190613a74565b935061219f600188613a74565b96508361221d57815180516020909101208514612218576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f496e76616c696420726f6f7420686173680000000000000000000000000000006044820152606401610550565b61230d565b81515160201161229957815180516020909101208514612218576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c206861736800000000006044820152606401610550565b815185906122a690613bb1565b1461230d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f646520686173680000000000006044820152606401610550565b61231960106001613a74565b8260200151511415612392578551841415612333576125ff565b600086858151811061234757612347613b82565b602001015160f81c60f81b60f81c9050600083602001518260ff168151811061237257612372613b82565b60200260200101519050612385816128cd565b96506001945050506125ed565b6002826020015151141561258b5760006123ab83612903565b90506000816000815181106123c2576123c2613b82565b016020015160f81c905060006123d9600283613bf6565b6123e4906002613c18565b905060006123f5848360ff16612927565b905060006124038b8a612927565b90506000612411838361295d565b905060ff851660021480612428575060ff85166003145b1561247e5780835114801561243d5750808251145b1561244f5761244c818b613a74565b99505b507f800000000000000000000000000000000000000000000000000000000000000099506125ff945050505050565b60ff85161580612491575060ff85166001145b1561250357825181146124cd57507f800000000000000000000000000000000000000000000000000000000000000099506125ff945050505050565b6124f488602001516001815181106124e7576124e7613b82565b60200260200101516128cd565b9a5097506125ed945050505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e2060448201527f70726566697800000000000000000000000000000000000000000000000000006064820152608401610550565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e0000006044820152606401610550565b806125f781613af2565b915050612161565b507f800000000000000000000000000000000000000000000000000000000000000084148661262e8786612927565b909e909d50909b509950505050505050505050565b6020810151805160609161146a9161265d906001906136f1565b815181106120c2576120c2613b82565b60408051808201825260008082526020918201528151808301909252825182528083019082015260609061146a90612a09565b606060008060006126b085612c3c565b9194509250905060008160018111156126cb576126cb613c3b565b14612732576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e00000000000000006044820152606401610550565b61274185602001518484613043565b95945050505050565b606060008251600261275c9190613943565b67ffffffffffffffff81111561277457612774613358565b6040519080825280601f01601f19166020018201604052801561279e576020820181803683370190505b50905060005b83518110156128c65760048482815181106127c1576127c1613b82565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c826127f6836002613943565b8151811061280657612806613b82565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350601084828151811061284957612849613b82565b016020015161285b919060f81c613bf6565b60f81b8261286a836002613943565b612875906001613a74565b8151811061288557612885613b82565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806128be81613af2565b9150506127a4565b5092915050565b600060606020836000015110156128ee576128e783613122565b90506128fa565b6128f7836126a0565b90505b6118b981613bb1565b606061146a61292283602001516000815181106120c2576120c2613b82565b61274a565b606082518210612946575060408051602081019091526000815261146a565b611467838384865161295891906136f1565b61312d565b6000805b8084511180156129715750808351115b80156129f2575082818151811061298a5761298a613b82565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168482815181106129c9576129c9613b82565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156114675780612a0181613af2565b915050612961565b6060600080612a1784612c3c565b91935090915060019050816001811115612a3357612a33613c3b565b14612a9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e0000000000000000006044820152606401610550565b6040805160208082526104208201909252600091816020015b6040805180820190915260008082526020820152815260200190600190039081612ab35790505090506000835b8651811015612c315760208210612b79576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201527f7374206c656e6774682e000000000000000000000000000000000000000000006064820152608401610550565b600080612bb66040518060400160405280858c60000151612b9a91906136f1565b8152602001858c60200151612baf9190613a74565b9052612c3c565b509150915060405180604001604052808383612bd29190613a74565b8152602001848b60200151612be79190613a74565b815250858581518110612bfc57612bfc613b82565b6020908102919091010152612c12600185613a74565b9350612c1e8183613a74565b612c289084613a74565b92505050612ae0565b508152949350505050565b600080600080846000015111612cae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e00000000000000006044820152606401610550565b6020840151805160001a607f8111612cd357600060016000945094509450505061303c565b60b78111612d69576000612ce86080836136f1565b905080876000015111612d57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e000000000000006044820152606401610550565b6001955093506000925061303c915050565b60bf8111612e8c576000612d7e60b7836136f1565b905080876000015111612ded576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e006044820152606401610550565b600183015160208290036101000a9004612e078183613a74565b885111612e70576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e00000000000000006044820152606401610550565b612e7b826001613a74565b965094506000935061303c92505050565b60f78111612f21576000612ea160c0836136f1565b905080876000015111612f10576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e0000000000000000006044820152606401610550565b60019550935084925061303c915050565b6000612f2e60f7836136f1565b905080876000015111612f9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e0000006044820152606401610550565b600183015160208290036101000a9004612fb78183613a74565b885111613020576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f496e76616c696420524c50206c6f6e67206c6973742e000000000000000000006044820152606401610550565b61302b826001613a74565b965094506001935061303c92505050565b9193909250565b606060008267ffffffffffffffff81111561306057613060613358565b6040519080825280601f01601f19166020018201604052801561308a576020820181803683370190505b50905080516000141561309e5790506118b9565b60006130aa8587613a74565b90506020820160005b6130be6020876139e4565b8110156130f557825182526130d4602084613a74565b92506130e1602083613a74565b9150806130ed81613af2565b9150506130b3565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b606061146a82613305565b60608182601f01101561319c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610550565b828284011015613208576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610550565b81830184511015613275576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610550565b60608215801561329457604051915060008252602082016040526132fc565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156132cd5780518352602092830192016132b5565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b606061146a826020015160008460000151613043565b60006020828403121561332d57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461167457600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156133ce576133ce613358565b604052919050565b600080600080600060a086880312156133ee57600080fd5b6133f786613334565b94506020808701359450604087013567ffffffffffffffff808216821461341d57600080fd5b909450606088013590811515821461343457600080fd5b9093506080880135908082111561344a57600080fd5b818901915089601f83011261345e57600080fd5b81358181111561347057613470613358565b6134a0847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613387565b91508082528a848285010111156134b657600080fd5b80848401858401376000848284010152508093505050509295509295909350565b60008083601f8401126134e957600080fd5b50813567ffffffffffffffff81111561350157600080fd5b60208301915083602082850101111561351957600080fd5b9250929050565b60008060008060008060008060008060006101808c8e03121561354257600080fd5b8b359a5061355260208d01613334565b995061356060408d01613334565b985060608c0135975060808c0135965067ffffffffffffffff60a08d0135111561358957600080fd5b6135998d60a08e01358e016134d7565b909650945060c08c0135935060808c8e037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff200112156135d757600080fd5b60e08c01925067ffffffffffffffff6101608d013511156135f757600080fd5b6136088d6101608e01358e016134d7565b81935080925050509295989b509295989b9093969950565b6000815180845260005b818110156136465760208185018101518683018201520161362a565b81811115613658576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b85815284602082015267ffffffffffffffff84166040820152821515606082015260a060808201526000611f2c60a0830184613620565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613703576137036136c2565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261374657613746613708565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561379a5761379a6136c2565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156137d9576137d96136c2565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561380d5761380d6136c2565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615613854576138546136c2565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561388f5761388f6136c2565b600087129250878205871284841616156138ab576138ab6136c2565b878505871281841616156138c1576138c16136c2565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03841381151615613909576139096136c2565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561393d5761393d6136c2565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561397b5761397b6136c2565b500290565b600067ffffffffffffffff8083168185168083038211156139a3576139a36136c2565b01949350505050565b60006fffffffffffffffffffffffffffffffff808316818516818304811182151516156139db576139db6136c2565b02949350505050565b6000826139f3576139f3613708565b500490565b600060408284031215613a0a57600080fd5b6040516040810181811067ffffffffffffffff82111715613a2d57613a2d613358565b604052825181526020928301519281019290925250919050565b600060208284031215613a5957600080fd5b5051919050565b600082613a6f57613a6f613708565b500690565b60008219821115613a8757613a876136c2565b500190565b600060808284031215613a9e57600080fd5b6040516080810181811067ffffffffffffffff82111715613ac157613ac1613358565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613b2457613b246136c2565b5060010190565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152613b7660c0830184613620565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b80516020808301519190811015613bf0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8160200360031b1b821691505b50919050565b600060ff831680613c0957613c09613708565b8060ff84160691505092915050565b600060ff821660ff841680821015613c3257613c326136c2565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080a000a"
...@@ -165,7 +165,7 @@ func TestL2OutputSubmitter(t *testing.T) { ...@@ -165,7 +165,7 @@ func TestL2OutputSubmitter(t *testing.T) {
l1Client := sys.Clients["l1"] l1Client := sys.Clients["l1"]
rollupRPCClient, err := rpc.DialContext(context.Background(), fmt.Sprintf("http://%s:%d", cfg.Nodes["sequencer"].RPC.ListenAddr, cfg.Nodes["sequencer"].RPC.ListenPort)) rollupRPCClient, err := rpc.DialContext(context.Background(), cfg.Nodes["sequencer"].RPC.HttpEndpoint())
require.Nil(t, err) require.Nil(t, err)
rollupClient := rollupclient.NewRollupClient(rollupRPCClient) rollupClient := rollupclient.NewRollupClient(rollupRPCClient)
...@@ -326,6 +326,18 @@ func TestSystemE2E(t *testing.T) { ...@@ -326,6 +326,18 @@ func TestSystemE2E(t *testing.T) {
require.Equal(t, verifBlock.NumberU64(), seqBlock.NumberU64(), "Verifier and sequencer blocks not the same after including a batch tx") require.Equal(t, verifBlock.NumberU64(), seqBlock.NumberU64(), "Verifier and sequencer blocks not the same after including a batch tx")
require.Equal(t, verifBlock.ParentHash(), seqBlock.ParentHash(), "Verifier and sequencer blocks parent hashes not the same after including a batch tx") require.Equal(t, verifBlock.ParentHash(), seqBlock.ParentHash(), "Verifier and sequencer blocks parent hashes not the same after including a batch tx")
require.Equal(t, verifBlock.Hash(), seqBlock.Hash(), "Verifier and sequencer blocks not the same after including a batch tx") require.Equal(t, verifBlock.Hash(), seqBlock.Hash(), "Verifier and sequencer blocks not the same after including a batch tx")
rollupRPCClient, err := rpc.DialContext(context.Background(), cfg.Nodes["sequencer"].RPC.HttpEndpoint())
require.Nil(t, err)
rollupClient := rollupclient.NewRollupClient(rollupRPCClient)
// basic check that sync status works
seqStatus, err := rollupClient.SyncStatus(context.Background())
require.Nil(t, err)
require.LessOrEqual(t, seqBlock.NumberU64(), seqStatus.UnsafeL2.Number)
// basic check that version endpoint works
seqVersion, err := rollupClient.Version(context.Background())
require.Nil(t, err)
require.NotEqual(t, "", seqVersion)
} }
// TestConfirmationDepth runs the rollup with both sequencer and verifier not immediately processing the tip of the chain. // TestConfirmationDepth runs the rollup with both sequencer and verifier not immediately processing the tip of the chain.
......
...@@ -87,9 +87,17 @@ func (n *nodeAPI) OutputAtBlock(ctx context.Context, number rpc.BlockNumber) ([] ...@@ -87,9 +87,17 @@ func (n *nodeAPI) OutputAtBlock(ctx context.Context, number rpc.BlockNumber) ([]
} }
func (n *nodeAPI) SyncStatus(ctx context.Context) (*driver.SyncStatus, error) { func (n *nodeAPI) SyncStatus(ctx context.Context) (*driver.SyncStatus, error) {
recordDur := n.m.RecordRPCServerRequest("optimism_syncStatus")
defer recordDur()
return n.dr.SyncStatus(ctx) return n.dr.SyncStatus(ctx)
} }
func (n *nodeAPI) RollupConfig(_ context.Context) (*rollup.Config, error) {
recordDur := n.m.RecordRPCServerRequest("optimism_rollupConfig")
defer recordDur()
return n.config, nil
}
func (n *nodeAPI) Version(ctx context.Context) (string, error) { func (n *nodeAPI) Version(ctx context.Context) (string, error) {
recordDur := n.m.RecordRPCServerRequest("optimism_version") recordDur := n.m.RecordRPCServerRequest("optimism_version")
defer recordDur() defer recordDur()
......
...@@ -37,6 +37,10 @@ type RPCConfig struct { ...@@ -37,6 +37,10 @@ type RPCConfig struct {
ListenPort int ListenPort int
} }
func (cfg *RPCConfig) HttpEndpoint() string {
return fmt.Sprintf("http://%s:%d", cfg.ListenAddr, cfg.ListenPort)
}
type MetricsConfig struct { type MetricsConfig struct {
Enabled bool Enabled bool
ListenAddr string ListenAddr string
......
package derive
import (
"context"
"fmt"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
)
// L1ReceiptsFetcher fetches L1 header info and receipts for the payload attributes derivation (the info tx and deposits)
type L1ReceiptsFetcher interface {
InfoByHash(ctx context.Context, hash common.Hash) (eth.L1Info, error)
Fetch(ctx context.Context, blockHash common.Hash) (eth.L1Info, types.Transactions, types.Receipts, error)
}
// PreparePayloadAttributes prepares a PayloadAttributes template that is ready to build a L2 block with deposits only, on top of the given l2Parent, with the given epoch as L1 origin.
// The template defaults to NoTxPool=true, and no sequencer transactions: the caller has to modify the template to add transactions,
// by setting NoTxPool=false as sequencer, or by appending batch transactions as verifier.
// The severity of the error is returned; a crit=false error means there was a temporary issue, like a failed RPC or time-out.
// A crit=true error means the input arguments are inconsistent or invalid.
func PreparePayloadAttributes(ctx context.Context, cfg *rollup.Config, dl L1ReceiptsFetcher, l2Parent eth.L2BlockRef, epoch eth.BlockID) (attrs *eth.PayloadAttributes, crit bool, err error) {
var l1Info eth.L1Info
var depositTxs []hexutil.Bytes
var seqNumber uint64
// If the L1 origin changed this block, then we are in the first block of the epoch. In this
// case we need to fetch all transaction receipts from the L1 origin block so we can scan for
// user deposits.
if l2Parent.L1Origin.Number != epoch.Number {
info, _, receipts, err := dl.Fetch(ctx, epoch.Hash)
if err != nil {
return nil, false, fmt.Errorf("failed to fetch L1 block info and receipts: %w", err)
}
if l2Parent.L1Origin.Hash != info.ParentHash() {
return nil, true, fmt.Errorf("cannot create new block with L1 origin %s (parent %s) on top of L1 origin %s", epoch, info.ParentHash(), l2Parent.L1Origin)
}
deposits, err := DeriveDeposits(receipts, cfg.DepositContractAddress)
if err != nil {
return nil, true, fmt.Errorf("failed to derive some deposits: %w", err)
}
l1Info = info
depositTxs = deposits
seqNumber = 0
} else {
if l2Parent.L1Origin.Hash != epoch.Hash {
return nil, true, fmt.Errorf("cannot create new block with L1 origin %s in conflict with L1 origin %s", epoch, l2Parent.L1Origin)
}
info, err := dl.InfoByHash(ctx, epoch.Hash)
if err != nil {
return nil, false, fmt.Errorf("failed to fetch L1 block info: %w", err)
}
l1Info = info
depositTxs = nil
seqNumber = l2Parent.SequenceNumber + 1
}
l1InfoTx, err := L1InfoDepositBytes(seqNumber, l1Info)
if err != nil {
return nil, true, fmt.Errorf("failed to create l1InfoTx: %w", err)
}
txs := make([]hexutil.Bytes, 0, 1+len(depositTxs))
txs = append(txs, l1InfoTx)
txs = append(txs, depositTxs...)
return &eth.PayloadAttributes{
Timestamp: hexutil.Uint64(l2Parent.Time + cfg.BlockTime),
PrevRandao: eth.Bytes32(l1Info.MixDigest()),
SuggestedFeeRecipient: cfg.FeeRecipientAddress,
Transactions: txs,
NoTxPool: true,
}, false, nil
}
...@@ -8,16 +8,9 @@ import ( ...@@ -8,16 +8,9 @@ import (
"github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
type L1ReceiptsFetcher interface {
Fetch(ctx context.Context, blockHash common.Hash) (eth.L1Info, types.Transactions, types.Receipts, error)
}
type AttributesQueueOutput interface { type AttributesQueueOutput interface {
AddSafeAttributes(attributes *eth.PayloadAttributes) AddSafeAttributes(attributes *eth.PayloadAttributes)
SafeL2Head() eth.L2BlockRef SafeL2Head() eth.L2BlockRef
...@@ -55,82 +48,43 @@ func (aq *AttributesQueue) Step(ctx context.Context, outer Progress) error { ...@@ -55,82 +48,43 @@ func (aq *AttributesQueue) Step(ctx context.Context, outer Progress) error {
if changed, err := aq.progress.Update(outer); err != nil || changed { if changed, err := aq.progress.Update(outer); err != nil || changed {
return err return err
} }
attr, err := aq.DeriveL2Inputs(ctx, aq.next.SafeL2Head())
if err != nil {
return err
}
aq.next.AddSafeAttributes(attr)
return nil
}
func (aq *AttributesQueue) ResetStep(ctx context.Context, l1Fetcher L1Fetcher) error {
aq.batches = aq.batches[:0]
aq.progress = aq.next.Progress()
return io.EOF
}
func (aq *AttributesQueue) SafeL2Head() eth.L2BlockRef {
return aq.next.SafeL2Head()
}
// DeriveL2Inputs turns the next L2 batch into an Payload Attributes that builds off of the safe head
func (aq *AttributesQueue) DeriveL2Inputs(ctx context.Context, l2SafeHead eth.L2BlockRef) (*eth.PayloadAttributes, error) {
if len(aq.batches) == 0 { if len(aq.batches) == 0 {
return nil, io.EOF return io.EOF
} }
batch := aq.batches[0] batch := aq.batches[0]
seqNumber := l2SafeHead.SequenceNumber + 1
// Check if we need to advance an epoch & update local state
if l2SafeHead.L1Origin != batch.Epoch() {
aq.log.Info("advancing epoch in the attributes queue", "l2SafeHead", l2SafeHead, "l2SafeHead_origin", l2SafeHead.L1Origin, "batch_timestamp", batch.Timestamp, "batch_epoch", batch.Epoch())
seqNumber = 0
}
fetchCtx, cancel := context.WithTimeout(ctx, 20*time.Second) fetchCtx, cancel := context.WithTimeout(ctx, 20*time.Second)
defer cancel() defer cancel()
l1Info, _, receipts, err := aq.dl.Fetch(fetchCtx, batch.EpochHash) attrs, crit, err := PreparePayloadAttributes(fetchCtx, aq.config, aq.dl, aq.next.SafeL2Head(), batch.Epoch())
if err != nil { if err != nil {
aq.log.Error("failed to fetch L1 block info", "l1Origin", batch.Epoch(), "err", err) if crit {
return nil, err return fmt.Errorf("failed to prepare payload attributes for batch: %v", err)
} } else {
aq.log.Error("temporarily failing to prepare payload attributes for batch", "err", err)
// Fill in deposits if we are the first block of the epoch return nil
var deposits []hexutil.Bytes
if seqNumber == 0 {
var errs []error
deposits, errs = DeriveDeposits(receipts, aq.config.DepositContractAddress)
for _, err := range errs {
aq.log.Error("Failed to derive a deposit", "l1Origin", batch.Epoch(), "err", err)
}
if len(errs) != 0 {
// TODO: Multierror here
return nil, fmt.Errorf("failed to derive some deposits: %v", errs)
} }
} }
var txns []eth.Data // we are verifying, not sequencing, we've got all transactions and do not pull from the tx-pool
l1InfoTx, err := L1InfoDepositBytes(seqNumber, l1Info) // (that would make the block derivation non-deterministic)
if err != nil { attrs.NoTxPool = true
return nil, fmt.Errorf("failed to create l1InfoTx: %w", err) attrs.Transactions = append(attrs.Transactions, batch.Transactions...)
}
txns = append(txns, l1InfoTx) aq.log.Info("generated attributes in payload queue", "txs", len(attrs.Transactions), "timestamp", batch.Timestamp)
if seqNumber == 0 {
txns = append(txns, deposits...)
}
txns = append(txns, batch.Transactions...)
attrs := &eth.PayloadAttributes{
Timestamp: hexutil.Uint64(batch.Timestamp),
PrevRandao: eth.Bytes32(l1Info.MixDigest()),
SuggestedFeeRecipient: aq.config.FeeRecipientAddress,
Transactions: txns,
// we are verifying, not sequencing, we've got all transactions and do not pull from the tx-pool
// (that would make the block derivation non-deterministic)
NoTxPool: true,
}
aq.log.Info("generated attributes in payload queue", "tx_count", len(txns), "timestamp", batch.Timestamp)
// Slice off the batch once we are guaranteed to succeed // Slice off the batch once we are guaranteed to succeed
aq.batches = aq.batches[1:] aq.batches = aq.batches[1:]
return attrs, nil
aq.next.AddSafeAttributes(attrs)
return nil
}
func (aq *AttributesQueue) ResetStep(ctx context.Context, l1Fetcher L1Fetcher) error {
aq.batches = aq.batches[:0]
aq.progress = aq.next.Progress()
return io.EOF
}
func (aq *AttributesQueue) SafeL2Head() eth.L2BlockRef {
return aq.next.SafeL2Head()
} }
package derive package derive
import (
"context"
"io"
"math/big"
"math/rand"
"testing"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum-optimism/optimism/op-node/testutils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
)
type MockAttributesQueueOutput struct {
MockOriginStage
}
func (m *MockAttributesQueueOutput) AddSafeAttributes(attributes *eth.PayloadAttributes) {
m.Mock.MethodCalled("AddSafeAttributes", attributes)
}
func (m *MockAttributesQueueOutput) ExpectAddSafeAttributes(attributes *eth.PayloadAttributes) {
m.Mock.On("AddSafeAttributes", attributes).Once().Return()
}
func (m *MockAttributesQueueOutput) SafeL2Head() eth.L2BlockRef {
return m.Mock.MethodCalled("SafeL2Head").Get(0).(eth.L2BlockRef)
}
func (m *MockAttributesQueueOutput) ExpectSafeL2Head(head eth.L2BlockRef) {
m.Mock.On("SafeL2Head").Once().Return(head)
}
var _ AttributesQueueOutput = (*MockAttributesQueueOutput)(nil)
func TestAttributesQueue_Step(t *testing.T) {
// test config, only init the necessary fields
cfg := &rollup.Config{
BlockTime: 2,
L1ChainID: big.NewInt(101),
L2ChainID: big.NewInt(102),
FeeRecipientAddress: common.Address{0xaa},
DepositContractAddress: common.Address{0xbb},
}
rng := rand.New(rand.NewSource(1234))
l1Info := testutils.RandomL1Info(rng)
l1Fetcher := &testutils.MockL1Source{}
defer l1Fetcher.AssertExpectations(t)
l1Fetcher.ExpectInfoByHash(l1Info.InfoHash, l1Info, nil)
out := &MockAttributesQueueOutput{}
out.progress = Progress{
Origin: l1Info.BlockRef(),
Closed: false,
}
defer out.AssertExpectations(t)
safeHead := testutils.RandomL2BlockRef(rng)
safeHead.L1Origin = l1Info.ID()
out.ExpectSafeL2Head(safeHead)
batch := &BatchData{BatchV1{
EpochNum: rollup.Epoch(l1Info.InfoNum),
EpochHash: l1Info.InfoHash,
Timestamp: 12345,
Transactions: []eth.Data{eth.Data("foobar"), eth.Data("example")},
}}
l1InfoTx, err := L1InfoDepositBytes(safeHead.SequenceNumber+1, l1Info)
require.NoError(t, err)
attrs := eth.PayloadAttributes{
Timestamp: eth.Uint64Quantity(safeHead.Time + cfg.BlockTime),
PrevRandao: eth.Bytes32(l1Info.InfoMixDigest),
SuggestedFeeRecipient: cfg.FeeRecipientAddress,
Transactions: []eth.Data{l1InfoTx, eth.Data("foobar"), eth.Data("example")},
NoTxPool: true,
}
out.ExpectAddSafeAttributes(&attrs)
aq := NewAttributesQueue(testlog.Logger(t, log.LvlError), cfg, l1Fetcher, out)
require.NoError(t, RepeatResetStep(t, aq.ResetStep, l1Fetcher, 1))
aq.AddBatch(batch)
require.NoError(t, aq.Step(context.Background(), out.progress), "adding batch to next stage, no EOF yet")
require.Equal(t, io.EOF, aq.Step(context.Background(), out.progress), "done with batches")
}
package derive
import (
"context"
"errors"
"fmt"
"math/big"
"math/rand"
"testing"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/testutils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/stretchr/testify/require"
)
func TestPreparePayloadAttributes(t *testing.T) {
// test config, only init the necessary fields
cfg := &rollup.Config{
BlockTime: 2,
L1ChainID: big.NewInt(101),
L2ChainID: big.NewInt(102),
FeeRecipientAddress: common.Address{0xaa},
DepositContractAddress: common.Address{0xbb},
}
t.Run("inconsistent next height origin", func(t *testing.T) {
rng := rand.New(rand.NewSource(1234))
l1Fetcher := &testutils.MockL1Source{}
defer l1Fetcher.AssertExpectations(t)
l2Parent := testutils.RandomL2BlockRef(rng)
l1Info := testutils.RandomL1Info(rng)
l1Info.InfoNum = l2Parent.L1Origin.Number + 1
epoch := l1Info.ID()
l1Fetcher.ExpectFetch(epoch.Hash, l1Info, nil, nil, nil)
_, crit, err := PreparePayloadAttributes(context.Background(), cfg, l1Fetcher, l2Parent, epoch)
require.NotNil(t, err, "inconsistent L1 origin error expected")
require.True(t, crit, "inconsistent L1 origin transition must be handled like a critical error with reorg")
})
t.Run("inconsistent equal height origin", func(t *testing.T) {
rng := rand.New(rand.NewSource(1234))
l1Fetcher := &testutils.MockL1Source{}
defer l1Fetcher.AssertExpectations(t)
l2Parent := testutils.RandomL2BlockRef(rng)
l1Info := testutils.RandomL1Info(rng)
l1Info.InfoNum = l2Parent.L1Origin.Number
epoch := l1Info.ID()
_, crit, err := PreparePayloadAttributes(context.Background(), cfg, l1Fetcher, l2Parent, epoch)
require.NotNil(t, err, "inconsistent L1 origin error expected")
require.True(t, crit, "inconsistent L1 origin transition must be handled like a critical error with reorg")
})
t.Run("rpc fail Fetch", func(t *testing.T) {
rng := rand.New(rand.NewSource(1234))
l1Fetcher := &testutils.MockL1Source{}
defer l1Fetcher.AssertExpectations(t)
l2Parent := testutils.RandomL2BlockRef(rng)
epoch := l2Parent.L1Origin
epoch.Number += 1
mockRPCErr := errors.New("mock rpc error")
l1Fetcher.ExpectFetch(epoch.Hash, nil, nil, nil, mockRPCErr)
_, crit, err := PreparePayloadAttributes(context.Background(), cfg, l1Fetcher, l2Parent, epoch)
require.ErrorIs(t, err, mockRPCErr, "mock rpc error expected")
require.False(t, crit, "rpc errors should not be critical, it is not necessary to reorg")
})
t.Run("rpc fail InfoByHash", func(t *testing.T) {
rng := rand.New(rand.NewSource(1234))
l1Fetcher := &testutils.MockL1Source{}
defer l1Fetcher.AssertExpectations(t)
l2Parent := testutils.RandomL2BlockRef(rng)
epoch := l2Parent.L1Origin
mockRPCErr := errors.New("mock rpc error")
l1Fetcher.ExpectInfoByHash(epoch.Hash, nil, mockRPCErr)
_, crit, err := PreparePayloadAttributes(context.Background(), cfg, l1Fetcher, l2Parent, epoch)
require.ErrorIs(t, err, mockRPCErr, "mock rpc error expected")
require.False(t, crit, "rpc errors should not be critical, it is not necessary to reorg")
})
t.Run("next origin without deposits", func(t *testing.T) {
rng := rand.New(rand.NewSource(1234))
l1Fetcher := &testutils.MockL1Source{}
defer l1Fetcher.AssertExpectations(t)
l2Parent := testutils.RandomL2BlockRef(rng)
l1Info := testutils.RandomL1Info(rng)
l1Info.InfoParentHash = l2Parent.L1Origin.Hash
l1Info.InfoNum = l2Parent.L1Origin.Number + 1
epoch := l1Info.ID()
l1InfoTx, err := L1InfoDepositBytes(0, l1Info)
require.NoError(t, err)
l1Fetcher.ExpectFetch(epoch.Hash, l1Info, nil, nil, nil)
attrs, crit, err := PreparePayloadAttributes(context.Background(), cfg, l1Fetcher, l2Parent, epoch)
require.NoError(t, err)
require.False(t, crit)
require.NotNil(t, attrs)
require.Equal(t, l2Parent.Time+cfg.BlockTime, uint64(attrs.Timestamp))
require.Equal(t, eth.Bytes32(l1Info.InfoMixDigest), attrs.PrevRandao)
require.Equal(t, cfg.FeeRecipientAddress, attrs.SuggestedFeeRecipient)
require.Equal(t, 1, len(attrs.Transactions))
require.Equal(t, l1InfoTx, []byte(attrs.Transactions[0]))
require.True(t, attrs.NoTxPool)
})
t.Run("next origin with deposits", func(t *testing.T) {
rng := rand.New(rand.NewSource(1234))
l1Fetcher := &testutils.MockL1Source{}
defer l1Fetcher.AssertExpectations(t)
l2Parent := testutils.RandomL2BlockRef(rng)
l1Info := testutils.RandomL1Info(rng)
l1Info.InfoParentHash = l2Parent.L1Origin.Hash
l1Info.InfoNum = l2Parent.L1Origin.Number + 1
receipts, depositTxs := makeReceipts(rng, l1Info.InfoHash, cfg.DepositContractAddress, []receiptData{
{goodReceipt: true, DepositLogs: []bool{true, false}},
{goodReceipt: true, DepositLogs: []bool{true}},
{goodReceipt: false, DepositLogs: []bool{true}},
{goodReceipt: false, DepositLogs: []bool{false}},
})
usedDepositTxs, err := encodeDeposits(depositTxs)
require.NoError(t, err)
epoch := l1Info.ID()
l1InfoTx, err := L1InfoDepositBytes(0, l1Info)
require.NoError(t, err)
l2Txs := append(append(make([]eth.Data, 0), l1InfoTx), usedDepositTxs...)
// txs are ignored, API is a bit bloated to previous approach. Only l1Info and receipts matter.
l1Txs := make(types.Transactions, len(receipts))
l1Fetcher.ExpectFetch(epoch.Hash, l1Info, l1Txs, receipts, nil)
attrs, crit, err := PreparePayloadAttributes(context.Background(), cfg, l1Fetcher, l2Parent, epoch)
require.NoError(t, err)
require.False(t, crit)
require.NotNil(t, attrs)
require.Equal(t, l2Parent.Time+cfg.BlockTime, uint64(attrs.Timestamp))
require.Equal(t, eth.Bytes32(l1Info.InfoMixDigest), attrs.PrevRandao)
require.Equal(t, cfg.FeeRecipientAddress, attrs.SuggestedFeeRecipient)
require.Equal(t, len(l2Txs), len(attrs.Transactions), "Expected txs to equal l1 info tx + user deposit txs")
require.Equal(t, l2Txs, attrs.Transactions)
require.True(t, attrs.NoTxPool)
})
t.Run("same origin again", func(t *testing.T) {
rng := rand.New(rand.NewSource(1234))
l1Fetcher := &testutils.MockL1Source{}
defer l1Fetcher.AssertExpectations(t)
l2Parent := testutils.RandomL2BlockRef(rng)
l1Info := testutils.RandomL1Info(rng)
l1Info.InfoHash = l2Parent.L1Origin.Hash
l1Info.InfoNum = l2Parent.L1Origin.Number
epoch := l1Info.ID()
l1InfoTx, err := L1InfoDepositBytes(l2Parent.SequenceNumber+1, l1Info)
require.NoError(t, err)
l1Fetcher.ExpectInfoByHash(epoch.Hash, l1Info, nil)
attrs, crit, err := PreparePayloadAttributes(context.Background(), cfg, l1Fetcher, l2Parent, epoch)
require.NoError(t, err)
require.False(t, crit)
require.NotNil(t, attrs)
require.Equal(t, l2Parent.Time+cfg.BlockTime, uint64(attrs.Timestamp))
require.Equal(t, eth.Bytes32(l1Info.InfoMixDigest), attrs.PrevRandao)
require.Equal(t, cfg.FeeRecipientAddress, attrs.SuggestedFeeRecipient)
require.Equal(t, 1, len(attrs.Transactions))
require.Equal(t, l1InfoTx, []byte(attrs.Transactions[0]))
require.True(t, attrs.NoTxPool)
})
}
func encodeDeposits(deposits []*types.DepositTx) (out []eth.Data, err error) {
for i, tx := range deposits {
opaqueTx, err := types.NewTx(tx).MarshalBinary()
if err != nil {
return nil, fmt.Errorf("bad deposit %d: %v", i, err)
}
out = append(out, opaqueTx)
}
return
}
...@@ -6,8 +6,10 @@ import ( ...@@ -6,8 +6,10 @@ import (
"testing" "testing"
"github.com/ethereum-optimism/optimism/op-node/testutils" "github.com/ethereum-optimism/optimism/op-node/testutils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func TestUnmarshalLogEvent(t *testing.T) { func TestUnmarshalLogEvent(t *testing.T) {
...@@ -43,6 +45,44 @@ type receiptData struct { ...@@ -43,6 +45,44 @@ type receiptData struct {
DepositLogs []bool DepositLogs []bool
} }
func makeReceipts(rng *rand.Rand, blockHash common.Hash, depositContractAddr common.Address, testReceipts []receiptData) (receipts []*types.Receipt, expectedDeposits []*types.DepositTx) {
logIndex := uint(0)
for txIndex, rData := range testReceipts {
var logs []*types.Log
status := types.ReceiptStatusSuccessful
if !rData.goodReceipt {
status = types.ReceiptStatusFailed
}
for _, isDeposit := range rData.DepositLogs {
var ev *types.Log
if isDeposit {
source := UserDepositSource{L1BlockHash: blockHash, LogIndex: uint64(logIndex)}
dep := testutils.GenerateDeposit(source.SourceHash(), rng)
if status == types.ReceiptStatusSuccessful {
expectedDeposits = append(expectedDeposits, dep)
}
ev = MarshalDepositLogEvent(depositContractAddr, dep)
} else {
ev = testutils.GenerateLog(testutils.RandomAddress(rng), nil, nil)
}
ev.TxIndex = uint(txIndex)
ev.Index = logIndex
ev.BlockHash = blockHash
logs = append(logs, ev)
logIndex++
}
receipts = append(receipts, &types.Receipt{
Type: types.DynamicFeeTxType,
Status: status,
Logs: logs,
BlockHash: blockHash,
TransactionIndex: uint(txIndex),
})
}
return
}
type DeriveUserDepositsTestCase struct { type DeriveUserDepositsTestCase struct {
name string name string
// generate len(receipts) receipts // generate len(receipts) receipts
...@@ -64,49 +104,14 @@ func TestDeriveUserDeposits(t *testing.T) { ...@@ -64,49 +104,14 @@ func TestDeriveUserDeposits(t *testing.T) {
for i, testCase := range testCases { for i, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) { t.Run(testCase.name, func(t *testing.T) {
rng := rand.New(rand.NewSource(1234 + int64(i))) rng := rand.New(rand.NewSource(1234 + int64(i)))
var receipts []*types.Receipt
var expectedDeposits []*types.DepositTx
logIndex := uint(0)
blockHash := testutils.RandomHash(rng) blockHash := testutils.RandomHash(rng)
for txIndex, rData := range testCase.receipts { receipts, expectedDeposits := makeReceipts(rng, blockHash, MockDepositContractAddr, testCase.receipts)
var logs []*types.Log got, err := UserDeposits(receipts, MockDepositContractAddr)
status := types.ReceiptStatusSuccessful require.NoError(t, err)
if !rData.goodReceipt { require.Equal(t, len(got), len(expectedDeposits))
status = types.ReceiptStatusFailed
}
for _, isDeposit := range rData.DepositLogs {
var ev *types.Log
if isDeposit {
source := UserDepositSource{L1BlockHash: blockHash, LogIndex: uint64(logIndex)}
dep := testutils.GenerateDeposit(source.SourceHash(), rng)
if status == types.ReceiptStatusSuccessful {
expectedDeposits = append(expectedDeposits, dep)
}
ev = MarshalDepositLogEvent(MockDepositContractAddr, dep)
} else {
ev = testutils.GenerateLog(testutils.RandomAddress(rng), nil, nil)
}
ev.TxIndex = uint(txIndex)
ev.Index = logIndex
ev.BlockHash = blockHash
logs = append(logs, ev)
logIndex++
}
receipts = append(receipts, &types.Receipt{
Type: types.DynamicFeeTxType,
Status: status,
Logs: logs,
BlockHash: blockHash,
TransactionIndex: uint(txIndex),
})
}
got, errs := UserDeposits(receipts, MockDepositContractAddr)
assert.Equal(t, len(errs), 0)
assert.Equal(t, len(got), len(expectedDeposits))
for d, depTx := range got { for d, depTx := range got {
expected := expectedDeposits[d] expected := expectedDeposits[d]
assert.Equal(t, expected, depTx) require.Equal(t, expected, depTx)
} }
}) })
} }
......
...@@ -3,16 +3,17 @@ package derive ...@@ -3,16 +3,17 @@ package derive
import ( import (
"fmt" "fmt"
"github.com/hashicorp/go-multierror"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
) )
// UserDeposits transforms the L2 block-height and L1 receipts into the transaction inputs for a full L2 block // UserDeposits transforms the L2 block-height and L1 receipts into the transaction inputs for a full L2 block
func UserDeposits(receipts []*types.Receipt, depositContractAddr common.Address) ([]*types.DepositTx, []error) { func UserDeposits(receipts []*types.Receipt, depositContractAddr common.Address) ([]*types.DepositTx, error) {
var out []*types.DepositTx var out []*types.DepositTx
var errs []error var result error
for i, rec := range receipts { for i, rec := range receipts {
if rec.Status != types.ReceiptStatusSuccessful { if rec.Status != types.ReceiptStatusSuccessful {
continue continue
...@@ -21,26 +22,30 @@ func UserDeposits(receipts []*types.Receipt, depositContractAddr common.Address) ...@@ -21,26 +22,30 @@ func UserDeposits(receipts []*types.Receipt, depositContractAddr common.Address)
if log.Address == depositContractAddr && len(log.Topics) > 0 && log.Topics[0] == DepositEventABIHash { if log.Address == depositContractAddr && len(log.Topics) > 0 && log.Topics[0] == DepositEventABIHash {
dep, err := UnmarshalDepositLogEvent(log) dep, err := UnmarshalDepositLogEvent(log)
if err != nil { if err != nil {
errs = append(errs, fmt.Errorf("malformatted L1 deposit log in receipt %d, log %d: %w", i, j, err)) result = multierror.Append(result, fmt.Errorf("malformatted L1 deposit log in receipt %d, log %d: %w", i, j, err))
} else { } else {
out = append(out, dep) out = append(out, dep)
} }
} }
} }
} }
return out, errs return out, result
} }
func DeriveDeposits(receipts []*types.Receipt, depositContractAddr common.Address) ([]hexutil.Bytes, []error) { func DeriveDeposits(receipts []*types.Receipt, depositContractAddr common.Address) ([]hexutil.Bytes, error) {
userDeposits, errs := UserDeposits(receipts, depositContractAddr) var result error
userDeposits, err := UserDeposits(receipts, depositContractAddr)
if err != nil {
result = multierror.Append(result, err)
}
encodedTxs := make([]hexutil.Bytes, 0, len(userDeposits)) encodedTxs := make([]hexutil.Bytes, 0, len(userDeposits))
for i, tx := range userDeposits { for i, tx := range userDeposits {
opaqueTx, err := types.NewTx(tx).MarshalBinary() opaqueTx, err := types.NewTx(tx).MarshalBinary()
if err != nil { if err != nil {
errs = append(errs, fmt.Errorf("failed to encode user tx %d", i)) result = multierror.Append(result, fmt.Errorf("failed to encode user tx %d", i))
} else { } else {
encodedTxs = append(encodedTxs, opaqueTx) encodedTxs = append(encodedTxs, opaqueTx)
} }
} }
return encodedTxs, errs return encodedTxs, result
} }
...@@ -9,8 +9,6 @@ import ( ...@@ -9,8 +9,6 @@ import (
"github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
...@@ -27,70 +25,16 @@ func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, ...@@ -27,70 +25,16 @@ func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef,
fetchCtx, cancel := context.WithTimeout(ctx, time.Second*20) fetchCtx, cancel := context.WithTimeout(ctx, time.Second*20)
defer cancel() defer cancel()
var l1Info eth.L1Info attrs, _, err := derive.PreparePayloadAttributes(fetchCtx, d.Config, d.dl, l2Head, l1Origin.ID())
var receipts types.Receipts
var err error
seqNumber := l2Head.SequenceNumber + 1
// If the L1 origin changed this block, then we are in the first block of the epoch. In this
// case we need to fetch all transaction receipts from the L1 origin block so we can scan for
// user deposits.
if l2Head.L1Origin.Number != l1Origin.Number {
if l2Head.L1Origin.Hash != l1Origin.ParentHash {
d.log.Error("SEQUENCING BUG: cannot create new block on top of l2Head with new origin", "head", l2Head,
"head_origin", l2Head.L1Origin, "head_seq_nr", l2Head.SequenceNumber, "new_origin", l1Origin, "new_origin_parent", l1Origin.ParentID())
return l2Head, nil, fmt.Errorf("cannot create new block with L1 origin %s (parent %s) on top of L1 origin %s", l1Origin, l1Origin.ParentID(), l2Head.L1Origin)
}
l1Info, _, receipts, err = d.dl.Fetch(fetchCtx, l1Origin.Hash)
seqNumber = 0 // reset sequence number at the start of the epoch
} else {
if l2Head.L1Origin.Hash != l1Origin.Hash {
d.log.Error("SEQUENCING BUG: cannot create new block on top of l2Head with different origin at same height",
"head", l2Head, "head_origin", l2Head.L1Origin, "head_seq_nr", l2Head.SequenceNumber, "new_origin", l1Origin, "new_origin_parent", l1Origin.ParentID())
return l2Head, nil, fmt.Errorf("cannot create new block with L1 origin %s (parent %s) on top of L1 origin %s", l1Origin, l1Origin.ParentID(), l2Head.L1Origin)
}
l1Info, err = d.dl.InfoByHash(fetchCtx, l1Origin.Hash)
}
if err != nil {
return l2Head, nil, fmt.Errorf("failed to fetch L1 block info of %s: %v", l1Origin, err)
}
// Start building the list of transactions to include in the new block.
var txns []eth.Data
// First transaction in every block is always the L1 info transaction.
l1InfoTx, err := derive.L1InfoDepositBytes(seqNumber, l1Info)
if err != nil { if err != nil {
return l2Head, nil, err return l2Head, nil, err
} }
txns = append(txns, l1InfoTx)
// Next we append user deposits. If we're not the first block in an epoch, then receipts will
// be empty and no deposits will be derived.
deposits, errs := derive.DeriveDeposits(receipts, d.Config.DepositContractAddress)
d.log.Info("Derived deposits", "deposits", deposits, "l2Parent", l2Head, "l1Origin", l1Origin)
for _, err := range errs {
d.log.Error("Failed to derive a deposit", "l1OriginHash", l1Origin.Hash, "err", err)
}
// TODO: Should we halt if len(errs) > 0? Opens up a denial of service attack, but prevents lockup of funds.
txns = append(txns, deposits...)
// If our next L2 block timestamp is beyond the Sequencer drift threshold, then we must produce // If our next L2 block timestamp is beyond the Sequencer drift threshold, then we must produce
// empty blocks (other than the L1 info deposit and any user deposits). We handle this by // empty blocks (other than the L1 info deposit and any user deposits). We handle this by
// setting NoTxPool to true, which will cause the Sequencer to not include any transactions // setting NoTxPool to true, which will cause the Sequencer to not include any transactions
// from the transaction pool. // from the transaction pool.
nextL2Time := l2Head.Time + d.Config.BlockTime attrs.NoTxPool = uint64(attrs.Timestamp) >= l1Origin.Time+d.Config.MaxSequencerDrift
shouldProduceEmptyBlock := nextL2Time >= l1Origin.Time+d.Config.MaxSequencerDrift
// Put together our payload attributes.
attrs := &eth.PayloadAttributes{
Timestamp: hexutil.Uint64(nextL2Time),
PrevRandao: eth.Bytes32(l1Info.MixDigest()),
SuggestedFeeRecipient: d.Config.FeeRecipientAddress,
Transactions: txns,
NoTxPool: shouldProduceEmptyBlock,
}
// And construct our fork choice state. This is our current fork choice state and will be // And construct our fork choice state. This is our current fork choice state and will be
// updated as a result of executing the block based on the attributes described above. // updated as a result of executing the block based on the attributes described above.
......
...@@ -13,6 +13,15 @@ type MockL1Source struct { ...@@ -13,6 +13,15 @@ type MockL1Source struct {
mock.Mock mock.Mock
} }
func (m *MockL1Source) InfoByHash(ctx context.Context, hash common.Hash) (eth.L1Info, error) {
out := m.Mock.MethodCalled("InfoByHash", hash)
return *out[0].(*eth.L1Info), *out[1].(*error)
}
func (m *MockL1Source) ExpectInfoByHash(hash common.Hash, info eth.L1Info, err error) {
m.Mock.On("InfoByHash", hash).Once().Return(&info, &err)
}
func (m *MockL1Source) L1BlockRefByNumber(ctx context.Context, u uint64) (eth.L1BlockRef, error) { func (m *MockL1Source) L1BlockRefByNumber(ctx context.Context, u uint64) (eth.L1BlockRef, error) {
out := m.Mock.MethodCalled("L1BlockRefByNumber", u) out := m.Mock.MethodCalled("L1BlockRefByNumber", u)
return out[0].(eth.L1BlockRef), *out[1].(*error) return out[0].(eth.L1BlockRef), *out[1].(*error)
...@@ -33,11 +42,11 @@ func (m *MockL1Source) ExpectL1BlockRefByHash(hash common.Hash, ref eth.L1BlockR ...@@ -33,11 +42,11 @@ func (m *MockL1Source) ExpectL1BlockRefByHash(hash common.Hash, ref eth.L1BlockR
func (m *MockL1Source) Fetch(ctx context.Context, blockHash common.Hash) (eth.L1Info, types.Transactions, types.Receipts, error) { func (m *MockL1Source) Fetch(ctx context.Context, blockHash common.Hash) (eth.L1Info, types.Transactions, types.Receipts, error) {
out := m.Mock.MethodCalled("Fetch", blockHash) out := m.Mock.MethodCalled("Fetch", blockHash)
return out[0].(eth.L1Info), out[1].(types.Transactions), out[2].(types.Receipts), *out[3].(*error) return *out[0].(*eth.L1Info), out[1].(types.Transactions), out[2].(types.Receipts), *out[3].(*error)
} }
func (m *MockL1Source) ExpectFetch(hash common.Hash, info eth.L1Info, transactions types.Transactions, receipts types.Receipts, err error) { func (m *MockL1Source) ExpectFetch(hash common.Hash, info eth.L1Info, transactions types.Transactions, receipts types.Receipts, err error) {
m.Mock.On("Fetch", hash).Once().Return(info, transactions, receipts, &err) m.Mock.On("Fetch", hash).Once().Return(&info, transactions, receipts, &err)
} }
func (m *MockL1Source) InfoAndTxsByHash(ctx context.Context, hash common.Hash) (eth.L1Info, types.Transactions, error) { func (m *MockL1Source) InfoAndTxsByHash(ctx context.Context, hash common.Hash) (eth.L1Info, types.Transactions, error) {
......
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"math/big" "math/big"
"github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/rollup/driver" "github.com/ethereum-optimism/optimism/op-node/rollup/driver"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
...@@ -30,6 +31,12 @@ func (r *RollupClient) SyncStatus(ctx context.Context) (*driver.SyncStatus, erro ...@@ -30,6 +31,12 @@ func (r *RollupClient) SyncStatus(ctx context.Context) (*driver.SyncStatus, erro
return output, err return output, err
} }
func (r *RollupClient) RollupConfig(ctx context.Context) (*rollup.Config, error) {
var output *rollup.Config
err := r.rpc.CallContext(ctx, &output, "optimism_rollupConfig")
return output, err
}
func (r *RollupClient) Version(ctx context.Context) (string, error) { func (r *RollupClient) Version(ctx context.Context) (string, error) {
var output string var output string
err := r.rpc.CallContext(ctx, &output, "optimism_version") err := r.rpc.CallContext(ctx, &output, "optimism_version")
......
...@@ -60,7 +60,7 @@ mkdir -p ./.devnet ...@@ -60,7 +60,7 @@ mkdir -p ./.devnet
if [ ! -f ./.devnet/rollup.json ]; then if [ ! -f ./.devnet/rollup.json ]; then
GENESIS_TIMESTAMP=$(date +%s | xargs printf "0x%x") GENESIS_TIMESTAMP=$(date +%s | xargs printf "0x%x")
else else
GENESIS_TIMESTAMP=$(jq '.genesis.l2_time' < .devnet/rollup.json) GENESIS_TIMESTAMP=$(jq '.timestamp' < .devnet/genesis-l1.json)
fi fi
# Regenerate the L1 genesis file if necessary. The existence of the genesis # Regenerate the L1 genesis file if necessary. The existence of the genesis
......
...@@ -9,7 +9,13 @@ ...@@ -9,7 +9,13 @@
echoerr() { echo "$@" 1>&2; } echoerr() { echo "$@" 1>&2; }
# Check if this is a CircleCI PR. # Check if this is a CircleCI PR.
if [[ -n $CIRCLE_PULL_REQUEST ]]; then if [[ -z ${CIRCLE_PULL_REQUEST+x} ]]; then
# CIRCLE_PULL_REQUEST is unbound here
# Non-PR builds always require a rebuild.
echoerr "Not a PR build, requiring a total rebuild."
echo "TRUE"
else
# CIRCLE_PULL_REQUEST is bound here
PACKAGE=$1 PACKAGE=$1
# Craft the URL to the GitHub API. The access token is optional for the monorepo since it's an open-source repo. # Craft the URL to the GitHub API. The access token is optional for the monorepo since it's an open-source repo.
GITHUB_API_URL="https://api.github.com/repos/ethereum-optimism/optimism/pulls/${CIRCLE_PULL_REQUEST/https:\/\/github.com\/ethereum-optimism\/optimism\/pull\//}" GITHUB_API_URL="https://api.github.com/repos/ethereum-optimism/optimism/pulls/${CIRCLE_PULL_REQUEST/https:\/\/github.com\/ethereum-optimism\/optimism\/pull\//}"
...@@ -30,8 +36,4 @@ if [[ -n $CIRCLE_PULL_REQUEST ]]; then ...@@ -30,8 +36,4 @@ if [[ -n $CIRCLE_PULL_REQUEST ]]; then
# Compare HEAD to the PR's base ref, stripping out the change percentages that come with git diff --dirstat. # Compare HEAD to the PR's base ref, stripping out the change percentages that come with git diff --dirstat.
# Pass in the diff pattern to grep, and echo TRUE if there's a match. False otherwise. # Pass in the diff pattern to grep, and echo TRUE if there's a match. False otherwise.
(echo "$DIFF" | sed 's/^[ 0-9.]\+% //g' | grep -q -E "$PACKAGE" && echo "TRUE") || echo "FALSE" (echo "$DIFF" | sed 's/^[ 0-9.]\+% //g' | grep -q -E "$PACKAGE" && echo "TRUE") || echo "FALSE"
else
# Non-PR builds always require a rebuild.
echoerr "Not a PR build, requiring a total rebuild."
echo "TRUE"
fi fi
...@@ -9,7 +9,7 @@ WORKDIR /opt/foundry ...@@ -9,7 +9,7 @@ WORKDIR /opt/foundry
# Only diff from upstream docker image is this clone instead # Only diff from upstream docker image is this clone instead
# of COPY. We select a specific commit to use. # of COPY. We select a specific commit to use.
RUN git clone https://github.com/foundry-rs/foundry.git . \ RUN git clone https://github.com/foundry-rs/foundry.git . \
&& git checkout b7b1ec471bdd38221773e1a569dc4f20297bd7db && git checkout 3c49efe58ca4bdeec4729490501da06914446405
RUN source $HOME/.profile && cargo build --release \ RUN source $HOME/.profile && cargo build --release \
&& strip /opt/foundry/target/release/forge \ && strip /opt/foundry/target/release/forge \
......
# @eth-optimism/go-builder
## 0.0.5
### Patch Changes
- df5eb9e7: Upgrade golangci-lint version for go 1.18
## 0.0.4
### Patch Changes
- 7317e2be: Bump versions
- 10e07754: Add abigen and gotestsum to go-builder
## 0.0.3
### Patch Changes
- ec446248: Trigger releases
## 0.0.2
### Patch Changes
- fa978257: Trigger releases
## 0.0.1
### Patch Changes
- 24bf252e: Add to changesets
FROM ethereum/client-go:alltools-v1.10.17 as geth
FROM golang:1.18.0-alpine3.15
COPY --from=geth /usr/local/bin/abigen /usr/local/bin/abigen
RUN apk add --no-cache make gcc musl-dev linux-headers git jq curl bash gzip ca-certificates openssh && \
go install gotest.tools/gotestsum@latest && \
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.46.2
CMD ["bash"]
{
"name": "@eth-optimism/go-builder",
"version": "0.0.5",
"scripts": {},
"license": "MIT",
"dependencies": {}
}
# @eth-optimism/js-builder
## 0.0.5
### Patch Changes
- 8a8efd51: Cache Solc 0.8.9 and 0.8.10 for use in CI
- 8dc50095: Fix broken build
## 0.0.4
### Patch Changes
- 7317e2be: Bump versions
- 10e07754: Add abigen
## 0.0.3
### Patch Changes
- ec446248: Trigger releases
## 0.0.2
### Patch Changes
- fa978257: Trigger releases
## 0.0.1
### Patch Changes
- 24bf252e: Add to changesets
FROM ethereum/client-go:alltools-v1.10.17 as geth
FROM ghcr.io/foundry-rs/foundry:latest as foundry
FROM python:3.8.12-slim-buster
COPY --from=foundry /usr/local/bin/forge /usr/local/bin/forge
COPY --from=foundry /usr/local/bin/cast /usr/local/bin/cast
COPY --from=geth /usr/local/bin/abigen /usr/local/bin/abigen
RUN apt-get update && \
apt-get install -y curl openssh-client git build-essential ca-certificates musl && \
curl -sL https://deb.nodesource.com/setup_16.x -o nodesource_setup.sh && \
curl -sL https://go.dev/dl/go1.18.2.linux-amd64.tar.gz -o go1.18.2.linux-amd64.tar.gz && \
tar -C /usr/local/ -xzvf go1.18.2.linux-amd64.tar.gz && \
ln -s /usr/local/go/bin/gofmt /usr/local/bin/gofmt && \
bash nodesource_setup.sh && \
apt-get install -y nodejs && \
npm i -g yarn && \
npm i -g depcheck && \
pip install slither-analyzer
RUN echo "downloading solidity compilers" && \
curl -o solc-linux-amd64-v0.5.17+commit.d19bba13 -sL https://binaries.soliditylang.org/linux-amd64/solc-linux-amd64-v0.5.17+commit.d19bba13 && \
curl -o solc-linux-amd64-v0.8.9+commit.e5eed63a -sL https://binaries.soliditylang.org/linux-amd64/solc-linux-amd64-v0.8.9+commit.e5eed63a && \
curl -o solc-linux-amd64-v0.8.10+commit.fc410830 -sL https://binaries.soliditylang.org/linux-amd64/solc-linux-amd64-v0.8.10+commit.fc410830 && \
curl -o solc-linux-amd64-v0.8.12+commit.f00d7308 -sL https://binaries.soliditylang.org/linux-amd64/solc-linux-amd64-v0.8.12+commit.f00d7308 && \
echo "verifying checksums" && \
(echo "c35ce7a4d3ffa5747c178b1e24c8541b2e5d8a82c1db3719eb4433a1f19e16f3 solc-linux-amd64-v0.5.17+commit.d19bba13" | sha256sum --check --status - || exit 1) && \
(echo "f851f11fad37496baabaf8d6cb5c057ca0d9754fddb7a351ab580d7fd728cb94 solc-linux-amd64-v0.8.9+commit.e5eed63a" | sha256sum --check --status - || exit 1) && \
(echo "c7effacf28b9d64495f81b75228fbf4266ac0ec87e8f1adc489ddd8a4dd06d89 solc-linux-amd64-v0.8.10+commit.fc410830" | sha256sum --check --status - || exit 1) && \
(echo "556c3ec44faf8ff6b67933fa8a8a403abe82c978d6e581dbfec4bd07360bfbf3 solc-linux-amd64-v0.8.12+commit.f00d7308" | sha256sum --check --status - || exit 1) && \
echo "caching compilers" && \
mkdir -p ~/.cache/hardhat-nodejs/compilers/linux-amd64 && \
cp solc-linux-amd64-v0.5.17+commit.d19bba13 ~/.cache/hardhat-nodejs/compilers/linux-amd64/ && \
cp solc-linux-amd64-v0.8.9+commit.e5eed63a ~/.cache/hardhat-nodejs/compilers/linux-amd64/ && \
cp solc-linux-amd64-v0.8.10+commit.fc410830 ~/.cache/hardhat-nodejs/compilers/linux-amd64/ && \
cp solc-linux-amd64-v0.8.12+commit.f00d7308 ~/.cache/hardhat-nodejs/compilers/linux-amd64/ && \
mkdir -p ~/.svm/0.5.17 && \
cp solc-linux-amd64-v0.5.17+commit.d19bba13 ~/.svm/0.5.17/solc-0.5.17 && \
mkdir -p ~/.svm/0.8.9 && \
cp solc-linux-amd64-v0.8.9+commit.e5eed63a ~/.svm/0.8.9/solc-0.8.9 && \
mkdir -p ~/.svm/0.8.10 && \
cp solc-linux-amd64-v0.8.10+commit.fc410830 ~/.svm/0.8.10/solc-0.8.10 && \
mkdir -p ~/.svm/0.8.12 && \
cp solc-linux-amd64-v0.8.12+commit.f00d7308 ~/.svm/0.8.12/solc-0.8.12
{
"name": "@eth-optimism/js-builder",
"version": "0.0.5",
"scripts": {},
"license": "MIT",
"dependencies": {}
}
GasBenchMark_L1CrossDomainMessenger:test_L1MessengerSendMessage_benchmark_0() (gas: 158650) GasBenchMark_L1CrossDomainMessenger:test_L1MessengerSendMessage_benchmark_0() (gas: 262334)
GasBenchMark_L1CrossDomainMessenger:test_L1MessengerSendMessage_benchmark_1() (gas: 75059) GasBenchMark_L1CrossDomainMessenger:test_L1MessengerSendMessage_benchmark_1() (gas: 75318)
GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 249871) GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 353380)
GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 116125) GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 116384)
GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 249893) GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 353402)
GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 116100) GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 116359)
GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 45413) GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 45413)
GasBenchMark_L2OutputOracle:test_appendL2Output_benchmark() (gas: 68673) GasBenchMark_L2OutputOracle:test_appendL2Output_benchmark() (gas: 68673)
GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 75069) GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 75069)
...@@ -35,22 +35,23 @@ L1BlockTest:test_updateValues() (gas: 28216) ...@@ -35,22 +35,23 @@ L1BlockTest:test_updateValues() (gas: 28216)
L1BlockNumberTest:test_fallback() (gas: 18774) L1BlockNumberTest:test_fallback() (gas: 18774)
L1BlockNumberTest:test_getL1BlockNumber() (gas: 10657) L1BlockNumberTest:test_getL1BlockNumber() (gas: 10657)
L1BlockNumberTest:test_receive() (gas: 25437) L1BlockNumberTest:test_receive() (gas: 25437)
L1CrossDomainMessenger_Test:testCannot_L1MessengerPause() (gas: 24517) L1CrossDomainMessenger_Test:testCannot_L1MessengerPause() (gas: 24561)
L1CrossDomainMessenger_Test:testCannot_L1MessengerUnpause() (gas: 24509) L1CrossDomainMessenger_Test:testCannot_L1MessengerUnpause() (gas: 24508)
L1CrossDomainMessenger_Test:test_L1MessengerMessageVersion() (gas: 24716) L1CrossDomainMessenger_Test:test_L1MessengerMessageVersion() (gas: 24748)
L1CrossDomainMessenger_Test:test_L1MessengerPause() (gas: 47995) L1CrossDomainMessenger_Test:test_L1MessengerPause() (gas: 48017)
L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageSucceeds() (gas: 77773) L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageSucceeds() (gas: 77750)
L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageToSystemContract() (gas: 67784) L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageToSystemContract() (gas: 67778)
L1CrossDomainMessenger_Test:test_L1MessengerRelayShouldRevertIfPaused() (gas: 60472) L1CrossDomainMessenger_Test:test_L1MessengerRelayShouldRevertIfPaused() (gas: 60471)
L1CrossDomainMessenger_Test:test_L1MessengerSendMessage() (gas: 196878) L1CrossDomainMessenger_Test:test_L1MessengerReplayMessageWithValue() (gas: 38127)
L1CrossDomainMessenger_Test:test_L1MessengerTwiceSendMessage() (gas: 1273626) L1CrossDomainMessenger_Test:test_L1MessengerSendMessage() (gas: 297745)
L1CrossDomainMessenger_Test:test_L1MessengerUnpause() (gas: 40890) L1CrossDomainMessenger_Test:test_L1MessengerTwiceSendMessage() (gas: 1490048)
L1CrossDomainMessenger_Test:test_L1MessengerXDomainSenderReverts() (gas: 24272) L1CrossDomainMessenger_Test:test_L1MessengerUnpause() (gas: 40889)
L1CrossDomainMessenger_Test:test_L1MessengerxDomainMessageSenderResets() (gas: 86701) L1CrossDomainMessenger_Test:test_L1MessengerXDomainSenderReverts() (gas: 24249)
L1StandardBridge_Test:test_depositERC20() (gas: 475008) L1CrossDomainMessenger_Test:test_L1MessengerxDomainMessageSenderResets() (gas: 86146)
L1StandardBridge_Test:test_depositERC20To() (gas: 477189) L1StandardBridge_Test:test_depositERC20() (gas: 578867)
L1StandardBridge_Test:test_depositETH() (gas: 268941) L1StandardBridge_Test:test_depositERC20To() (gas: 581048)
L1StandardBridge_Test:test_depositETHTo() (gas: 226763) L1StandardBridge_Test:test_depositETH() (gas: 372975)
L1StandardBridge_Test:test_depositETHTo() (gas: 330097)
L1StandardBridge_Test:test_finalizeERC20Withdrawal() (gas: 490759) L1StandardBridge_Test:test_finalizeERC20Withdrawal() (gas: 490759)
L1StandardBridge_Test:test_finalizeETHWithdrawal() (gas: 64409) L1StandardBridge_Test:test_finalizeETHWithdrawal() (gas: 64409)
L1StandardBridge_Test:test_initialize() (gas: 26336) L1StandardBridge_Test:test_initialize() (gas: 26336)
...@@ -58,17 +59,17 @@ L1StandardBridge_Test:test_onlyEOADepositERC20() (gas: 22363) ...@@ -58,17 +59,17 @@ L1StandardBridge_Test:test_onlyEOADepositERC20() (gas: 22363)
L1StandardBridge_Test:test_onlyEOADepositETH() (gas: 40882) L1StandardBridge_Test:test_onlyEOADepositETH() (gas: 40882)
L1StandardBridge_Test:test_onlyL2BridgeFinalizeERC20Withdrawal() (gas: 36271) L1StandardBridge_Test:test_onlyL2BridgeFinalizeERC20Withdrawal() (gas: 36271)
L1StandardBridge_Test:test_onlyPortalFinalizeERC20Withdrawal() (gas: 35600) L1StandardBridge_Test:test_onlyPortalFinalizeERC20Withdrawal() (gas: 35600)
L1StandardBridge_Test:test_receive() (gas: 413521) L1StandardBridge_Test:test_receive() (gas: 519560)
L2CrossDomainMessenger_Test:testCannot_L2MessengerPause() (gas: 10821) L2CrossDomainMessenger_Test:testCannot_L2MessengerPause() (gas: 10800)
L2CrossDomainMessenger_Test:test_L2MessengerMessageVersion() (gas: 8445) L2CrossDomainMessenger_Test:test_L2MessengerMessageVersion() (gas: 8477)
L2CrossDomainMessenger_Test:test_L2MessengerPause() (gas: 31815) L2CrossDomainMessenger_Test:test_L2MessengerPause() (gas: 31772)
L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageSucceeds() (gas: 57332) L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageSucceeds() (gas: 57309)
L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageToSystemContract() (gas: 36140) L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageToSystemContract() (gas: 36137)
L2CrossDomainMessenger_Test:test_L2MessengerRelayShouldRevertIfPaused() (gas: 41664) L2CrossDomainMessenger_Test:test_L2MessengerRelayShouldRevertIfPaused() (gas: 41600)
L2CrossDomainMessenger_Test:test_L2MessengerSendMessage() (gas: 119627) L2CrossDomainMessenger_Test:test_L2MessengerSendMessage() (gas: 120536)
L2CrossDomainMessenger_Test:test_L2MessengerTwiceSendMessage() (gas: 133248) L2CrossDomainMessenger_Test:test_L2MessengerTwiceSendMessage() (gas: 133720)
L2CrossDomainMessenger_Test:test_L2MessengerXDomainSenderReverts() (gas: 10599) L2CrossDomainMessenger_Test:test_L2MessengerXDomainSenderReverts() (gas: 10576)
L2CrossDomainMessenger_Test:test_L2MessengerxDomainMessageSenderResets() (gas: 54844) L2CrossDomainMessenger_Test:test_L2MessengerxDomainMessageSenderResets() (gas: 54776)
L2OutputOracleTest:testCannot_AppendWithUnmatchedBlockhash() (gas: 26811) L2OutputOracleTest:testCannot_AppendWithUnmatchedBlockhash() (gas: 26811)
L2OutputOracleTest:testCannot_appendEmptyOutput() (gas: 24086) L2OutputOracleTest:testCannot_appendEmptyOutput() (gas: 24086)
L2OutputOracleTest:testCannot_appendFutureTimetamp() (gas: 26075) L2OutputOracleTest:testCannot_appendFutureTimetamp() (gas: 26075)
...@@ -88,18 +89,18 @@ L2OutputOracleTest:test_getL2Output() (gas: 82869) ...@@ -88,18 +89,18 @@ L2OutputOracleTest:test_getL2Output() (gas: 82869)
L2OutputOracleTest:test_latestBlockNumber() (gas: 76176) L2OutputOracleTest:test_latestBlockNumber() (gas: 76176)
L2OutputOracleTest:test_nextBlockNumber() (gas: 15122) L2OutputOracleTest:test_nextBlockNumber() (gas: 15122)
L2OutputOracleTest:test_updateOwner() (gas: 34603) L2OutputOracleTest:test_updateOwner() (gas: 34603)
L2OutputOracleUpgradeable_Test:test_cannotInitImpl() (gas: 8476) L2OutputOracleUpgradeable_Test:test_cannotInitImpl() (gas: 19451)
L2OutputOracleUpgradeable_Test:test_cannotInitProxy() (gas: 13497) L2OutputOracleUpgradeable_Test:test_cannotInitProxy() (gas: 24516)
L2OutputOracleUpgradeable_Test:test_initValuesOnProxy() (gas: 38865) L2OutputOracleUpgradeable_Test:test_initValuesOnProxy() (gas: 38865)
L2OutputOracleUpgradeable_Test:test_upgrading() (gas: 230843) L2OutputOracleUpgradeable_Test:test_upgrading() (gas: 230843)
L2StandardBridge_Test:test_ERC20BridgeFailed_whenLocalTokenIsBridge() (gas: 133200) L2StandardBridge_Test:test_ERC20BridgeFailed_whenLocalTokenIsBridge() (gas: 133459)
L2StandardBridge_Test:test_cannotWithdrawEthWithoutSendingIt() (gas: 21656) L2StandardBridge_Test:test_cannotWithdrawEthWithoutSendingIt() (gas: 21656)
L2StandardBridge_Test:test_finalizeDeposit() (gas: 93203) L2StandardBridge_Test:test_finalizeDeposit() (gas: 93203)
L2StandardBridge_Test:test_finalizeDeposit_failsToCompleteOutboundTransfer() (gas: 140210) L2StandardBridge_Test:test_finalizeDeposit_failsToCompleteOutboundTransfer() (gas: 140469)
L2StandardBridge_Test:test_initialize() (gas: 14802) L2StandardBridge_Test:test_initialize() (gas: 14802)
L2StandardBridge_Test:test_receive() (gas: 136525) L2StandardBridge_Test:test_receive() (gas: 136864)
L2StandardBridge_Test:test_withdraw() (gas: 352813) L2StandardBridge_Test:test_withdraw() (gas: 353020)
L2StandardBridge_Test:test_withdrawTo() (gas: 353498) L2StandardBridge_Test:test_withdrawTo() (gas: 353705)
L2StandardBridge_Test:test_withdraw_onlyEOA() (gas: 252006) L2StandardBridge_Test:test_withdraw_onlyEOA() (gas: 252006)
L2ToL1MessagePasserTest:test_burn() (gas: 112037) L2ToL1MessagePasserTest:test_burn() (gas: 112037)
L2ToL1MessagePasserTest:test_initiateWithdrawal_fromContract() (gas: 67892) L2ToL1MessagePasserTest:test_initiateWithdrawal_fromContract() (gas: 67892)
...@@ -126,8 +127,8 @@ OptimismMintableTokenFactory_Test:test_bridge() (gas: 7663) ...@@ -126,8 +127,8 @@ OptimismMintableTokenFactory_Test:test_bridge() (gas: 7663)
OptimismMintableTokenFactory_Test:test_createStandardL2Token() (gas: 1113150) OptimismMintableTokenFactory_Test:test_createStandardL2Token() (gas: 1113150)
OptimismMintableTokenFactory_Test:test_createStandardL2TokenSameTwice() (gas: 2209211) OptimismMintableTokenFactory_Test:test_createStandardL2TokenSameTwice() (gas: 2209211)
OptimismMintableTokenFactory_Test:test_createStandardL2TokenShouldRevertIfRemoteIsZero() (gas: 9399) OptimismMintableTokenFactory_Test:test_createStandardL2TokenShouldRevertIfRemoteIsZero() (gas: 9399)
OptimismPortalUpgradeable_Test:test_cannotInitImpl() (gas: 10933) OptimismPortalUpgradeable_Test:test_cannotInitImpl() (gas: 10686)
OptimismPortalUpgradeable_Test:test_cannotInitProxy() (gas: 15975) OptimismPortalUpgradeable_Test:test_cannotInitProxy() (gas: 15728)
OptimismPortalUpgradeable_Test:test_initValuesOnProxy() (gas: 15990) OptimismPortalUpgradeable_Test:test_initValuesOnProxy() (gas: 15990)
OptimismPortalUpgradeable_Test:test_upgrading() (gas: 230843) OptimismPortalUpgradeable_Test:test_upgrading() (gas: 230843)
OptimismPortal_Test:test_OptimismPortalConstructor() (gas: 17319) OptimismPortal_Test:test_OptimismPortalConstructor() (gas: 17319)
...@@ -254,19 +255,19 @@ RLPWriter_Test:test_writeUint_smallint3() (gas: 7372) ...@@ -254,19 +255,19 @@ RLPWriter_Test:test_writeUint_smallint3() (gas: 7372)
RLPWriter_Test:test_writeUint_smallint4() (gas: 7351) RLPWriter_Test:test_writeUint_smallint4() (gas: 7351)
RLPWriter_Test:test_writeUint_zero() (gas: 7798) RLPWriter_Test:test_writeUint_zero() (gas: 7798)
ResourceMetering_Test:test_initialResourceParams() (gas: 8964) ResourceMetering_Test:test_initialResourceParams() (gas: 8964)
ResourceMetering_Test:test_updateNoGasDelta() (gas: 2008269) ResourceMetering_Test:test_updateNoGasDelta() (gas: 2008317)
ResourceMetering_Test:test_updateOneEmptyBlock() (gas: 18123) ResourceMetering_Test:test_updateOneEmptyBlock() (gas: 18171)
ResourceMetering_Test:test_updateParamsNoChange() (gas: 13860) ResourceMetering_Test:test_updateParamsNoChange() (gas: 13956)
ResourceMetering_Test:test_updateTenEmptyBlocks() (gas: 20523) ResourceMetering_Test:test_updateTenEmptyBlocks() (gas: 20571)
ResourceMetering_Test:test_updateTwoEmptyBlocks() (gas: 20546) ResourceMetering_Test:test_updateTwoEmptyBlocks() (gas: 20594)
ResourceMetering_Test:test_useMaxSucceeds() (gas: 8017023) ResourceMetering_Test:test_useMaxSucceeds() (gas: 8017087)
ResourceMetering_Test:test_useMoreThanMaxReverts() (gas: 16002) ResourceMetering_Test:test_useMoreThanMaxReverts() (gas: 16047)
Semver_Test:test_behindProxy() (gas: 504908) Semver_Test:test_behindProxy() (gas: 504908)
Semver_Test:test_major() (gas: 5406) Semver_Test:test_major() (gas: 5406)
Semver_Test:test_minor() (gas: 5430) Semver_Test:test_minor() (gas: 5430)
Semver_Test:test_patch() (gas: 5364) Semver_Test:test_patch() (gas: 5364)
SequencerFeeVault_Test:test_constructor() (gas: 7656) SequencerFeeVault_Test:test_constructor() (gas: 7656)
SequencerFeeVault_Test:test_minWithdrawalAmount() (gas: 5407) SequencerFeeVault_Test:test_minWithdrawalAmount() (gas: 5407)
SequencerFeeVault_Test:test_receive() (gas: 17258) SequencerFeeVault_Test:test_receive() (gas: 17338)
SequencerFeeVault_Test:test_revertWithdraw() (gas: 9332) SequencerFeeVault_Test:test_revertWithdraw() (gas: 9332)
SequencerFeeVault_Test:test_withdraw() (gas: 147323) SequencerFeeVault_Test:test_withdraw() (gas: 147582)
...@@ -10,6 +10,9 @@ ...@@ -10,6 +10,9 @@
"modifier-name-mixedcase": "error", "modifier-name-mixedcase": "error",
"ordering": "warn", "ordering": "warn",
"avoid-low-level-calls": "off", "avoid-low-level-calls": "off",
"no-inline-assembly": "off",
"no-empty-blocks": "off",
"not-rely-on-time": "off",
"event-name-camelcase": "off", "event-name-camelcase": "off",
"reason-string": "off", "reason-string": "off",
"avoid-tx-origin": "off", "avoid-tx-origin": "off",
......
...@@ -46,7 +46,7 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, Semver { ...@@ -46,7 +46,7 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, Semver {
* *
* @return True if the message was sent from the messenger, false otherwise. * @return True if the message was sent from the messenger, false otherwise.
*/ */
function _isSystemMessageSender() internal view override returns (bool) { function _isOtherMessenger() internal view override returns (bool) {
return msg.sender == address(portal) && portal.l2Sender() == otherMessenger; return msg.sender == address(portal) && portal.l2Sender() == otherMessenger;
} }
......
...@@ -86,6 +86,8 @@ contract L1StandardBridge is StandardBridge, Semver { ...@@ -86,6 +86,8 @@ contract L1StandardBridge is StandardBridge, Semver {
); );
/** /**
* @custom:semver 0.0.1
*
* @param _messenger Address of the L1CrossDomainMessenger. * @param _messenger Address of the L1CrossDomainMessenger.
*/ */
constructor(address payable _messenger) Semver(0, 0, 1) { constructor(address payable _messenger) Semver(0, 0, 1) {
......
...@@ -63,26 +63,31 @@ contract L2OutputOracle is OwnableUpgradeable, Semver { ...@@ -63,26 +63,31 @@ contract L2OutputOracle is OwnableUpgradeable, Semver {
/** /**
* @notice The interval in L2 blocks at which checkpoints must be submitted. * @notice The interval in L2 blocks at which checkpoints must be submitted.
*/ */
// solhint-disable-next-line var-name-mixedcase
uint256 public immutable SUBMISSION_INTERVAL; uint256 public immutable SUBMISSION_INTERVAL;
/** /**
* @notice The number of blocks in the chain before the first block in this contract. * @notice The number of blocks in the chain before the first block in this contract.
*/ */
// solhint-disable-next-line var-name-mixedcase
uint256 public immutable HISTORICAL_TOTAL_BLOCKS; uint256 public immutable HISTORICAL_TOTAL_BLOCKS;
/** /**
* @notice The number of the first L2 block recorded in this contract. * @notice The number of the first L2 block recorded in this contract.
*/ */
// solhint-disable-next-line var-name-mixedcase
uint256 public immutable STARTING_BLOCK_NUMBER; uint256 public immutable STARTING_BLOCK_NUMBER;
/** /**
* @notice The timestamp of the first L2 block recorded in this contract. * @notice The timestamp of the first L2 block recorded in this contract.
*/ */
// solhint-disable-next-line var-name-mixedcase
uint256 public immutable STARTING_TIMESTAMP; uint256 public immutable STARTING_TIMESTAMP;
/** /**
* @notice The time between L2 blocks in seconds. * @notice The time between L2 blocks in seconds.
*/ */
// solhint-disable-next-line var-name-mixedcase
uint256 public immutable L2_BLOCK_TIME; uint256 public immutable L2_BLOCK_TIME;
/** /**
......
...@@ -56,11 +56,13 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { ...@@ -56,11 +56,13 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
/** /**
* @notice Minimum time (in seconds) that must elapse before a withdrawal can be finalized. * @notice Minimum time (in seconds) that must elapse before a withdrawal can be finalized.
*/ */
// solhint-disable-next-line var-name-mixedcase
uint256 public immutable FINALIZATION_PERIOD_SECONDS; uint256 public immutable FINALIZATION_PERIOD_SECONDS;
/** /**
* @notice Address of the L2OutputOracle. * @notice Address of the L2OutputOracle.
*/ */
// solhint-disable-next-line var-name-mixedcase
L2OutputOracle public immutable L2_ORACLE; L2OutputOracle public immutable L2_ORACLE;
/** /**
...@@ -99,12 +101,11 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { ...@@ -99,12 +101,11 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
constructor(L2OutputOracle _l2Oracle, uint256 _finalizationPeriodSeconds) Semver(0, 0, 1) { constructor(L2OutputOracle _l2Oracle, uint256 _finalizationPeriodSeconds) Semver(0, 0, 1) {
L2_ORACLE = _l2Oracle; L2_ORACLE = _l2Oracle;
FINALIZATION_PERIOD_SECONDS = _finalizationPeriodSeconds; FINALIZATION_PERIOD_SECONDS = _finalizationPeriodSeconds;
initialize(); initialize();
} }
/** /**
* @notice Intializes mutable variables. * @notice Initializer;
*/ */
function initialize() public initializer { function initialize() public initializer {
l2Sender = DEFAULT_L2_SENDER; l2Sender = DEFAULT_L2_SENDER;
...@@ -142,7 +143,6 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { ...@@ -142,7 +143,6 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
) public payable metered(_gasLimit) { ) public payable metered(_gasLimit) {
// Just to be safe, make sure that people specify address(0) as the target when doing // Just to be safe, make sure that people specify address(0) as the target when doing
// contract creations. // contract creations.
// TODO: Do we really need this? Prevents some user error, but adds gas.
if (_isCreation) { if (_isCreation) {
require( require(
_to == address(0), _to == address(0),
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.10; pragma solidity 0.8.10;
import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; import { Math } from "@openzeppelin/contracts/utils/math/Math.sol";
import { SignedMath } from "@openzeppelin/contracts/utils/math/SignedMath.sol"; import { SignedMath } from "@openzeppelin/contracts/utils/math/SignedMath.sol";
import { FixedPointMathLib } from "@rari-capital/solmate/src/utils/FixedPointMathLib.sol"; import { FixedPointMathLib } from "@rari-capital/solmate/src/utils/FixedPointMathLib.sol";
...@@ -11,7 +12,7 @@ import { Burn } from "../libraries/Burn.sol"; ...@@ -11,7 +12,7 @@ import { Burn } from "../libraries/Burn.sol";
* @notice ResourceMetering implements an EIP-1559 style resource metering system where pricing * @notice ResourceMetering implements an EIP-1559 style resource metering system where pricing
* updates automatically based on current demand. * updates automatically based on current demand.
*/ */
contract ResourceMetering { abstract contract ResourceMetering is Initializable {
/** /**
* @notice Represents the various parameters that control the way in which resources are * @notice Represents the various parameters that control the way in which resources are
* metered. Corresponds to the EIP-1559 resource metering system. * metered. Corresponds to the EIP-1559 resource metering system.
...@@ -62,19 +63,12 @@ contract ResourceMetering { ...@@ -62,19 +63,12 @@ contract ResourceMetering {
*/ */
uint256[49] private __gap; uint256[49] private __gap;
/**
* @notice Set the initial values. In order to enable this contract to be used in an upgradable
* context, the constructor calls a separate init function.
*/
constructor() {
__ResourceMetering_init();
}
/** /**
* @notice Sets initial resource parameter values. This function must either be called by the * @notice Sets initial resource parameter values. This function must either be called by the
* initializer function of an upgradeable child contract. * initializer function of an upgradeable child contract.
*/ */
function __ResourceMetering_init() internal { // solhint-disable-next-line func-name-mixedcase
function __ResourceMetering_init() internal onlyInitializing {
params = ResourceParams({ params = ResourceParams({
prevBaseFee: INITIAL_BASE_FEE, prevBaseFee: INITIAL_BASE_FEE,
prevBoughtGas: 0, prevBoughtGas: 0,
......
...@@ -35,6 +35,7 @@ contract L1BlockNumber is Semver { ...@@ -35,6 +35,7 @@ contract L1BlockNumber is Semver {
/** /**
* @notice Returns the L1 block number. * @notice Returns the L1 block number.
*/ */
// solhint-disable-next-line no-complex-fallback
fallback() external payable { fallback() external payable {
uint256 l1BlockNumber = getL1BlockNumber(); uint256 l1BlockNumber = getL1BlockNumber();
assembly { assembly {
......
...@@ -52,7 +52,7 @@ contract L2CrossDomainMessenger is CrossDomainMessenger, Semver { ...@@ -52,7 +52,7 @@ contract L2CrossDomainMessenger is CrossDomainMessenger, Semver {
* *
* @return True if the message sender is the L1CrossDomainMessenger on L1. * @return True if the message sender is the L1CrossDomainMessenger on L1.
*/ */
function _isSystemMessageSender() internal view override returns (bool) { function _isOtherMessenger() internal view override returns (bool) {
return AddressAliasHelper.undoL1ToL2Alias(msg.sender) == otherMessenger; return AddressAliasHelper.undoL1ToL2Alias(msg.sender) == otherMessenger;
} }
......
...@@ -16,7 +16,6 @@ import { OptimismMintableERC20 } from "../universal/OptimismMintableERC20.sol"; ...@@ -16,7 +16,6 @@ import { OptimismMintableERC20 } from "../universal/OptimismMintableERC20.sol";
* Examples of some token types that may not be properly supported by this contract include, * Examples of some token types that may not be properly supported by this contract include,
* but are not limited to: tokens with transfer fees, rebasing tokens, and * but are not limited to: tokens with transfer fees, rebasing tokens, and
* tokens with blocklists. * tokens with blocklists.
* TODO: ensure that this has 1:1 backwards compatibility
*/ */
contract L2StandardBridge is StandardBridge, Semver { contract L2StandardBridge is StandardBridge, Semver {
/** /**
......
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
pragma solidity ^0.8.9; pragma solidity ^0.8.9;
/** /**
* @title iL1ChugSplashDeployer * @title IL1ChugSplashDeployer
*/ */
interface iL1ChugSplashDeployer { interface IL1ChugSplashDeployer {
function isUpgrading() external view returns (bool); function isUpgrading() external view returns (bool);
} }
...@@ -58,7 +58,7 @@ contract L1ChugSplashProxy { ...@@ -58,7 +58,7 @@ contract L1ChugSplashProxy {
// L1ChugSplashDeployer contract and Solidity will throw errors if we do a normal call and // L1ChugSplashDeployer contract and Solidity will throw errors if we do a normal call and
// it turns out that it isn't the right type of contract. // it turns out that it isn't the right type of contract.
(bool success, bytes memory returndata) = owner.staticcall( (bool success, bytes memory returndata) = owner.staticcall(
abi.encodeWithSelector(iL1ChugSplashDeployer.isUpgrading.selector) abi.encodeWithSelector(IL1ChugSplashDeployer.isUpgrading.selector)
); );
// If the call was unsuccessful then we assume that there's no "isUpgrading" method and we // If the call was unsuccessful then we assume that there's no "isUpgrading" method and we
......
...@@ -23,87 +23,62 @@ contract LegacyERC20ETH is OptimismMintableERC20 { ...@@ -23,87 +23,62 @@ contract LegacyERC20ETH is OptimismMintableERC20 {
{} {}
/** /**
* @custom:blocked
* @notice Mints some amount of ETH. * @notice Mints some amount of ETH.
*
* @param _to Address of the recipient.
* @param _amount Amount of ETH to mint.
*/ */
function mint(address _to, uint256 _amount) public virtual override { function mint(address, uint256) public virtual override {
revert("LegacyERC20ETH: mint is disabled"); revert("LegacyERC20ETH: mint is disabled");
} }
/** /**
* @custom:blocked
* @notice Burns some amount of ETH. * @notice Burns some amount of ETH.
*
* @param _from Address to burn from.
* @param _amount Amount of ETH to burn.
*/ */
function burn(address _from, uint256 _amount) public virtual override { function burn(address, uint256) public virtual override {
revert("LegacyERC20ETH: burn is disabled"); revert("LegacyERC20ETH: burn is disabled");
} }
/** /**
* @custom:blocked
* @notice Transfers some amount of ETH. * @notice Transfers some amount of ETH.
*
* @param _recipient Address to send to.
* @param _amount Amount of ETH to send.
*/ */
function transfer(address _recipient, uint256 _amount) public virtual override returns (bool) { function transfer(address, uint256) public virtual override returns (bool) {
revert("LegacyERC20ETH: transfer is disabled"); revert("LegacyERC20ETH: transfer is disabled");
} }
/** /**
* @custom:blocked
* @notice Approves a spender to spend some amount of ETH. * @notice Approves a spender to spend some amount of ETH.
*
* @param _spender Address of the spender.
* @param _amount Amount of ETH to approve.
*/ */
function approve(address _spender, uint256 _amount) public virtual override returns (bool) { function approve(address, uint256) public virtual override returns (bool) {
revert("LegacyERC20ETH: approve is disabled"); revert("LegacyERC20ETH: approve is disabled");
} }
/** /**
* @custom:blocked
* @notice Transfers funds from some sender account. * @notice Transfers funds from some sender account.
*
* @param _sender Address of the sender.
* @param _recipient Address of the recipient.
* @param _amount Amount of ETH to transfer.
*/ */
function transferFrom( function transferFrom(
address _sender, address,
address _recipient, address,
uint256 _amount uint256
) public virtual override returns (bool) { ) public virtual override returns (bool) {
revert("LegacyERC20ETH: transferFrom is disabled"); revert("LegacyERC20ETH: transferFrom is disabled");
} }
/** /**
* @custom:blocked
* @notice Increases the allowance of a spender. * @notice Increases the allowance of a spender.
*
* @param _spender Address of the spender.
* @param _addedValue Amount of ETH to increase the allowance by.
*/ */
function increaseAllowance(address _spender, uint256 _addedValue) function increaseAllowance(address, uint256) public virtual override returns (bool) {
public
virtual
override
returns (bool)
{
revert("LegacyERC20ETH: increaseAllowance is disabled"); revert("LegacyERC20ETH: increaseAllowance is disabled");
} }
/** /**
* @custom:blocked
* @notice Decreases the allowance of a spender. * @notice Decreases the allowance of a spender.
*
* @param _spender Address of the spender.
* @param _subtractedValue Amount of ETH to decrease the allowance by.
*/ */
function decreaseAllowance(address _spender, uint256 _subtractedValue) function decreaseAllowance(address, uint256) public virtual override returns (bool) {
public
virtual
override
returns (bool)
{
revert("LegacyERC20ETH: decreaseAllowance is disabled"); revert("LegacyERC20ETH: decreaseAllowance is disabled");
} }
} }
...@@ -40,6 +40,7 @@ contract ResolvedDelegateProxy { ...@@ -40,6 +40,7 @@ contract ResolvedDelegateProxy {
/** /**
* @notice Fallback, performs a delegatecall to the resolved implementation address. * @notice Fallback, performs a delegatecall to the resolved implementation address.
*/ */
// solhint-disable-next-line no-complex-fallback
fallback() external payable { fallback() external payable {
address target = addressManager[address(this)].getAddress( address target = addressManager[address(this)].getAddress(
(implementationName[address(this)]) (implementationName[address(this)])
......
...@@ -3,20 +3,31 @@ pragma solidity ^0.8.9; ...@@ -3,20 +3,31 @@ pragma solidity ^0.8.9;
/** /**
* @title BytesUtils * @title BytesUtils
* @notice BytesUtils is a library for manipulating byte arrays.
*/ */
library BytesUtils { library BytesUtils {
/********************** /**
* Internal Functions * * @custom:attribution https://github.com/GNSPS/solidity-bytes-utils
**********************/ * @notice Slices a byte array with a given starting index and length. Returns a new byte array
* as opposed to a pointer to the original array. Will throw if trying to slice more
* bytes than exist in the array.
*
* @param _bytes Byte array to slice.
* @param _start Starting index of the slice.
* @param _length Length of the slice.
*
* @return Slice of the input byte array.
*/
function slice( function slice(
bytes memory _bytes, bytes memory _bytes,
uint256 _start, uint256 _start,
uint256 _length uint256 _length
) internal pure returns (bytes memory) { ) internal pure returns (bytes memory) {
require(_length + 31 >= _length, "slice_overflow"); unchecked {
require(_start + _length >= _start, "slice_overflow"); require(_length + 31 >= _length, "slice_overflow");
require(_bytes.length >= _start + _length, "slice_outOfBounds"); require(_start + _length >= _start, "slice_overflow");
require(_bytes.length >= _start + _length, "slice_outOfBounds");
}
bytes memory tempBytes; bytes memory tempBytes;
...@@ -76,51 +87,63 @@ library BytesUtils { ...@@ -76,51 +87,63 @@ library BytesUtils {
return tempBytes; return tempBytes;
} }
/**
* @notice Slices a byte array with a given starting index up to the end of the original byte
* array. Returns a new array rathern than a pointer to the original.
*
* @param _bytes Byte array to slice.
* @param _start Starting index of the slice.
*
* @return Slice of the input byte array.
*/
function slice(bytes memory _bytes, uint256 _start) internal pure returns (bytes memory) { function slice(bytes memory _bytes, uint256 _start) internal pure returns (bytes memory) {
if (_start >= _bytes.length) { if (_start >= _bytes.length) {
return bytes(""); return bytes("");
} }
return slice(_bytes, _start, _bytes.length - _start); return slice(_bytes, _start, _bytes.length - _start);
} }
function toBytes32(bytes memory _bytes) internal pure returns (bytes32) { /**
if (_bytes.length < 32) { * @notice Converts a byte array into a nibble array by splitting each byte into two nibbles.
bytes32 ret; * Resulting nibble array will be exactly twice as long as the input byte array.
assembly { *
ret := mload(add(_bytes, 32)) * @param _bytes Input byte array to convert.
} *
return ret; * @return Resulting nibble array.
} */
return abi.decode(_bytes, (bytes32)); // will truncate if input length > 32 bytes
}
function toUint256(bytes memory _bytes) internal pure returns (uint256) {
return uint256(toBytes32(_bytes));
}
function toNibbles(bytes memory _bytes) internal pure returns (bytes memory) { function toNibbles(bytes memory _bytes) internal pure returns (bytes memory) {
bytes memory nibbles = new bytes(_bytes.length * 2); bytes memory nibbles = new bytes(_bytes.length * 2);
for (uint256 i = 0; i < _bytes.length; i++) { for (uint256 i = 0; i < _bytes.length; i++) {
nibbles[i * 2] = _bytes[i] >> 4; nibbles[i * 2] = _bytes[i] >> 4;
nibbles[i * 2 + 1] = bytes1(uint8(_bytes[i]) % 16); nibbles[i * 2 + 1] = bytes1(uint8(_bytes[i]) % 16);
} }
return nibbles; return nibbles;
} }
/**
* @notice Generates a byte array from a nibble array by joining each set of two nibbles into a
* single byte. Resulting byte array will be half as long as the input byte array.
*
* @param _bytes Input nibble array to convert.
*
* @return Resulting byte array.
*/
function fromNibbles(bytes memory _bytes) internal pure returns (bytes memory) { function fromNibbles(bytes memory _bytes) internal pure returns (bytes memory) {
bytes memory ret = new bytes(_bytes.length / 2); bytes memory ret = new bytes(_bytes.length / 2);
for (uint256 i = 0; i < ret.length; i++) { for (uint256 i = 0; i < ret.length; i++) {
ret[i] = (_bytes[i * 2] << 4) | (_bytes[i * 2 + 1]); ret[i] = (_bytes[i * 2] << 4) | (_bytes[i * 2 + 1]);
} }
return ret; return ret;
} }
/**
* @notice Compares two byte arrays by comparing their keccak256 hashes.
*
* @param _bytes First byte array to compare.
* @param _other Second byte array to compare.
*
* @return True if the two byte arrays are equal, false otherwise.
*/
function equal(bytes memory _bytes, bytes memory _other) internal pure returns (bool) { function equal(bytes memory _bytes, bytes memory _other) internal pure returns (bool) {
return keccak256(_bytes) == keccak256(_other); return keccak256(_bytes) == keccak256(_other);
} }
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity ^0.8.9; pragma solidity ^0.8.9;
/* Library Imports */
import { BytesUtils } from "../BytesUtils.sol"; import { BytesUtils } from "../BytesUtils.sol";
import { RLPReader } from "../rlp/RLPReader.sol"; import { RLPReader } from "../rlp/RLPReader.sol";
import { RLPWriter } from "../rlp/RLPWriter.sol"; import { RLPWriter } from "../rlp/RLPWriter.sol";
/** /**
* @title MerkleTrie * @title MerkleTrie
* @notice MerkleTrie is a small library for verifying standard Ethereum Merkle-Patricia trie
* inclusion proofs. By default, this library assumes a hexary trie. One can change the
* trie radix constant to support other trie radixes.
*/ */
library MerkleTrie { library MerkleTrie {
/******************* /**
* Data Structures * * @notice Struct representing a node in the trie.
*******************/ */
struct TrieNode { struct TrieNode {
bytes encoded; bytes encoded;
RLPReader.RLPItem[] decoded; RLPReader.RLPItem[] decoded;
} }
/********************** /**
* Contract Constants * * @notice Determines the number of elements per branch node.
**********************/ */
// TREE_RADIX determines the number of elements per branch node.
uint256 constant TREE_RADIX = 16; uint256 constant TREE_RADIX = 16;
// Branch nodes have TREE_RADIX elements plus an additional `value` slot.
/**
* @notice Branch nodes have TREE_RADIX elements and one value element.
*/
uint256 constant BRANCH_NODE_LENGTH = TREE_RADIX + 1; uint256 constant BRANCH_NODE_LENGTH = TREE_RADIX + 1;
// Leaf nodes and extension nodes always have two elements, a `path` and a `value`.
/**
* @notice Leaf nodes and extension nodes have two elements, a `path` and a `value`.
*/
uint256 constant LEAF_OR_EXTENSION_NODE_LENGTH = 2; uint256 constant LEAF_OR_EXTENSION_NODE_LENGTH = 2;
// Prefixes are prepended to the `path` within a leaf or extension node and /**
// allow us to differentiate between the two node types. `ODD` or `EVEN` is * @notice Prefix for even-nibbled extension node paths.
// determined by the number of nibbles within the unprefixed `path`. If the */
// number of nibbles if even, we need to insert an extra padding nibble so
// the resulting prefixed `path` has an even number of nibbles.
uint8 constant PREFIX_EXTENSION_EVEN = 0; uint8 constant PREFIX_EXTENSION_EVEN = 0;
/**
* @notice Prefix for odd-nibbled extension node paths.
*/
uint8 constant PREFIX_EXTENSION_ODD = 1; uint8 constant PREFIX_EXTENSION_ODD = 1;
/**
* @notice Prefix for even-nibbled leaf node paths.
*/
uint8 constant PREFIX_LEAF_EVEN = 2; uint8 constant PREFIX_LEAF_EVEN = 2;
/**
* @notice Prefix for odd-nibbled leaf node paths.
*/
uint8 constant PREFIX_LEAF_ODD = 3; uint8 constant PREFIX_LEAF_ODD = 3;
// Just a utility constant. RLP represents `NULL` as 0x80. /**
* @notice RLP representation of `NULL`.
*/
bytes1 constant RLP_NULL = bytes1(0x80); bytes1 constant RLP_NULL = bytes1(0x80);
/**********************
* Internal Functions *
**********************/
/** /**
* @notice Verifies a proof that a given key/value pair is present in the * @notice Verifies a proof that a given key/value pair is present in the trie.
* Merkle trie. *
* @param _key Key of the node to search for, as a hex string. * @param _key Key of the node to search for, as a hex string.
* @param _value Value of the node to search for, as a hex string. * @param _value Value of the node to search for, as a hex string.
* @param _proof Merkle trie inclusion proof for the desired node. Unlike * @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle
* traditional Merkle trees, this proof is executed top-down and consists * trees, this proof is executed top-down and consists of a list of RLP-encoded
* of a list of RLP-encoded nodes that make a path down to the target node. * nodes that make a path down to the target node.
* @param _root Known root of the Merkle trie. Used to verify that the * @param _root Known root of the Merkle trie. Used to verify that the included proof is
* included proof is correctly constructed. * correctly constructed.
* @return _verified `true` if the k/v pair exists in the trie, `false` otherwise. *
* @return Whether or not the proof is valid.
*/ */
function verifyInclusionProof( function verifyInclusionProof(
bytes memory _key, bytes memory _key,
bytes memory _value, bytes memory _value,
bytes memory _proof, bytes memory _proof,
bytes32 _root bytes32 _root
) internal pure returns (bool _verified) { ) internal pure returns (bool) {
(bool exists, bytes memory value) = get(_key, _proof, _root); (bool exists, bytes memory value) = get(_key, _proof, _root);
return (exists && BytesUtils.equal(_value, value)); return (exists && BytesUtils.equal(_value, value));
} }
/** /**
* @notice Retrieves the value associated with a given key. * @notice Retrieves the value associated with a given key.
* @param _key Key to search for, as hex bytes. *
* @param _key Key to search for, as hex bytes.
* @param _proof Merkle trie inclusion proof for the key. * @param _proof Merkle trie inclusion proof for the key.
* @param _root Known root of the Merkle trie. * @param _root Known root of the Merkle trie.
* @return _exists Whether or not the key exists. *
* @return _value Value of the key if it exists. * @return Whether or not the key exists.
* @return Value of the key if it exists.
*/ */
function get( function get(
bytes memory _key, bytes memory _key,
bytes memory _proof, bytes memory _proof,
bytes32 _root bytes32 _root
) internal pure returns (bool _exists, bytes memory _value) { ) internal pure returns (bool, bytes memory) {
TrieNode[] memory proof = _parseProof(_proof); TrieNode[] memory proof = _parseProof(_proof);
(uint256 pathLength, bytes memory keyRemainder, bool isFinalNode) = _walkNodePath( (uint256 pathLength, bytes memory keyRemainder, bool isFinalNode) = _walkNodePath(
proof, proof,
...@@ -99,18 +114,16 @@ library MerkleTrie { ...@@ -99,18 +114,16 @@ library MerkleTrie {
return (exists, value); return (exists, value);
} }
/*********************
* Private Functions *
*********************/
/** /**
* @notice Walks through a proof using a provided key. * @notice Walks through a proof using a provided key.
*
* @param _proof Inclusion proof to walk through. * @param _proof Inclusion proof to walk through.
* @param _key Key to use for the walk. * @param _key Key to use for the walk.
* @param _root Known root of the trie. * @param _root Known root of the trie.
* @return _pathLength Length of the final path *
* @return _keyRemainder Portion of the key remaining after the walk. * @return Length of the final path
* @return _isFinalNode Whether or not we've hit a dead end. * @return Portion of the key remaining after the walk.
* @return Whether or not we've hit a dead end.
*/ */
function _walkNodePath( function _walkNodePath(
TrieNode[] memory _proof, TrieNode[] memory _proof,
...@@ -120,9 +133,9 @@ library MerkleTrie { ...@@ -120,9 +133,9 @@ library MerkleTrie {
private private
pure pure
returns ( returns (
uint256 _pathLength, uint256,
bytes memory _keyRemainder, bytes memory,
bool _isFinalNode bool
) )
{ {
uint256 pathLength = 0; uint256 pathLength = 0;
...@@ -154,7 +167,7 @@ library MerkleTrie { ...@@ -154,7 +167,7 @@ library MerkleTrie {
} else { } else {
// Nodes smaller than 31 bytes aren't hashed. // Nodes smaller than 31 bytes aren't hashed.
require( require(
BytesUtils.toBytes32(currentNode.encoded) == currentNodeID, bytes32(currentNode.encoded) == currentNodeID,
"Invalid internal node hash" "Invalid internal node hash"
); );
} }
...@@ -223,10 +236,12 @@ library MerkleTrie { ...@@ -223,10 +236,12 @@ library MerkleTrie {
/** /**
* @notice Parses an RLP-encoded proof into something more useful. * @notice Parses an RLP-encoded proof into something more useful.
*
* @param _proof RLP-encoded proof to parse. * @param _proof RLP-encoded proof to parse.
* @return _parsed Proof parsed into easily accessible structs. *
* @return Proof parsed into easily accessible structs.
*/ */
function _parseProof(bytes memory _proof) private pure returns (TrieNode[] memory _parsed) { function _parseProof(bytes memory _proof) private pure returns (TrieNode[] memory) {
RLPReader.RLPItem[] memory nodes = RLPReader.readList(_proof); RLPReader.RLPItem[] memory nodes = RLPReader.readList(_proof);
TrieNode[] memory proof = new TrieNode[](nodes.length); TrieNode[] memory proof = new TrieNode[](nodes.length);
...@@ -239,13 +254,14 @@ library MerkleTrie { ...@@ -239,13 +254,14 @@ library MerkleTrie {
} }
/** /**
* @notice Picks out the ID for a node. Node ID is referred to as the * @notice Picks out the ID for a node. Node ID is referred to as the "hash" within the
* "hash" within the specification, but nodes < 32 bytes are not actually * specification, but nodes < 32 bytes are not actually hashed.
* hashed. *
* @param _node Node to pull an ID for. * @param _node Node to pull an ID for.
* @return _nodeID ID for the node, depending on the size of its contents. *
* @return ID for the node, depending on the size of its contents.
*/ */
function _getNodeID(RLPReader.RLPItem memory _node) private pure returns (bytes32 _nodeID) { function _getNodeID(RLPReader.RLPItem memory _node) private pure returns (bytes32) {
bytes memory nodeID; bytes memory nodeID;
if (_node.length < 32) { if (_node.length < 32) {
...@@ -256,38 +272,43 @@ library MerkleTrie { ...@@ -256,38 +272,43 @@ library MerkleTrie {
nodeID = RLPReader.readBytes(_node); nodeID = RLPReader.readBytes(_node);
} }
return BytesUtils.toBytes32(nodeID); return bytes32(nodeID);
} }
/** /**
* @notice Gets the path for a leaf or extension node. * @notice Gets the path for a leaf or extension node.
*
* @param _node Node to get a path for. * @param _node Node to get a path for.
* @return _path Node path, converted to an array of nibbles. *
* @return Node path, converted to an array of nibbles.
*/ */
function _getNodePath(TrieNode memory _node) private pure returns (bytes memory _path) { function _getNodePath(TrieNode memory _node) private pure returns (bytes memory) {
return BytesUtils.toNibbles(RLPReader.readBytes(_node.decoded[0])); return BytesUtils.toNibbles(RLPReader.readBytes(_node.decoded[0]));
} }
/** /**
* @notice Gets the path for a node. * @notice Gets the path for a node.
*
* @param _node Node to get a value for. * @param _node Node to get a value for.
* @return _value Node value, as hex bytes. *
* @return Node value, as hex bytes.
*/ */
function _getNodeValue(TrieNode memory _node) private pure returns (bytes memory _value) { function _getNodeValue(TrieNode memory _node) private pure returns (bytes memory) {
return RLPReader.readBytes(_node.decoded[_node.decoded.length - 1]); return RLPReader.readBytes(_node.decoded[_node.decoded.length - 1]);
} }
/** /**
* @notice Utility; determines the number of nibbles shared between two * @notice Utility; determines the number of nibbles shared between two nibble arrays.
* nibble arrays. *
* @param _a First nibble array. * @param _a First nibble array.
* @param _b Second nibble array. * @param _b Second nibble array.
* @return _shared Number of shared nibbles. *
* @return Number of shared nibbles.
*/ */
function _getSharedNibbleLength(bytes memory _a, bytes memory _b) function _getSharedNibbleLength(bytes memory _a, bytes memory _b)
private private
pure pure
returns (uint256 _shared) returns (uint256)
{ {
uint256 i = 0; uint256 i = 0;
while (_a.length > i && _b.length > i && _a[i] == _b[i]) { while (_a.length > i && _b.length > i && _a[i] == _b[i]) {
......
...@@ -6,61 +6,60 @@ import { MerkleTrie } from "./MerkleTrie.sol"; ...@@ -6,61 +6,60 @@ import { MerkleTrie } from "./MerkleTrie.sol";
/** /**
* @title SecureMerkleTrie * @title SecureMerkleTrie
* @notice SecureMerkleTrie is a thin wrapper around the MerkleTrie library that hashes the input
* keys. Ethereum's state trie hashes input keys before storing them.
*/ */
library SecureMerkleTrie { library SecureMerkleTrie {
/**********************
* Internal Functions *
**********************/
/** /**
* @notice Verifies a proof that a given key/value pair is present in the * @notice Verifies a proof that a given key/value pair is present in the Merkle trie.
* Merkle trie. *
* @param _key Key of the node to search for, as a hex string. * @param _key Key of the node to search for, as a hex string.
* @param _value Value of the node to search for, as a hex string. * @param _value Value of the node to search for, as a hex string.
* @param _proof Merkle trie inclusion proof for the desired node. Unlike * @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle
* traditional Merkle trees, this proof is executed top-down and consists * trees, this proof is executed top-down and consists of a list of RLP-encoded
* of a list of RLP-encoded nodes that make a path down to the target node. * nodes that make a path down to the target node.
* @param _root Known root of the Merkle trie. Used to verify that the * @param _root Known root of the Merkle trie. Used to verify that the included proof is
* included proof is correctly constructed. * correctly constructed.
* @return _verified `true` if the k/v pair exists in the trie, `false` otherwise. *
* @return Whether or not the proof is valid.
*/ */
function verifyInclusionProof( function verifyInclusionProof(
bytes memory _key, bytes memory _key,
bytes memory _value, bytes memory _value,
bytes memory _proof, bytes memory _proof,
bytes32 _root bytes32 _root
) internal pure returns (bool _verified) { ) internal pure returns (bool) {
bytes memory key = _getSecureKey(_key); bytes memory key = _getSecureKey(_key);
return MerkleTrie.verifyInclusionProof(key, _value, _proof, _root); return MerkleTrie.verifyInclusionProof(key, _value, _proof, _root);
} }
/** /**
* @notice Retrieves the value associated with a given key. * @notice Retrieves the value associated with a given key.
* @param _key Key to search for, as hex bytes. *
* @param _key Key to search for, as hex bytes.
* @param _proof Merkle trie inclusion proof for the key. * @param _proof Merkle trie inclusion proof for the key.
* @param _root Known root of the Merkle trie. * @param _root Known root of the Merkle trie.
* @return _exists Whether or not the key exists. *
* @return _value Value of the key if it exists. * @return Whether or not the key exists.
* @return Value of the key if it exists.
*/ */
function get( function get(
bytes memory _key, bytes memory _key,
bytes memory _proof, bytes memory _proof,
bytes32 _root bytes32 _root
) internal pure returns (bool _exists, bytes memory _value) { ) internal pure returns (bool, bytes memory) {
bytes memory key = _getSecureKey(_key); bytes memory key = _getSecureKey(_key);
return MerkleTrie.get(key, _proof, _root); return MerkleTrie.get(key, _proof, _root);
} }
/*********************
* Private Functions *
*********************/
/** /**
* Computes the secure counterpart to a key. * @notice Computes the hashed version of the input key.
* @param _key Key to get a secure key from. *
* @return _secureKey Secure version of the key. * @param _key Key to hash.
*
* @return Hashed version of the key.
*/ */
function _getSecureKey(bytes memory _key) private pure returns (bytes memory _secureKey) { function _getSecureKey(bytes memory _key) private pure returns (bytes memory) {
return abi.encodePacked(keccak256(_key)); return abi.encodePacked(keccak256(_key));
} }
} }
...@@ -22,7 +22,7 @@ import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable ...@@ -22,7 +22,7 @@ import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable
import { ResolvedDelegateProxy } from "../legacy/ResolvedDelegateProxy.sol"; import { ResolvedDelegateProxy } from "../legacy/ResolvedDelegateProxy.sol";
import { AddressManager } from "../legacy/AddressManager.sol"; import { AddressManager } from "../legacy/AddressManager.sol";
import { L1ChugSplashProxy } from "../legacy/L1ChugSplashProxy.sol"; import { L1ChugSplashProxy } from "../legacy/L1ChugSplashProxy.sol";
import { iL1ChugSplashDeployer } from "../legacy/L1ChugSplashProxy.sol"; import { IL1ChugSplashDeployer } from "../legacy/L1ChugSplashProxy.sol";
contract CommonTest is Test { contract CommonTest is Test {
address alice = address(128); address alice = address(128);
...@@ -341,7 +341,7 @@ contract Bridge_Initializer is Messenger_Initializer { ...@@ -341,7 +341,7 @@ contract Bridge_Initializer is Messenger_Initializer {
L1ChugSplashProxy proxy = new L1ChugSplashProxy(multisig); L1ChugSplashProxy proxy = new L1ChugSplashProxy(multisig);
vm.mockCall( vm.mockCall(
multisig, multisig,
abi.encodeWithSelector(iL1ChugSplashDeployer.isUpgrading.selector), abi.encodeWithSelector(IL1ChugSplashDeployer.isUpgrading.selector),
abi.encode(true) abi.encode(true)
); );
vm.startPrank(multisig); vm.startPrank(multisig);
......
...@@ -56,11 +56,8 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -56,11 +56,8 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
// the version is encoded in the nonce // the version is encoded in the nonce
function test_L1MessengerMessageVersion() external { function test_L1MessengerMessageVersion() external {
(,uint16 version) = Encoding.decodeVersionedNonce(L1Messenger.messageNonce()); (, uint16 version) = Encoding.decodeVersionedNonce(L1Messenger.messageNonce());
assertEq( assertEq(version, L1Messenger.MESSAGE_VERSION());
version,
L1Messenger.MESSAGE_VERSION()
);
} }
// sendMessage: should be able to send a single message // sendMessage: should be able to send a single message
...@@ -74,7 +71,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -74,7 +71,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
OptimismPortal.depositTransaction.selector, OptimismPortal.depositTransaction.selector,
PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER, PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER,
0, 0,
100 + L1Messenger.baseGas(hex"ff"), L1Messenger.baseGas(hex"ff", 100),
false, false,
Encoding.encodeCrossDomainMessage( Encoding.encodeCrossDomainMessage(
L1Messenger.messageNonce(), L1Messenger.messageNonce(),
...@@ -94,7 +91,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -94,7 +91,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER, PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER,
0, 0,
0, 0,
100 + L1Messenger.baseGas(hex"ff"), L1Messenger.baseGas(hex"ff", 100),
false, false,
Encoding.encodeCrossDomainMessage( Encoding.encodeCrossDomainMessage(
L1Messenger.messageNonce(), L1Messenger.messageNonce(),
...@@ -172,7 +169,6 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -172,7 +169,6 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
address sender = PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER; address sender = PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER;
bytes memory message = hex"1111"; bytes memory message = hex"1111";
// set the value of op.l2Sender() to be the L2 Cross Domain Messenger.
vm.prank(address(op)); vm.prank(address(op));
vm.expectRevert("Message cannot be replayed."); vm.expectRevert("Message cannot be replayed.");
L1Messenger.relayMessage(0, sender, target, 0, 0, message); L1Messenger.relayMessage(0, sender, target, 0, 0, message);
...@@ -182,6 +178,18 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -182,6 +178,18 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
L1Messenger.relayMessage(0, sender, target, 0, 0, message); L1Messenger.relayMessage(0, sender, target, 0, 0, message);
} }
// relayMessage: should revert if eth is sent from a contract other than the standard bridge
function test_L1MessengerReplayMessageWithValue() external {
address target = address(0xabcd);
address sender = PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER;
bytes memory message = hex"1111";
vm.expectRevert(
"CrossDomainMessenger: Value must be zero unless message is from a system address."
);
L1Messenger.relayMessage{ value: 100 }(0, sender, target, 0, 0, message);
}
// relayMessage: the xDomainMessageSender is reset to the original value // relayMessage: the xDomainMessageSender is reset to the original value
function test_L1MessengerxDomainMessageSenderResets() external { function test_L1MessengerxDomainMessageSenderResets() external {
vm.expectRevert("xDomainMessageSender is not set"); vm.expectRevert("xDomainMessageSender is not set");
...@@ -190,7 +198,6 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -190,7 +198,6 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
address sender = PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER; address sender = PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER;
uint256 senderSlotIndex = 51; uint256 senderSlotIndex = 51;
bytes32 slotValue = vm.load(address(op), bytes32(senderSlotIndex));
vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
vm.prank(address(op)); vm.prank(address(op));
......
...@@ -59,7 +59,8 @@ contract L1StandardBridge_Test is Bridge_Initializer { ...@@ -59,7 +59,8 @@ contract L1StandardBridge_Test is Bridge_Initializer {
); );
vm.prank(alice, alice); vm.prank(alice, alice);
address(L1Bridge).call{ value: 100 }(hex""); (bool success,) = address(L1Bridge).call{ value: 100 }(hex"");
assertEq(success, true);
assertEq(address(op).balance, 100); assertEq(address(op).balance, 100);
} }
......
...@@ -44,7 +44,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -44,7 +44,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
abi.encodeWithSelector( abi.encodeWithSelector(
L2ToL1MessagePasser.initiateWithdrawal.selector, L2ToL1MessagePasser.initiateWithdrawal.selector,
address(L1Messenger), address(L1Messenger),
100 + L2Messenger.baseGas(hex"ff"), L2Messenger.baseGas(hex"ff", 100),
Encoding.encodeCrossDomainMessage( Encoding.encodeCrossDomainMessage(
L2Messenger.messageNonce(), L2Messenger.messageNonce(),
alice, alice,
...@@ -63,7 +63,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -63,7 +63,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
address(L2Messenger), address(L2Messenger),
address(L1Messenger), address(L1Messenger),
0, 0,
100 + L2Messenger.baseGas(hex"ff"), L2Messenger.baseGas(hex"ff", 100),
Encoding.encodeCrossDomainMessage( Encoding.encodeCrossDomainMessage(
L2Messenger.messageNonce(), L2Messenger.messageNonce(),
alice, alice,
......
...@@ -357,12 +357,22 @@ contract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer { ...@@ -357,12 +357,22 @@ contract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer {
function test_cannotInitProxy() external { function test_cannotInitProxy() external {
vm.expectRevert("Initializable: contract is already initialized"); vm.expectRevert("Initializable: contract is already initialized");
address(proxy).call(abi.encodeWithSelector(L2OutputOracle.initialize.selector)); L2OutputOracle(payable(proxy)).initialize(
genesisL2Output,
startingBlockNumber,
sequencer,
owner
);
} }
function test_cannotInitImpl() external { function test_cannotInitImpl() external {
vm.expectRevert("Initializable: contract is already initialized"); vm.expectRevert("Initializable: contract is already initialized");
address(oracleImpl).call(abi.encodeWithSelector(L2OutputOracle.initialize.selector)); L2OutputOracle(oracleImpl).initialize(
genesisL2Output,
startingBlockNumber,
sequencer,
owner
);
} }
function test_upgrading() external { function test_upgrading() external {
......
...@@ -40,7 +40,8 @@ contract L2StandardBridge_Test is Bridge_Initializer { ...@@ -40,7 +40,8 @@ contract L2StandardBridge_Test is Bridge_Initializer {
// TODO: events from each contract // TODO: events from each contract
vm.prank(alice, alice); vm.prank(alice, alice);
address(L2Bridge).call{ value: 100 }(hex""); (bool success,) = address(L2Bridge).call{ value: 100 }(hex"");
assertEq(success, true);
assertEq(address(messagePasser).balance, 100); assertEq(address(messagePasser).balance, 100);
} }
......
...@@ -334,12 +334,12 @@ contract OptimismPortalUpgradeable_Test is Portal_Initializer { ...@@ -334,12 +334,12 @@ contract OptimismPortalUpgradeable_Test is Portal_Initializer {
function test_cannotInitProxy() external { function test_cannotInitProxy() external {
vm.expectRevert("Initializable: contract is already initialized"); vm.expectRevert("Initializable: contract is already initialized");
address(proxy).call(abi.encodeWithSelector(OptimismPortal.initialize.selector)); OptimismPortal(payable(proxy)).initialize();
} }
function test_cannotInitImpl() external { function test_cannotInitImpl() external {
vm.expectRevert("Initializable: contract is already initialized"); vm.expectRevert("Initializable: contract is already initialized");
address(opImpl).call(abi.encodeWithSelector(OptimismPortal.initialize.selector)); OptimismPortal(opImpl).initialize();
} }
function test_upgrading() external { function test_upgrading() external {
......
...@@ -18,7 +18,7 @@ contract SimpleStorage { ...@@ -18,7 +18,7 @@ contract SimpleStorage {
} }
contract Clasher { contract Clasher {
function upgradeTo(address _implementation) external view { function upgradeTo(address) external pure {
revert("upgradeTo"); revert("upgradeTo");
} }
} }
...@@ -150,8 +150,8 @@ contract Proxy_Test is Test { ...@@ -150,8 +150,8 @@ contract Proxy_Test is Test {
function test_upgradeToAndCall() external { function test_upgradeToAndCall() external {
{ {
// There should be nothing in the current proxy storage // There should be nothing in the current proxy storage
uint256 result = SimpleStorage(address(proxy)).get(1); uint256 expect = SimpleStorage(address(proxy)).get(1);
assertEq(result, 0); assertEq(expect, 0);
} }
// Deploy a new SimpleStorage // Deploy a new SimpleStorage
......
...@@ -7,6 +7,10 @@ import { Proxy } from "../universal/Proxy.sol"; ...@@ -7,6 +7,10 @@ import { Proxy } from "../universal/Proxy.sol";
contract MeterUser is ResourceMetering { contract MeterUser is ResourceMetering {
constructor() { constructor() {
initialize();
}
function initialize() public initializer {
__ResourceMetering_init(); __ResourceMetering_init();
} }
...@@ -88,12 +92,12 @@ contract ResourceMetering_Test is CommonTest { ...@@ -88,12 +92,12 @@ contract ResourceMetering_Test is CommonTest {
uint64 elasticity = uint64(uint256(meter.ELASTICITY_MULTIPLIER())); uint64 elasticity = uint64(uint256(meter.ELASTICITY_MULTIPLIER()));
meter.use(target * elasticity); meter.use(target * elasticity);
(uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params(); (, uint64 prevBoughtGas, ) = meter.params();
assertEq(prevBoughtGas, target * elasticity); assertEq(prevBoughtGas, target * elasticity);
vm.roll(initialBlockNum + 1); vm.roll(initialBlockNum + 1);
meter.use(0); meter.use(0);
(uint128 postBaseFee, uint64 postBoughtGas, uint64 postBlockNum) = meter.params(); (uint128 postBaseFee,,) = meter.params();
// Base fee increases by 1/8 the difference // Base fee increases by 1/8 the difference
assertEq(postBaseFee, 1375000000); assertEq(postBaseFee, 1375000000);
} }
......
...@@ -48,8 +48,9 @@ contract SequencerFeeVault_Test is Bridge_Initializer { ...@@ -48,8 +48,9 @@ contract SequencerFeeVault_Test is Bridge_Initializer {
); );
vm.prank(alice); vm.prank(alice);
address(vault).call{ value: 100 }(hex""); (bool success,) = address(vault).call{ value: 100 }(hex"");
assertEq(success, true);
assertEq( assertEq(
address(vault).balance, address(vault).balance,
100 100
......
...@@ -64,14 +64,24 @@ abstract contract CrossDomainMessenger is ...@@ -64,14 +64,24 @@ abstract contract CrossDomainMessenger is
uint16 public constant MESSAGE_VERSION = 1; uint16 public constant MESSAGE_VERSION = 1;
/** /**
* @notice Dynamic overhead applied to the base gas for a message. * @notice Constant overhead added to the base gas for a message.
*/ */
uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD = 1; uint32 public constant MIN_GAS_CONSTANT_OVERHEAD = 200_000;
/** /**
* @notice Constant overhead added to the base gas for a message. * @notice Numerator for dynamic overhead added to the base gas for a message.
*/
uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR = 1016;
/**
* @notice Denominator for dynamic overhead added to the base gas for a message.
*/
uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR = 1000;
/**
* @notice Extra gas added to base gas for each byte of calldata in a message.
*/ */
uint32 public constant MIN_GAS_CONSTANT_OVERHEAD = 100_000; uint32 public constant MIN_GAS_CALLDATA_OVERHEAD = 16;
/** /**
* @notice Minimum amount of gas required to relay a message. * @notice Minimum amount of gas required to relay a message.
...@@ -181,15 +191,20 @@ abstract contract CrossDomainMessenger is ...@@ -181,15 +191,20 @@ abstract contract CrossDomainMessenger is
* will not run out of gas is important because this ensures that a message can always * will not run out of gas is important because this ensures that a message can always
* be replayed on the other chain if it fails to execute completely. * be replayed on the other chain if it fails to execute completely.
* *
* @param _message Message to compute the amount of required gas for. * @param _message Message to compute the amount of required gas for.
* @param _minGasLimit Minimum desired gas limit when message goes to target.
* *
* @return Amount of gas required to guarantee message receipt. * @return Amount of gas required to guarantee message receipt.
*/ */
function baseGas(bytes memory _message) public pure returns (uint32) { function baseGas(bytes memory _message, uint32 _minGasLimit) public pure returns (uint32) {
// TODO: Values here are meant to be good enough to get a devnet running. We need to do return
// some simple experimentation with the smallest and largest possible message sizes to find // Dynamic overhead
// the correct constant and dynamic overhead values. ((_minGasLimit * MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR) /
return (uint32(_message.length) * MIN_GAS_DYNAMIC_OVERHEAD) + MIN_GAS_CONSTANT_OVERHEAD; MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR) +
// Calldata overhead
(uint32(_message.length) * MIN_GAS_CALLDATA_OVERHEAD) +
// Constant overhead
MIN_GAS_CONSTANT_OVERHEAD;
} }
/** /**
...@@ -210,7 +225,7 @@ abstract contract CrossDomainMessenger is ...@@ -210,7 +225,7 @@ abstract contract CrossDomainMessenger is
// the minimum gas limit specified by the user. // the minimum gas limit specified by the user.
_sendMessage( _sendMessage(
otherMessenger, otherMessenger,
_minGasLimit + baseGas(_message), baseGas(_message, _minGasLimit),
msg.value, msg.value,
abi.encodeWithSelector( abi.encodeWithSelector(
this.relayMessage.selector, this.relayMessage.selector,
...@@ -259,17 +274,17 @@ abstract contract CrossDomainMessenger is ...@@ -259,17 +274,17 @@ abstract contract CrossDomainMessenger is
_message _message
); );
if (_isSystemMessageSender()) { if (_isOtherMessenger()) {
// Should never happen. // Should never happen.
require(msg.value == _value, "Mismatched message value."); require(msg.value == _value, "Mismatched message value.");
} else { } else {
// TODO(tynes): could require that msg.value == 0 here require(
// to prevent eth from getting stuck msg.value == 0,
"CrossDomainMessenger: Value must be zero unless message is from a system address."
);
require(receivedMessages[versionedHash], "Message cannot be replayed."); require(receivedMessages[versionedHash], "Message cannot be replayed.");
} }
// TODO: Should blocking happen on sending or receiving side?
// TODO: Should this just return with an event instead of reverting?
require( require(
blockedSystemAddresses[_target] == false, blockedSystemAddresses[_target] == false,
"Cannot send message to blocked system address." "Cannot send message to blocked system address."
...@@ -277,7 +292,6 @@ abstract contract CrossDomainMessenger is ...@@ -277,7 +292,6 @@ abstract contract CrossDomainMessenger is
require(successfulMessages[versionedHash] == false, "Message has already been relayed."); require(successfulMessages[versionedHash] == false, "Message has already been relayed.");
// TODO: Make sure this will always give us enough gas.
require( require(
gasleft() >= _minGasLimit + RELAY_GAS_REQUIRED, gasleft() >= _minGasLimit + RELAY_GAS_REQUIRED,
"Insufficient gas to relay message." "Insufficient gas to relay message."
...@@ -313,6 +327,7 @@ abstract contract CrossDomainMessenger is ...@@ -313,6 +327,7 @@ abstract contract CrossDomainMessenger is
* detailed information about what this block list can and * detailed information about what this block list can and
* cannot be used for. * cannot be used for.
*/ */
// solhint-disable-next-line func-name-mixedcase
function __CrossDomainMessenger_init( function __CrossDomainMessenger_init(
address _otherMessenger, address _otherMessenger,
address[] memory _blockedSystemAddresses address[] memory _blockedSystemAddresses
...@@ -334,7 +349,7 @@ abstract contract CrossDomainMessenger is ...@@ -334,7 +349,7 @@ abstract contract CrossDomainMessenger is
* contracts because the logic for this depends on the network where the messenger is * contracts because the logic for this depends on the network where the messenger is
* being deployed. * being deployed.
*/ */
function _isSystemMessageSender() internal view virtual returns (bool); function _isOtherMessenger() internal view virtual returns (bool);
/** /**
* @notice Sends a low-level message to the other messenger. Needs to be implemented by child * @notice Sends a low-level message to the other messenger. Needs to be implemented by child
......
...@@ -9,16 +9,19 @@ contract Semver { ...@@ -9,16 +9,19 @@ contract Semver {
/** /**
* @notice Contract version number (major). * @notice Contract version number (major).
*/ */
// solhint-disable-next-line var-name-mixedcase
uint256 public immutable MAJOR_VERSION; uint256 public immutable MAJOR_VERSION;
/** /**
* @notice Contract version number (minor). * @notice Contract version number (minor).
*/ */
// solhint-disable-next-line var-name-mixedcase
uint256 public immutable MINOR_VERSION; uint256 public immutable MINOR_VERSION;
/** /**
* @notice Contract version number (patch). * @notice Contract version number (patch).
*/ */
// solhint-disable-next-line var-name-mixedcase
uint256 public immutable PATCH_VERSION; uint256 public immutable PATCH_VERSION;
/** /**
......
...@@ -368,6 +368,7 @@ abstract contract StandardBridge is Initializable { ...@@ -368,6 +368,7 @@ abstract contract StandardBridge is Initializable {
* @param _messenger Address of CrossDomainMessenger on this network. * @param _messenger Address of CrossDomainMessenger on this network.
* @param _otherBridge Address of the other StandardBridge contract. * @param _otherBridge Address of the other StandardBridge contract.
*/ */
// solhint-disable-next-line func-name-mixedcase
function __StandardBridge_init(address payable _messenger, address payable _otherBridge) function __StandardBridge_init(address payable _messenger, address payable _otherBridge)
internal internal
onlyInitializing onlyInitializing
...@@ -442,7 +443,6 @@ abstract contract StandardBridge is Initializable { ...@@ -442,7 +443,6 @@ abstract contract StandardBridge is Initializable {
OptimismMintableERC20(_localToken).burn(_from, _amount); OptimismMintableERC20(_localToken).burn(_from, _amount);
} else { } else {
// TODO: Do we need to confirm that the transfer was successful?
IERC20(_localToken).safeTransferFrom(_from, address(this), _amount); IERC20(_localToken).safeTransferFrom(_from, address(this), _amount);
deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] + _amount; deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] + _amount;
} }
......
...@@ -66,6 +66,10 @@ task('deposit', 'Deposits funds onto L2.') ...@@ -66,6 +66,10 @@ task('deposit', 'Deposits funds onto L2.')
const amountWei = utils.parseEther(amountEth) const amountWei = utils.parseEther(amountEth)
const value = amountWei.add(utils.parseEther('0.01')) const value = amountWei.add(utils.parseEther('0.01'))
console.log(`Depositing ${amountEth} ETH to ${to}`) console.log(`Depositing ${amountEth} ETH to ${to}`)
const preL2Balance = await l2Provider.getBalance(to)
console.log(`${to} has ${utils.formatEther(preL2Balance)} ETH on L2`)
// Below adds 0.01 ETH to account for gas. // Below adds 0.01 ETH to account for gas.
const tx = await OptimismPortal.depositTransaction( const tx = await OptimismPortal.depositTransaction(
to, to,
...@@ -77,26 +81,39 @@ task('deposit', 'Deposits funds onto L2.') ...@@ -77,26 +81,39 @@ task('deposit', 'Deposits funds onto L2.')
) )
console.log(`Got TX hash ${tx.hash}. Waiting...`) console.log(`Got TX hash ${tx.hash}. Waiting...`)
const receipt = await tx.wait() const receipt = await tx.wait()
console.log( console.log(`Included in block ${receipt.blockHash}`)
`Included in block ${receipt.blockHash} with index ${receipt.logIndex}`
)
// find the transaction deposited event and derive // find the transaction deposited event and derive
// the deposit transaction from it // the deposit transaction from it
const event = receipt.events.find( const event = receipt.events.find(
(e: Event) => e.event === 'TransactionDeposited' (e: Event) => e.event === 'TransactionDeposited'
) )
const l2tx = DepositTx.fromL1Event(event)
console.log(`Deposit has log index ${event.logIndex}`) console.log(`Deposit has log index ${event.logIndex}`)
const l2tx = DepositTx.fromL1Event(event)
const hash = l2tx.hash() const hash = l2tx.hash()
console.log(`Waiting for L2 TX hash ${hash}`) console.log(`Waiting for L2 TX hash ${hash}`)
let i = 0
while (true) { while (true) {
const expected = await l2Provider.send('eth_getTransactionByHash', [hash]) const expected = await l2Provider.send('eth_getTransactionByHash', [hash])
if (expected) { if (expected) {
console.log('Deposit success') console.log('Deposit success')
console.log(JSON.stringify(expected, null, 2))
break break
} }
const postL2Balance = await l2Provider.getBalance(to)
if (postL2Balance.gt(preL2Balance)) {
console.log(
`Unexpected balance increase without detecting deposit transaction`
)
}
if (i % 100 === 0) {
const block = await l2Provider.getBlock('latest')
console.log(`latest block ${block.number}:${block.hash}`)
}
await sleep(500) await sleep(500)
i++
} }
}) })
...@@ -52,6 +52,7 @@ task('genesis-l2', 'create a genesis config') ...@@ -52,6 +52,7 @@ task('genesis-l2', 'create a genesis config')
'The file to write the output JSON to', 'The file to write the output JSON to',
'genesis.json' 'genesis.json'
) )
.addOptionalParam('l1RpcUrl', 'The L1 RPC URL', 'http://127.0.0.1:8545')
.setAction(async (args, hre) => { .setAction(async (args, hre) => {
const { const {
computeStorageSlots, computeStorageSlots,
...@@ -60,6 +61,8 @@ task('genesis-l2', 'create a genesis config') ...@@ -60,6 +61,8 @@ task('genesis-l2', 'create a genesis config')
const { deployConfig } = hre const { deployConfig } = hre
const l1 = new ethers.providers.StaticJsonRpcProvider(args.l1RpcUrl)
// Use the addresses of the proxies here instead of the implementations // Use the addresses of the proxies here instead of the implementations
// Be backwards compatible // Be backwards compatible
let ProxyL1CrossDomainMessenger = await hre.deployments.getOrNull( let ProxyL1CrossDomainMessenger = await hre.deployments.getOrNull(
...@@ -256,6 +259,9 @@ task('genesis-l2', 'create a genesis config') ...@@ -256,6 +259,9 @@ task('genesis-l2', 'create a genesis config')
} }
} }
const portal = await hre.deployments.get('OptimismPortalProxy')
const l1StartingBlock = await l1.getBlock(portal.receipt.blockHash)
const genesis: OptimismGenesis = { const genesis: OptimismGenesis = {
config: { config: {
chainId: deployConfig.genesisBlockChainid, chainId: deployConfig.genesisBlockChainid,
...@@ -279,9 +285,7 @@ task('genesis-l2', 'create a genesis config') ...@@ -279,9 +285,7 @@ task('genesis-l2', 'create a genesis config')
}, },
nonce: '0x1234', nonce: '0x1234',
difficulty: '0x1', difficulty: '0x1',
timestamp: ethers.BigNumber.from( timestamp: ethers.BigNumber.from(l1StartingBlock.timestamp).toHexString(),
deployConfig.startingTimestamp
).toHexString(),
gasLimit: deployConfig.genesisBlockGasLimit, gasLimit: deployConfig.genesisBlockGasLimit,
extraData: deployConfig.genesisBlockExtradata, extraData: deployConfig.genesisBlockExtradata,
optimism: { optimism: {
......
...@@ -21,6 +21,7 @@ task('rollup-config', 'create a genesis config') ...@@ -21,6 +21,7 @@ task('rollup-config', 'create a genesis config')
const l2Genesis = await l2.getBlock('earliest') const l2Genesis = await l2.getBlock('earliest')
const portal = await hre.deployments.get('OptimismPortalProxy') const portal = await hre.deployments.get('OptimismPortalProxy')
const l1StartingBlock = await l1.getBlock(portal.receipt.blockHash)
const config: OpNodeConfig = { const config: OpNodeConfig = {
genesis: { genesis: {
...@@ -32,7 +33,7 @@ task('rollup-config', 'create a genesis config') ...@@ -32,7 +33,7 @@ task('rollup-config', 'create a genesis config')
hash: l2Genesis.hash, hash: l2Genesis.hash,
number: 0, number: 0,
}, },
l2_time: deployConfig.startingTimestamp, l2_time: l1StartingBlock.timestamp,
}, },
block_time: deployConfig.l2BlockTime, block_time: deployConfig.l2BlockTime,
max_sequencer_drift: deployConfig.maxSequencerDrift, max_sequencer_drift: deployConfig.maxSequencerDrift,
......
...@@ -2,7 +2,7 @@ import { BaseServiceV2, Gauge, validators } from '@eth-optimism/common-ts' ...@@ -2,7 +2,7 @@ import { BaseServiceV2, Gauge, validators } from '@eth-optimism/common-ts'
import { getChainId, sleep, toRpcHexString } from '@eth-optimism/core-utils' import { getChainId, sleep, toRpcHexString } from '@eth-optimism/core-utils'
import { CrossChainMessenger } from '@eth-optimism/sdk' import { CrossChainMessenger } from '@eth-optimism/sdk'
import { Provider } from '@ethersproject/abstract-provider' import { Provider } from '@ethersproject/abstract-provider'
import { Contract, ethers } from 'ethers' import { Contract, ethers, Transaction } from 'ethers'
import dateformat from 'dateformat' import dateformat from 'dateformat'
import { import {
...@@ -20,10 +20,12 @@ type Metrics = { ...@@ -20,10 +20,12 @@ type Metrics = {
highestCheckedBatchIndex: Gauge highestCheckedBatchIndex: Gauge
highestKnownBatchIndex: Gauge highestKnownBatchIndex: Gauge
isCurrentlyMismatched: Gauge isCurrentlyMismatched: Gauge
inUnexpectedErrorState: Gauge l1NodeConnectionFailures: Gauge
l2NodeConnectionFailures: Gauge
} }
type State = { type State = {
fpw: number
scc: Contract scc: Contract
messenger: CrossChainMessenger messenger: CrossChainMessenger
highestCheckedBatchIndex: number highestCheckedBatchIndex: number
...@@ -68,9 +70,13 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> { ...@@ -68,9 +70,13 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
type: Gauge, type: Gauge,
desc: '0 if state is ok, 1 if state is mismatched', desc: '0 if state is ok, 1 if state is mismatched',
}, },
inUnexpectedErrorState: { l1NodeConnectionFailures: {
type: Gauge, type: Gauge,
desc: '0 if service is ok, 1 service is in unexpected error state', desc: 'Number of times L1 node connection has failed',
},
l2NodeConnectionFailures: {
type: Gauge,
desc: 'Number of times L2 node connection has failed',
}, },
}, },
}) })
...@@ -86,6 +92,7 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> { ...@@ -86,6 +92,7 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
// We use this a lot, a bit cleaner to pull out to the top level of the state object. // We use this a lot, a bit cleaner to pull out to the top level of the state object.
this.state.scc = this.state.messenger.contracts.l1.StateCommitmentChain this.state.scc = this.state.messenger.contracts.l1.StateCommitmentChain
this.state.fpw = (await this.state.scc.FRAUD_PROOF_WINDOW()).toNumber()
// Figure out where to start syncing from. // Figure out where to start syncing from.
if (this.options.startBatchIndex === -1) { if (this.options.startBatchIndex === -1) {
...@@ -102,17 +109,30 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> { ...@@ -102,17 +109,30 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
} }
async main(): Promise<void> { async main(): Promise<void> {
const latestBatchIndex = await this.state.scc.getTotalBatches() let latestBatchIndex: number
if (this.state.highestCheckedBatchIndex >= latestBatchIndex.toNumber()) { try {
latestBatchIndex = (await this.state.scc.getTotalBatches()).toNumber()
} catch (err) {
this.logger.error(`got error when connecting to node`, {
error: err,
node: 'l1',
section: 'getTotalBatches',
})
this.metrics.l1NodeConnectionFailures.inc()
await sleep(15000) await sleep(15000)
return return
} }
this.metrics.highestKnownBatchIndex.set(latestBatchIndex.toNumber()) if (this.state.highestCheckedBatchIndex >= latestBatchIndex) {
await sleep(15000)
return
} else {
this.metrics.highestKnownBatchIndex.set(latestBatchIndex)
}
this.logger.info(`checking batch`, { this.logger.info(`checking batch`, {
batchIndex: this.state.highestCheckedBatchIndex, batchIndex: this.state.highestCheckedBatchIndex,
latestIndex: latestBatchIndex.toNumber(), latestIndex: latestBatchIndex,
}) })
let event: ethers.Event let event: ethers.Event
...@@ -122,13 +142,30 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> { ...@@ -122,13 +142,30 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
this.state.highestCheckedBatchIndex this.state.highestCheckedBatchIndex
) )
} catch (err) { } catch (err) {
this.logger.error(`got unexpected error while searching for batch`, { this.logger.error(`got error when connecting to node`, {
batchIndex: this.state.highestCheckedBatchIndex,
error: err, error: err,
node: 'l1',
section: 'findEventForStateBatch',
}) })
this.metrics.l1NodeConnectionFailures.inc()
await sleep(15000)
return
}
let batchTransaction: Transaction
try {
batchTransaction = await event.getTransaction()
} catch (err) {
this.logger.error(`got error when connecting to node`, {
error: err,
node: 'l1',
section: 'getTransaction',
})
this.metrics.l1NodeConnectionFailures.inc()
await sleep(15000)
return
} }
const batchTransaction = await event.getTransaction()
const [stateRoots] = this.state.scc.interface.decodeFunctionData( const [stateRoots] = this.state.scc.interface.decodeFunctionData(
'appendStateBatch', 'appendStateBatch',
batchTransaction.data batchTransaction.data
...@@ -138,7 +175,20 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> { ...@@ -138,7 +175,20 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
const batchSize = event.args._batchSize.toNumber() const batchSize = event.args._batchSize.toNumber()
const batchEnd = batchStart + batchSize const batchEnd = batchStart + batchSize
const latestBlock = await this.options.l2RpcProvider.getBlockNumber() let latestBlock: number
try {
latestBlock = await this.options.l2RpcProvider.getBlockNumber()
} catch (err) {
this.logger.error(`got error when connecting to node`, {
error: err,
node: 'l2',
section: 'getBlockNumber',
})
this.metrics.l2NodeConnectionFailures.inc()
await sleep(15000)
return
}
if (latestBlock < batchEnd) { if (latestBlock < batchEnd) {
this.logger.info(`node is behind, waiting for sync`, { this.logger.info(`node is behind, waiting for sync`, {
batchEnd, batchEnd,
...@@ -151,21 +201,32 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> { ...@@ -151,21 +201,32 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
// multiple requests of maximum 1000 blocks in the case that batchSize > 1000. // multiple requests of maximum 1000 blocks in the case that batchSize > 1000.
let blocks: any[] = [] let blocks: any[] = []
for (let i = 0; i < batchSize; i += 1000) { for (let i = 0; i < batchSize; i += 1000) {
const provider = this.options let newBlocks: any[]
.l2RpcProvider as ethers.providers.JsonRpcProvider try {
blocks = blocks.concat( newBlocks = await (
await provider.send('eth_getBlockRange', [ this.options.l2RpcProvider as ethers.providers.JsonRpcProvider
).send('eth_getBlockRange', [
toRpcHexString(batchStart + i), toRpcHexString(batchStart + i),
toRpcHexString(batchStart + i + Math.min(batchSize - i, 1000) - 1), toRpcHexString(batchStart + i + Math.min(batchSize - i, 1000) - 1),
false, false,
]) ])
) } catch (err) {
this.logger.error(`got error when connecting to node`, {
error: err,
node: 'l2',
section: 'getBlockRange',
})
this.metrics.l2NodeConnectionFailures.inc()
await sleep(15000)
return
}
blocks = blocks.concat(newBlocks)
} }
for (const [i, stateRoot] of stateRoots.entries()) { for (const [i, stateRoot] of stateRoots.entries()) {
if (blocks[i].stateRoot !== stateRoot) { if (blocks[i].stateRoot !== stateRoot) {
this.metrics.isCurrentlyMismatched.set(1) this.metrics.isCurrentlyMismatched.set(1)
const fpw = await this.state.scc.FRAUD_PROOF_WINDOW()
this.logger.error(`state root mismatch`, { this.logger.error(`state root mismatch`, {
blockNumber: blocks[i].number, blockNumber: blocks[i].number,
expectedStateRoot: blocks[i].stateRoot, expectedStateRoot: blocks[i].stateRoot,
...@@ -173,7 +234,7 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> { ...@@ -173,7 +234,7 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
finalizationTime: dateformat( finalizationTime: dateformat(
new Date( new Date(
(ethers.BigNumber.from(blocks[i].timestamp).toNumber() + (ethers.BigNumber.from(blocks[i].timestamp).toNumber() +
fpw.toNumber()) * this.state.fpw) *
1000 1000
), ),
'mmmm dS, yyyy, h:MM:ss TT' 'mmmm dS, yyyy, h:MM:ss TT'
...@@ -190,7 +251,6 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> { ...@@ -190,7 +251,6 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
// If we got through the above without throwing an error, we should be fine to reset. // If we got through the above without throwing an error, we should be fine to reset.
this.metrics.isCurrentlyMismatched.set(0) this.metrics.isCurrentlyMismatched.set(0)
this.metrics.inUnexpectedErrorState.set(0)
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment