├── .github
└── workflows
│ └── release.yml
├── .gitignore
├── LICENSE
├── README.md
├── funding.json
├── optimism
├── __init__.py
├── assets
│ ├── dispute_game_factory.json
│ ├── erc20.json
│ ├── fault_dispute_game.json
│ ├── l1_cross_messenger.json
│ ├── l1_standard_bridge.json
│ ├── l2_cross_messenger.json
│ ├── l2_output_oracle.json
│ ├── l2_standard_bridge.json
│ ├── l2_to_l1_message_passer.json
│ ├── optimism_erc20.json
│ └── optimism_portal.json
├── config.json
├── constants.py
├── contracts.py
├── cross_chain_messenger.py
├── types.py
└── utils.py
├── pyproject.toml
├── requirements.txt
└── test
├── README.md
├── __init__.py
├── extract_addresses.py
├── test_deposit.py
├── test_withdrawl.py
└── utils.py
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | release:
5 | types: [created]
6 |
7 | jobs:
8 | publish-pypi:
9 | name: Publish to PyPi
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 | - uses: actions/checkout@v4
14 | - name: Set up Python
15 | uses: actions/setup-python@v4
16 | with:
17 | python-version: '3.11.0'
18 | - name: Install dependencies
19 | run: |
20 | python -m pip install --upgrade pip
21 | pip install poetry
22 | - name: Build and publish
23 | env:
24 | PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
25 | run: |
26 | # set pyproject.toml version to github.ref_name (without v prefix)
27 | VERSION=$(echo "${{ github.ref_name }}" | sed 's/^v//')
28 | sed -i 's/^version = ".*"$/version = "'"$VERSION"'"/' pyproject.toml
29 | poetry publish --build --username=__token__ --password=$PYPI_TOKEN
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | __pycache__
3 |
4 | dist
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2023 rafalum
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Optimism-Python: Unofficial Python Client for the OP-Stack
2 |
3 | > [!WARNING]
4 | > Reference SDK is still under active development so the repository might be temporarily out of date.
5 |
6 |
7 |

