diff --git a/clients/ops-l2/genesis.json b/clients/ops-l2/genesis.json index 54bed7f237..0c0f80fe48 100644 --- a/clients/ops-l2/genesis.json +++ b/clients/ops-l2/genesis.json @@ -811,6 +811,18 @@ }, "70997970C51812dc3A010C7d01b50e0d17dc79C8": { "balance": "0x200000000000000000000000000000000000000000000000000000000000000" + }, + "0000000000000000000000000000000000000314": { + "balance": "0x0", + "code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063a223e05d1461006a578063abd1a0cf1461008d578063abfced1d146100d4578063e05c914a14610110578063e6768b451461014c575b610000565b346100005761007761019d565b6040518082815260200191505060405180910390f35b34610000576100be600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506101a3565b6040518082815260200191505060405180910390f35b346100005761010e600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101ed565b005b346100005761014a600480803590602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610236565b005b346100005761017960048080359060200190919080359060200190919080359060200190919050506103c4565b60405180848152602001838152602001828152602001935050505060405180910390f35b60005481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b80600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b5050565b7f6031a8d62d7c95988fa262657cd92107d90ed96e08d8f867d32f26edfe85502260405180905060405180910390a17f47e2689743f14e97f7dcfa5eec10ba1dff02f83b3d1d4b9c07b206cbbda66450826040518082815260200191505060405180910390a1817fa48a6b249a5084126c3da369fbc9b16827ead8cb5cdc094b717d3f1dcd995e2960405180905060405180910390a27f7890603b316f3509577afd111710f9ebeefa15e12f72347d9dffd0d65ae3bade81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a18073ffffffffffffffffffffffffffffffffffffffff167f7efef9ea3f60ddc038e50cccec621f86a0195894dc0520482abf8b5c6b659e4160405180905060405180910390a28181604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a05b5050565b6000600060008585859250925092505b935093509390505600a165627a7a72305820aaf842d0d0c35c45622c5263cbb54813d2974d3999c8c38551d7c613ea2bc1170029", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x1234", + "0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9": "0x01" + } + }, + "0000000000000000000000000000000000000315": { + "balance": "0x9999999999999999999999999999999", + "code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063ef2769ca1461003e575b610000565b3461000057610078600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061007a565b005b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051809050600060405180830381858888f1935050505015610106578173ffffffffffffffffffffffffffffffffffffffff167f30a3c50752f2552dcc2b93f5b96866280816a986c0c0408cb6778b9fa198288f826040518082815260200191505060405180910390a25b5b50505600a165627a7a72305820637991fabcc8abad4294bf2bb615db78fbec4edff1635a2647d3894e2daf6a610029" } }, "number": "0x0", diff --git a/simulators/optimism/devnet/abi.go b/simulators/optimism/devnet/abi.go new file mode 100644 index 0000000000..669e1e82cb --- /dev/null +++ b/simulators/optimism/devnet/abi.go @@ -0,0 +1,255 @@ +package main + +import ( + "context" + "math/big" + "math/rand" + "strings" + "time" + + "github.com/ethereum-optimism/hive/simulators/optimism/devnet/testcontract" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" +) + +//go:generate abigen -abi ./contractABI.json -pkg testcontract -type Contract -out ./testcontract/contract.go + +// callContractTest uses the generated ABI binding to call methods in the +// pre-deployed contract. +func callContractTest(t *TestEnv) { + contract, err := testcontract.NewContractCaller(predeployedContractAddr, t.Eth) + if err != nil { + t.Fatalf("Unable to instantiate contract caller: %v", err) + } + + opts := &bind.CallOpts{Pending: true} + value, err := contract.Ui(opts) + if err != nil { + t.Fatalf("Unable to fetch `ui` variable: %v", err) + } + + expected, _ := new(big.Int).SetString("0x1234", 0) + if expected.Cmp(value) != 0 { + t.Fatalf("UI variable has invalid value, want %d, got %d", expected, value) + } + + expected.SetString("0x1", 0) + value, err = contract.GetFromMap(opts, predeployedContractWithAddress) + if err != nil { + t.Fatalf("Unable to fetch map value: %v", err) + } + if expected.Cmp(value) != 0 { + t.Errorf("Invalid value retrieve from address=>uint mapping, want %d, got %d", expected, value) + } + + expA, expB, expC := big.NewInt(1111), big.NewInt(2222), big.NewInt(3333) + a, b, c, err := contract.ConstFunc(opts, expA, expB, expC) + if err != nil { + t.Fatalf("Unable to call ConstFunc: %v", err) + } + + if expA.Cmp(a) != 0 { + t.Errorf("A has invalid value, want %d, got %d", expA, a) + } + if expB.Cmp(b) != 0 { + t.Errorf("B has invalid value, want %d, got %d", expB, b) + } + if expC.Cmp(c) != 0 { + t.Errorf("C has invalid value, want %d, got %d", expC, c) + } +} + +// transactContractTest deploys a new contract and sends transactions to it and +// waits for logs. +func transactContractTest(t *TestEnv) { + var ( + address = t.Vault.createAccount(t, big.NewInt(params.Ether)) + nonce = uint64(0) + + expectedContractAddress = crypto.CreateAddress(address, nonce) + gasPrice = big.NewInt(30 * params.GWei) + gasLimit = uint64(1200000) + + contractABI, _ = abi.JSON(strings.NewReader(predeployedContractABI)) + intArg = big.NewInt(rand.Int63()) + addrArg = address + ) + + rawTx := types.NewContractCreation(nonce, big0, gasLimit, gasPrice, deployCode) + deployTx, err := t.Vault.signTransaction(address, rawTx) + nonce++ + if err != nil { + t.Fatalf("Unable to sign deploy tx: %v", err) + } + + // deploy contract + if err := t.Eth.SendTransaction(t.Ctx(), deployTx); err != nil { + t.Fatalf("Unable to send transaction: %v", err) + } + + t.Logf("Deploy ABI Test contract transaction: 0x%x", deployTx.Hash()) + + // fetch transaction receipt for contract address + var contractAddress common.Address + receipt, err := waitForTxConfirmations(t, deployTx.Hash(), 5) + if err != nil { + t.Fatalf("Unable to retrieve receipt %v: %v", deployTx.Hash(), err) + } + + // ensure receipt has the expected address + if expectedContractAddress != receipt.ContractAddress { + t.Fatalf("Contract deploy on different address, expected %x, got %x", expectedContractAddress, contractAddress) + } + + t.Logf("ABI test contract deployed on 0x%x", receipt.ContractAddress) + + // send transaction to events method + payload, err := contractABI.Pack("events", intArg, addrArg) + if err != nil { + t.Fatalf("Unable to prepare tx payload: %v", err) + } + + eventsTx := types.NewTransaction(nonce, predeployedContractAddr, big0, 500000, gasPrice, payload) + tx, err := t.Vault.signTransaction(address, eventsTx) + nonce++ + if err != nil { + t.Fatalf("Unable to sign deploy tx: %v", err) + } + if err := t.Eth.SendTransaction(t.Ctx(), tx); err != nil { + t.Fatalf("Unable to send transaction: %v", err) + } + + t.Logf("Waiting for receipt for events tx %v", tx.Hash()) + + // wait for transaction + receipt, err = waitForTxConfirmations(t, tx.Hash(), 0) + if err != nil { + t.Fatalf("Unable to send transaction to events method: %v", err) + } + + var ( + intArgBytes = common.LeftPadBytes(intArg.Bytes(), 32) + addrArgBytes = common.LeftPadBytes(addrArg.Bytes(), 32) + ) + + if len(receipt.Logs) != 6 { + t.Fatalf("Want 6 logs, got %d", len(receipt.Logs)) + } + + validateLog(t, tx, *receipt.Logs[0], predeployedContractAddr, receipt.Logs[0].Index+0, contractABI.Events["E0"], nil) + validateLog(t, tx, *receipt.Logs[1], predeployedContractAddr, receipt.Logs[0].Index+1, contractABI.Events["E1"], intArgBytes) + validateLog(t, tx, *receipt.Logs[2], predeployedContractAddr, receipt.Logs[0].Index+2, contractABI.Events["E2"], intArgBytes) + validateLog(t, tx, *receipt.Logs[3], predeployedContractAddr, receipt.Logs[0].Index+3, contractABI.Events["E3"], addrArgBytes) + validateLog(t, tx, *receipt.Logs[4], predeployedContractAddr, receipt.Logs[0].Index+4, contractABI.Events["E4"], addrArgBytes) + validateLog(t, tx, *receipt.Logs[5], predeployedContractAddr, receipt.Logs[0].Index+5, contractABI.Events["E5"], intArgBytes, addrArgBytes) +} + +// transactContractSubscriptionTest deploys a new contract and sends transactions to it and +// waits for logs. It uses subscription to track logs. +func transactContractSubscriptionTest(t *TestEnv) { + var ( + address = t.Vault.createAccountWithSubscription(t, big.NewInt(params.Ether)) + nonce = uint64(0) + + expectedContractAddress = crypto.CreateAddress(address, nonce) + gasPrice = big.NewInt(30 * params.GWei) + gasLimit = uint64(1200000) + + contractABI, _ = abi.JSON(strings.NewReader(predeployedContractABI)) + intArg = big.NewInt(rand.Int63()) + addrArg = address + + logs = make(chan types.Log) + ) + + // deploy contract + rawTx := types.NewContractCreation(nonce, big0, gasLimit, gasPrice, deployCode) + deployTx, err := t.Vault.signTransaction(address, rawTx) + nonce++ + if err != nil { + t.Fatalf("Unable to sign deploy tx: %v", err) + } + + ctx, _ := context.WithTimeout(context.Background(), rpcTimeout) + if err := t.Eth.SendTransaction(ctx, deployTx); err != nil { + t.Fatalf("Unable to send transaction: %v", err) + } + + t.Logf("Deploy ABI Test contract transaction: 0x%x", deployTx.Hash()) + + // fetch transaction receipt for contract address + receipt, err := waitForTxConfirmations(t, deployTx.Hash(), 5) + if err != nil { + t.Fatalf("Unable to retrieve receipt %v: %v", deployTx.Hash(), err) + } + + // ensure receipt has the expected address + if expectedContractAddress != receipt.ContractAddress { + t.Fatalf("Contract deploy on different address, expected %x, got %x", expectedContractAddress, receipt.ContractAddress) + } + + t.Logf("ABI test contract deployed on 0x%x", receipt.ContractAddress) + + // setup log subscription + ctx, _ = context.WithTimeout(context.Background(), rpcTimeout) + q := ethereum.FilterQuery{Addresses: []common.Address{receipt.ContractAddress}} + sub, err := t.Eth.SubscribeFilterLogs(ctx, q, logs) + if err != nil { + t.Fatalf("Unable to create log subscription: %v", err) + } + + contractAddress := receipt.ContractAddress + t.Logf("Log filter created on contract 0x%x", contractAddress) + + defer sub.Unsubscribe() + + contract, err := testcontract.NewContractTransactor(receipt.ContractAddress, t.Eth) + if err != nil { + t.Fatalf("Could not instantiate contract instance: %v", err) + } + + // send transaction to events method + opts := &bind.TransactOpts{ + From: address, + Nonce: new(big.Int).SetUint64(nonce), + Signer: t.Vault.signTransaction, + } + tx, err := contract.Events(opts, intArg, addrArg) + if err != nil { + t.Fatalf("Could not send events transaction: %v", err) + } + + t.Logf("Send events transaction 0x%x", tx.Hash()) + + // wait for logs + var collectedLogs []types.Log + timer := time.NewTimer(60 * time.Second) + for len(collectedLogs) < 6 { + select { + case log := <-logs: + collectedLogs = append(collectedLogs, log) + case err := <-sub.Err(): + t.Fatalf("Received error from subscription: %v", err) + case <-timer.C: + t.Fatal("Waiting for logs took too long") + } + } + + // check logs + var ( + intArgBytes = common.LeftPadBytes(intArg.Bytes(), 32) + addrArgBytes = common.LeftPadBytes(addrArg.Bytes(), 32) + ) + + validateLog(t, tx, collectedLogs[0], contractAddress, collectedLogs[0].Index+0, contractABI.Events["E0"], nil) + validateLog(t, tx, collectedLogs[1], contractAddress, collectedLogs[0].Index+1, contractABI.Events["E1"], intArgBytes) + validateLog(t, tx, collectedLogs[2], contractAddress, collectedLogs[0].Index+2, contractABI.Events["E2"], intArgBytes) + validateLog(t, tx, collectedLogs[3], contractAddress, collectedLogs[0].Index+3, contractABI.Events["E3"], addrArgBytes) + validateLog(t, tx, collectedLogs[4], contractAddress, collectedLogs[0].Index+4, contractABI.Events["E4"], addrArgBytes) + validateLog(t, tx, collectedLogs[5], contractAddress, collectedLogs[0].Index+5, contractABI.Events["E5"], intArgBytes, addrArgBytes) +} diff --git a/simulators/optimism/devnet/ethclient.go b/simulators/optimism/devnet/ethclient.go index 9a9e829fbe..b291504b06 100644 --- a/simulators/optimism/devnet/ethclient.go +++ b/simulators/optimism/devnet/ethclient.go @@ -3,9 +3,12 @@ package main import ( "bytes" "math/big" + "math/rand" + "strings" "time" "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" @@ -13,10 +16,57 @@ import ( ) var ( + contractCode = ` +pragma solidity ^0.4.6; + +contract Test { + event E0(); + event E1(uint); + event E2(uint indexed); + event E3(address); + event E4(address indexed); + event E5(uint, address) anonymous; + + uint public ui; + mapping(address => uint) map; + + function Test(uint ui_) { + ui = ui_; + map[msg.sender] = ui_; + } + + function events(uint ui_, address addr_) { + E0(); + E1(ui_); + E2(ui_); + E3(addr_); + E4(addr_); + E5(ui_, addr_); + } + + function constFunc(uint a, uint b, uint c) constant returns(uint, uint, uint) { + return (a, b, c); + } + + function getFromMap(address addr) constant returns(uint) { + return map[addr]; + } + + function addToMap(address addr, uint value) { + map[addr] = value; + } +} + ` // test contract deploy code, will deploy the contract with 1234 as argument deployCode = common.Hex2Bytes("6060604052346100005760405160208061048c833981016040528080519060200190919050505b8060008190555080600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b505b610409806100836000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063a223e05d1461006a578063abd1a0cf1461008d578063abfced1d146100d4578063e05c914a14610110578063e6768b451461014c575b610000565b346100005761007761019d565b6040518082815260200191505060405180910390f35b34610000576100be600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506101a3565b6040518082815260200191505060405180910390f35b346100005761010e600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101ed565b005b346100005761014a600480803590602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610236565b005b346100005761017960048080359060200190919080359060200190919080359060200190919050506103c4565b60405180848152602001838152602001828152602001935050505060405180910390f35b60005481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b80600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b5050565b7f6031a8d62d7c95988fa262657cd92107d90ed96e08d8f867d32f26edfe85502260405180905060405180910390a17f47e2689743f14e97f7dcfa5eec10ba1dff02f83b3d1d4b9c07b206cbbda66450826040518082815260200191505060405180910390a1817fa48a6b249a5084126c3da369fbc9b16827ead8cb5cdc094b717d3f1dcd995e2960405180905060405180910390a27f7890603b316f3509577afd111710f9ebeefa15e12f72347d9dffd0d65ae3bade81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a18073ffffffffffffffffffffffffffffffffffffffff167f7efef9ea3f60ddc038e50cccec621f86a0195894dc0520482abf8b5c6b659e4160405180905060405180910390a28181604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a05b5050565b6000600060008585859250925092505b935093509390505600a165627a7a72305820aaf842d0d0c35c45622c5263cbb54813d2974d3999c8c38551d7c613ea2bc117002900000000000000000000000000000000000000000000000000000000000004d2") // test contract code as deployed runtimeCode = common.Hex2Bytes("60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063a223e05d1461006a578063abd1a0cf1461008d578063abfced1d146100d4578063e05c914a14610110578063e6768b451461014c575b610000565b346100005761007761019d565b6040518082815260200191505060405180910390f35b34610000576100be600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506101a3565b6040518082815260200191505060405180910390f35b346100005761010e600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101ed565b005b346100005761014a600480803590602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610236565b005b346100005761017960048080359060200190919080359060200190919080359060200190919050506103c4565b60405180848152602001838152602001828152602001935050505060405180910390f35b60005481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b80600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b5050565b7f6031a8d62d7c95988fa262657cd92107d90ed96e08d8f867d32f26edfe85502260405180905060405180910390a17f47e2689743f14e97f7dcfa5eec10ba1dff02f83b3d1d4b9c07b206cbbda66450826040518082815260200191505060405180910390a1817fa48a6b249a5084126c3da369fbc9b16827ead8cb5cdc094b717d3f1dcd995e2960405180905060405180910390a27f7890603b316f3509577afd111710f9ebeefa15e12f72347d9dffd0d65ae3bade81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a18073ffffffffffffffffffffffffffffffffffffffff167f7efef9ea3f60ddc038e50cccec621f86a0195894dc0520482abf8b5c6b659e4160405180905060405180910390a28181604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a05b5050565b6000600060008585859250925092505b935093509390505600a165627a7a72305820aaf842d0d0c35c45622c5263cbb54813d2974d3999c8c38551d7c613ea2bc1170029") + // contractSrc is predeploy on the following address in the genesis block. + predeployedContractAddr = common.HexToAddress("0000000000000000000000000000000000000314") + // contractSrc is pre-deployed with the following address in the genesis block. + predeployedContractWithAddress = common.HexToAddress("391694e7e0b0cce554cb130d723a9d27458f9298") + // holds the pre-deployed contract ABI + predeployedContractABI = `[{"constant":true,"inputs":[],"name":"ui","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"addr","type":"address"}],"name":"getFromMap","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"},{"name":"value","type":"uint256"}],"name":"addToMap","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"ui_","type":"uint256"},{"name":"addr_","type":"address"}],"name":"events","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"a","type":"uint256"},{"name":"b","type":"uint256"},{"name":"c","type":"uint256"}],"name":"constFunc","outputs":[{"name":"","type":"uint256"},{"name":"","type":"uint256"},{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"ui_","type":"uint256"}],"payable":false,"type":"constructor"},{"anonymous":false,"inputs":[],"name":"E0","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"","type":"uint256"}],"name":"E1","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"","type":"uint256"}],"name":"E2","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"","type":"address"}],"name":"E3","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"","type":"address"}],"name":"E4","type":"event"},{"anonymous":true,"inputs":[{"indexed":false,"name":"","type":"uint256"},{"indexed":false,"name":"","type":"address"}],"name":"E5","type":"event"}]` ) var ( @@ -24,6 +74,66 @@ var ( big1 = big.NewInt(1) ) +// CodeAtTest tests the code for the pre-deployed contract. +func CodeAtTest(t *TestEnv) { + code, err := t.Eth.CodeAt(t.Ctx(), predeployedContractAddr, big0) + if err != nil { + t.Fatalf("Could not fetch code for predeployed contract: %v", err) + } + if bytes.Compare(runtimeCode, code) != 0 { + t.Fatalf("Unexpected code, want %x, got %x", runtimeCode, code) + } +} + +// estimateGasTest fetches the estimated gas usage for a call to the events method. +func estimateGasTest(t *TestEnv) { + var ( + address = t.Vault.createAccount(t, big.NewInt(params.Ether)) + contractABI, _ = abi.JSON(strings.NewReader(predeployedContractABI)) + intArg = big.NewInt(rand.Int63()) + ) + + payload, err := contractABI.Pack("events", intArg, address) + if err != nil { + t.Fatalf("Unable to prepare tx payload: %v", err) + } + msg := ethereum.CallMsg{ + From: address, + To: &predeployedContractAddr, + Data: payload, + } + estimated, err := t.Eth.EstimateGas(t.Ctx(), msg) + if err != nil { + t.Fatalf("Could not estimate gas: %v", err) + } + + // send the actual tx and test gas usage + txGas := estimated + 100000 + rawTx := types.NewTransaction(0, *msg.To, msg.Value, txGas, big.NewInt(32*params.GWei), msg.Data) + tx, err := t.Vault.signTransaction(address, rawTx) + if err != nil { + t.Fatalf("Could not sign transaction: %v", err) + } + + if err := t.Eth.SendTransaction(t.Ctx(), tx); err != nil { + t.Fatalf("Could not send tx: %v", err) + } + + receipt, err := waitForTxConfirmations(t, tx.Hash(), 1) + if err != nil { + t.Fatalf("Could not wait for confirmations: %v", err) + } + + // test lower bound + if estimated < receipt.GasUsed { + t.Fatalf("Estimated gas too low, want %d >= %d", estimated, receipt.GasUsed) + } + // test upper bound + if receipt.GasUsed+5000 < estimated { + t.Fatalf("Estimated gas too high, estimated: %d, used: %d", estimated, receipt.GasUsed) + } +} + // genesisByHash fetches the known genesis header and compares // it against the genesis file to determine if block fields are // returned correct. @@ -83,6 +193,70 @@ func genesisBlockByNumberTest(t *TestEnv) { } } +// canonicalChainTest loops over 10 blocks and does some basic validations +// to ensure the chain form a valid canonical chain and resources like uncles, +// transactions and receipts can be fetched and provide a consistent view. +func canonicalChainTest(t *TestEnv) { + // wait a bit so there is actually a chain with enough height + for { + latestBlock, err := t.Eth.BlockByNumber(t.Ctx(), nil) + if err != nil { + t.Fatalf("Unable to fetch latest block") + } + if latestBlock.NumberU64() >= 20 { + break + } + time.Sleep(time.Second) + } + + var childBlock *types.Block + for i := 10; i >= 0; i-- { + block, err := t.Eth.BlockByNumber(t.Ctx(), big.NewInt(int64(i))) + if err != nil { + t.Fatalf("Unable to fetch block #%d", i) + } + if childBlock != nil { + if childBlock.ParentHash() != block.Hash() { + t.Errorf("Canonical chain broken on %d-%d / %x-%x", block.NumberU64(), childBlock.NumberU64(), block.Hash(), childBlock.Hash()) + } + } + + // try to fetch all txs and receipts and do some basic validation on them + // to check if the fetched chain is consistent. + for _, tx := range block.Transactions() { + fetchedTx, _, err := t.Eth.TransactionByHash(t.Ctx(), tx.Hash()) + if err != nil { + t.Fatalf("Unable to fetch transaction %x from block %x: %v", tx.Hash(), block.Hash(), err) + } + if fetchedTx == nil { + t.Fatalf("Transaction %x could not be found but was included in block %x", tx.Hash(), block.Hash()) + } + receipt, err := t.Eth.TransactionReceipt(t.Ctx(), fetchedTx.Hash()) + if err != nil { + t.Fatalf("Unable to fetch receipt for %x from block %x: %v", fetchedTx.Hash(), block.Hash(), err) + } + if receipt == nil { + t.Fatalf("Receipt for %x could not be found but was included in block %x", fetchedTx.Hash(), block.Hash()) + } + if receipt.TxHash != fetchedTx.Hash() { + t.Fatalf("Receipt has an invalid tx, expected %x, got %x", fetchedTx.Hash(), receipt.TxHash) + } + } + + // make sure all uncles can be fetched + for _, uncle := range block.Uncles() { + uBlock, err := t.Eth.HeaderByHash(t.Ctx(), uncle.Hash()) + if err != nil { + t.Fatalf("Unable to fetch uncle block: %v", err) + } + if uBlock == nil { + t.Logf("Could not fetch uncle block %x", uncle.Hash()) + } + } + + childBlock = block + } +} // deployContractTest deploys `contractSrc` and tests if the code and state // on the contract address contain the expected values (as set in the ctor). @@ -112,7 +286,7 @@ func deployContractTest(t *TestEnv) { var contractAddress common.Address receipt, err := waitForTxConfirmations(t, deployTx.Hash(), 5) if err != nil { - t.Fatalf("Unable to retrieve receipt: %v", err) + t.Fatalf("Unable to retrieve receipt %v: %v", deployTx.Hash(), err) } // ensure receipt has the expected address @@ -183,7 +357,7 @@ func deployContractOutOfGasTest(t *TestEnv) { // Wait for the transaction receipt. receipt, err := waitForTxConfirmations(t, deployTx.Hash(), 5) if err != nil { - t.Fatalf("unable to fetch tx receipt: %v", err) + t.Fatalf("unable to fetch tx receipt %v: %v", deployTx.Hash(), err) } // Check receipt fields. if receipt.Status != types.ReceiptStatusFailed { @@ -208,6 +382,109 @@ func deployContractOutOfGasTest(t *TestEnv) { } } +// receiptTest tests whether the created receipt is correct by calling the `events` method +// on the pre-deployed contract. +func receiptTest(t *TestEnv) { + var ( + contractABI, _ = abi.JSON(strings.NewReader(predeployedContractABI)) + address = t.Vault.createAccount(t, big.NewInt(params.Ether)) + nonce = uint64(0) + + intArg = big.NewInt(rand.Int63()) + ) + + payload, err := contractABI.Pack("events", intArg, address) + if err != nil { + t.Fatalf("Unable to prepare tx payload: %v", err) + } + + rawTx := types.NewTransaction(nonce, predeployedContractAddr, big0, 500000, gasPrice, payload) + tx, err := t.Vault.signTransaction(address, rawTx) + if err != nil { + t.Fatalf("Unable to sign deploy tx: %v", err) + } + + if err := t.Eth.SendTransaction(t.Ctx(), tx); err != nil { + t.Fatalf("Unable to send transaction: %v", err) + } + + // wait for transaction + receipt, err := waitForTxConfirmations(t, tx.Hash(), 0) + if err != nil { + t.Fatalf("Unable to retrieve tx receipt %v: %v", tx.Hash(), err) + } + // validate receipt fields + if receipt.TxHash != tx.Hash() { + t.Errorf("Receipt contains invalid tx hash, want %x, got %x", tx.Hash(), receipt.TxHash) + } + if receipt.ContractAddress != (common.Address{}) { + t.Errorf("Receipt contains invalid contract address, want empty address got %x", receipt.ContractAddress) + } + bloom := types.CreateBloom(types.Receipts{receipt}) + if receipt.Bloom != bloom { + t.Errorf("Receipt contains invalid bloom, want %x, got %x", bloom, receipt.Bloom) + } + + var ( + intArgBytes = common.LeftPadBytes(intArg.Bytes(), 32) + addrArgBytes = common.LeftPadBytes(address.Bytes(), 32) + ) + + if len(receipt.Logs) != 6 { + t.Fatalf("Want 6 logs, got %d", len(receipt.Logs)) + } + + validateLog(t, tx, *receipt.Logs[0], predeployedContractAddr, receipt.Logs[0].Index+0, contractABI.Events["E0"], nil) + validateLog(t, tx, *receipt.Logs[1], predeployedContractAddr, receipt.Logs[0].Index+1, contractABI.Events["E1"], intArgBytes) + validateLog(t, tx, *receipt.Logs[2], predeployedContractAddr, receipt.Logs[0].Index+2, contractABI.Events["E2"], intArgBytes) + validateLog(t, tx, *receipt.Logs[3], predeployedContractAddr, receipt.Logs[0].Index+3, contractABI.Events["E3"], addrArgBytes) + validateLog(t, tx, *receipt.Logs[4], predeployedContractAddr, receipt.Logs[0].Index+4, contractABI.Events["E4"], addrArgBytes) + validateLog(t, tx, *receipt.Logs[5], predeployedContractAddr, receipt.Logs[0].Index+5, contractABI.Events["E5"], intArgBytes, addrArgBytes) +} + +// validateLog is a helper method that tests if the given set of logs are valid when the events method on the +// standard contract is called with argData. +func validateLog(t *TestEnv, tx *types.Transaction, log types.Log, contractAddress common.Address, index uint, ev abi.Event, argData ...[]byte) { + if log.Address != contractAddress { + t.Errorf("Log[%d] contains invalid address, want 0x%x, got 0x%x [tx=0x%x]", index, contractAddress, log.Address, tx.Hash()) + } + if log.TxHash != tx.Hash() { + t.Errorf("Log[%d] contains invalid hash, want 0x%x, got 0x%x [tx=0x%x]", index, tx.Hash(), log.TxHash, tx.Hash()) + } + if log.Index != index { + t.Errorf("Log[%d] has invalid index, want %d, got %d [tx=0x%x]", index, index, log.Index, tx.Hash()) + } + + // assemble expected topics and log data + var ( + topics []common.Hash + data []byte + ) + if !ev.Anonymous { + topics = append(topics, ev.ID) + } + for i, arg := range ev.Inputs { + if arg.Indexed { + topics = append(topics, common.BytesToHash(argData[i])) + } else { + data = append(data, argData[i]...) + } + } + + if len(log.Topics) != len(topics) { + t.Errorf("Log[%d] contains invalid number of topics, want %d, got %d [tx=0x%x]", index, len(topics), len(log.Topics), tx.Hash()) + } else { + for i, topic := range topics { + if topics[i] != topic { + t.Errorf("Log[%d] contains invalid topic, want 0x%x, got 0x%x [tx=0x%x]", index, topics[i], topic, tx.Hash()) + } + } + } + if !bytes.Equal(log.Data, data) { + t.Errorf("Log[%d] contains invalid data, want 0x%x, got 0x%x [tx=0x%x]", index, data, log.Data, tx.Hash()) + } +} + // syncProgressTest only tests if this function is supported by the node. func syncProgressTest(t *TestEnv) { _, err := t.Eth.SyncProgress(t.Ctx()) @@ -216,6 +493,93 @@ func syncProgressTest(t *TestEnv) { } } +// transactionInBlockTest will wait for a new block with transaction +// and retrieves transaction details by block hash and position. +func transactionInBlockTest(t *TestEnv) { + var ( + key = t.Vault.createAccount(t, big.NewInt(params.Ether)) + nonce = uint64(0) + blockNumber = new(big.Int) + ) + + for { + blockNumber.Add(blockNumber, big1) + + block, err := t.Eth.BlockByNumber(t.Ctx(), blockNumber) + if err == ethereum.NotFound { // end of chain + rawTx := types.NewTransaction(nonce, predeployedVaultAddr, big1, 100000, gasPrice, nil) + nonce++ + + tx, err := t.Vault.signTransaction(key, rawTx) + if err != nil { + t.Fatalf("Unable to sign deploy tx: %v", err) + } + if err = t.Eth.SendTransaction(t.Ctx(), tx); err != nil { + t.Fatalf("Unable to send transaction: %v", err) + } + time.Sleep(time.Second) + continue + } + if err != nil { + t.Fatalf("Unable to fetch latest block: %v", err) + } + if len(block.Transactions()) == 0 { + continue + } + for i := 0; i < len(block.Transactions()); i++ { + _, err := t.Eth.TransactionInBlock(t.Ctx(), block.Hash(), uint(i)) + if err != nil { + t.Fatalf("Unable to fetch transaction by block hash and index: %v", err) + } + } + return + } +} + +// transactionInBlockSubscriptionTest will wait for a new block with transaction +// and retrieves transaction details by block hash and position. +func transactionInBlockSubscriptionTest(t *TestEnv) { + var heads = make(chan *types.Header, 100) + + sub, err := t.Eth.SubscribeNewHead(t.Ctx(), heads) + if err != nil { + t.Fatalf("Unable to subscribe to new heads: %v", err) + } + + key := t.Vault.createAccount(t, big.NewInt(params.Ether)) + for i := 0; i < 5; i++ { + rawTx := types.NewTransaction(uint64(i), predeployedVaultAddr, big1, 100000, gasPrice, nil) + tx, err := t.Vault.signTransaction(key, rawTx) + if err != nil { + t.Fatalf("Unable to sign deploy tx: %v", err) + } + if err = t.Eth.SendTransaction(t.Ctx(), tx); err != nil { + t.Fatalf("Unable to send transaction: %v", err) + } + } + + // wait until transaction + defer sub.Unsubscribe() + for { + head := <-heads + + block, err := t.Eth.BlockByHash(t.Ctx(), head.Hash()) + if err != nil { + t.Fatalf("Unable to retrieve block %x: %v", head.Hash(), err) + } + if len(block.Transactions()) == 0 { + continue + } + for i := 0; i < len(block.Transactions()); i++ { + _, err = t.Eth.TransactionInBlock(t.Ctx(), head.Hash(), uint(i)) + if err != nil { + t.Fatalf("Unable to fetch transaction by block hash and index: %v", err) + } + } + return + } +} + // newHeadSubscriptionTest tests whether func newHeadSubscriptionTest(t *TestEnv) { var ( @@ -244,6 +608,70 @@ func newHeadSubscriptionTest(t *TestEnv) { } } +func logSubscriptionTest(t *TestEnv) { + var ( + criteria = ethereum.FilterQuery{ + Addresses: []common.Address{predeployedContractAddr}, + Topics: [][]common.Hash{}, + } + logs = make(chan types.Log) + ) + + sub, err := t.Eth.SubscribeFilterLogs(t.Ctx(), criteria, logs) + if err != nil { + t.Fatalf("Unable to create log subscription: %v", err) + } + defer sub.Unsubscribe() + + var ( + contractABI, _ = abi.JSON(strings.NewReader(predeployedContractABI)) + address = t.Vault.createAccount(t, big.NewInt(params.Ether)) + nonce = uint64(0) + + arg0 = big.NewInt(rand.Int63()) + arg1 = address + ) + + payload, _ := contractABI.Pack("events", arg0, arg1) + rawTx := types.NewTransaction(nonce, predeployedContractAddr, big0, 500000, gasPrice, payload) + tx, err := t.Vault.signTransaction(address, rawTx) + if err != nil { + t.Fatalf("Unable to sign deploy tx: %v", err) + } + + if err = t.Eth.SendTransaction(t.Ctx(), tx); err != nil { + t.Fatalf("Unable to send transaction: %v", err) + } + + t.Logf("Wait for logs generated for transaction: %x", tx.Hash()) + var ( + expectedLogs = 6 + currentLogs = 0 + fetchedLogs []types.Log + deadline = time.NewTimer(30 * time.Second) + ) + + // ensure we receive all logs that are generated by our transaction. + // log fields are in depth verified in another test. + for len(fetchedLogs) < expectedLogs { + select { + case log := <-logs: + // other tests also send transaction to the predeployed + // contract ensure these logs are from "our" transaction. + if log.TxHash != tx.Hash() { + continue + } + fetchedLogs = append(fetchedLogs, log) + case err := <-sub.Err(): + t.Fatalf("Log subscription returned error: %v", err) + case <-deadline.C: + t.Fatalf("Only received %d/%d logs", currentLogs, expectedLogs) + } + } + + validatePredeployContractLogs(t, tx, fetchedLogs, arg0, arg1) +} + // balanceAndNonceAtTest creates a new account and transfers funds to it. // It then tests if the balance and nonce of the sender and receiver // address are updated correct. @@ -334,3 +762,111 @@ func balanceAndNonceAtTest(t *TestEnv) { t.Fatalf("Invalid nonce, want %d, got %d", expectedNonce, nonceAfter) } } + +// validatePredeployContractLogs tests wether the given logs are expected when +// the event function was called on the predeployed test contract was called +// with the given args. The event function raises the following events: +// event E0(); +// event E1(uint); +// event E2(uint indexed); +// event E3(address); +// event E4(address indexed); +// event E5(uint, address) anonymous; +func validatePredeployContractLogs(t *TestEnv, tx *types.Transaction, logs []types.Log, intArg *big.Int, addrArg common.Address) { + if len(logs) != 6 { + t.Fatalf("Unexpected log count, want 6, got %d", len(logs)) + } + + var ( + contractABI, _ = abi.JSON(strings.NewReader(predeployedContractABI)) + intArgBytes = common.LeftPadBytes(intArg.Bytes(), 32) + addrArgBytes = common.LeftPadBytes(addrArg.Bytes(), 32) + ) + + validateLog(t, tx, logs[0], predeployedContractAddr, logs[0].Index+0, contractABI.Events["E0"], nil) + validateLog(t, tx, logs[1], predeployedContractAddr, logs[0].Index+1, contractABI.Events["E1"], intArgBytes) + validateLog(t, tx, logs[2], predeployedContractAddr, logs[0].Index+2, contractABI.Events["E2"], intArgBytes) + validateLog(t, tx, logs[3], predeployedContractAddr, logs[0].Index+3, contractABI.Events["E3"], addrArgBytes) + validateLog(t, tx, logs[4], predeployedContractAddr, logs[0].Index+4, contractABI.Events["E4"], addrArgBytes) + validateLog(t, tx, logs[5], predeployedContractAddr, logs[0].Index+5, contractABI.Events["E5"], intArgBytes, addrArgBytes) +} + +func transactionCountTest(t *TestEnv) { + var ( + key = t.Vault.createAccount(t, big.NewInt(params.Ether)) + ) + + for i := 0; i < 60; i++ { + rawTx := types.NewTransaction(uint64(i), predeployedVaultAddr, big1, 100000, gasPrice, nil) + tx, err := t.Vault.signTransaction(key, rawTx) + if err != nil { + t.Fatalf("Unable to sign deploy tx: %v", err) + } + + if err = t.Eth.SendTransaction(t.Ctx(), tx); err != nil { + t.Fatalf("Unable to send transaction: %v", err) + } + block, err := t.Eth.BlockByNumber(t.Ctx(), nil) + if err != nil { + t.Fatalf("Unable to retrieve latest block: %v", err) + } + + if len(block.Transactions()) > 0 { + count, err := t.Eth.TransactionCount(t.Ctx(), block.Hash()) + if err != nil { + t.Fatalf("Unable to retrieve block transaction count: %v", err) + } + if count != uint(len(block.Transactions())) { + t.Fatalf("Invalid block tx count, want %d, got %d", len(block.Transactions()), count) + } + return + } + + time.Sleep(time.Second) + } +} + +// TransactionReceiptTest sends a transaction and tests the receipt fields. +func TransactionReceiptTest(t *TestEnv) { + var ( + key = t.Vault.createAccount(t, big.NewInt(params.Ether)) + ) + + rawTx := types.NewTransaction(uint64(0), common.Address{}, big1, 100000, gasPrice, nil) + tx, err := t.Vault.signTransaction(key, rawTx) + if err != nil { + t.Fatalf("Unable to sign deploy tx: %v", err) + } + + if err = t.Eth.SendTransaction(t.Ctx(), tx); err != nil { + t.Fatalf("Unable to send transaction: %v", err) + } + + for i := 0; i < 60; i++ { + receipt, err := t.Eth.TransactionReceipt(t.Ctx(), tx.Hash()) + if err == ethereum.NotFound { + time.Sleep(time.Second) + continue + } + + if err != nil { + t.Errorf("Unable to fetch receipt: %v", err) + } + if receipt.TxHash != tx.Hash() { + t.Errorf("Receipt [tx=%x] contains invalid tx hash, want %x, got %x", tx.Hash(), receipt.TxHash) + } + if receipt.ContractAddress != (common.Address{}) { + t.Errorf("Receipt [tx=%x] contains invalid contract address, expected empty address but got %x", tx.Hash(), receipt.ContractAddress) + } + if receipt.Bloom.Big().Cmp(big0) != 0 { + t.Errorf("Receipt [tx=%x] bloom not empty, %x", tx.Hash(), receipt.Bloom) + } + if receipt.GasUsed != params.TxGas { + t.Errorf("Receipt [tx=%x] has invalid gas used, want %d, got %d", tx.Hash(), params.TxGas, receipt.GasUsed) + } + if len(receipt.Logs) != 0 { + t.Errorf("Receipt [tx=%x] should not contain logs but got %d logs", tx.Hash(), len(receipt.Logs)) + } + return + } +} diff --git a/simulators/optimism/devnet/main.go b/simulators/optimism/devnet/main.go index cfd707fcb1..bcba87cf85 100644 --- a/simulators/optimism/devnet/main.go +++ b/simulators/optimism/devnet/main.go @@ -17,28 +17,51 @@ type testSpec struct { } var tests = []testSpec{ - // HTTP RPC tests. {Name: "http/BalanceAndNonceAt", Run: balanceAndNonceAtTest}, + {Name: "http/CanonicalChain", Run: canonicalChainTest}, + {Name: "http/CodeAt", Run: CodeAtTest}, {Name: "http/ContractDeployment", Run: deployContractTest}, {Name: "http/ContractDeploymentOutOfGas", Run: deployContractOutOfGasTest}, + {Name: "http/EstimateGas", Run: estimateGasTest}, {Name: "http/GenesisBlockByHash", Run: genesisBlockByHashTest}, {Name: "http/GenesisBlockByNumber", Run: genesisBlockByNumberTest}, {Name: "http/GenesisHeaderByHash", Run: genesisHeaderByHashTest}, {Name: "http/GenesisHeaderByNumber", Run: genesisHeaderByNumberTest}, + {Name: "http/Receipt", Run: receiptTest}, {Name: "http/SyncProgress", Run: syncProgressTest}, + {Name: "http/TransactionCount", Run: transactionCountTest}, + {Name: "http/TransactionInBlock", Run: transactionInBlockTest}, + {Name: "http/TransactionReceipt", Run: TransactionReceiptTest}, + + // HTTP ABI tests. + {Name: "http/ABICall", Run: callContractTest}, + {Name: "http/ABITransact", Run: transactContractTest}, + + // WebSocket ABI tests. + {Name: "ws/ABICall", Run: callContractTest}, + {Name: "ws/ABITransact", Run: transactContractTest}, + + // WebSocket subscription tests. + {Name: "ws/NewHeadSubscription", Run: newHeadSubscriptionTest}, + {Name: "ws/LogSubscription", Run: logSubscriptionTest}, + {Name: "ws/TransactionInBlockSubscription", Run: transactionInBlockSubscriptionTest}, // WebSocket RPC tests. {Name: "ws/BalanceAndNonceAt", Run: balanceAndNonceAtTest}, + {Name: "ws/CanonicalChain", Run: canonicalChainTest}, + {Name: "ws/CodeAt", Run: CodeAtTest}, {Name: "ws/ContractDeployment", Run: deployContractTest}, {Name: "ws/ContractDeploymentOutOfGas", Run: deployContractOutOfGasTest}, + {Name: "ws/EstimateGas", Run: estimateGasTest}, {Name: "ws/GenesisBlockByHash", Run: genesisBlockByHashTest}, {Name: "ws/GenesisBlockByNumber", Run: genesisBlockByNumberTest}, {Name: "ws/GenesisHeaderByHash", Run: genesisHeaderByHashTest}, {Name: "ws/GenesisHeaderByNumber", Run: genesisHeaderByNumberTest}, + {Name: "ws/Receipt", Run: receiptTest}, {Name: "ws/SyncProgress", Run: syncProgressTest}, - - // WebSocket subscription tests. - {Name: "ws/NewHeadSubscription", Run: newHeadSubscriptionTest}, + {Name: "ws/TransactionCount", Run: transactionCountTest}, + {Name: "ws/TransactionInBlock", Run: transactionInBlockTest}, + {Name: "ws/TransactionReceipt", Run: TransactionReceiptTest}, } func main() { diff --git a/simulators/optimism/devnet/testcontract/contract.go b/simulators/optimism/devnet/testcontract/contract.go new file mode 100644 index 0000000000..ae4ea8c13d --- /dev/null +++ b/simulators/optimism/devnet/testcontract/contract.go @@ -0,0 +1,993 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package testcontract + +import ( + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// ContractABI is the input ABI used to generate the binding from. +const ContractABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"ui\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"getFromMap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"addToMap\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"ui_\",\"type\":\"uint256\"},{\"name\":\"addr_\",\"type\":\"address\"}],\"name\":\"events\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"a\",\"type\":\"uint256\"},{\"name\":\"b\",\"type\":\"uint256\"},{\"name\":\"c\",\"type\":\"uint256\"}],\"name\":\"constFunc\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"ui_\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"E0\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"E1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"E2\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"\",\"type\":\"address\"}],\"name\":\"E3\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"\",\"type\":\"address\"}],\"name\":\"E4\",\"type\":\"event\"},{\"anonymous\":true,\"inputs\":[{\"indexed\":false,\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"\",\"type\":\"address\"}],\"name\":\"E5\",\"type\":\"event\"}]" + +// Contract is an auto generated Go binding around an Ethereum contract. +type Contract struct { + ContractCaller // Read-only binding to the contract + ContractTransactor // Write-only binding to the contract + ContractFilterer // Log filterer for contract events +} + +// ContractCaller is an auto generated read-only Go binding around an Ethereum contract. +type ContractCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ContractTransactor is an auto generated write-only Go binding around an Ethereum contract. +type ContractTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ContractFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ContractFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ContractSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ContractSession struct { + Contract *Contract // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ContractCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ContractCallerSession struct { + Contract *ContractCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ContractTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ContractTransactorSession struct { + Contract *ContractTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ContractRaw is an auto generated low-level Go binding around an Ethereum contract. +type ContractRaw struct { + Contract *Contract // Generic contract binding to access the raw methods on +} + +// ContractCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ContractCallerRaw struct { + Contract *ContractCaller // Generic read-only contract binding to access the raw methods on +} + +// ContractTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ContractTransactorRaw struct { + Contract *ContractTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewContract creates a new instance of Contract, bound to a specific deployed contract. +func NewContract(address common.Address, backend bind.ContractBackend) (*Contract, error) { + contract, err := bindContract(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Contract{ContractCaller: ContractCaller{contract: contract}, ContractTransactor: ContractTransactor{contract: contract}, ContractFilterer: ContractFilterer{contract: contract}}, nil +} + +// NewContractCaller creates a new read-only instance of Contract, bound to a specific deployed contract. +func NewContractCaller(address common.Address, caller bind.ContractCaller) (*ContractCaller, error) { + contract, err := bindContract(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ContractCaller{contract: contract}, nil +} + +// NewContractTransactor creates a new write-only instance of Contract, bound to a specific deployed contract. +func NewContractTransactor(address common.Address, transactor bind.ContractTransactor) (*ContractTransactor, error) { + contract, err := bindContract(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ContractTransactor{contract: contract}, nil +} + +// NewContractFilterer creates a new log filterer instance of Contract, bound to a specific deployed contract. +func NewContractFilterer(address common.Address, filterer bind.ContractFilterer) (*ContractFilterer, error) { + contract, err := bindContract(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ContractFilterer{contract: contract}, nil +} + +// bindContract binds a generic wrapper to an already deployed contract. +func bindContract(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(ContractABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Contract *ContractRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Contract.Contract.ContractCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Contract *ContractRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Contract.Contract.ContractTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Contract *ContractRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Contract.Contract.ContractTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Contract *ContractCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Contract.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Contract *ContractTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Contract.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Contract *ContractTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Contract.Contract.contract.Transact(opts, method, params...) +} + +// ConstFunc is a free data retrieval call binding the contract method 0xe6768b45. +// +// Solidity: function constFunc(uint256 a, uint256 b, uint256 c) returns(uint256, uint256, uint256) +func (_Contract *ContractCaller) ConstFunc(opts *bind.CallOpts, a *big.Int, b *big.Int, c *big.Int) (*big.Int, *big.Int, *big.Int, error) { + var out []interface{} + err := _Contract.contract.Call(opts, &out, "constFunc", a, b, c) + + if err != nil { + return *new(*big.Int), *new(*big.Int), *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + out1 := *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + out2 := *abi.ConvertType(out[2], new(*big.Int)).(**big.Int) + + return out0, out1, out2, err + +} + +// ConstFunc is a free data retrieval call binding the contract method 0xe6768b45. +// +// Solidity: function constFunc(uint256 a, uint256 b, uint256 c) returns(uint256, uint256, uint256) +func (_Contract *ContractSession) ConstFunc(a *big.Int, b *big.Int, c *big.Int) (*big.Int, *big.Int, *big.Int, error) { + return _Contract.Contract.ConstFunc(&_Contract.CallOpts, a, b, c) +} + +// ConstFunc is a free data retrieval call binding the contract method 0xe6768b45. +// +// Solidity: function constFunc(uint256 a, uint256 b, uint256 c) returns(uint256, uint256, uint256) +func (_Contract *ContractCallerSession) ConstFunc(a *big.Int, b *big.Int, c *big.Int) (*big.Int, *big.Int, *big.Int, error) { + return _Contract.Contract.ConstFunc(&_Contract.CallOpts, a, b, c) +} + +// GetFromMap is a free data retrieval call binding the contract method 0xabd1a0cf. +// +// Solidity: function getFromMap(address addr) returns(uint256) +func (_Contract *ContractCaller) GetFromMap(opts *bind.CallOpts, addr common.Address) (*big.Int, error) { + var out []interface{} + err := _Contract.contract.Call(opts, &out, "getFromMap", addr) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetFromMap is a free data retrieval call binding the contract method 0xabd1a0cf. +// +// Solidity: function getFromMap(address addr) returns(uint256) +func (_Contract *ContractSession) GetFromMap(addr common.Address) (*big.Int, error) { + return _Contract.Contract.GetFromMap(&_Contract.CallOpts, addr) +} + +// GetFromMap is a free data retrieval call binding the contract method 0xabd1a0cf. +// +// Solidity: function getFromMap(address addr) returns(uint256) +func (_Contract *ContractCallerSession) GetFromMap(addr common.Address) (*big.Int, error) { + return _Contract.Contract.GetFromMap(&_Contract.CallOpts, addr) +} + +// Ui is a free data retrieval call binding the contract method 0xa223e05d. +// +// Solidity: function ui() returns(uint256) +func (_Contract *ContractCaller) Ui(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.contract.Call(opts, &out, "ui") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Ui is a free data retrieval call binding the contract method 0xa223e05d. +// +// Solidity: function ui() returns(uint256) +func (_Contract *ContractSession) Ui() (*big.Int, error) { + return _Contract.Contract.Ui(&_Contract.CallOpts) +} + +// Ui is a free data retrieval call binding the contract method 0xa223e05d. +// +// Solidity: function ui() returns(uint256) +func (_Contract *ContractCallerSession) Ui() (*big.Int, error) { + return _Contract.Contract.Ui(&_Contract.CallOpts) +} + +// AddToMap is a paid mutator transaction binding the contract method 0xabfced1d. +// +// Solidity: function addToMap(address addr, uint256 value) returns() +func (_Contract *ContractTransactor) AddToMap(opts *bind.TransactOpts, addr common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.contract.Transact(opts, "addToMap", addr, value) +} + +// AddToMap is a paid mutator transaction binding the contract method 0xabfced1d. +// +// Solidity: function addToMap(address addr, uint256 value) returns() +func (_Contract *ContractSession) AddToMap(addr common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.AddToMap(&_Contract.TransactOpts, addr, value) +} + +// AddToMap is a paid mutator transaction binding the contract method 0xabfced1d. +// +// Solidity: function addToMap(address addr, uint256 value) returns() +func (_Contract *ContractTransactorSession) AddToMap(addr common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.AddToMap(&_Contract.TransactOpts, addr, value) +} + +// Events is a paid mutator transaction binding the contract method 0xe05c914a. +// +// Solidity: function events(uint256 ui_, address addr_) returns() +func (_Contract *ContractTransactor) Events(opts *bind.TransactOpts, ui_ *big.Int, addr_ common.Address) (*types.Transaction, error) { + return _Contract.contract.Transact(opts, "events", ui_, addr_) +} + +// Events is a paid mutator transaction binding the contract method 0xe05c914a. +// +// Solidity: function events(uint256 ui_, address addr_) returns() +func (_Contract *ContractSession) Events(ui_ *big.Int, addr_ common.Address) (*types.Transaction, error) { + return _Contract.Contract.Events(&_Contract.TransactOpts, ui_, addr_) +} + +// Events is a paid mutator transaction binding the contract method 0xe05c914a. +// +// Solidity: function events(uint256 ui_, address addr_) returns() +func (_Contract *ContractTransactorSession) Events(ui_ *big.Int, addr_ common.Address) (*types.Transaction, error) { + return _Contract.Contract.Events(&_Contract.TransactOpts, ui_, addr_) +} + +// ContractE0Iterator is returned from FilterE0 and is used to iterate over the raw logs and unpacked data for E0 events raised by the Contract contract. +type ContractE0Iterator struct { + Event *ContractE0 // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ContractE0Iterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ContractE0) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ContractE0) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ContractE0Iterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ContractE0Iterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ContractE0 represents a E0 event raised by the Contract contract. +type ContractE0 struct { + Raw types.Log // Blockchain specific contextual infos +} + +// FilterE0 is a free log retrieval operation binding the contract event 0x6031a8d62d7c95988fa262657cd92107d90ed96e08d8f867d32f26edfe855022. +// +// Solidity: event E0() +func (_Contract *ContractFilterer) FilterE0(opts *bind.FilterOpts) (*ContractE0Iterator, error) { + + logs, sub, err := _Contract.contract.FilterLogs(opts, "E0") + if err != nil { + return nil, err + } + return &ContractE0Iterator{contract: _Contract.contract, event: "E0", logs: logs, sub: sub}, nil +} + +// WatchE0 is a free log subscription operation binding the contract event 0x6031a8d62d7c95988fa262657cd92107d90ed96e08d8f867d32f26edfe855022. +// +// Solidity: event E0() +func (_Contract *ContractFilterer) WatchE0(opts *bind.WatchOpts, sink chan<- *ContractE0) (event.Subscription, error) { + + logs, sub, err := _Contract.contract.WatchLogs(opts, "E0") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ContractE0) + if err := _Contract.contract.UnpackLog(event, "E0", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseE0 is a log parse operation binding the contract event 0x6031a8d62d7c95988fa262657cd92107d90ed96e08d8f867d32f26edfe855022. +// +// Solidity: event E0() +func (_Contract *ContractFilterer) ParseE0(log types.Log) (*ContractE0, error) { + event := new(ContractE0) + if err := _Contract.contract.UnpackLog(event, "E0", log); err != nil { + return nil, err + } + return event, nil +} + +// ContractE1Iterator is returned from FilterE1 and is used to iterate over the raw logs and unpacked data for E1 events raised by the Contract contract. +type ContractE1Iterator struct { + Event *ContractE1 // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ContractE1Iterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ContractE1) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ContractE1) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ContractE1Iterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ContractE1Iterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ContractE1 represents a E1 event raised by the Contract contract. +type ContractE1 struct { + Arg0 *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterE1 is a free log retrieval operation binding the contract event 0x47e2689743f14e97f7dcfa5eec10ba1dff02f83b3d1d4b9c07b206cbbda66450. +// +// Solidity: event E1(uint256 arg0) +func (_Contract *ContractFilterer) FilterE1(opts *bind.FilterOpts) (*ContractE1Iterator, error) { + + logs, sub, err := _Contract.contract.FilterLogs(opts, "E1") + if err != nil { + return nil, err + } + return &ContractE1Iterator{contract: _Contract.contract, event: "E1", logs: logs, sub: sub}, nil +} + +// WatchE1 is a free log subscription operation binding the contract event 0x47e2689743f14e97f7dcfa5eec10ba1dff02f83b3d1d4b9c07b206cbbda66450. +// +// Solidity: event E1(uint256 arg0) +func (_Contract *ContractFilterer) WatchE1(opts *bind.WatchOpts, sink chan<- *ContractE1) (event.Subscription, error) { + + logs, sub, err := _Contract.contract.WatchLogs(opts, "E1") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ContractE1) + if err := _Contract.contract.UnpackLog(event, "E1", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseE1 is a log parse operation binding the contract event 0x47e2689743f14e97f7dcfa5eec10ba1dff02f83b3d1d4b9c07b206cbbda66450. +// +// Solidity: event E1(uint256 arg0) +func (_Contract *ContractFilterer) ParseE1(log types.Log) (*ContractE1, error) { + event := new(ContractE1) + if err := _Contract.contract.UnpackLog(event, "E1", log); err != nil { + return nil, err + } + return event, nil +} + +// ContractE2Iterator is returned from FilterE2 and is used to iterate over the raw logs and unpacked data for E2 events raised by the Contract contract. +type ContractE2Iterator struct { + Event *ContractE2 // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ContractE2Iterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ContractE2) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ContractE2) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ContractE2Iterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ContractE2Iterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ContractE2 represents a E2 event raised by the Contract contract. +type ContractE2 struct { + Arg0 *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterE2 is a free log retrieval operation binding the contract event 0xa48a6b249a5084126c3da369fbc9b16827ead8cb5cdc094b717d3f1dcd995e29. +// +// Solidity: event E2(uint256 indexed arg0) +func (_Contract *ContractFilterer) FilterE2(opts *bind.FilterOpts, arg0 []*big.Int) (*ContractE2Iterator, error) { + + var arg0Rule []interface{} + for _, arg0Item := range arg0 { + arg0Rule = append(arg0Rule, arg0Item) + } + + logs, sub, err := _Contract.contract.FilterLogs(opts, "E2", arg0Rule) + if err != nil { + return nil, err + } + return &ContractE2Iterator{contract: _Contract.contract, event: "E2", logs: logs, sub: sub}, nil +} + +// WatchE2 is a free log subscription operation binding the contract event 0xa48a6b249a5084126c3da369fbc9b16827ead8cb5cdc094b717d3f1dcd995e29. +// +// Solidity: event E2(uint256 indexed arg0) +func (_Contract *ContractFilterer) WatchE2(opts *bind.WatchOpts, sink chan<- *ContractE2, arg0 []*big.Int) (event.Subscription, error) { + + var arg0Rule []interface{} + for _, arg0Item := range arg0 { + arg0Rule = append(arg0Rule, arg0Item) + } + + logs, sub, err := _Contract.contract.WatchLogs(opts, "E2", arg0Rule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ContractE2) + if err := _Contract.contract.UnpackLog(event, "E2", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseE2 is a log parse operation binding the contract event 0xa48a6b249a5084126c3da369fbc9b16827ead8cb5cdc094b717d3f1dcd995e29. +// +// Solidity: event E2(uint256 indexed arg0) +func (_Contract *ContractFilterer) ParseE2(log types.Log) (*ContractE2, error) { + event := new(ContractE2) + if err := _Contract.contract.UnpackLog(event, "E2", log); err != nil { + return nil, err + } + return event, nil +} + +// ContractE3Iterator is returned from FilterE3 and is used to iterate over the raw logs and unpacked data for E3 events raised by the Contract contract. +type ContractE3Iterator struct { + Event *ContractE3 // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ContractE3Iterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ContractE3) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ContractE3) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ContractE3Iterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ContractE3Iterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ContractE3 represents a E3 event raised by the Contract contract. +type ContractE3 struct { + Arg0 common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterE3 is a free log retrieval operation binding the contract event 0x7890603b316f3509577afd111710f9ebeefa15e12f72347d9dffd0d65ae3bade. +// +// Solidity: event E3(address arg0) +func (_Contract *ContractFilterer) FilterE3(opts *bind.FilterOpts) (*ContractE3Iterator, error) { + + logs, sub, err := _Contract.contract.FilterLogs(opts, "E3") + if err != nil { + return nil, err + } + return &ContractE3Iterator{contract: _Contract.contract, event: "E3", logs: logs, sub: sub}, nil +} + +// WatchE3 is a free log subscription operation binding the contract event 0x7890603b316f3509577afd111710f9ebeefa15e12f72347d9dffd0d65ae3bade. +// +// Solidity: event E3(address arg0) +func (_Contract *ContractFilterer) WatchE3(opts *bind.WatchOpts, sink chan<- *ContractE3) (event.Subscription, error) { + + logs, sub, err := _Contract.contract.WatchLogs(opts, "E3") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ContractE3) + if err := _Contract.contract.UnpackLog(event, "E3", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseE3 is a log parse operation binding the contract event 0x7890603b316f3509577afd111710f9ebeefa15e12f72347d9dffd0d65ae3bade. +// +// Solidity: event E3(address arg0) +func (_Contract *ContractFilterer) ParseE3(log types.Log) (*ContractE3, error) { + event := new(ContractE3) + if err := _Contract.contract.UnpackLog(event, "E3", log); err != nil { + return nil, err + } + return event, nil +} + +// ContractE4Iterator is returned from FilterE4 and is used to iterate over the raw logs and unpacked data for E4 events raised by the Contract contract. +type ContractE4Iterator struct { + Event *ContractE4 // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ContractE4Iterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ContractE4) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ContractE4) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ContractE4Iterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ContractE4Iterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ContractE4 represents a E4 event raised by the Contract contract. +type ContractE4 struct { + Arg0 common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterE4 is a free log retrieval operation binding the contract event 0x7efef9ea3f60ddc038e50cccec621f86a0195894dc0520482abf8b5c6b659e41. +// +// Solidity: event E4(address indexed arg0) +func (_Contract *ContractFilterer) FilterE4(opts *bind.FilterOpts, arg0 []common.Address) (*ContractE4Iterator, error) { + + var arg0Rule []interface{} + for _, arg0Item := range arg0 { + arg0Rule = append(arg0Rule, arg0Item) + } + + logs, sub, err := _Contract.contract.FilterLogs(opts, "E4", arg0Rule) + if err != nil { + return nil, err + } + return &ContractE4Iterator{contract: _Contract.contract, event: "E4", logs: logs, sub: sub}, nil +} + +// WatchE4 is a free log subscription operation binding the contract event 0x7efef9ea3f60ddc038e50cccec621f86a0195894dc0520482abf8b5c6b659e41. +// +// Solidity: event E4(address indexed arg0) +func (_Contract *ContractFilterer) WatchE4(opts *bind.WatchOpts, sink chan<- *ContractE4, arg0 []common.Address) (event.Subscription, error) { + + var arg0Rule []interface{} + for _, arg0Item := range arg0 { + arg0Rule = append(arg0Rule, arg0Item) + } + + logs, sub, err := _Contract.contract.WatchLogs(opts, "E4", arg0Rule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ContractE4) + if err := _Contract.contract.UnpackLog(event, "E4", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseE4 is a log parse operation binding the contract event 0x7efef9ea3f60ddc038e50cccec621f86a0195894dc0520482abf8b5c6b659e41. +// +// Solidity: event E4(address indexed arg0) +func (_Contract *ContractFilterer) ParseE4(log types.Log) (*ContractE4, error) { + event := new(ContractE4) + if err := _Contract.contract.UnpackLog(event, "E4", log); err != nil { + return nil, err + } + return event, nil +} diff --git a/simulators/optimism/devnet/vault.go b/simulators/optimism/devnet/vault.go index 2ccd2e6d35..755f5780c2 100644 --- a/simulators/optimism/devnet/vault.go +++ b/simulators/optimism/devnet/vault.go @@ -19,6 +19,7 @@ var ( vaultAccountAddr = common.HexToAddress("0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266") vaultKey, _ = crypto.HexToECDSA("ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80") // Address of the vault in genesis. + predeployedVaultAddr = common.HexToAddress("0000000000000000000000000000000000000315") // Number of blocks to wait before funding tx is considered valid. vaultTxConfirmationCount = uint64(5) )