8 |
9 |
10 |
11 | This library is a Python implementation of the [OP-Stack SDK](https://sdk.optimism.io/). It tries to mirror some of the core functionalities such as:
12 |
13 | - providing easy access to the OP-Stack contracts
14 | - bridging of assets from L1 to L2 (deposits) and vice-versa (withdrawls)
15 | - creating withdrawl proofs
16 |
17 | ## Getting started
18 |
19 | ### Installation
20 |
21 | ```bash
22 | pip install optimism-python
23 | ```
24 |
25 | ### Deposit ETH to L2
26 |
27 | ```python
28 | from web3 import Web3
29 | from optimism import CrossChainMessenger
30 | from optimism.types import Chains
31 |
32 | # Create a node provider for each chain
33 | provider_l1 = Web3(Web3.HTTPProvider("https://eth-mainnet.g.alchemy.com/v2/"))
34 | provider_l2 = Web3(Web3.HTTPProvider("https://optimism-mainnet.g.alchemy.com/v2/"))
35 |
36 | # Specify an account for each chain (can be the same)
37 | account_l1 = provider_l1.eth.account.from_key("")
38 | account_l2 = provider_l2.eth.account.from_key("")
39 |
40 | # Create a messenger instance
41 | messenger = CrossChainMessenger(chain_l1=Chains.ETHEREUM_MAINNET,
42 | chain_l2=Chains.OPTIMISM_MAINNET,
43 | account_l1=account_l1,
44 | account_l2=account_l2,
45 | provider_l1=provider_l1,
46 | provider_l2=provider_l2)
47 |
48 | # Deposit 1 ETH to L2
49 | messenger.deposit_eth(10**18)
50 | ```
51 |
--------------------------------------------------------------------------------
/funding.json:
--------------------------------------------------------------------------------
1 | {
2 | "opRetro": {
3 | "projectId": "0x0b723463dee5c51f19dec738932260e89c9641f7342b8021551123605dee2dd6"
4 | }
5 | }
--------------------------------------------------------------------------------
/optimism/__init__.py:
--------------------------------------------------------------------------------
1 | from .cross_chain_messenger import CrossChainMessenger
2 | from .contracts import OptimismPortal, StandardBridge, L2ToL1MessagePasser, L2OutputOracle, DisputeGameFactory, FaultDisputeGame, CrossChainMessengerContract
3 | from .types import Chains
4 |
5 | __all__ = ["CrossChainMessenger", "OptimismPortal", "StandardBridge", "CrossChainMessengerContract", "L2OutputOracle", "DisputeGameFactory", "FaultDisputeGame", "L2ToL1MessagePasser", "Chains"]
--------------------------------------------------------------------------------
/optimism/assets/dispute_game_factory.json:
--------------------------------------------------------------------------------
1 | [{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"Hash","name":"uuid","type":"bytes32"}],"name":"GameAlreadyExists","type":"error"},{"inputs":[],"name":"IncorrectBondAmount","type":"error"},{"inputs":[{"internalType":"GameType","name":"gameType","type":"uint32"}],"name":"NoImplementation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"disputeProxy","type":"address"},{"indexed":true,"internalType":"GameType","name":"gameType","type":"uint32"},{"indexed":true,"internalType":"Claim","name":"rootClaim","type":"bytes32"}],"name":"DisputeGameCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"impl","type":"address"},{"indexed":true,"internalType":"GameType","name":"gameType","type":"uint32"}],"name":"ImplementationSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"GameType","name":"gameType","type":"uint32"},{"indexed":true,"internalType":"uint256","name":"newBond","type":"uint256"}],"name":"InitBondUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"internalType":"GameType","name":"_gameType","type":"uint32"},{"internalType":"Claim","name":"_rootClaim","type":"bytes32"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"create","outputs":[{"internalType":"contract IDisputeGame","name":"proxy_","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"GameType","name":"_gameType","type":"uint32"},{"internalType":"uint256","name":"_start","type":"uint256"},{"internalType":"uint256","name":"_n","type":"uint256"}],"name":"findLatestGames","outputs":[{"components":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"GameId","name":"metadata","type":"bytes32"},{"internalType":"Timestamp","name":"timestamp","type":"uint64"},{"internalType":"Claim","name":"rootClaim","type":"bytes32"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct IDisputeGameFactory.GameSearchResult[]","name":"games_","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"gameAtIndex","outputs":[{"internalType":"GameType","name":"gameType_","type":"uint32"},{"internalType":"Timestamp","name":"timestamp_","type":"uint64"},{"internalType":"contract IDisputeGame","name":"proxy_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gameCount","outputs":[{"internalType":"uint256","name":"gameCount_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"GameType","name":"","type":"uint32"}],"name":"gameImpls","outputs":[{"internalType":"contract IDisputeGame","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"GameType","name":"_gameType","type":"uint32"},{"internalType":"Claim","name":"_rootClaim","type":"bytes32"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"games","outputs":[{"internalType":"contract IDisputeGame","name":"proxy_","type":"address"},{"internalType":"Timestamp","name":"timestamp_","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"GameType","name":"_gameType","type":"uint32"},{"internalType":"Claim","name":"_rootClaim","type":"bytes32"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"getGameUUID","outputs":[{"internalType":"Hash","name":"uuid_","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"GameType","name":"","type":"uint32"}],"name":"initBonds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"GameType","name":"_gameType","type":"uint32"},{"internalType":"contract IDisputeGame","name":"_impl","type":"address"}],"name":"setImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"GameType","name":"_gameType","type":"uint32"},{"internalType":"uint256","name":"_initBond","type":"uint256"}],"name":"setInitBond","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]
--------------------------------------------------------------------------------
/optimism/assets/erc20.json:
--------------------------------------------------------------------------------
1 | [{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"authorizer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"nonce","type":"bytes32"}],"name":"AuthorizationCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"authorizer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"nonce","type":"bytes32"}],"name":"AuthorizationUsed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_account","type":"address"}],"name":"Blacklisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newBlacklister","type":"address"}],"name":"BlacklisterChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"burner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newMasterMinter","type":"address"}],"name":"MasterMinterChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minter","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minter","type":"address"},{"indexed":false,"internalType":"uint256","name":"minterAllowedAmount","type":"uint256"}],"name":"MinterConfigured","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldMinter","type":"address"}],"name":"MinterRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newAddress","type":"address"}],"name":"PauserChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newRescuer","type":"address"}],"name":"RescuerChanged","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":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_account","type":"address"}],"name":"UnBlacklisted","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpause","type":"event"},{"inputs":[],"name":"CANCEL_AUTHORIZATION_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RECEIVE_WITH_AUTHORIZATION_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TRANSFER_WITH_AUTHORIZATION_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"authorizer","type":"address"},{"internalType":"bytes32","name":"nonce","type":"bytes32"}],"name":"authorizationState","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"blacklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"blacklister","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"authorizer","type":"address"},{"internalType":"bytes32","name":"nonce","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"cancelAuthorization","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"},{"internalType":"uint256","name":"minterAllowedAmount","type":"uint256"}],"name":"configureMinter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currency","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"decrement","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"increment","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"tokenName","type":"string"},{"internalType":"string","name":"tokenSymbol","type":"string"},{"internalType":"string","name":"tokenCurrency","type":"string"},{"internalType":"uint8","name":"tokenDecimals","type":"uint8"},{"internalType":"address","name":"newMasterMinter","type":"address"},{"internalType":"address","name":"newPauser","type":"address"},{"internalType":"address","name":"newBlacklister","type":"address"},{"internalType":"address","name":"newOwner","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newName","type":"string"}],"name":"initializeV2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"lostAndFound","type":"address"}],"name":"initializeV2_1","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isBlacklisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isMinter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"masterMinter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"minterAllowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pauser","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"validAfter","type":"uint256"},{"internalType":"uint256","name":"validBefore","type":"uint256"},{"internalType":"bytes32","name":"nonce","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"receiveWithAuthorization","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"removeMinter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"tokenContract","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"rescueERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rescuer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"validAfter","type":"uint256"},{"internalType":"uint256","name":"validBefore","type":"uint256"},{"internalType":"bytes32","name":"nonce","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"transferWithAuthorization","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"unBlacklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newBlacklister","type":"address"}],"name":"updateBlacklister","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newMasterMinter","type":"address"}],"name":"updateMasterMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newPauser","type":"address"}],"name":"updatePauser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newRescuer","type":"address"}],"name":"updateRescuer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]
--------------------------------------------------------------------------------
/optimism/assets/fault_dispute_game.json:
--------------------------------------------------------------------------------
1 | [{"inputs":[{"internalType":"GameType","name":"_gameType","type":"uint32"},{"internalType":"Claim","name":"_absolutePrestate","type":"bytes32"},{"internalType":"uint256","name":"_maxGameDepth","type":"uint256"},{"internalType":"uint256","name":"_splitDepth","type":"uint256"},{"internalType":"Duration","name":"_clockExtension","type":"uint64"},{"internalType":"Duration","name":"_maxClockDuration","type":"uint64"},{"internalType":"contract IBigStepper","name":"_vm","type":"address"},{"internalType":"contract IDelayedWETH","name":"_weth","type":"address"},{"internalType":"contract IAnchorStateRegistry","name":"_anchorStateRegistry","type":"address"},{"internalType":"uint256","name":"_l2ChainId","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"AnchorRootNotFound","type":"error"},{"inputs":[],"name":"BlockNumberMatches","type":"error"},{"inputs":[],"name":"BondTransferFailed","type":"error"},{"inputs":[],"name":"CannotDefendRootClaim","type":"error"},{"inputs":[],"name":"ClaimAboveSplit","type":"error"},{"inputs":[],"name":"ClaimAlreadyExists","type":"error"},{"inputs":[],"name":"ClaimAlreadyResolved","type":"error"},{"inputs":[],"name":"ClockNotExpired","type":"error"},{"inputs":[],"name":"ClockTimeExceeded","type":"error"},{"inputs":[],"name":"ContentLengthMismatch","type":"error"},{"inputs":[],"name":"DuplicateStep","type":"error"},{"inputs":[],"name":"EmptyItem","type":"error"},{"inputs":[],"name":"GameDepthExceeded","type":"error"},{"inputs":[],"name":"GameNotInProgress","type":"error"},{"inputs":[],"name":"IncorrectBondAmount","type":"error"},{"inputs":[],"name":"InvalidClockExtension","type":"error"},{"inputs":[],"name":"InvalidDataRemainder","type":"error"},{"inputs":[],"name":"InvalidDisputedClaimIndex","type":"error"},{"inputs":[],"name":"InvalidHeader","type":"error"},{"inputs":[],"name":"InvalidHeaderRLP","type":"error"},{"inputs":[],"name":"InvalidLocalIdent","type":"error"},{"inputs":[],"name":"InvalidOutputRootProof","type":"error"},{"inputs":[],"name":"InvalidParent","type":"error"},{"inputs":[],"name":"InvalidPrestate","type":"error"},{"inputs":[],"name":"InvalidSplitDepth","type":"error"},{"inputs":[],"name":"L2BlockNumberChallenged","type":"error"},{"inputs":[],"name":"MaxDepthTooLarge","type":"error"},{"inputs":[],"name":"NoCreditToClaim","type":"error"},{"inputs":[],"name":"OutOfOrderResolution","type":"error"},{"inputs":[],"name":"UnexpectedList","type":"error"},{"inputs":[{"internalType":"Claim","name":"rootClaim","type":"bytes32"}],"name":"UnexpectedRootClaim","type":"error"},{"inputs":[],"name":"UnexpectedString","type":"error"},{"inputs":[],"name":"ValidStep","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"parentIndex","type":"uint256"},{"indexed":true,"internalType":"Claim","name":"claim","type":"bytes32"},{"indexed":true,"internalType":"address","name":"claimant","type":"address"}],"name":"Move","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum GameStatus","name":"status","type":"uint8"}],"name":"Resolved","type":"event"},{"inputs":[],"name":"absolutePrestate","outputs":[{"internalType":"Claim","name":"absolutePrestate_","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_ident","type":"uint256"},{"internalType":"uint256","name":"_execLeafIdx","type":"uint256"},{"internalType":"uint256","name":"_partOffset","type":"uint256"}],"name":"addLocalData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"anchorStateRegistry","outputs":[{"internalType":"contract IAnchorStateRegistry","name":"registry_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"Claim","name":"_disputed","type":"bytes32"},{"internalType":"uint256","name":"_parentIndex","type":"uint256"},{"internalType":"Claim","name":"_claim","type":"bytes32"}],"name":"attack","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"version","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"internalType":"bytes32","name":"messagePasserStorageRoot","type":"bytes32"},{"internalType":"bytes32","name":"latestBlockhash","type":"bytes32"}],"internalType":"struct Types.OutputRootProof","name":"_outputRootProof","type":"tuple"},{"internalType":"bytes","name":"_headerRLP","type":"bytes"}],"name":"challengeRootL2Block","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimCredit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"claimData","outputs":[{"internalType":"uint32","name":"parentIndex","type":"uint32"},{"internalType":"address","name":"counteredBy","type":"address"},{"internalType":"address","name":"claimant","type":"address"},{"internalType":"uint128","name":"bond","type":"uint128"},{"internalType":"Claim","name":"claim","type":"bytes32"},{"internalType":"Position","name":"position","type":"uint128"},{"internalType":"Clock","name":"clock","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimDataLen","outputs":[{"internalType":"uint256","name":"len_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"Hash","name":"","type":"bytes32"}],"name":"claims","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"clockExtension","outputs":[{"internalType":"Duration","name":"clockExtension_","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"createdAt","outputs":[{"internalType":"Timestamp","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"credit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"Claim","name":"_disputed","type":"bytes32"},{"internalType":"uint256","name":"_parentIndex","type":"uint256"},{"internalType":"Claim","name":"_claim","type":"bytes32"}],"name":"defend","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"extraData","outputs":[{"internalType":"bytes","name":"extraData_","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"gameCreator","outputs":[{"internalType":"address","name":"creator_","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"gameData","outputs":[{"internalType":"GameType","name":"gameType_","type":"uint32"},{"internalType":"Claim","name":"rootClaim_","type":"bytes32"},{"internalType":"bytes","name":"extraData_","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gameType","outputs":[{"internalType":"GameType","name":"gameType_","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_claimIndex","type":"uint256"}],"name":"getChallengerDuration","outputs":[{"internalType":"Duration","name":"duration_","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_claimIndex","type":"uint256"}],"name":"getNumToResolve","outputs":[{"internalType":"uint256","name":"numRemainingChildren_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"Position","name":"_position","type":"uint128"}],"name":"getRequiredBond","outputs":[{"internalType":"uint256","name":"requiredBond_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"l1Head","outputs":[{"internalType":"Hash","name":"l1Head_","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"l2BlockNumber","outputs":[{"internalType":"uint256","name":"l2BlockNumber_","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"l2BlockNumberChallenged","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"l2BlockNumberChallenger","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"l2ChainId","outputs":[{"internalType":"uint256","name":"l2ChainId_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxClockDuration","outputs":[{"internalType":"Duration","name":"maxClockDuration_","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxGameDepth","outputs":[{"internalType":"uint256","name":"maxGameDepth_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"Claim","name":"_disputed","type":"bytes32"},{"internalType":"uint256","name":"_challengeIndex","type":"uint256"},{"internalType":"Claim","name":"_claim","type":"bytes32"},{"internalType":"bool","name":"_isAttack","type":"bool"}],"name":"move","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"resolutionCheckpoints","outputs":[{"internalType":"bool","name":"initialCheckpointComplete","type":"bool"},{"internalType":"uint32","name":"subgameIndex","type":"uint32"},{"internalType":"Position","name":"leftmostPosition","type":"uint128"},{"internalType":"address","name":"counteredBy","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"resolve","outputs":[{"internalType":"enum GameStatus","name":"status_","type":"uint8"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_claimIndex","type":"uint256"},{"internalType":"uint256","name":"_numToResolve","type":"uint256"}],"name":"resolveClaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resolvedAt","outputs":[{"internalType":"Timestamp","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"resolvedSubgames","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rootClaim","outputs":[{"internalType":"Claim","name":"rootClaim_","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"splitDepth","outputs":[{"internalType":"uint256","name":"splitDepth_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startingBlockNumber","outputs":[{"internalType":"uint256","name":"startingBlockNumber_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startingOutputRoot","outputs":[{"internalType":"Hash","name":"root","type":"bytes32"},{"internalType":"uint256","name":"l2BlockNumber","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startingRootHash","outputs":[{"internalType":"Hash","name":"startingRootHash_","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"status","outputs":[{"internalType":"enum GameStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_claimIndex","type":"uint256"},{"internalType":"bool","name":"_isAttack","type":"bool"},{"internalType":"bytes","name":"_stateData","type":"bytes"},{"internalType":"bytes","name":"_proof","type":"bytes"}],"name":"step","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"subgames","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vm","outputs":[{"internalType":"contract IBigStepper","name":"vm_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"contract IDelayedWETH","name":"weth_","type":"address"}],"stateMutability":"view","type":"function"}]
--------------------------------------------------------------------------------
/optimism/assets/l1_cross_messenger.json:
--------------------------------------------------------------------------------
1 | [{"inputs":[{"internalType":"contract OptimismPortal","name":"_portal","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"msgHash","type":"bytes32"}],"name":"FailedRelayedMessage","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"msgHash","type":"bytes32"}],"name":"RelayedMessage","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"bytes","name":"message","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"messageNonce","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasLimit","type":"uint256"}],"name":"SentMessage","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"SentMessageExtension1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"MESSAGE_VERSION","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_GAS_CALLDATA_OVERHEAD","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_GAS_CONSTANT_OVERHEAD","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OTHER_MESSENGER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PORTAL","outputs":[{"internalType":"contract OptimismPortal","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"uint32","name":"_minGasLimit","type":"uint32"}],"name":"baseGas","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"failedMessages","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"messageNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":"_minGasLimit","type":"uint256"},{"internalType":"bytes","name":"_message","type":"bytes"}],"name":"relayMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_target","type":"address"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"uint32","name":"_minGasLimit","type":"uint32"}],"name":"sendMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"successfulMessages","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"xDomainMessageSender","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
--------------------------------------------------------------------------------
/optimism/assets/l1_standard_bridge.json:
--------------------------------------------------------------------------------
1 | [{"inputs":[{"internalType":"address payable","name":"_messenger","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"localToken","type":"address"},{"indexed":true,"internalType":"address","name":"remoteToken","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"ERC20BridgeFinalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"localToken","type":"address"},{"indexed":true,"internalType":"address","name":"remoteToken","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"ERC20BridgeInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"l1Token","type":"address"},{"indexed":true,"internalType":"address","name":"l2Token","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"ERC20DepositInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"l1Token","type":"address"},{"indexed":true,"internalType":"address","name":"l2Token","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"ERC20WithdrawalFinalized","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":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"ETHBridgeFinalized","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":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"ETHBridgeInitiated","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":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"ETHDepositInitiated","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":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"ETHWithdrawalFinalized","type":"event"},{"inputs":[],"name":"MESSENGER","outputs":[{"internalType":"contract CrossDomainMessenger","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OTHER_BRIDGE","outputs":[{"internalType":"contract StandardBridge","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_localToken","type":"address"},{"internalType":"address","name":"_remoteToken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint32","name":"_minGasLimit","type":"uint32"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"bridgeERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_localToken","type":"address"},{"internalType":"address","name":"_remoteToken","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint32","name":"_minGasLimit","type":"uint32"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"bridgeERC20To","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_minGasLimit","type":"uint32"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"bridgeETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint32","name":"_minGasLimit","type":"uint32"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"bridgeETHTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_l1Token","type":"address"},{"internalType":"address","name":"_l2Token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint32","name":"_minGasLimit","type":"uint32"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"depositERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_l1Token","type":"address"},{"internalType":"address","name":"_l2Token","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint32","name":"_minGasLimit","type":"uint32"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"depositERC20To","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_minGasLimit","type":"uint32"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"depositETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint32","name":"_minGasLimit","type":"uint32"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"depositETHTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"deposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_localToken","type":"address"},{"internalType":"address","name":"_remoteToken","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"finalizeBridgeERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"finalizeBridgeETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_l1Token","type":"address"},{"internalType":"address","name":"_l2Token","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"finalizeERC20Withdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"finalizeETHWithdrawal","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"l2TokenBridge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"messenger","outputs":[{"internalType":"contract CrossDomainMessenger","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
--------------------------------------------------------------------------------
/optimism/assets/l2_cross_messenger.json:
--------------------------------------------------------------------------------
1 | [{"inputs":[{"internalType":"address","name":"_l1CrossDomainMessenger","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"msgHash","type":"bytes32"}],"name":"FailedRelayedMessage","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"msgHash","type":"bytes32"}],"name":"RelayedMessage","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"bytes","name":"message","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"messageNonce","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasLimit","type":"uint256"}],"name":"SentMessage","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"SentMessageExtension1","type":"event"},{"inputs":[],"name":"MESSAGE_VERSION","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_GAS_CALLDATA_OVERHEAD","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OTHER_MESSENGER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RELAY_CALL_OVERHEAD","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RELAY_CONSTANT_OVERHEAD","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RELAY_GAS_CHECK_BUFFER","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RELAY_RESERVED_GAS","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"uint32","name":"_minGasLimit","type":"uint32"}],"name":"baseGas","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"failedMessages","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"l1CrossDomainMessenger","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"messageNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"_minGasLimit","type":"uint256"},{"internalType":"bytes","name":"_message","type":"bytes"}],"name":"relayMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_target","type":"address"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"uint32","name":"_minGasLimit","type":"uint32"}],"name":"sendMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"successfulMessages","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"xDomainMessageSender","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
--------------------------------------------------------------------------------
/optimism/assets/l2_output_oracle.json:
--------------------------------------------------------------------------------
1 | [{"inputs":[{"internalType":"uint256","name":"_submissionInterval","type":"uint256"},{"internalType":"uint256","name":"_l2BlockTime","type":"uint256"},{"internalType":"uint256","name":"_startingBlockNumber","type":"uint256"},{"internalType":"uint256","name":"_startingTimestamp","type":"uint256"},{"internalType":"address","name":"_proposer","type":"address"},{"internalType":"address","name":"_challenger","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":"bytes32","name":"outputRoot","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"l2OutputIndex","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"l2BlockNumber","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"l1Timestamp","type":"uint256"}],"name":"OutputProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"prevNextOutputIndex","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"newNextOutputIndex","type":"uint256"}],"name":"OutputsDeleted","type":"event"},{"inputs":[],"name":"CHALLENGER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FINALIZATION_PERIOD_SECONDS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"L2_BLOCK_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PROPOSER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUBMISSION_INTERVAL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_l2BlockNumber","type":"uint256"}],"name":"computeL2Timestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_l2OutputIndex","type":"uint256"}],"name":"deleteL2Outputs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_l2OutputIndex","type":"uint256"}],"name":"getL2Output","outputs":[{"components":[{"internalType":"bytes32","name":"outputRoot","type":"bytes32"},{"internalType":"uint128","name":"timestamp","type":"uint128"},{"internalType":"uint128","name":"l2BlockNumber","type":"uint128"}],"internalType":"struct Types.OutputProposal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_l2BlockNumber","type":"uint256"}],"name":"getL2OutputAfter","outputs":[{"components":[{"internalType":"bytes32","name":"outputRoot","type":"bytes32"},{"internalType":"uint128","name":"timestamp","type":"uint128"},{"internalType":"uint128","name":"l2BlockNumber","type":"uint128"}],"internalType":"struct Types.OutputProposal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_l2BlockNumber","type":"uint256"}],"name":"getL2OutputIndexAfter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_startingBlockNumber","type":"uint256"},{"internalType":"uint256","name":"_startingTimestamp","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"latestBlockNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestOutputIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextBlockNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextOutputIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_outputRoot","type":"bytes32"},{"internalType":"uint256","name":"_l2BlockNumber","type":"uint256"},{"internalType":"bytes32","name":"_l1BlockHash","type":"bytes32"},{"internalType":"uint256","name":"_l1BlockNumber","type":"uint256"}],"name":"proposeL2Output","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"startingBlockNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startingTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]
--------------------------------------------------------------------------------
/optimism/assets/l2_standard_bridge.json:
--------------------------------------------------------------------------------
1 | [{"inputs":[{"internalType":"addresspayable","name":"_otherBridge","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"l1Token","type":"address"},{"indexed":true,"internalType":"address","name":"l2Token","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"DepositFinalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"localToken","type":"address"},{"indexed":true,"internalType":"address","name":"remoteToken","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"ERC20BridgeFinalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"localToken","type":"address"},{"indexed":true,"internalType":"address","name":"remoteToken","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"ERC20BridgeInitiated","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":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"ETHBridgeFinalized","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":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"ETHBridgeInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"l1Token","type":"address"},{"indexed":true,"internalType":"address","name":"l2Token","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"WithdrawalInitiated","type":"event"},{"inputs":[],"name":"MESSENGER","outputs":[{"internalType":"contractCrossDomainMessenger","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OTHER_BRIDGE","outputs":[{"internalType":"contractStandardBridge","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_localToken","type":"address"},{"internalType":"address","name":"_remoteToken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint32","name":"_minGasLimit","type":"uint32"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"bridgeERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_localToken","type":"address"},{"internalType":"address","name":"_remoteToken","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint32","name":"_minGasLimit","type":"uint32"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"bridgeERC20To","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_minGasLimit","type":"uint32"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"bridgeETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint32","name":"_minGasLimit","type":"uint32"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"bridgeETHTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"deposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_localToken","type":"address"},{"internalType":"address","name":"_remoteToken","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"finalizeBridgeERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"finalizeBridgeETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_l1Token","type":"address"},{"internalType":"address","name":"_l2Token","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"finalizeDeposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"l1TokenBridge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"messenger","outputs":[{"internalType":"contractCrossDomainMessenger","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_l2Token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint32","name":"_minGasLimit","type":"uint32"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"withdraw","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_l2Token","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint32","name":"_minGasLimit","type":"uint32"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"withdrawTo","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]
--------------------------------------------------------------------------------
/optimism/assets/l2_to_l1_message_passer.json:
--------------------------------------------------------------------------------
1 | [{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasLimit","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"bytes32","name":"withdrawalHash","type":"bytes32"}],"name":"MessagePassed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawerBalanceBurnt","type":"event"},{"inputs":[],"name":"MESSAGE_VERSION","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_target","type":"address"},{"internalType":"uint256","name":"_gasLimit","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"initiateWithdrawal","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"messageNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"sentMessages","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
--------------------------------------------------------------------------------
/optimism/assets/optimism_erc20.json:
--------------------------------------------------------------------------------
1 | [{"inputs":[{"internalType":"address","name":"_bridge","type":"address"},{"internalType":"address","name":"_remoteToken","type":"address"},{"internalType":"uint8","name":"_decimals","type":"uint8"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Mint","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":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"BRIDGE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REMOTE_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bridge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"l1Token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"l2Bridge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"remoteToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]
--------------------------------------------------------------------------------
/optimism/assets/optimism_portal.json:
--------------------------------------------------------------------------------
1 | [{"inputs":[{"internalType":"uint256","name":"_proofMaturityDelaySeconds","type":"uint256"},{"internalType":"uint256","name":"_disputeGameFinalityDelaySeconds","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BadTarget","type":"error"},{"inputs":[],"name":"CallPaused","type":"error"},{"inputs":[],"name":"ContentLengthMismatch","type":"error"},{"inputs":[],"name":"EmptyItem","type":"error"},{"inputs":[],"name":"GasEstimation","type":"error"},{"inputs":[],"name":"InvalidDataRemainder","type":"error"},{"inputs":[],"name":"InvalidHeader","type":"error"},{"inputs":[],"name":"LargeCalldata","type":"error"},{"inputs":[],"name":"OutOfGas","type":"error"},{"inputs":[],"name":"SmallGasLimit","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"UnexpectedList","type":"error"},{"inputs":[],"name":"UnexpectedString","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IDisputeGame","name":"disputeGame","type":"address"}],"name":"DisputeGameBlacklisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"GameType","name":"newGameType","type":"uint32"},{"indexed":true,"internalType":"Timestamp","name":"updatedAt","type":"uint64"}],"name":"RespectedGameTypeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"version","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"opaqueData","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"withdrawalHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"WithdrawalProven","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"withdrawalHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"proofSubmitter","type":"address"}],"name":"WithdrawalProvenExtension1","type":"event"},{"inputs":[{"internalType":"contract IDisputeGame","name":"_disputeGame","type":"address"}],"name":"blacklistDisputeGame","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_withdrawalHash","type":"bytes32"},{"internalType":"address","name":"_proofSubmitter","type":"address"}],"name":"checkWithdrawal","outputs":[],"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":"contract IDisputeGame","name":"","type":"address"}],"name":"disputeGameBlacklist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"disputeGameFactory","outputs":[{"internalType":"contract DisputeGameFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"disputeGameFinalityDelaySeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"donateETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"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":"struct Types.WithdrawalTransaction","name":"_tx","type":"tuple"}],"name":"finalizeWithdrawalTransaction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"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":"struct Types.WithdrawalTransaction","name":"_tx","type":"tuple"},{"internalType":"address","name":"_proofSubmitter","type":"address"}],"name":"finalizeWithdrawalTransactionExternalProof","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"finalizedWithdrawals","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"guardian","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract DisputeGameFactory","name":"_disputeGameFactory","type":"address"},{"internalType":"contract SystemConfig","name":"_systemConfig","type":"address"},{"internalType":"contract SuperchainConfig","name":"_superchainConfig","type":"address"},{"internalType":"GameType","name":"_initialRespectedGameType","type":"uint32"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"l2Sender","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"_byteCount","type":"uint64"}],"name":"minimumGasLimit","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_withdrawalHash","type":"bytes32"}],"name":"numProofSubmitters","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proofMaturityDelaySeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"proofSubmitters","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"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":"struct Types.WithdrawalTransaction","name":"_tx","type":"tuple"},{"internalType":"uint256","name":"_disputeGameIndex","type":"uint256"},{"components":[{"internalType":"bytes32","name":"version","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"internalType":"bytes32","name":"messagePasserStorageRoot","type":"bytes32"},{"internalType":"bytes32","name":"latestBlockhash","type":"bytes32"}],"internalType":"struct Types.OutputRootProof","name":"_outputRootProof","type":"tuple"},{"internalType":"bytes[]","name":"_withdrawalProof","type":"bytes[]"}],"name":"proveWithdrawalTransaction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"","type":"address"}],"name":"provenWithdrawals","outputs":[{"internalType":"contract IDisputeGame","name":"disputeGameProxy","type":"address"},{"internalType":"uint64","name":"timestamp","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"respectedGameType","outputs":[{"internalType":"GameType","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"respectedGameTypeUpdatedAt","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"GameType","name":"_gameType","type":"uint32"}],"name":"setRespectedGameType","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"superchainConfig","outputs":[{"internalType":"contract SuperchainConfig","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"systemConfig","outputs":[{"internalType":"contract SystemConfig","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
--------------------------------------------------------------------------------
/optimism/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": {
3 | "10": {
4 | "l1_addresses": {
5 | "OPTIMISM_PORTAL": "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed",
6 | "L1_STANDARD_BRIDGE": "0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1",
7 | "L1_CROSS_CHAIN_MESSENGER": "0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1",
8 | "DISPUTE_GAME_FACTORY": "0xe5965Ab5962eDc7477C8520243A95517CD252fA9"
9 | },
10 | "l2_addresses": {
11 | "L2_STANDARD_BRIDGE": "0x4200000000000000000000000000000000000010",
12 | "L2_CROSS_CHAIN_MESSENGER": "0x4200000000000000000000000000000000000007",
13 | "L2_TO_L1_MESSAGE_PASSER": "0x4200000000000000000000000000000000000016"
14 | },
15 | "name": "OPTIMISM ETHEREUM MAINNET"
16 | },
17 | "8453": {
18 | "l1_addresses": {
19 | "OPTIMISM_PORTAL": "0x49048044D57e1C92A77f79988d21Fa8fAF74E97e",
20 | "L1_STANDARD_BRIDGE": "0x3154Cf16ccdb4C6d922629664174b904d80F2C35",
21 | "L1_CROSS_CHAIN_MESSENGER": "0x866E82a600A1414e583f7F13623F1aC5d58b0Afa",
22 | "DISPUTE_GAME_FACTORY": "0x43edB88C4B80fDD2AdFF2412A7BebF9dF42cB40e"
23 | },
24 | "l2_addresses": {
25 | "L2_STANDARD_BRIDGE": "0x4200000000000000000000000000000000000010",
26 | "L2_CROSS_CHAIN_MESSENGER": "0x4200000000000000000000000000000000000007",
27 | "L2_TO_L1_MESSAGE_PASSER": "0x4200000000000000000000000000000000000016"
28 | },
29 | "name": "BASE ETHEREUM MAINNET"
30 | }
31 | },
32 | "11155111": {
33 | "11155420": {
34 | "l1_addresses": {
35 | "OPTIMISM_PORTAL": "0x16Fc5058F25648194471939df75CF27A2fdC48BC",
36 | "L1_STANDARD_BRIDGE": "0xFBb0621E0B23b5478B630BD55a5f21f67730B0F1",
37 | "L1_CROSS_CHAIN_MESSENGER": "0x58Cc85b8D04EA49cC6DBd3CbFFd00B4B8D6cb3ef",
38 | "DISPUTE_GAME_FACTORY": "0x05F9613aDB30026FFd634f38e5C4dFd30a197Fa1"
39 | },
40 | "l2_addresses": {
41 | "L2_STANDARD_BRIDGE": "0x4200000000000000000000000000000000000010",
42 | "L2_CROSS_CHAIN_MESSENGER": "0x4200000000000000000000000000000000000007",
43 | "L2_TO_L1_MESSAGE_PASSER": "0x4200000000000000000000000000000000000016"
44 | },
45 | "name": "OPTIMISM ETHEREUM SEPOLIA"
46 | },
47 | "84532": {
48 | "l1_addresses": {
49 | "OPTIMISM_PORTAL": "0x49f53e41452C74589E85cA1677426Ba426459e85",
50 | "L1_STANDARD_BRIDGE": "0xfd0Bf71F60660E2f608ed56e1659C450eB113120",
51 | "L1_CROSS_CHAIN_MESSENGER": "0xC34855F4De64F1840e5686e64278da901e261f20",
52 | "DISPUTE_GAME_FACTORY": "0xd6E6dBf4F7EA0ac412fD8b65ED297e64BB7a06E1"
53 | },
54 | "l2_addresses": {
55 | "L2_STANDARD_BRIDGE": "0x4200000000000000000000000000000000000010",
56 | "L2_CROSS_CHAIN_MESSENGER": "0x4200000000000000000000000000000000000007",
57 | "L2_TO_L1_MESSAGE_PASSER": "0x4200000000000000000000000000000000000016"
58 | },
59 | "name": "BASE ETHEREUM SEPOLIA"
60 | }
61 | },
62 | "900": {
63 | "901": {
64 | "l1_addresses": {
65 | "OPTIMISM_PORTAL": "0xB8D51FB7CA777D93aC7BdEAAE09a68A55D5DA2CE",
66 | "L1_STANDARD_BRIDGE": "0xf1a49dC6AA8DB645362E367c07312bC2eb175B6b",
67 | "L1_CROSS_CHAIN_MESSENGER": "0x448AD78a66aCA245F059bE7b8e6e3a29d5Cc9306",
68 | "L2_OUTPUT_ORACLE": "0xfA661Ac734F86AAF427a3ED1858031A5516E917b"
69 | },
70 | "l2_addresses": {
71 | "L2_STANDARD_BRIDGE": "0x4200000000000000000000000000000000000010",
72 | "L2_CROSS_CHAIN_MESSENGER": "0x4200000000000000000000000000000000000007",
73 | "L2_TO_L1_MESSAGE_PASSER": "0x4200000000000000000000000000000000000016"
74 | },
75 | "name": "OPTIMISM ETHEREUM DEVNET"
76 | }
77 | }
78 | }
--------------------------------------------------------------------------------
/optimism/constants.py:
--------------------------------------------------------------------------------
1 | OUTPUT_ROOT_PROOF_VERSION = "0x0000000000000000000000000000000000000000000000000000000000000000"
2 | MESSAGE_PASSED_ID = "0x02a52367d10742d8032712c1bb8e0144ff1ec5ffda1ed7d70bb05a2744955054"
3 | CHALLENGE_PERIOD_MAINNET = 604800
4 | CHALLENGE_PERIOD_TESTNET = 100
--------------------------------------------------------------------------------
/optimism/contracts.py:
--------------------------------------------------------------------------------
1 | from web3 import Web3
2 |
3 | from .types import MessageStatus
4 | from .utils import load_abi, is_l1_to_l2, is_chain_supported, read_addresses
5 |
6 | class Contract():
7 |
8 | def __int__():
9 | pass
10 |
11 | def sign_and_broadcast(self, transaction):
12 | signed_txn = self.provider.eth.account.sign_transaction(transaction, self.account.key)
13 | txn_hash = self.provider.eth.send_raw_transaction(signed_txn.rawTransaction)
14 | txn_receipt = self.provider.eth.wait_for_transaction_receipt(txn_hash)
15 |
16 | return txn_hash.hex(), txn_receipt
17 |
18 | class OptimismPortal(Contract):
19 |
20 | def __init__(self, chain_id_l1, chain_id_l2, account, provider):
21 |
22 | self.provider = provider
23 |
24 | if is_chain_supported(chain_id_l1) is False:
25 | raise Exception(f"Chain ID {chain_id_l1} not supported: add it to the config.json file or open a request to add it.")
26 | if is_chain_supported(chain_id_l2) is False:
27 | raise Exception(f"Chain ID {chain_id_l2} not supported: add it to the config.json file or open a request to add it.")
28 |
29 | self.address = read_addresses(chain_id_l1, chain_id_l2, layer="l1")["OPTIMISM_PORTAL"]
30 |
31 | self.account = account
32 | self.contract = self.provider.eth.contract(address=self.address, abi=load_abi("OPTIMISM_PORTAL"))
33 |
34 | def deposit_transaction(self, to, value, gas_limit, is_creation, data):
35 |
36 | deposit_transaction_tx = self.contract.functions.depositTransaction(to, value, gas_limit, is_creation, data).build_transaction({
37 | "from": self.account.address,
38 | "gas": 500000,
39 | "value": value,
40 | "nonce": self.provider.eth.get_transaction_count(self.account.address)
41 | })
42 |
43 | return self.sign_and_broadcast(deposit_transaction_tx)
44 |
45 | def prove_withdrawl_transaction(self, tx, l2_output_index, output_root_proof, withdrawl_proof):
46 |
47 | prove_withdrawl_transaction_tx = self.contract.functions.proveWithdrawalTransaction(tx, l2_output_index, output_root_proof, withdrawl_proof).build_transaction({
48 | "from": self.account.address,
49 | "gas": 1000000,
50 | "nonce": self.provider.eth.get_transaction_count(self.account.address)
51 | })
52 |
53 | return self.sign_and_broadcast(prove_withdrawl_transaction_tx)
54 |
55 | def finalize_withdrawl_transaction(self, tx):
56 |
57 | finalize_withdrawl_transaction_tx = self.contract.functions.finalizeWithdrawalTransaction(tx).build_transaction({
58 | "from": self.account.address,
59 | "gas": 100000,
60 | "nonce": self.provider.eth.get_transaction_count(self.account.address)
61 | })
62 |
63 | return self.sign_and_broadcast(finalize_withdrawl_transaction_tx)
64 |
65 | def is_output_finalized():
66 | pass
67 |
68 | def proof_maturity_delay_seconds(self):
69 |
70 | return self.contract.functions.proofMaturityDelaySeconds().call()
71 |
72 | def proven_withdrawls(self, withdrawl_hash, proof_submitter):
73 |
74 | return self.contract.functions.provenWithdrawals(withdrawl_hash, proof_submitter).call()
75 |
76 | class StandardBridge(Contract):
77 |
78 | def __init__(self, account, from_chain_id, to_chain_id, provider):
79 |
80 | self.l1_to_l2 = is_l1_to_l2(from_chain_id, to_chain_id)
81 |
82 | self.provider = provider
83 |
84 | if is_chain_supported(from_chain_id) is False:
85 | raise Exception(f"Origin Chain ID {from_chain_id} not supported: add it to the config.json file or open a request to add it.")
86 | if is_chain_supported(to_chain_id) is False:
87 | raise Exception(f"Destination Chain ID {to_chain_id} not supported: add it to the config.json file or open a request to add it.")
88 |
89 | if self.l1_to_l2:
90 | self.address = read_addresses(from_chain_id, to_chain_id, layer="l1")["L1_STANDARD_BRIDGE"]
91 | else:
92 | self.address = read_addresses(to_chain_id, from_chain_id, layer="l2")["L2_STANDARD_BRIDGE"]
93 |
94 | self.from_chain_id = from_chain_id
95 | self.to_chain_id = to_chain_id
96 |
97 | self.account = account
98 |
99 | if self.l1_to_l2:
100 | self.contract = self.provider.eth.contract(address=self.address, abi=load_abi("L1_STANDARD_BRIDGE"))
101 | else:
102 | self.contract = self.provider.eth.contract(address=self.address, abi=load_abi("L2_STANDARD_BRIDGE"))
103 |
104 | def deposit_eth_to(self, to, value, gas_limit, extra_data):
105 |
106 | if not self.l1_to_l2:
107 | raise Exception("This method can only be called on a L1 to L2 Bridge")
108 |
109 | deposit_eth_to_tx = self.contract.functions.depositETHTo(to, gas_limit, extra_data).build_transaction({
110 | "from": self.account.address,
111 | "gas": 500000,
112 | "nonce": self.provider.eth.get_transaction_count(self.account.address),
113 | "value": value
114 | })
115 |
116 | return self.sign_and_broadcast(deposit_eth_to_tx)
117 |
118 | def deposit_erc20(self, l1_token_address, l2_token_address, value, gas_limit, extra_data):
119 |
120 | if not self.l1_to_l2:
121 | raise Exception("This method can only be called on a L1 to L2 Bridge")
122 |
123 | deposit_erc20_tx = self.contract.functions.depositERC20(l1_token_address, l2_token_address, value, gas_limit, extra_data).build_transaction({
124 | "from": self.account.address,
125 | "gas": 700000,
126 | "nonce": self.provider.eth.get_transaction_count(self.account.address)
127 | })
128 |
129 | return self.sign_and_broadcast(deposit_erc20_tx)
130 |
131 | def deposit_erc20_to(self, l1_token_address, l2_token_address, to, value, gas_limit, extra_data):
132 |
133 | if not self.l1_to_l2:
134 | raise Exception("This method can only be called on a L1 to L2 Bridge")
135 |
136 | deposit_erc20_to_tx = self.contract.functions.depositERC20To(l1_token_address, l2_token_address, to, value, gas_limit, extra_data).build_transaction({
137 | "from": self.account.address,
138 | "gas": 700000,
139 | "nonce": self.provider.eth.get_transaction_count(self.account.address)
140 | })
141 |
142 | return self.sign_and_broadcast(deposit_erc20_to_tx)
143 |
144 |
145 | def withdraw_eth_to(self, to, value, gas_limit, extra_data):
146 |
147 | if self.l1_to_l2:
148 | raise Exception("This method can only be called on a L2 to L1 Bridge")
149 |
150 | withdraw_eth_to_tx = self.contract.functions.withdrawTo("0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000", to, value, gas_limit, extra_data).build_transaction({
151 | "from": self.account.address,
152 | "gas": 500000,
153 | "nonce": self.provider.eth.get_transaction_count(self.account.address),
154 | "value": value
155 | })
156 |
157 | return self.sign_and_broadcast(withdraw_eth_to_tx)
158 |
159 | def bridge_erc20(self, l1_token_address, l2_token_address, value, gas_limit, extra_data):
160 |
161 | if self.l1_to_l2:
162 | raise Exception("This method can only be called on a L2 to L1 Bridge")
163 |
164 | withdraw_erc20_tx = self.contract.functions.bridgeERC20(l2_token_address, l1_token_address, value, gas_limit, extra_data).build_transaction({
165 | "from": self.account.address,
166 | "gas": 500000,
167 | "nonce": self.provider.eth.get_transaction_count(self.account.address)
168 | })
169 |
170 | return self.sign_and_broadcast(withdraw_erc20_tx)
171 |
172 | def bridge_erc20_to(self, l1_token_address, l2_token_address, to, value, gas_limit, extra_data):
173 |
174 | if self.l1_to_l2:
175 | raise Exception("This method can only be called on a L2 to L1 Bridge")
176 |
177 | withdraw_erc20_to_tx = self.contract.functions.bridgeERC20To(l2_token_address, l1_token_address, to, value, gas_limit, extra_data).build_transaction({
178 | "from": self.account.address,
179 | "gas": 500000,
180 | "nonce": self.provider.eth.get_transaction_count(self.account.address)
181 | })
182 |
183 | class CrossChainMessengerContract(Contract):
184 |
185 | def __init__(self, account, from_chain_id, to_chain_id, provider):
186 |
187 | self.l1_to_l2 = is_l1_to_l2(from_chain_id, to_chain_id)
188 |
189 | self.provider = provider
190 |
191 | if is_chain_supported(from_chain_id) is False:
192 | raise Exception(f"Origin Chain ID {from_chain_id} not supported: add it to the config.json file or open a request to add it.")
193 | if is_chain_supported(to_chain_id) is False:
194 | raise Exception(f"Destination Chain ID {to_chain_id} not supported: add it to the config.json file or open a request to add it.")
195 |
196 | if self.l1_to_l2:
197 | self.address = read_addresses(from_chain_id, to_chain_id, layer="l1")["L1_CROSS_CHAIN_MESSENGER"]
198 | else:
199 | self.address = read_addresses(to_chain_id, from_chain_id, layer="l2")["L2_CROSS_CHAIN_MESSENGER"]
200 |
201 | self.from_chain_id = from_chain_id
202 | self.to_chain_id = to_chain_id
203 |
204 | self.account = account
205 |
206 | if self.l1_to_l2:
207 | self.contract = self.provider.eth.contract(address=self.address, abi=load_abi("L1_CROSS_MESSENGER"))
208 | else:
209 | self.contract = self.provider.eth.contract(address=self.address, abi=load_abi("L2_CROSS_MESSENGER"))
210 |
211 |
212 | def send_message(self, target, message, min_gas_limit, value=None):
213 |
214 | send_message_tx = self.contract.functions.sendMessage(target, message, min_gas_limit).build_transaction({
215 | "from": self.account.address,
216 | "gas": 500000,
217 | "nonce": self.provider.eth.get_transaction_count(self.account.address),
218 | "value": 0 if value is None else value
219 | })
220 |
221 | return self.sign_and_broadcast(send_message_tx)
222 |
223 | def message_nonce(self):
224 |
225 | return self.contract.functions.messageNonce().call()
226 |
227 |
228 | class L2OutputOracle():
229 |
230 | def __init__(self, chain_id_l1, chain_id_l2, account, provider):
231 |
232 | self.provider = provider
233 |
234 | if is_chain_supported(chain_id_l1) is False:
235 | raise Exception(f"Chain ID {chain_id_l1} not supported: add it to the config.json file or open a request to add it.")
236 | if is_chain_supported(chain_id_l2) is False:
237 | raise Exception(f"Chain ID {chain_id_l2} not supported: add it to the config.json file or open a request to add it.")
238 |
239 | self.address = read_addresses(chain_id_l1, chain_id_l2, layer="l1")["L2_OUTPUT_ORACLE"]
240 |
241 | self.account = account
242 |
243 | self.contract = self.provider.eth.contract(address=self.address, abi=load_abi("L2_OUTPUT_ORACLE"))
244 |
245 | def latest_output_index(self):
246 |
247 | return self.contract.functions.latestOutputIndex().call()
248 |
249 | def latest_block_number(self):
250 |
251 | return self.contract.functions.latestBlockNumber().call()
252 |
253 | def next_output_index(self):
254 |
255 | return self.contract.functions.nextOutputIndex().call()
256 |
257 | def get_l2_output_index_after(self, l2_block_nummer):
258 |
259 | return self.contract.functions.getL2OutputIndexAfter(l2_block_nummer).call()
260 |
261 | def get_l2_output_after(self, l2_block_number):
262 |
263 | output_root, timestamp, l2_block_number = self.contract.functions.getL2OutputAfter(l2_block_number).call()
264 |
265 | return output_root.hex(), timestamp, l2_block_number
266 |
267 | def get_l2_output(self, l2_output_index):
268 |
269 | output_root, timestamp, l2_block_number = self.contract.functions.getL2Output(l2_output_index).call()
270 |
271 | return output_root.hex(), timestamp, l2_block_number
272 |
273 | class DisputeGameFactory(Contract):
274 |
275 | def __init__(self, chain_id_l1, chain_id_l2, provider):
276 |
277 | self.provider = provider
278 |
279 | if is_chain_supported(chain_id_l1) is False:
280 | raise Exception(f"Chain ID {chain_id_l1} not supported: add it to the config.json file or open a request to add it.")
281 | if is_chain_supported(chain_id_l2) is False:
282 | raise Exception(f"Chain ID {chain_id_l2} not supported: add it to the config.json file or open a request to add it.")
283 |
284 | self.address = read_addresses(chain_id_l1, chain_id_l2, layer="l1")["DISPUTE_GAME_FACTORY"]
285 |
286 | self.contract = self.provider.eth.contract(address=self.address, abi=load_abi("DISPUTE_GAME_FACTORY"))
287 |
288 | def game_count(self):
289 |
290 | return self.contract.functions.gameCount().call()
291 |
292 | def game_at_index(self, index):
293 |
294 | return self.contract.functions.gameAtIndex(index).call()
295 |
296 |
297 | class FaultDisputeGame(Contract):
298 |
299 | def __init__(self, address, provider):
300 |
301 | self.provider = provider
302 |
303 | self.address = address
304 |
305 | self.contract = self.provider.eth.contract(address=self.address, abi=load_abi("FAULT_DISPUTE_GAME"))
306 |
307 | def root_claim(self):
308 |
309 | return self.contract.functions.rootClaim().call()
310 |
311 | def l2_block_number(self):
312 |
313 | return self.contract.functions.l2BlockNumber().call()
314 |
315 | class L2ToL1MessagePasser(Contract):
316 |
317 | def __init__(self, chain_id_l1, chain_id_l2, account, provider):
318 |
319 | self.provider = provider
320 |
321 | self.address = read_addresses(chain_id_l1, chain_id_l2, layer="l2")["L2_TO_L1_MESSAGE_PASSER"]
322 |
323 | self.account = account
324 |
325 | self.contract = self.provider.eth.contract(address=self.address, abi=load_abi("L2_TO_L1_MESSAGE_PASSER"))
326 |
327 | def initiate_withdrawl(self, to, gas_limit, data, value):
328 |
329 | initiate_withdrawl_tx = self.contract.functions.initiateWithdrawal(to, gas_limit, data).build_transaction({
330 | "from": self.account.address,
331 | "gas": 100000,
332 | "nonce": self.provider.eth.get_transaction_count(self.account.address),
333 | "value": value
334 | })
335 |
336 | return self.sign_and_broadcast(initiate_withdrawl_tx)
--------------------------------------------------------------------------------
/optimism/cross_chain_messenger.py:
--------------------------------------------------------------------------------
1 | from .constants import OUTPUT_ROOT_PROOF_VERSION
2 |
3 | from .types import MessageStatus, OutputRootProof, BedrockMessageProof, Chains
4 | from .utils import to_low_level_message, make_state_trie_proof, hash_message_hash, read_addresses, load_abi
5 | from .contracts import L2ToL1MessagePasser, DisputeGameFactory, FaultDisputeGame, OptimismPortal, CrossChainMessengerContract, StandardBridge
6 |
7 | class CrossChainMessenger():
8 |
9 | def __init__(self, chain_l1, chain_l2, account_l1, account_l2, provider_l1, provider_l2):
10 |
11 | if isinstance(chain_l1, Chains) and isinstance(chain_l2, Chains):
12 | self.chain_id_l1 = chain_l1.chain_id()
13 | self.chain_id_l2 = chain_l2.chain_id()
14 | else:
15 | self.chain_id_l1 = chain_l1
16 | self.chain_id_l2 = chain_l2
17 |
18 | self.provider_l1 = provider_l1
19 | self.provider_l2 = provider_l2
20 |
21 | self.account_l1 = account_l1
22 | self.account_l2 = account_l2
23 |
24 | self.l1_cross_chain_messenger = CrossChainMessengerContract(account_l1, self.chain_id_l1, self.chain_id_l2, provider=provider_l1)
25 | self.l2_cross_chain_messenger = CrossChainMessengerContract(account_l2, self.chain_id_l2, self.chain_id_l1, provider=provider_l2)
26 |
27 | self.l1_bridge = StandardBridge(account_l1, from_chain_id=self.chain_id_l1, to_chain_id=self.chain_id_l2, provider=provider_l1)
28 | self.l2_bridge = StandardBridge(account_l2, from_chain_id=self.chain_id_l2, to_chain_id=self.chain_id_l1, provider=provider_l2)
29 |
30 | def deposit_eth(self, value):
31 |
32 | return self.l1_cross_chain_messenger.send_message(self.account_l1.address, b"", 0, value)
33 |
34 | def deposit_eth_to(self, to, value):
35 |
36 | return self.l1_cross_chain_messenger.send_message(to, b"", 0, value)
37 |
38 | def deposit_erc20(self, token_address_l1, token_address_l2, value):
39 |
40 | if not self._supports_token_pair(token_address_l1, token_address_l2):
41 | raise Exception("Token pair not supported")
42 |
43 | return self.l1_bridge.deposit_erc20(token_address_l1, token_address_l2, value, 0, b"")
44 |
45 | def deposit_erc20_to(self, token_address_l1, token_address_l2, to, value):
46 |
47 | if not self._supports_token_pair(token_address_l1, token_address_l2):
48 | raise Exception("Token pair not supported")
49 |
50 | return self.l1_bridge.deposit_erc20_to(token_address_l1, token_address_l2, to, value, 0, b"")
51 |
52 | def approve_erc20(self, token_address_l1, token_address_l2, value):
53 |
54 | if not self._supports_token_pair(token_address_l1, token_address_l2):
55 | raise Exception("Token pair not supported")
56 |
57 | token_contract_l1 = self.provider_l1.eth.contract(address=token_address_l1, abi=load_abi("ERC20"))
58 |
59 | approve_tx = token_contract_l1.functions.approve(self.l1_bridge.address, value).build_transaction({
60 | "from": self.account_l1.address,
61 | "nonce": self.provider_l1.eth.get_transaction_count(self.account_l1.address)
62 | })
63 |
64 | signed_txn = self.provider_l1.eth.account.sign_transaction(approve_tx, self.account_l1.key)
65 | txn_hash = self.provider_l1.eth.send_raw_transaction(signed_txn.rawTransaction)
66 | txn_receipt = self.provider_l1.eth.wait_for_transaction_receipt(txn_hash)
67 |
68 | return txn_hash.hex(), txn_receipt
69 |
70 |
71 | def withdraw_eth(self, value):
72 |
73 | l2_to_l1_message_passer = L2ToL1MessagePasser(self.chain_id_l1, self.chain_id_l2, self.account_l2, provider=self.provider_l2)
74 |
75 | return l2_to_l1_message_passer.initiate_withdrawl(self.account_l2.address, 0, b"", value)
76 |
77 | def withdraw_eth_to(self, to, value):
78 |
79 | l2_to_l1_message_passer = L2ToL1MessagePasser(self.chain_id_l1, self.chain_id_l2, self.account_l2, provider=self.provider_l2)
80 |
81 | return l2_to_l1_message_passer.initiate_withdrawl(to, 0, b"", value)
82 |
83 | def withdraw_erc20(self, token_address_l1, token_address_l2, value):
84 |
85 | if not self._supports_token_pair(token_address_l1, token_address_l2):
86 | raise Exception("Token pair not supported")
87 |
88 | return self.l2_bridge.bridge_erc20(token_address_l1, token_address_l2, value, 0, b"")
89 |
90 | def withdraw_erc20_to(self, token_address_l1, token_address_l2, to, value):
91 |
92 | if not self._supports_token_pair(token_address_l1, token_address_l2):
93 | raise Exception("Token pair not supported")
94 |
95 | return self.l2_bridge.bridge_erc20_to(token_address_l1, token_address_l2, to, value, 0, b"")
96 |
97 | def prove_message(self, l2_txn_hash):
98 |
99 | l2_txn = self.provider_l2.eth.get_transaction(l2_txn_hash)
100 | l2_txn_receipt = self.provider_l2.eth.get_transaction_receipt(l2_txn_hash)
101 |
102 | withdrawl_message, withrawl_message_hash = to_low_level_message(l2_txn, l2_txn_receipt)
103 | message_proof = self.get_bedrock_message_proof(l2_txn, withrawl_message_hash)
104 |
105 | optimism_portal = OptimismPortal(self.chain_id_l1, self.chain_id_l2, self.account_l1, provider=self.provider_l1)
106 | return optimism_portal.prove_withdrawl_transaction(withdrawl_message.values(), message_proof.get_dispute_game_index(), message_proof.get_output_root_proof(), message_proof.get_withdrawl_proof())
107 |
108 | def finalize_message(self, l2_txn_hash):
109 |
110 | l2_txn = self.provider_l2.eth.get_transaction(l2_txn_hash)
111 | l2_txn_receipt = self.provider_l2.eth.get_transaction_receipt(l2_txn_hash)
112 |
113 | withdrawl_message, withrawl_message_hash = to_low_level_message(l2_txn, l2_txn_receipt)
114 |
115 | optimism_portal = OptimismPortal(self.chain_id_l1, self.chain_id_l2, self.account_l1, provider=self.provider_l1)
116 | return optimism_portal.finalize_withdrawl_transaction(tuple(withdrawl_message.values()))
117 |
118 |
119 | def get_bedrock_message_proof(self, txn, withdrawl_hash):
120 |
121 | l2_block_number = txn.blockNumber
122 |
123 | dispute_game_factory = DisputeGameFactory(self.chain_id_l1, self.chain_id_l2, provider=self.provider_l1)
124 | game_count = dispute_game_factory.game_count()
125 |
126 | game_index = game_count - 1
127 |
128 | latest_game_type, latest_game_timestamp, latest_game_address = dispute_game_factory.game_at_index(game_index)
129 |
130 | fault_dispute_game = FaultDisputeGame(latest_game_address, self.provider_l1)
131 | l2_block_number = fault_dispute_game.l2_block_number()
132 |
133 | message_slot = hash_message_hash(withdrawl_hash)
134 |
135 | state_trie_proof = make_state_trie_proof(self.provider_l2, l2_block_number, read_addresses(self.chain_id_l1, self.chain_id_l2, layer="l2")["L2_TO_L1_MESSAGE_PASSER"], message_slot)
136 | block = self.provider_l2.eth.get_block(l2_block_number)
137 |
138 | output_root_proof = OutputRootProof(version=OUTPUT_ROOT_PROOF_VERSION,
139 | state_root=block.stateRoot.hex(),
140 | message_passer_storage_root=state_trie_proof.storage_root.hex(),
141 | latest_blockhash=block.hash.hex())
142 |
143 | bedrock_message_proof = BedrockMessageProof(output_root_proof=output_root_proof,
144 | withdrawl_proof=[el.hex() for el in state_trie_proof.storage_proof],
145 | dispute_game_index=game_index)
146 |
147 | return bedrock_message_proof
148 |
149 | def get_message_status(self, txn_hash):
150 |
151 | l1_to_l2 = True
152 |
153 | try:
154 | txn = self.provider_l1.eth.get_transaction(txn_hash)
155 | txn_receipt = self.provider_l1.eth.get_transaction_receipt(txn_hash)
156 | except:
157 | txn = self.provider_l2.eth.get_transaction(txn_hash)
158 | txn_receipt = self.provider_l2.eth.get_transaction_receipt(txn_hash)
159 | l1_to_l2 = False
160 |
161 | if l1_to_l2:
162 | if txn_receipt is None:
163 | return MessageStatus.UNCONFIRMED_L1_TO_L2_MESSAGE
164 | else:
165 | if txn_receipt.status == 1:
166 | return MessageStatus.RELAYED
167 | else:
168 | return MessageStatus.FAILED_L1_TO_L2_MESSAGE
169 | else:
170 | if txn_receipt is None:
171 | return MessageStatus.UNCONFIRMED_L2_TO_L1_MESSAGE
172 | else:
173 | if txn_receipt.status == 1:
174 |
175 | dispute_game_factory = DisputeGameFactory(self.chain_id_l1, self.chain_id_l2, provider=self.provider_l1)
176 | game_count = dispute_game_factory.game_count()
177 |
178 | game_index = game_count - 1
179 |
180 | latest_game_type, latest_game_timestamp, latest_game_address = dispute_game_factory.game_at_index(game_index)
181 |
182 | fault_dispute_game = FaultDisputeGame(latest_game_address, self.provider_l1)
183 | latest_block_number = fault_dispute_game.l2_block_number()
184 |
185 | try:
186 | _, message_hash = to_low_level_message(txn, txn_receipt)
187 | except:
188 | raise Exception("Transaction is not a valid L2 to L1 message")
189 |
190 | if int(latest_block_number) < int(txn.blockNumber):
191 | return MessageStatus.STATE_ROOT_NOT_PUBLISHED
192 | else:
193 | optimism_portal = OptimismPortal(self.chain_id_l1, self.chain_id_l2, self.account_l1, provider=self.provider_l1)
194 | proven = optimism_portal.proven_withdrawls(message_hash, txn["from"])
195 | if proven[-1] == 0:
196 | return MessageStatus.READY_TO_PROVE
197 | else:
198 | current_timestamp = self.provider_l2.eth.get_block(self.provider_l2.eth.block_number).timestamp
199 | if current_timestamp > proven[1] + optimism_portal.proof_maturity_delay_seconds():
200 | return MessageStatus.READY_FOR_RELAY
201 | else:
202 | return MessageStatus.IN_CHALLENGE_PERIOD
203 | else:
204 | return MessageStatus.FAILED_L2_TO_L1_MESSAGE
205 |
206 | def get_erc20_deposits_by_address(self, address, from_block=0, to_block="latest"):
207 |
208 | """
209 | Returns a list of ERC20 deposits initiated by the given address
210 | """
211 |
212 | events = self.l1_bridge.contract.events.ERC20DepositInitiated.create_filter(
213 | fromBlock=from_block,
214 | toBlock=to_block,
215 | argument_filters={'from': address}
216 | ).get_all_entries()
217 |
218 | token_bridge_messages = []
219 |
220 | for event in events:
221 |
222 | message = {
223 | 'direction': 'L1_TO_L2',
224 | 'from': event.args['from'],
225 | 'to': event.args['to'],
226 | 'l1Token': event.args['l1Token'],
227 | 'l2Token': event.args['l2Token'],
228 | 'amount': event.args['amount'],
229 | 'data': event.args['extraData'],
230 | 'logIndex': event.logIndex,
231 | 'blockNumber': event.blockNumber,
232 | 'transactionHash': event.transactionHash.hex()
233 | }
234 | token_bridge_messages.append(message)
235 |
236 | token_bridge_messages.sort(key=lambda x: x['blockNumber'], reverse=True)
237 |
238 | return token_bridge_messages
239 |
240 | def get_eth_deposits_by_address(self, address, from_block=0, to_block="latest"):
241 |
242 | """
243 | Returns a list of ETH deposits initiated by the given address
244 | """
245 |
246 | events = self.l1_bridge.contract.events.ETHDepositInitiated.create_filter(
247 | fromBlock=from_block,
248 | toBlock=to_block,
249 | argument_filters={'from': address}
250 | ).get_all_entries()
251 |
252 | eth_bridge_messages = []
253 |
254 | for event in events:
255 |
256 | message = {
257 | 'direction': 'L1_TO_L2',
258 | 'from': event.args['from'],
259 | 'to': event.args['to'],
260 | 'amount': event.args['amount'],
261 | 'data': event.args['extraData'],
262 | 'logIndex': event.logIndex,
263 | 'blockNumber': event.blockNumber,
264 | 'transactionHash': event.transactionHash.hex()
265 | }
266 | eth_bridge_messages.append(message)
267 |
268 | eth_bridge_messages.sort(key=lambda x: x['blockNumber'], reverse=True)
269 |
270 | return eth_bridge_messages
271 |
272 | def get_erc20_withdrawals_by_address(self, address, from_block=0, to_block='latest'):
273 |
274 | """
275 | Returns a list of ERC20 withdrawals initiated by the given address
276 | """
277 |
278 | events = self.l2_bridge.contract.events.ERC20BridgeInitiated.create_filter(
279 | fromBlock=from_block,
280 | toBlock=to_block,
281 | argument_filters={'from': address}
282 | ).get_all_entries()
283 |
284 | token_bridge_messages = []
285 |
286 | for event in events:
287 |
288 | message = {
289 | 'direction': 'L2_TO_L1',
290 | 'from': event.args['from'],
291 | 'to': event.args['to'],
292 | 'l1Token': event.args['remoteToken'],
293 | 'l2Token': event.args['localToken'],
294 | 'amount': event.args['amount'],
295 | 'data': event.args['extraData'],
296 | 'logIndex': event.logIndex,
297 | 'blockNumber': event.blockNumber,
298 | 'transactionHash': event.transactionHash.hex()
299 | }
300 | token_bridge_messages.append(message)
301 |
302 | token_bridge_messages.sort(key=lambda x: x['blockNumber'], reverse=True)
303 |
304 | return token_bridge_messages
305 |
306 | def get_eth_withdrawals_by_address(self, address, from_block=0, to_block='latest'):
307 |
308 | """
309 | Returns a list of ETH withdrawals initiated by the given address
310 | """
311 |
312 | events = self.l2_bridge.contract.events.ETHBridgeInitiated.create_filter(
313 | fromBlock=from_block,
314 | toBlock=to_block,
315 | argument_filters={'from': address}
316 | ).get_all_entries()
317 |
318 | eth_bridge_messages = []
319 |
320 | for event in events:
321 |
322 | message = {
323 | 'direction': 'L2_TO_L1',
324 | 'from': event.args['from'],
325 | 'to': event.args['to'],
326 | 'amount': event.args['amount'],
327 | 'data': event.args['extraData'],
328 | 'logIndex': event.logIndex,
329 | 'blockNumber': event.blockNumber,
330 | 'transactionHash': event.transactionHash.hex()
331 | }
332 | eth_bridge_messages.append(message)
333 |
334 | eth_bridge_messages.sort(key=lambda x: x['blockNumber'], reverse=True)
335 |
336 | return eth_bridge_messages
337 |
338 | def estimate_l2_gas_limit(self, message):
339 | raise NotImplementedError
340 |
341 | def estimate_message_wait_time_seconds(self, message):
342 | raise NotImplementedError
343 |
344 | def get_challenge_period_seconds(self):
345 | raise NotImplementedError
346 |
347 | def get_proven_withdrawl(self):
348 | raise NotImplementedError
349 |
350 | def get_message_state_root(self):
351 | raise NotImplementedError
352 |
353 | def get_state_batch_appended_event_by_batch_index(self):
354 | raise NotImplementedError
355 |
356 | def get_state_batch_appended_event_by_transaction_index(self):
357 | raise NotImplementedError
358 |
359 | def get_state_root_batch_by_transaction_index(self):
360 | raise NotImplementedError
361 |
362 | def _supports_token_pair(self, token_address_l1, token_address_l2):
363 |
364 | token_contract_l2 = self.provider_l2.eth.contract(address=token_address_l2, abi=load_abi("OPTIMISM_ERC20"))
365 | try:
366 | l1_token = token_contract_l2.functions.l1Token().call()
367 | except:
368 | raise Exception(f"Token Contract {token_address_l2} is not an Optimism ERC20")
369 |
370 | return l1_token == token_address_l1
--------------------------------------------------------------------------------
/optimism/types.py:
--------------------------------------------------------------------------------
1 | from enum import Enum
2 |
3 | class MessageStatus(Enum):
4 | UNCONFIRMED_L1_TO_L2_MESSAGE = 0
5 | UNCONFIRMED_L2_TO_L1_MESSAGE = 1
6 | FAILED_L1_TO_L2_MESSAGE = 2
7 | FAILED_L2_TO_L1_MESSAGE = 3
8 | STATE_ROOT_NOT_PUBLISHED = 4
9 | READY_TO_PROVE = 5
10 | IN_CHALLENGE_PERIOD = 6
11 | READY_FOR_RELAY = 7
12 | RELAYED = 8
13 |
14 | class ChainInfo:
15 | def __init__(self, chain_id, layer):
16 | self.chain_id = chain_id
17 | self.layer = layer
18 |
19 | class Chains(Enum):
20 | ETHEREUM_MAINNET = ChainInfo(1, 'L1')
21 | OPTIMISM_MAINNET = ChainInfo(10, 'L2')
22 | BASE_MAINNET = ChainInfo(8453, 'L2')
23 |
24 | ETHEREUM_SEPOLIA = ChainInfo(11155111, 'L1')
25 | OPTIMISM_SEPOLIA = ChainInfo(11155420, 'L2')
26 | BASE_SEPOLIA = ChainInfo(84532, 'L2')
27 |
28 | def chain_id(self):
29 | return self.value.chain_id
30 |
31 | def layer(self):
32 | return self.value.layer
33 |
34 | class StateTrieProof():
35 |
36 | def __init__(self, account_proof, storage_proof, storage_value, storage_root):
37 |
38 | self.account_proof = account_proof
39 | self.storage_proof = storage_proof
40 | self.storage_value = storage_value
41 | self.storage_root = storage_root
42 |
43 | def __str__(self):
44 |
45 | return f"StateTrieProof(account_proof={self.account_proof}, storage_proof={self.storage_proof}, storage_value={self.storage_value}, storage_root={self.storage_root})"
46 |
47 | class MessagePassedEvent():
48 |
49 | def __init__(self, message_nonce, sender, target, value, min_gas_limit, message):
50 |
51 | self.message_nonce = message_nonce
52 | self.sender = sender
53 | self.target = target
54 | self.value = value
55 | self.min_gas_limit = min_gas_limit
56 | self.message = message
57 |
58 | def __str__(self):
59 |
60 | return f"MessagePassedEvent(message_nonce={self.message_nonce}, sender={self.sender}, target={self.target}, value={self.value}, min_gas_limit={self.min_gas_limit}, message={self.message})"
61 |
62 | def values(self):
63 |
64 | return (self.message_nonce, self.sender, self.target, self.value, self.min_gas_limit, self.message)
65 |
66 | class OutputRootProof():
67 |
68 | def __init__(self, version, state_root, message_passer_storage_root, latest_blockhash):
69 |
70 | self.version = version
71 | self.state_root = state_root
72 | self.message_passer_storage_root = message_passer_storage_root
73 | self.latest_blockhash = latest_blockhash
74 |
75 | def __str__(self):
76 |
77 | return f"OutputRootProof(version={self.version}, state_root={self.state_root}, message_passer_storage_root={self.message_passer_storage_root}, latest_blockhash={self.latest_blockhash})"
78 |
79 | def values(self):
80 |
81 | return (self.version, self.state_root, self.message_passer_storage_root, self.latest_blockhash)
82 |
83 |
84 | class BedrockMessageProof():
85 |
86 | def __init__(self, output_root_proof, withdrawl_proof, dispute_game_index):
87 |
88 | self.output_root_proof = output_root_proof
89 | self.withdrawl_proof = withdrawl_proof
90 | self.dispute_game_index = dispute_game_index
91 |
92 | def __str__(self):
93 |
94 | return f"BedrockMessageProof(output_root_proof={self.output_root_proof}, withdrawl_proof={self.withdrawl_proof}, dispute_game_index={self.dispute_game_index})"
95 |
96 | def get_dispute_game_index(self):
97 |
98 | return self.dispute_game_index
99 |
100 | def get_output_root_proof(self):
101 |
102 | return self.output_root_proof.values()
103 |
104 | def get_withdrawl_proof(self):
105 |
106 | return tuple(self.withdrawl_proof)
107 |
--------------------------------------------------------------------------------
/optimism/utils.py:
--------------------------------------------------------------------------------
1 | import os
2 | import json
3 |
4 | from web3 import Web3
5 |
6 | from .constants import MESSAGE_PASSED_ID
7 | from .types import MessagePassedEvent, StateTrieProof, Chains
8 |
9 | def get_env_variable(var_name):
10 | return os.environ.get(var_name)
11 |
12 | def load_abi(name: str) -> str:
13 |
14 | abi = name.lower()
15 |
16 | path = f"{os.path.dirname(os.path.abspath(__file__))}/assets/"
17 | with open(os.path.abspath(path + f"{abi}.json")) as f:
18 | abi: str = json.load(f)
19 | return abi
20 |
21 | def is_l1_to_l2(from_chain_id, to_chain_id):
22 |
23 | chain_id_to_info = {chain.value.chain_id: chain.value.layer for chain in Chains}
24 |
25 | if chain_id_to_info.get(from_chain_id) == "L1" and chain_id_to_info.get(to_chain_id) == "L2":
26 | return True
27 | elif chain_id_to_info.get(from_chain_id) == "L2" and chain_id_to_info.get(to_chain_id) == "L1":
28 | return False
29 | else:
30 | raise ValueError("Invalid chain ids")
31 |
32 | def hash_message_hash(message_hash: str) -> str:
33 | # Web3 provides utility functions similar to ethers
34 | w3 = Web3()
35 |
36 | # These are equivalent constants in web3.py for ethers.constants.HashZero
37 | HASH_ZERO = int('0x0000000000000000000000000000000000000000000000000000000000000000', 16)
38 |
39 | # Use solidityKeccak for both encoding and hashing
40 | return w3.solidity_keccak(['bytes32', 'uint256'], [message_hash, HASH_ZERO]).hex()
41 |
42 | def log_to_address(log):
43 |
44 | return Web3.to_checksum_address("0x" + log[-40:])
45 |
46 | def to_low_level_message(txn, txn_receipt):
47 |
48 | logs = txn_receipt.logs
49 |
50 | for log in logs:
51 | if log.topics[0].hex() == MESSAGE_PASSED_ID:
52 | message_passed_log = log
53 | break
54 |
55 | message_length = int(message_passed_log.data[128:160].hex(), 16)
56 |
57 | return MessagePassedEvent(
58 | message_nonce=int(message_passed_log.topics[1].hex(), 16),
59 | sender=log_to_address(message_passed_log.topics[2].hex()),
60 | target=log_to_address(message_passed_log.topics[3].hex()),
61 | value=int(message_passed_log.data[:32].hex(), 16),
62 | min_gas_limit=int(message_passed_log.data[32:64].hex(), 16),
63 | message=message_passed_log.data[160:160 + message_length].hex()
64 | ), message_passed_log.data[96:128].hex()
65 |
66 | def make_state_trie_proof(provider, block_number, address, slot):
67 |
68 | proof = provider.eth.get_proof(address, [slot], block_identifier=block_number)
69 |
70 | return StateTrieProof(
71 | account_proof=proof.accountProof,
72 | storage_proof=proof.storageProof[0].proof,
73 | storage_value=proof.storageProof[0].value,
74 | storage_root=proof.storageHash
75 | )
76 |
77 | def is_chain_supported(chain_id):
78 |
79 | l1_chain_ids = get_l1_chain_ids()
80 | l2_chain_ids = get_l2_chain_ids()
81 |
82 | return str(chain_id) in l1_chain_ids or str(chain_id) in l2_chain_ids
83 |
84 | def read_addresses(chain_id_l1, chain_id_l2, layer="l1"):
85 |
86 | path = f"{os.path.dirname(os.path.abspath(__file__))}"
87 | with open(os.path.abspath(path + f"/config.json")) as f:
88 | addresses: dict = json.load(f)
89 |
90 | return addresses[str(chain_id_l1)][str(chain_id_l2)][layer + "_addresses"]
91 |
92 |
93 | def get_l1_chain_ids():
94 | path = f"{os.path.dirname(os.path.abspath(__file__))}"
95 | with open(os.path.abspath(path + f"/config.json")) as f:
96 | addresses: dict = json.load(f)
97 |
98 | return addresses.keys()
99 |
100 | def get_l2_chain_ids():
101 | path = f"{os.path.dirname(os.path.abspath(__file__))}"
102 | with open(os.path.abspath(path + f"/config.json")) as f:
103 | addresses: dict = json.load(f)
104 |
105 | l1_chain_ids = addresses.keys()
106 | l2_chain_ids = []
107 | for id in l1_chain_ids:
108 | l2_chain_ids += addresses[id].keys()
109 |
110 | return l2_chain_ids
111 |
112 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.poetry]
2 | name = "optimism-python"
3 | version = "0.3.1"
4 | description = "Unofficial Python Client for the OP-Stack"
5 | authors = ["rafalum "]
6 | license = "MIT"
7 | repository = "https://github.com/rafalum/optimism-python"
8 | readme = "README.md"
9 | packages = [
10 | { include = "optimism" },
11 | ]
12 | include = ["optimism/assets/*.abi", "optimism/assets/*.json", "op.png"]
13 |
14 | [tool.poetry.dependencies]
15 | python = "^3.11"
16 | web3 = "6.11.1"
17 | python-dotenv = "1.0.0"
18 |
19 |
20 | [build-system]
21 | requires = ["poetry-core"]
22 | build-backend = "poetry.core.masonry.api"
23 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | web3=="6.11.1"
2 | python-dotenv=="1.0.0"
--------------------------------------------------------------------------------
/test/README.md:
--------------------------------------------------------------------------------
1 | # Testing
2 |
3 | Testing is done by spinning up a local dev node in a QEMU VM and running the tests against it. Follow [this guide](https://github.com/rafalum/optimism-local-devnet) to setup your local dev net and place the .qcow2 file in the root of this directory. Further make the binaries `start_devnet` and `stop_devnet` available in your path.
4 |
5 | Then, run the tests with:
6 | ```bash
7 | python -m unittest discover -s test -p 'test_*.py'
8 | ```
9 |
10 |
--------------------------------------------------------------------------------
/test/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rafalum/optimism-python/48a25b021c5b7c16cfca8f96a09553765acd1c0c/test/__init__.py
--------------------------------------------------------------------------------
/test/extract_addresses.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 | # Load the JSON data from the new file
4 | with open('/home/sandbox/optimism/packages/contracts-bedrock/deployments/31337-deploy.json') as f:
5 | data = json.load(f)
6 |
7 | # Extract the addresses based on the keys provided in the new JSON file
8 | addresses = {
9 | "OPTIMISM_PORTAL": data.get("OptimismPortal2"),
10 | "L1_STANDARD_BRIDGE": data.get("L1StandardBridgeProxy"),
11 | "L1_CROSS_CHAIN_MESSENGER": data.get("L1CrossDomainMessengerProxy"),
12 | "L2_OUTPUT_ORACLE": data.get("L2OutputOracleProxy"),
13 | "DISPUTE_GAME_FACTORY": data.get("DisputeGameFactoryProxy")
14 | }
15 |
16 | # Print the addresses
17 | print(addresses)
18 |
--------------------------------------------------------------------------------
/test/test_deposit.py:
--------------------------------------------------------------------------------
1 | import os
2 | import time
3 | import json
4 | import signal
5 | import psutil
6 | import unittest
7 | import subprocess
8 |
9 | from web3 import Web3
10 | from web3.middleware import geth_poa_middleware
11 |
12 | from optimism import CrossChainMessenger
13 |
14 | from test.utils import TestUtil
15 |
16 | class TestDeposit(unittest.TestCase, TestUtil):
17 |
18 | def setUp(self) -> None:
19 |
20 | self.node_process = subprocess.Popen(["start_devnet", "devnode"])
21 |
22 | if self.node_process.returncode == None:
23 | print("Local dev net started successfully")
24 | else:
25 | print(f"Error starting local dev net. Exit code: {self.node_process.returncode}")
26 |
27 | time.sleep(40)
28 |
29 | subprocess.Popen(["sshpass", "-p", "sandbox", "ssh", "-o", "IdentitiesOnly=yes", "-t", "sandbox@127.0.0.1", "-p", "10022", "cd ~/optimism && make devnet-up"])
30 |
31 | time.sleep(40)
32 |
33 | vm_process = subprocess.Popen(["sshpass", "-p", "sandbox", "ssh", "-o", "IdentitiesOnly=yes", "-t", "sandbox@127.0.0.1", "-p", "10022", "python3 extract_addresses.py"], stdout=subprocess.PIPE)
34 |
35 | output, error = vm_process.communicate()
36 | if error:
37 | print(f"Error: {error}")
38 | else:
39 | l1_addresses_devnet = json.loads(output.decode().split("\r\n")[-2].strip("\r\n").replace("'", "\""))
40 |
41 | with open("optimism/config.json", 'r') as file:
42 | addresses = json.load(file)
43 |
44 | addresses["900"]["901"]["l1_addresses"] = l1_addresses_devnet
45 |
46 | with open("optimism/config.json", 'w') as json_file:
47 | json.dump(addresses, json_file, indent=4)
48 |
49 | subprocess.Popen(["sshpass", "-p", "sandbox", "ssh", "-o", "IdentitiesOnly=yes", "-t", "sandbox@127.0.0.1", "-p", "10022", f"echo 'export L2OO_ADDRESS={l1_addresses_devnet['L2_OUTPUT_ORACLE']}' >> '/home/sandbox/.bashrc'"])
50 | subprocess.Popen(["sshpass", "-p", "sandbox", "ssh", "-o", "IdentitiesOnly=yes", "-t", "sandbox@127.0.0.1", "-p", "10022", f"echo 'export DGF_ADDRESS={l1_addresses_devnet['DISPUTE_GAME_FACTORY']}' >> '/home/sandbox/.bashrc'"])
51 | subprocess.Popen(["sshpass", "-p", "sandbox", "ssh", "-o", "IdentitiesOnly=yes", "-t", "sandbox@127.0.0.1", "-p", "10022", f"echo 'export DG_TYPE=0' >> '/home/sandbox/.bashrc'"])
52 | subprocess.Popen(["sshpass", "-p", "sandbox", "ssh", "-o", "IdentitiesOnly=yes", "-t", "sandbox@127.0.0.1", "-p", "10022", f"cd ~/optimism && python3 bedrock-devnet/main.py"])
53 |
54 | time.sleep(20)
55 |
56 | self.l1_provider = Web3(Web3.HTTPProvider("http://127.0.0.1:8545"))
57 | self.l2_provider = Web3(Web3.HTTPProvider("http://127.0.0.1:9545"))
58 |
59 | self.l1_provider.middleware_onion.inject(geth_poa_middleware, layer=0)
60 | self.l2_provider.middleware_onion.inject(geth_poa_middleware, layer=0)
61 |
62 | self.faucet = self.l1_provider.eth.account.from_key("0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80")
63 |
64 | self.account = self.l1_provider.eth.account.from_key("0x" + "1" * 64)
65 |
66 | self.fund_account(self.account, 10**18, layer="l1")
67 |
68 |
69 |
70 | def tearDown(self) -> None:
71 | print("Tearing down devnet")
72 |
73 | subprocess.Popen(["sshpass", "-p", "sandbox", "ssh", "-o", "IdentitiesOnly=yes", "-t", "sandbox@127.0.0.1", "-p", "10022", "cd ~/optimism && make devnet-down"])
74 | time.sleep(30)
75 | subprocess.Popen(["sshpass", "-p", "sandbox", "ssh", "-o", "IdentitiesOnly=yes", "-t", "sandbox@127.0.0.1", "-p", "10022", "cd ~/optimism && make devnet-clean"])
76 | time.sleep(30)
77 | subprocess.Popen(["sshpass", "-p", "sandbox", "ssh", "-o", "IdentitiesOnly=yes", "-t", "sandbox@127.0.0.1", "-p", "10022", "sudo poweroff"])
78 | time.sleep(10)
79 |
80 | node_process_pid = self.node_process.pid
81 |
82 | parent_process = psutil.Process(node_process_pid)
83 | child_processes = parent_process.children(recursive=True)
84 |
85 | self.node_process.terminate()
86 |
87 | # kill all child processes
88 | for child in child_processes:
89 | if parent_process.pid != child.pid:
90 | os.kill(child.pid, signal.SIGTERM)
91 |
92 |
93 | def testDepositETH(self):
94 |
95 | l1_chain_id = 900
96 | l2_chain_id = 901
97 |
98 | cross_chain_messenger = CrossChainMessenger(l1_chain_id, l2_chain_id, account_l1=self.account, account_l2=self.account, provider_l1=self.l1_provider, provider_l2=self.l2_provider)
99 |
100 | balance_l1 = self.l1_provider.eth.get_balance(self.account.address)
101 | balance_l2 = self.l2_provider.eth.get_balance(self.account.address)
102 |
103 | self.assertEqual(balance_l1, 10**18)
104 | self.assertEqual(balance_l2, 0)
105 |
106 | deposit_txn_hash, deposit_txn_receipt = cross_chain_messenger.deposit_eth(5*10**17)
107 |
108 | time.sleep(30)
109 |
110 | balance_l1 = self.l1_provider.eth.get_balance(self.account.address)
111 | balance_l2 = self.l2_provider.eth.get_balance(self.account.address)
112 |
113 | self.assertGreater(balance_l1, 0.498*10**18)
114 | self.assertLess(balance_l1, 0.5*10**18)
115 |
116 | self.assertEqual(balance_l2, 0.5*10**18)
117 |
118 |
119 |
120 |
121 |
122 |
123 |
--------------------------------------------------------------------------------
/test/test_withdrawl.py:
--------------------------------------------------------------------------------
1 | import os
2 | import time
3 | import json
4 | import signal
5 | import psutil
6 | import unittest
7 | import subprocess
8 |
9 | from web3 import Web3
10 | from web3.middleware import geth_poa_middleware
11 |
12 | from optimism import CrossChainMessenger
13 | from optimism.types import MessageStatus
14 |
15 | from test.utils import TestUtil
16 |
17 | class TestWithdrawl(unittest.TestCase, TestUtil):
18 |
19 | def setUp(self) -> None:
20 |
21 | self.node_process = subprocess.Popen(["start_devnet", "devnode"])
22 |
23 | if self.node_process.returncode == None:
24 | print("Local dev net started successfully")
25 | else:
26 | print(f"Error starting local dev net. Exit code: {self.node_process.returncode}")
27 |
28 | time.sleep(40)
29 |
30 | subprocess.Popen(["sshpass", "-p", "sandbox", "ssh", "-o", "IdentitiesOnly=yes", "-t", "sandbox@127.0.0.1", "-p", "10022", "cd ~/optimism && make devnet-up"])
31 |
32 | time.sleep(40)
33 |
34 | vm_process = subprocess.Popen(["sshpass", "-p", "sandbox", "ssh", "-o", "IdentitiesOnly=yes", "-t", "sandbox@127.0.0.1", "-p", "10022", "python3 extract_addresses.py"], stdout=subprocess.PIPE)
35 |
36 | output, error = vm_process.communicate()
37 | if error:
38 | print(f"Error: {error}")
39 | else:
40 | l1_addresses_devnet = json.loads(output.decode().split("\r\n")[-2].strip("\r\n").replace("'", "\""))
41 |
42 | with open("optimism/config.json", 'r') as file:
43 | addresses = json.load(file)
44 |
45 | addresses["900"]["901"]["l1_addresses"] = l1_addresses_devnet
46 |
47 | with open("optimism/config.json", 'w') as json_file:
48 | json.dump(addresses, json_file, indent=4)
49 |
50 |
51 | subprocess.Popen(["sshpass", "-p", "sandbox", "ssh", "-o", "IdentitiesOnly=yes", "-t", "sandbox@127.0.0.1", "-p", "10022", f"echo 'export L2OO_ADDRESS={l1_addresses_devnet['L2_OUTPUT_ORACLE']}' >> '/home/sandbox/.bashrc'"])
52 | subprocess.Popen(["sshpass", "-p", "sandbox", "ssh", "-o", "IdentitiesOnly=yes", "-t", "sandbox@127.0.0.1", "-p", "10022", f"echo 'export DGF_ADDRESS={l1_addresses_devnet['DISPUTE_GAME_FACTORY']}' >> '/home/sandbox/.bashrc'"])
53 | subprocess.Popen(["sshpass", "-p", "sandbox", "ssh", "-o", "IdentitiesOnly=yes", "-t", "sandbox@127.0.0.1", "-p", "10022", f"echo 'export DG_TYPE=0' >> '/home/sandbox/.bashrc'"])
54 | subprocess.Popen(["sshpass", "-p", "sandbox", "ssh", "-o", "IdentitiesOnly=yes", "-t", "sandbox@127.0.0.1", "-p", "10022", f"cd ~/optimism && python3 bedrock-devnet/main.py"])
55 |
56 | time.sleep(20)
57 |
58 | self.l1_provider = Web3(Web3.HTTPProvider("http://127.0.0.1:8545"))
59 | self.l2_provider = Web3(Web3.HTTPProvider("http://127.0.0.1:9545"))
60 |
61 | self.l1_provider.middleware_onion.inject(geth_poa_middleware, layer=0)
62 | self.l2_provider.middleware_onion.inject(geth_poa_middleware, layer=0)
63 |
64 | self.faucet = self.l1_provider.eth.account.from_key("0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80")
65 |
66 | self.account = self.l1_provider.eth.account.from_key("0x" + "1" * 64)
67 |
68 | self.fund_account(self.account, 10**18, "l1")
69 | self.fund_account(self.account, 10**18, "l2")
70 |
71 |
72 |
73 | def tearDown(self) -> None:
74 | print("Tearing down devnet")
75 |
76 | subprocess.Popen(["sshpass", "-p", "sandbox", "ssh", "-o", "IdentitiesOnly=yes", "-t", "sandbox@127.0.0.1, -p", "10022", "sed -i '$d' '/home/sandbox/.bashrc'"])
77 | subprocess.Popen(["sshpass", "-p", "sandbox", "ssh", "-o", "IdentitiesOnly=yes", "-t", "sandbox@127.0.0.1", "-p", "10022", "cd ~/optimism && make devnet-down"])
78 | time.sleep(30)
79 | subprocess.Popen(["sshpass", "-p", "sandbox", "ssh", "-o", "IdentitiesOnly=yes", "-t", "sandbox@127.0.0.1", "-p", "10022", "cd ~/optimism && make devnet-clean"])
80 | time.sleep(30)
81 | subprocess.Popen(["sshpass", "-p", "sandbox", "ssh", "-o", "IdentitiesOnly=yes", "-t", "sandbox@127.0.0.1", "-p", "10022", "sudo poweroff"])
82 | time.sleep(10)
83 |
84 | node_process_pid = self.node_process.pid
85 |
86 | parent_process = psutil.Process(node_process_pid)
87 | child_processes = parent_process.children(recursive=True)
88 |
89 | self.node_process.terminate()
90 |
91 | # kill all child processes
92 | for child in child_processes:
93 | if parent_process.pid != child.pid:
94 | os.kill(child.pid, signal.SIGTERM)
95 |
96 |
97 | def testWithdrawETH(self):
98 |
99 | l1_chain_id = 900
100 | l2_chain_id = 901
101 |
102 | cross_chain_messenger = CrossChainMessenger(l1_chain_id, l2_chain_id, account_l1=self.account, account_l2=self.account, provider_l1=self.l1_provider, provider_l2=self.l2_provider)
103 |
104 | balance_l1 = self.l1_provider.eth.get_balance(self.account.address)
105 | balance_l2 = self.l2_provider.eth.get_balance(self.account.address)
106 |
107 | self.assertEqual(balance_l1, 10**18)
108 | self.assertEqual(balance_l2, 10**18)
109 |
110 | withdrawl_txn_hash, withdrawl_txn_receipt = cross_chain_messenger.withdraw_eth(5*10**17)
111 |
112 | self.assertEqual(withdrawl_txn_receipt.status, 1)
113 |
114 | print(withdrawl_txn_hash)
115 |
116 | while True:
117 | status = cross_chain_messenger.get_message_status(withdrawl_txn_hash)
118 | print(status)
119 | if status == MessageStatus.READY_TO_PROVE:
120 | break
121 | else:
122 | time.sleep(10)
123 |
124 | prove_message_txn, prove_message_receipt = cross_chain_messenger.prove_message(withdrawl_txn_hash)
125 |
126 | self.assertEqual(prove_message_receipt.status, 1)
127 |
128 | while True:
129 | status = cross_chain_messenger.get_message_status(withdrawl_txn_hash)
130 | print(status)
131 | if status == MessageStatus.READY_FOR_RELAY:
132 | break
133 | else:
134 | time.sleep(10)
135 |
136 | finalize_message_tx, finalize_message_receipt = cross_chain_messenger.finalize_message(withdrawl_txn_hash)
137 |
138 | self.assertEqual(finalize_message_receipt.status, 1)
139 |
140 | print(finalize_message_receipt)
141 |
142 | time.sleep(30)
143 |
144 | balance_l1 = self.l1_provider.eth.get_balance(self.account.address)
145 | balance_l2 = self.l2_provider.eth.get_balance(self.account.address)
146 |
147 | # TODO: Balance should be 0.5 ETH for L2 and 1.5 ETH for L1. This is not the case. Fix.
148 | print(balance_l1)
149 | print(balance_l2)
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
--------------------------------------------------------------------------------
/test/utils.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | class TestUtil():
4 |
5 | def __init__(self) -> None:
6 | pass
7 |
8 | def fund_account(self, account, value, layer="l1"):
9 |
10 | if layer == "l1":
11 | provider = self.l1_provider
12 | elif layer == "l2":
13 | provider = self.l2_provider
14 | else:
15 | raise Exception(f"Invalid layer: {layer}")
16 |
17 | tx = {
18 | 'nonce': provider.eth.get_transaction_count(self.faucet.address),
19 | 'to': account.address,
20 | 'value': value,
21 | 'gas': 50000,
22 | 'gasPrice': provider.eth.gas_price
23 | }
24 |
25 | # Sign and broadcast the transaction
26 | signed_tx = provider.eth.account.sign_transaction(tx, self.faucet.key)
27 | tx_hash = provider.eth.send_raw_transaction(signed_tx.rawTransaction)
28 | receipt = provider.eth.wait_for_transaction_receipt(tx_hash)
29 |
30 | return tx_hash.hex(), receipt
--------------------------------------------------------------------------------