From 0c421419e55319f39bcc27c3ce5e68d9ae3340e9 Mon Sep 17 00:00:00 2001 From: skosito Date: Thu, 5 Sep 2024 18:20:07 +0100 Subject: [PATCH 1/2] test(e2e): call prototype precompile through contract (#2822) * add missing prototype precompile test to call precompile through contract * fund precompile acc and add to gen accounts * split tests into 2 files --- cmd/zetae2e/local/local.go | 1 + .../localnet/orchestrator/start-zetae2e.sh | 3 + contrib/localnet/scripts/start-zetacored.sh | 2 +- e2e/contracts/testprototype/TestPrototype.abi | 64 ++++ e2e/contracts/testprototype/TestPrototype.bin | 1 + e2e/contracts/testprototype/TestPrototype.go | 296 ++++++++++++++++++ .../testprototype/TestPrototype.json | 67 ++++ e2e/contracts/testprototype/TestPrototype.sol | 36 +++ e2e/contracts/testprototype/bindings.go | 8 + e2e/e2etests/e2etests.go | 11 +- ..._precompiles_prototype_through_contract.go | 38 +++ 11 files changed, 524 insertions(+), 3 deletions(-) create mode 100644 e2e/contracts/testprototype/TestPrototype.abi create mode 100644 e2e/contracts/testprototype/TestPrototype.bin create mode 100644 e2e/contracts/testprototype/TestPrototype.go create mode 100644 e2e/contracts/testprototype/TestPrototype.json create mode 100644 e2e/contracts/testprototype/TestPrototype.sol create mode 100644 e2e/contracts/testprototype/bindings.go create mode 100644 e2e/e2etests/test_precompiles_prototype_through_contract.go diff --git a/cmd/zetae2e/local/local.go b/cmd/zetae2e/local/local.go index fdde8e5840..ab6ca1248e 100644 --- a/cmd/zetae2e/local/local.go +++ b/cmd/zetae2e/local/local.go @@ -310,6 +310,7 @@ func localE2ETest(cmd *cobra.Command, _ []string) { if !skipPrecompiles { precompiledContractTests = []string{ e2etests.TestPrecompilesPrototypeName, + e2etests.TestPrecompilesPrototypeThroughContractName, e2etests.TestPrecompilesStakingName, } } diff --git a/contrib/localnet/orchestrator/start-zetae2e.sh b/contrib/localnet/orchestrator/start-zetae2e.sh index ed762288bc..aa0531e141 100644 --- a/contrib/localnet/orchestrator/start-zetae2e.sh +++ b/contrib/localnet/orchestrator/start-zetae2e.sh @@ -116,6 +116,9 @@ fund_eth_from_config '.additional_accounts.user_admin.evm_address' 10000 "admin # unlock migration tests accounts fund_eth_from_config '.additional_accounts.user_migration.evm_address' 10000 "migration tester" +# unlock precompile tests accounts +fund_eth_from_config '.additional_accounts.user_precompile.evm_address' 10000 "precompile tester" + # unlock v2 ethers tests accounts fund_eth_from_config '.additional_accounts.user_v2_ether.evm_address' 10000 "V2 ethers tester" diff --git a/contrib/localnet/scripts/start-zetacored.sh b/contrib/localnet/scripts/start-zetacored.sh index a7cf53021f..1f5e2fca12 100755 --- a/contrib/localnet/scripts/start-zetacored.sh +++ b/contrib/localnet/scripts/start-zetacored.sh @@ -254,7 +254,7 @@ then # migration tester address=$(yq -r '.additional_accounts.user_migration.bech32_address' /root/config.yml) zetacored add-genesis-account "$address" 100000000000000000000000000azeta -# precompiles tester +# precompile tester address=$(yq -r '.additional_accounts.user_precompile.bech32_address' /root/config.yml) zetacored add-genesis-account "$address" 100000000000000000000000000azeta # v2 ether tester diff --git a/e2e/contracts/testprototype/TestPrototype.abi b/e2e/contracts/testprototype/TestPrototype.abi new file mode 100644 index 0000000000..d510aa3ec5 --- /dev/null +++ b/e2e/contracts/testprototype/TestPrototype.abi @@ -0,0 +1,64 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "bech32", + "type": "string" + } + ], + "name": "bech32ToHexAddr", + "outputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "prefix", + "type": "string" + }, + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "bech32ify", + "outputs": [ + { + "internalType": "string", + "name": "bech32", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int64", + "name": "chainID", + "type": "int64" + } + ], + "name": "getGasStabilityPoolBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "result", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/e2e/contracts/testprototype/TestPrototype.bin b/e2e/contracts/testprototype/TestPrototype.bin new file mode 100644 index 0000000000..5206be2b24 --- /dev/null +++ b/e2e/contracts/testprototype/TestPrototype.bin @@ -0,0 +1 @@ +608060405260656000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561005157600080fd5b50610878806100616000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80630615b74e146100465780633ee8d1a414610076578063e4e2a4ec146100a6575b600080fd5b610060600480360381019061005b9190610481565b6100d6565b60405161006d9190610565565b60405180910390f35b610090600480360381019061008b91906105c0565b610181565b60405161009d9190610606565b60405180910390f35b6100c060048036038101906100bb9190610621565b610225565b6040516100cd9190610679565b60405180910390f35b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630615b74e84846040518363ffffffff1660e01b8152600401610133929190610694565b600060405180830381865afa158015610150573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906101799190610734565b905092915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16633ee8d1a4836040518263ffffffff1660e01b81526004016101dd919061078c565b602060405180830381865afa1580156101fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061021e91906107d3565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e4e2a4ec836040518263ffffffff1660e01b81526004016102819190610565565b602060405180830381865afa15801561029e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102c29190610815565b9050919050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610330826102e7565b810181811067ffffffffffffffff8211171561034f5761034e6102f8565b5b80604052505050565b60006103626102c9565b905061036e8282610327565b919050565b600067ffffffffffffffff82111561038e5761038d6102f8565b5b610397826102e7565b9050602081019050919050565b82818337600083830152505050565b60006103c66103c184610373565b610358565b9050828152602081018484840111156103e2576103e16102e2565b5b6103ed8482856103a4565b509392505050565b600082601f83011261040a576104096102dd565b5b813561041a8482602086016103b3565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061044e82610423565b9050919050565b61045e81610443565b811461046957600080fd5b50565b60008135905061047b81610455565b92915050565b60008060408385031215610498576104976102d3565b5b600083013567ffffffffffffffff8111156104b6576104b56102d8565b5b6104c2858286016103f5565b92505060206104d38582860161046c565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156105175780820151818401526020810190506104fc565b83811115610526576000848401525b50505050565b6000610537826104dd565b61054181856104e8565b93506105518185602086016104f9565b61055a816102e7565b840191505092915050565b6000602082019050818103600083015261057f818461052c565b905092915050565b60008160070b9050919050565b61059d81610587565b81146105a857600080fd5b50565b6000813590506105ba81610594565b92915050565b6000602082840312156105d6576105d56102d3565b5b60006105e4848285016105ab565b91505092915050565b6000819050919050565b610600816105ed565b82525050565b600060208201905061061b60008301846105f7565b92915050565b600060208284031215610637576106366102d3565b5b600082013567ffffffffffffffff811115610655576106546102d8565b5b610661848285016103f5565b91505092915050565b61067381610443565b82525050565b600060208201905061068e600083018461066a565b92915050565b600060408201905081810360008301526106ae818561052c565b90506106bd602083018461066a565b9392505050565b60006106d76106d284610373565b610358565b9050828152602081018484840111156106f3576106f26102e2565b5b6106fe8482856104f9565b509392505050565b600082601f83011261071b5761071a6102dd565b5b815161072b8482602086016106c4565b91505092915050565b60006020828403121561074a576107496102d3565b5b600082015167ffffffffffffffff811115610768576107676102d8565b5b61077484828501610706565b91505092915050565b61078681610587565b82525050565b60006020820190506107a1600083018461077d565b92915050565b6107b0816105ed565b81146107bb57600080fd5b50565b6000815190506107cd816107a7565b92915050565b6000602082840312156107e9576107e86102d3565b5b60006107f7848285016107be565b91505092915050565b60008151905061080f81610455565b92915050565b60006020828403121561082b5761082a6102d3565b5b600061083984828501610800565b9150509291505056fea26469706673582212203599aa5bcc18cda9492a410a6619dfd803fa572b0624c47efa4d4159a8f2430f64736f6c634300080a0033 diff --git a/e2e/contracts/testprototype/TestPrototype.go b/e2e/contracts/testprototype/TestPrototype.go new file mode 100644 index 0000000000..ba3b78b119 --- /dev/null +++ b/e2e/contracts/testprototype/TestPrototype.go @@ -0,0 +1,296 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package testprototype + +import ( + "errors" + "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 ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// TestPrototypeMetaData contains all meta data concerning the TestPrototype contract. +var TestPrototypeMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"bech32\",\"type\":\"string\"}],\"name\":\"bech32ToHexAddr\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"prefix\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"bech32ify\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"bech32\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int64\",\"name\":\"chainID\",\"type\":\"int64\"}],\"name\":\"getGasStabilityPoolBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"result\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x608060405260656000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561005157600080fd5b50610878806100616000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80630615b74e146100465780633ee8d1a414610076578063e4e2a4ec146100a6575b600080fd5b610060600480360381019061005b9190610481565b6100d6565b60405161006d9190610565565b60405180910390f35b610090600480360381019061008b91906105c0565b610181565b60405161009d9190610606565b60405180910390f35b6100c060048036038101906100bb9190610621565b610225565b6040516100cd9190610679565b60405180910390f35b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630615b74e84846040518363ffffffff1660e01b8152600401610133929190610694565b600060405180830381865afa158015610150573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906101799190610734565b905092915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16633ee8d1a4836040518263ffffffff1660e01b81526004016101dd919061078c565b602060405180830381865afa1580156101fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061021e91906107d3565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e4e2a4ec836040518263ffffffff1660e01b81526004016102819190610565565b602060405180830381865afa15801561029e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102c29190610815565b9050919050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610330826102e7565b810181811067ffffffffffffffff8211171561034f5761034e6102f8565b5b80604052505050565b60006103626102c9565b905061036e8282610327565b919050565b600067ffffffffffffffff82111561038e5761038d6102f8565b5b610397826102e7565b9050602081019050919050565b82818337600083830152505050565b60006103c66103c184610373565b610358565b9050828152602081018484840111156103e2576103e16102e2565b5b6103ed8482856103a4565b509392505050565b600082601f83011261040a576104096102dd565b5b813561041a8482602086016103b3565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061044e82610423565b9050919050565b61045e81610443565b811461046957600080fd5b50565b60008135905061047b81610455565b92915050565b60008060408385031215610498576104976102d3565b5b600083013567ffffffffffffffff8111156104b6576104b56102d8565b5b6104c2858286016103f5565b92505060206104d38582860161046c565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156105175780820151818401526020810190506104fc565b83811115610526576000848401525b50505050565b6000610537826104dd565b61054181856104e8565b93506105518185602086016104f9565b61055a816102e7565b840191505092915050565b6000602082019050818103600083015261057f818461052c565b905092915050565b60008160070b9050919050565b61059d81610587565b81146105a857600080fd5b50565b6000813590506105ba81610594565b92915050565b6000602082840312156105d6576105d56102d3565b5b60006105e4848285016105ab565b91505092915050565b6000819050919050565b610600816105ed565b82525050565b600060208201905061061b60008301846105f7565b92915050565b600060208284031215610637576106366102d3565b5b600082013567ffffffffffffffff811115610655576106546102d8565b5b610661848285016103f5565b91505092915050565b61067381610443565b82525050565b600060208201905061068e600083018461066a565b92915050565b600060408201905081810360008301526106ae818561052c565b90506106bd602083018461066a565b9392505050565b60006106d76106d284610373565b610358565b9050828152602081018484840111156106f3576106f26102e2565b5b6106fe8482856104f9565b509392505050565b600082601f83011261071b5761071a6102dd565b5b815161072b8482602086016106c4565b91505092915050565b60006020828403121561074a576107496102d3565b5b600082015167ffffffffffffffff811115610768576107676102d8565b5b61077484828501610706565b91505092915050565b61078681610587565b82525050565b60006020820190506107a1600083018461077d565b92915050565b6107b0816105ed565b81146107bb57600080fd5b50565b6000815190506107cd816107a7565b92915050565b6000602082840312156107e9576107e86102d3565b5b60006107f7848285016107be565b91505092915050565b60008151905061080f81610455565b92915050565b60006020828403121561082b5761082a6102d3565b5b600061083984828501610800565b9150509291505056fea26469706673582212203599aa5bcc18cda9492a410a6619dfd803fa572b0624c47efa4d4159a8f2430f64736f6c634300080a0033", +} + +// TestPrototypeABI is the input ABI used to generate the binding from. +// Deprecated: Use TestPrototypeMetaData.ABI instead. +var TestPrototypeABI = TestPrototypeMetaData.ABI + +// TestPrototypeBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use TestPrototypeMetaData.Bin instead. +var TestPrototypeBin = TestPrototypeMetaData.Bin + +// DeployTestPrototype deploys a new Ethereum contract, binding an instance of TestPrototype to it. +func DeployTestPrototype(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *TestPrototype, error) { + parsed, err := TestPrototypeMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(TestPrototypeBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &TestPrototype{TestPrototypeCaller: TestPrototypeCaller{contract: contract}, TestPrototypeTransactor: TestPrototypeTransactor{contract: contract}, TestPrototypeFilterer: TestPrototypeFilterer{contract: contract}}, nil +} + +// TestPrototype is an auto generated Go binding around an Ethereum contract. +type TestPrototype struct { + TestPrototypeCaller // Read-only binding to the contract + TestPrototypeTransactor // Write-only binding to the contract + TestPrototypeFilterer // Log filterer for contract events +} + +// TestPrototypeCaller is an auto generated read-only Go binding around an Ethereum contract. +type TestPrototypeCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// TestPrototypeTransactor is an auto generated write-only Go binding around an Ethereum contract. +type TestPrototypeTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// TestPrototypeFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type TestPrototypeFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// TestPrototypeSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type TestPrototypeSession struct { + Contract *TestPrototype // 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 +} + +// TestPrototypeCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type TestPrototypeCallerSession struct { + Contract *TestPrototypeCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// TestPrototypeTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type TestPrototypeTransactorSession struct { + Contract *TestPrototypeTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// TestPrototypeRaw is an auto generated low-level Go binding around an Ethereum contract. +type TestPrototypeRaw struct { + Contract *TestPrototype // Generic contract binding to access the raw methods on +} + +// TestPrototypeCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type TestPrototypeCallerRaw struct { + Contract *TestPrototypeCaller // Generic read-only contract binding to access the raw methods on +} + +// TestPrototypeTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type TestPrototypeTransactorRaw struct { + Contract *TestPrototypeTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewTestPrototype creates a new instance of TestPrototype, bound to a specific deployed contract. +func NewTestPrototype(address common.Address, backend bind.ContractBackend) (*TestPrototype, error) { + contract, err := bindTestPrototype(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &TestPrototype{TestPrototypeCaller: TestPrototypeCaller{contract: contract}, TestPrototypeTransactor: TestPrototypeTransactor{contract: contract}, TestPrototypeFilterer: TestPrototypeFilterer{contract: contract}}, nil +} + +// NewTestPrototypeCaller creates a new read-only instance of TestPrototype, bound to a specific deployed contract. +func NewTestPrototypeCaller(address common.Address, caller bind.ContractCaller) (*TestPrototypeCaller, error) { + contract, err := bindTestPrototype(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &TestPrototypeCaller{contract: contract}, nil +} + +// NewTestPrototypeTransactor creates a new write-only instance of TestPrototype, bound to a specific deployed contract. +func NewTestPrototypeTransactor(address common.Address, transactor bind.ContractTransactor) (*TestPrototypeTransactor, error) { + contract, err := bindTestPrototype(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &TestPrototypeTransactor{contract: contract}, nil +} + +// NewTestPrototypeFilterer creates a new log filterer instance of TestPrototype, bound to a specific deployed contract. +func NewTestPrototypeFilterer(address common.Address, filterer bind.ContractFilterer) (*TestPrototypeFilterer, error) { + contract, err := bindTestPrototype(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &TestPrototypeFilterer{contract: contract}, nil +} + +// bindTestPrototype binds a generic wrapper to an already deployed contract. +func bindTestPrototype(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := TestPrototypeMetaData.GetAbi() + 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 (_TestPrototype *TestPrototypeRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _TestPrototype.Contract.TestPrototypeCaller.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 (_TestPrototype *TestPrototypeRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _TestPrototype.Contract.TestPrototypeTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_TestPrototype *TestPrototypeRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _TestPrototype.Contract.TestPrototypeTransactor.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 (_TestPrototype *TestPrototypeCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _TestPrototype.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 (_TestPrototype *TestPrototypeTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _TestPrototype.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_TestPrototype *TestPrototypeTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _TestPrototype.Contract.contract.Transact(opts, method, params...) +} + +// Bech32ToHexAddr is a free data retrieval call binding the contract method 0xe4e2a4ec. +// +// Solidity: function bech32ToHexAddr(string bech32) view returns(address addr) +func (_TestPrototype *TestPrototypeCaller) Bech32ToHexAddr(opts *bind.CallOpts, bech32 string) (common.Address, error) { + var out []interface{} + err := _TestPrototype.contract.Call(opts, &out, "bech32ToHexAddr", bech32) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Bech32ToHexAddr is a free data retrieval call binding the contract method 0xe4e2a4ec. +// +// Solidity: function bech32ToHexAddr(string bech32) view returns(address addr) +func (_TestPrototype *TestPrototypeSession) Bech32ToHexAddr(bech32 string) (common.Address, error) { + return _TestPrototype.Contract.Bech32ToHexAddr(&_TestPrototype.CallOpts, bech32) +} + +// Bech32ToHexAddr is a free data retrieval call binding the contract method 0xe4e2a4ec. +// +// Solidity: function bech32ToHexAddr(string bech32) view returns(address addr) +func (_TestPrototype *TestPrototypeCallerSession) Bech32ToHexAddr(bech32 string) (common.Address, error) { + return _TestPrototype.Contract.Bech32ToHexAddr(&_TestPrototype.CallOpts, bech32) +} + +// Bech32ify is a free data retrieval call binding the contract method 0x0615b74e. +// +// Solidity: function bech32ify(string prefix, address addr) view returns(string bech32) +func (_TestPrototype *TestPrototypeCaller) Bech32ify(opts *bind.CallOpts, prefix string, addr common.Address) (string, error) { + var out []interface{} + err := _TestPrototype.contract.Call(opts, &out, "bech32ify", prefix, addr) + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Bech32ify is a free data retrieval call binding the contract method 0x0615b74e. +// +// Solidity: function bech32ify(string prefix, address addr) view returns(string bech32) +func (_TestPrototype *TestPrototypeSession) Bech32ify(prefix string, addr common.Address) (string, error) { + return _TestPrototype.Contract.Bech32ify(&_TestPrototype.CallOpts, prefix, addr) +} + +// Bech32ify is a free data retrieval call binding the contract method 0x0615b74e. +// +// Solidity: function bech32ify(string prefix, address addr) view returns(string bech32) +func (_TestPrototype *TestPrototypeCallerSession) Bech32ify(prefix string, addr common.Address) (string, error) { + return _TestPrototype.Contract.Bech32ify(&_TestPrototype.CallOpts, prefix, addr) +} + +// GetGasStabilityPoolBalance is a free data retrieval call binding the contract method 0x3ee8d1a4. +// +// Solidity: function getGasStabilityPoolBalance(int64 chainID) view returns(uint256 result) +func (_TestPrototype *TestPrototypeCaller) GetGasStabilityPoolBalance(opts *bind.CallOpts, chainID int64) (*big.Int, error) { + var out []interface{} + err := _TestPrototype.contract.Call(opts, &out, "getGasStabilityPoolBalance", chainID) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetGasStabilityPoolBalance is a free data retrieval call binding the contract method 0x3ee8d1a4. +// +// Solidity: function getGasStabilityPoolBalance(int64 chainID) view returns(uint256 result) +func (_TestPrototype *TestPrototypeSession) GetGasStabilityPoolBalance(chainID int64) (*big.Int, error) { + return _TestPrototype.Contract.GetGasStabilityPoolBalance(&_TestPrototype.CallOpts, chainID) +} + +// GetGasStabilityPoolBalance is a free data retrieval call binding the contract method 0x3ee8d1a4. +// +// Solidity: function getGasStabilityPoolBalance(int64 chainID) view returns(uint256 result) +func (_TestPrototype *TestPrototypeCallerSession) GetGasStabilityPoolBalance(chainID int64) (*big.Int, error) { + return _TestPrototype.Contract.GetGasStabilityPoolBalance(&_TestPrototype.CallOpts, chainID) +} diff --git a/e2e/contracts/testprototype/TestPrototype.json b/e2e/contracts/testprototype/TestPrototype.json new file mode 100644 index 0000000000..a066b36437 --- /dev/null +++ b/e2e/contracts/testprototype/TestPrototype.json @@ -0,0 +1,67 @@ +{ + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "bech32", + "type": "string" + } + ], + "name": "bech32ToHexAddr", + "outputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "prefix", + "type": "string" + }, + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "bech32ify", + "outputs": [ + { + "internalType": "string", + "name": "bech32", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int64", + "name": "chainID", + "type": "int64" + } + ], + "name": "getGasStabilityPoolBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "result", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bin": "608060405260656000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561005157600080fd5b50610878806100616000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80630615b74e146100465780633ee8d1a414610076578063e4e2a4ec146100a6575b600080fd5b610060600480360381019061005b9190610481565b6100d6565b60405161006d9190610565565b60405180910390f35b610090600480360381019061008b91906105c0565b610181565b60405161009d9190610606565b60405180910390f35b6100c060048036038101906100bb9190610621565b610225565b6040516100cd9190610679565b60405180910390f35b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630615b74e84846040518363ffffffff1660e01b8152600401610133929190610694565b600060405180830381865afa158015610150573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906101799190610734565b905092915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16633ee8d1a4836040518263ffffffff1660e01b81526004016101dd919061078c565b602060405180830381865afa1580156101fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061021e91906107d3565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e4e2a4ec836040518263ffffffff1660e01b81526004016102819190610565565b602060405180830381865afa15801561029e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102c29190610815565b9050919050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610330826102e7565b810181811067ffffffffffffffff8211171561034f5761034e6102f8565b5b80604052505050565b60006103626102c9565b905061036e8282610327565b919050565b600067ffffffffffffffff82111561038e5761038d6102f8565b5b610397826102e7565b9050602081019050919050565b82818337600083830152505050565b60006103c66103c184610373565b610358565b9050828152602081018484840111156103e2576103e16102e2565b5b6103ed8482856103a4565b509392505050565b600082601f83011261040a576104096102dd565b5b813561041a8482602086016103b3565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061044e82610423565b9050919050565b61045e81610443565b811461046957600080fd5b50565b60008135905061047b81610455565b92915050565b60008060408385031215610498576104976102d3565b5b600083013567ffffffffffffffff8111156104b6576104b56102d8565b5b6104c2858286016103f5565b92505060206104d38582860161046c565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156105175780820151818401526020810190506104fc565b83811115610526576000848401525b50505050565b6000610537826104dd565b61054181856104e8565b93506105518185602086016104f9565b61055a816102e7565b840191505092915050565b6000602082019050818103600083015261057f818461052c565b905092915050565b60008160070b9050919050565b61059d81610587565b81146105a857600080fd5b50565b6000813590506105ba81610594565b92915050565b6000602082840312156105d6576105d56102d3565b5b60006105e4848285016105ab565b91505092915050565b6000819050919050565b610600816105ed565b82525050565b600060208201905061061b60008301846105f7565b92915050565b600060208284031215610637576106366102d3565b5b600082013567ffffffffffffffff811115610655576106546102d8565b5b610661848285016103f5565b91505092915050565b61067381610443565b82525050565b600060208201905061068e600083018461066a565b92915050565b600060408201905081810360008301526106ae818561052c565b90506106bd602083018461066a565b9392505050565b60006106d76106d284610373565b610358565b9050828152602081018484840111156106f3576106f26102e2565b5b6106fe8482856104f9565b509392505050565b600082601f83011261071b5761071a6102dd565b5b815161072b8482602086016106c4565b91505092915050565b60006020828403121561074a576107496102d3565b5b600082015167ffffffffffffffff811115610768576107676102d8565b5b61077484828501610706565b91505092915050565b61078681610587565b82525050565b60006020820190506107a1600083018461077d565b92915050565b6107b0816105ed565b81146107bb57600080fd5b50565b6000815190506107cd816107a7565b92915050565b6000602082840312156107e9576107e86102d3565b5b60006107f7848285016107be565b91505092915050565b60008151905061080f81610455565b92915050565b60006020828403121561082b5761082a6102d3565b5b600061083984828501610800565b9150509291505056fea26469706673582212203599aa5bcc18cda9492a410a6619dfd803fa572b0624c47efa4d4159a8f2430f64736f6c634300080a0033" +} diff --git a/e2e/contracts/testprototype/TestPrototype.sol b/e2e/contracts/testprototype/TestPrototype.sol new file mode 100644 index 0000000000..3e64bf7f29 --- /dev/null +++ b/e2e/contracts/testprototype/TestPrototype.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +interface IPrototype { + function bech32ToHexAddr( + string memory bech32 + ) external view returns (address addr); + + function bech32ify( + string memory prefix, + address addr + ) external view returns (string memory bech32); + + function getGasStabilityPoolBalance( + int64 chainID + ) external view returns (uint256 result); +} + +// @dev Purpose of this contract is to test calling prototype precompile through contract +// every function calling precompiles must have return so solidity doesn't check for precompile code size and revert because it's 0 +// version of solidity used must be >= 0.8.10 to support this +contract TestPrototype { + IPrototype prototype = IPrototype(0x0000000000000000000000000000000000000065); + + function bech32ToHexAddr(string memory bech32) external view returns (address addr) { + return prototype.bech32ToHexAddr(bech32); + } + + function bech32ify(string memory prefix, address addr) external view returns (string memory bech32) { + return prototype.bech32ify(prefix, addr); + } + + function getGasStabilityPoolBalance(int64 chainID) external view returns (uint256 result) { + return prototype.getGasStabilityPoolBalance(chainID); + } +} \ No newline at end of file diff --git a/e2e/contracts/testprototype/bindings.go b/e2e/contracts/testprototype/bindings.go new file mode 100644 index 0000000000..bcb8fb2159 --- /dev/null +++ b/e2e/contracts/testprototype/bindings.go @@ -0,0 +1,8 @@ +//go:generate sh -c "solc TestPrototype.sol --combined-json abi,bin | jq '.contracts.\"TestPrototype.sol:TestPrototype\"' > TestPrototype.json" +//go:generate sh -c "cat TestPrototype.json | jq .abi > TestPrototype.abi" +//go:generate sh -c "cat TestPrototype.json | jq .bin | tr -d '\"' > TestPrototype.bin" +//go:generate sh -c "abigen --abi TestPrototype.abi --bin TestPrototype.bin --pkg testprototype --type TestPrototype --out TestPrototype.go" + +package testprototype + +var _ TestPrototype diff --git a/e2e/e2etests/e2etests.go b/e2e/e2etests/e2etests.go index 7d09bd966c..b2fbabeebf 100644 --- a/e2e/e2etests/e2etests.go +++ b/e2e/e2etests/e2etests.go @@ -147,8 +147,9 @@ const ( /* Stateful precompiled contracts tests */ - TestPrecompilesPrototypeName = "precompile_contracts_prototype" - TestPrecompilesStakingName = "precompile_contracts_staking" + TestPrecompilesPrototypeName = "precompile_contracts_prototype" + TestPrecompilesPrototypeThroughContractName = "precompile_contracts_prototype_through_contract" + TestPrecompilesStakingName = "precompile_contracts_staking" ) // AllE2ETests is an ordered list of all e2e tests @@ -820,6 +821,12 @@ var AllE2ETests = []runner.E2ETest{ []runner.ArgDefinition{}, TestPrecompilesPrototype, ), + runner.NewE2ETest( + TestPrecompilesPrototypeThroughContractName, + "test stateful precompiled contracts prototype through contract", + []runner.ArgDefinition{}, + TestPrecompilesPrototypeThroughContract, + ), runner.NewE2ETest( TestPrecompilesStakingName, "test stateful precompiled contracts staking", diff --git a/e2e/e2etests/test_precompiles_prototype_through_contract.go b/e2e/e2etests/test_precompiles_prototype_through_contract.go new file mode 100644 index 0000000000..91b958592b --- /dev/null +++ b/e2e/e2etests/test_precompiles_prototype_through_contract.go @@ -0,0 +1,38 @@ +package e2etests + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + "github.com/zeta-chain/node/e2e/contracts/testprototype" + "github.com/zeta-chain/node/e2e/runner" + "github.com/zeta-chain/node/e2e/utils" +) + +func TestPrecompilesPrototypeThroughContract(r *runner.E2ERunner, args []string) { + require.Len(r, args, 0, "No arguments expected") + + _, testPrototypeTx, testPrototype, err := testprototype.DeployTestPrototype(r.ZEVMAuth, r.ZEVMClient) + require.NoError(r, err) + utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, testPrototypeTx, r.Logger, r.ReceiptTimeout) + + res, err := testPrototype.Bech32ify(nil, "zeta", common.HexToAddress("0xB9Dbc229Bf588A613C00BEE8e662727AB8121cfE")) + require.NoError(r, err, "Error calling Bech32ify") + require.Equal(r, "zeta1h8duy2dltz9xz0qqhm5wvcnj02upy887fyn43u", res, "Failed to validate Bech32ify result") + + addr, err := testPrototype.Bech32ToHexAddr(nil, "zeta1h8duy2dltz9xz0qqhm5wvcnj02upy887fyn43u") + require.NoError(r, err, "Error calling Bech32ToHexAddr") + require.Equal( + r, + "0xB9Dbc229Bf588A613C00BEE8e662727AB8121cfE", + addr.String(), + "Failed to validate Bech32ToHexAddr result", + ) + + chainID, err := r.EVMClient.ChainID(r.Ctx) + require.NoError(r, err, "Error retrieving ChainID") + + balance, err := testPrototype.GetGasStabilityPoolBalance(nil, chainID.Int64()) + require.NoError(r, err, "Error calling GetGasStabilityPoolBalance") + require.NotNil(r, balance, "GetGasStabilityPoolBalance returned balance is nil") +} From ba3b1c0f14e34ac91893401abac607a48cb3cda4 Mon Sep 17 00:00:00 2001 From: skosito Date: Thu, 5 Sep 2024 20:03:46 +0100 Subject: [PATCH 2/2] test(e2e): extend staking precompile tests (#2830) * add boilerplate for staking precompile with empty delegate method * add simple undelegate and redelegate methods * add new methods to run * add simple tests * add delegator caller checks * fix del addr origin check * add unit tests for delegate method * changelog * add undelegate tests * add redelegate unit tests * renamings * generate * pr comments * codecov * renaming * e2e test and fixes * generate * fix tests * fix view methods required gas * add queries unit tests * add more unit tests and refactor a bit * fmt * fixes after merge * cleanup * PR comments * add todo with issue * debugging calling precompiles through contract * pr comments and refactorings * fix e2e test * fixes * fmt * changelog * cleanup --- changelog.md | 1 + cmd/zetae2e/local/local.go | 1 + .../localnet/orchestrator/start-zetae2e.sh | 5 + e2e/contracts/teststaking/TestStaking.abi | 192 ++++++++ e2e/contracts/teststaking/TestStaking.bin | 1 + e2e/contracts/teststaking/TestStaking.go | 420 ++++++++++++++++++ e2e/contracts/teststaking/TestStaking.json | 195 ++++++++ e2e/contracts/teststaking/TestStaking.sol | 107 +++++ e2e/contracts/teststaking/bindings.go | 8 + e2e/e2etests/e2etests.go | 7 + e2e/e2etests/test_precompiles_staking.go | 34 +- ...st_precompiles_staking_through_contract.go | 136 ++++++ e2e/runner/runner.go | 3 + pkg/rpc/clients.go | 4 + precompiles/staking/staking.go | 31 +- precompiles/staking/staking_test.go | 330 +++++++++++--- 16 files changed, 1382 insertions(+), 93 deletions(-) create mode 100644 e2e/contracts/teststaking/TestStaking.abi create mode 100644 e2e/contracts/teststaking/TestStaking.bin create mode 100644 e2e/contracts/teststaking/TestStaking.go create mode 100644 e2e/contracts/teststaking/TestStaking.json create mode 100644 e2e/contracts/teststaking/TestStaking.sol create mode 100644 e2e/contracts/teststaking/bindings.go create mode 100644 e2e/e2etests/test_precompiles_staking_through_contract.go diff --git a/changelog.md b/changelog.md index 3298e433b1..0a30f07657 100644 --- a/changelog.md +++ b/changelog.md @@ -30,6 +30,7 @@ * [2726](https://github.com/zeta-chain/node/pull/2726) - add e2e tests for deposit and call, deposit and revert * [2703](https://github.com/zeta-chain/node/pull/2703) - add e2e tests for stateful precompiled contracts * [2763](https://github.com/zeta-chain/node/pull/2763) - add V2 contracts migration test +* [2830] (https://github.com/zeta-chain/node/pull/2830) - extend staking precompile tests ### Fixes diff --git a/cmd/zetae2e/local/local.go b/cmd/zetae2e/local/local.go index ab6ca1248e..5eae28ab22 100644 --- a/cmd/zetae2e/local/local.go +++ b/cmd/zetae2e/local/local.go @@ -312,6 +312,7 @@ func localE2ETest(cmd *cobra.Command, _ []string) { e2etests.TestPrecompilesPrototypeName, e2etests.TestPrecompilesPrototypeThroughContractName, e2etests.TestPrecompilesStakingName, + e2etests.TestPrecompilesStakingThroughContractName, } } diff --git a/contrib/localnet/orchestrator/start-zetae2e.sh b/contrib/localnet/orchestrator/start-zetae2e.sh index aa0531e141..b26a1c7544 100644 --- a/contrib/localnet/orchestrator/start-zetae2e.sh +++ b/contrib/localnet/orchestrator/start-zetae2e.sh @@ -136,6 +136,11 @@ address=$(yq -r '.additional_accounts.user_precompile.evm_address' config.yml) echo "funding precompile tester address ${address} with 10000 Ether" geth --exec "eth.sendTransaction({from: eth.coinbase, to: '${address}', value: web3.toWei(10000,'ether')})" attach http://eth:8545 > /dev/null +# unlock precompile tests accounts +address=$(yq -r '.additional_accounts.user_precompile.evm_address' config.yml) +echo "funding precompile tester address ${address} with 10000 Ether" +geth --exec "eth.sendTransaction({from: eth.coinbase, to: '${address}', value: web3.toWei(10000,'ether')})" attach http://eth:8545 > /dev/null + # unlock local solana relayer accounts if host solana > /dev/null; then solana_url=$(config_str '.rpcs.solana') diff --git a/e2e/contracts/teststaking/TestStaking.abi b/e2e/contracts/teststaking/TestStaking.abi new file mode 100644 index 0000000000..1dc4f1592e --- /dev/null +++ b/e2e/contracts/teststaking/TestStaking.abi @@ -0,0 +1,192 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_wzeta", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "depositWZETA", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "getAllValidators", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "operatorAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "consensusPubKey", + "type": "string" + }, + { + "internalType": "bool", + "name": "jailed", + "type": "bool" + }, + { + "internalType": "enum BondStatus", + "name": "bondStatus", + "type": "uint8" + } + ], + "internalType": "struct Validator[]", + "name": "validators", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "staker", + "type": "address" + }, + { + "internalType": "string", + "name": "validator", + "type": "string" + } + ], + "name": "getShares", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "staker", + "type": "address" + }, + { + "internalType": "string", + "name": "validatorSrc", + "type": "string" + }, + { + "internalType": "string", + "name": "validatorDst", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "moveStake", + "outputs": [ + { + "internalType": "int64", + "name": "completionTime", + "type": "int64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "staker", + "type": "address" + }, + { + "internalType": "string", + "name": "validator", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "stake", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "staker", + "type": "address" + }, + { + "internalType": "string", + "name": "validator", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "unstake", + "outputs": [ + { + "internalType": "int64", + "name": "completionTime", + "type": "int64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "withdrawWZETA", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/e2e/contracts/teststaking/TestStaking.bin b/e2e/contracts/teststaking/TestStaking.bin new file mode 100644 index 0000000000..f2b883adb0 --- /dev/null +++ b/e2e/contracts/teststaking/TestStaking.bin @@ -0,0 +1 @@ +608060405260666000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503480156200005257600080fd5b50604051620014d3380380620014d383398181016040528101906200007891906200016b565b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555033600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506200019d565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620001338262000106565b9050919050565b620001458162000126565b81146200015157600080fd5b50565b60008151905062000165816200013a565b92915050565b60006020828403121562000184576200018362000101565b5b6000620001948482850162000154565b91505092915050565b61132680620001ad6000396000f3fe6080604052600436106100745760003560e01c806390b8436f1161004e57806390b8436f146101015780639a0fb6731461013e578063d11a93d014610167578063f3513a37146101a45761007b565b80630d1b3daf1461007d5780632c5d24ae146100ba57806357c6ea3e146100c45761007b565b3661007b57005b005b34801561008957600080fd5b506100a4600480360381019061009f91906109a4565b6101cf565b6040516100b19190610a19565b60405180910390f35b6100c2610276565b005b3480156100d057600080fd5b506100eb60048036038101906100e69190610a60565b610355565b6040516100f89190610aeb565b60405180910390f35b34801561010d57600080fd5b5061012860048036038101906101239190610a60565b61045a565b6040516101359190610b21565b60405180910390f35b34801561014a57600080fd5b5061016560048036038101906101609190610b3c565b61055f565b005b34801561017357600080fd5b5061018e60048036038101906101899190610b69565b610649565b60405161019b9190610aeb565b60405180910390f35b3480156101b057600080fd5b506101b9610751565b6040516101c69190610e42565b60405180910390f35b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630d1b3daf84846040518363ffffffff1660e01b815260040161022d929190610ebd565b602060405180830381865afa15801561024a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061026e9190610f02565b905092915050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146102d057600080fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561033a57600080fd5b505af115801561034e573d6000803e3d6000fd5b5050505050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103b157600080fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166357c6ea3e8585856040518463ffffffff1660e01b815260040161040e93929190610f2f565b6020604051808303816000875af115801561042d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104519190610f99565b90509392505050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104b657600080fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166390b8436f8585856040518463ffffffff1660e01b815260040161051393929190610f2f565b6020604051808303816000875af1158015610532573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105569190610ff2565b90509392505050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146105b957600080fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d826040518263ffffffff1660e01b81526004016106149190610a19565b600060405180830381600087803b15801561062e57600080fd5b505af1158015610642573d6000803e3d6000fd5b5050505050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106a557600080fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d11a93d0868686866040518563ffffffff1660e01b8152600401610704949392919061101f565b6020604051808303816000875af1158015610723573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107479190610f99565b9050949350505050565b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f3513a376040518163ffffffff1660e01b8152600401600060405180830381865afa1580156107be573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906107e791906112a7565b905090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061082b82610800565b9050919050565b61083b81610820565b811461084657600080fd5b50565b60008135905061085881610832565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6108b182610868565b810181811067ffffffffffffffff821117156108d0576108cf610879565b5b80604052505050565b60006108e36107ec565b90506108ef82826108a8565b919050565b600067ffffffffffffffff82111561090f5761090e610879565b5b61091882610868565b9050602081019050919050565b82818337600083830152505050565b6000610947610942846108f4565b6108d9565b90508281526020810184848401111561096357610962610863565b5b61096e848285610925565b509392505050565b600082601f83011261098b5761098a61085e565b5b813561099b848260208601610934565b91505092915050565b600080604083850312156109bb576109ba6107f6565b5b60006109c985828601610849565b925050602083013567ffffffffffffffff8111156109ea576109e96107fb565b5b6109f685828601610976565b9150509250929050565b6000819050919050565b610a1381610a00565b82525050565b6000602082019050610a2e6000830184610a0a565b92915050565b610a3d81610a00565b8114610a4857600080fd5b50565b600081359050610a5a81610a34565b92915050565b600080600060608486031215610a7957610a786107f6565b5b6000610a8786828701610849565b935050602084013567ffffffffffffffff811115610aa857610aa76107fb565b5b610ab486828701610976565b9250506040610ac586828701610a4b565b9150509250925092565b60008160070b9050919050565b610ae581610acf565b82525050565b6000602082019050610b006000830184610adc565b92915050565b60008115159050919050565b610b1b81610b06565b82525050565b6000602082019050610b366000830184610b12565b92915050565b600060208284031215610b5257610b516107f6565b5b6000610b6084828501610a4b565b91505092915050565b60008060008060808587031215610b8357610b826107f6565b5b6000610b9187828801610849565b945050602085013567ffffffffffffffff811115610bb257610bb16107fb565b5b610bbe87828801610976565b935050604085013567ffffffffffffffff811115610bdf57610bde6107fb565b5b610beb87828801610976565b9250506060610bfc87828801610a4b565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610c6e578082015181840152602081019050610c53565b83811115610c7d576000848401525b50505050565b6000610c8e82610c34565b610c988185610c3f565b9350610ca8818560208601610c50565b610cb181610868565b840191505092915050565b610cc581610b06565b82525050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60048110610d0b57610d0a610ccb565b5b50565b6000819050610d1c82610cfa565b919050565b6000610d2c82610d0e565b9050919050565b610d3c81610d21565b82525050565b60006080830160008301518482036000860152610d5f8282610c83565b91505060208301518482036020860152610d798282610c83565b9150506040830151610d8e6040860182610cbc565b506060830151610da16060860182610d33565b508091505092915050565b6000610db88383610d42565b905092915050565b6000602082019050919050565b6000610dd882610c08565b610de28185610c13565b935083602082028501610df485610c24565b8060005b85811015610e305784840389528151610e118582610dac565b9450610e1c83610dc0565b925060208a01995050600181019050610df8565b50829750879550505050505092915050565b60006020820190508181036000830152610e5c8184610dcd565b905092915050565b610e6d81610820565b82525050565b600082825260208201905092915050565b6000610e8f82610c34565b610e998185610e73565b9350610ea9818560208601610c50565b610eb281610868565b840191505092915050565b6000604082019050610ed26000830185610e64565b8181036020830152610ee48184610e84565b90509392505050565b600081519050610efc81610a34565b92915050565b600060208284031215610f1857610f176107f6565b5b6000610f2684828501610eed565b91505092915050565b6000606082019050610f446000830186610e64565b8181036020830152610f568185610e84565b9050610f656040830184610a0a565b949350505050565b610f7681610acf565b8114610f8157600080fd5b50565b600081519050610f9381610f6d565b92915050565b600060208284031215610faf57610fae6107f6565b5b6000610fbd84828501610f84565b91505092915050565b610fcf81610b06565b8114610fda57600080fd5b50565b600081519050610fec81610fc6565b92915050565b600060208284031215611008576110076107f6565b5b600061101684828501610fdd565b91505092915050565b60006080820190506110346000830187610e64565b81810360208301526110468186610e84565b9050818103604083015261105a8185610e84565b90506110696060830184610a0a565b95945050505050565b600067ffffffffffffffff82111561108d5761108c610879565b5b602082029050602081019050919050565b600080fd5b600080fd5b600080fd5b60006110c06110bb846108f4565b6108d9565b9050828152602081018484840111156110dc576110db610863565b5b6110e7848285610c50565b509392505050565b600082601f8301126111045761110361085e565b5b81516111148482602086016110ad565b91505092915050565b6004811061112a57600080fd5b50565b60008151905061113c8161111d565b92915050565b600060808284031215611158576111576110a3565b5b61116260806108d9565b9050600082015167ffffffffffffffff811115611182576111816110a8565b5b61118e848285016110ef565b600083015250602082015167ffffffffffffffff8111156111b2576111b16110a8565b5b6111be848285016110ef565b60208301525060406111d284828501610fdd565b60408301525060606111e68482850161112d565b60608301525092915050565b600061120561120084611072565b6108d9565b905080838252602082019050602084028301858111156112285761122761109e565b5b835b8181101561126f57805167ffffffffffffffff81111561124d5761124c61085e565b5b80860161125a8982611142565b8552602085019450505060208101905061122a565b5050509392505050565b600082601f83011261128e5761128d61085e565b5b815161129e8482602086016111f2565b91505092915050565b6000602082840312156112bd576112bc6107f6565b5b600082015167ffffffffffffffff8111156112db576112da6107fb565b5b6112e784828501611279565b9150509291505056fea26469706673582212209d34227b9c73d9c6eb2b67ca8fabedb28adcac235655b12df2a572847549ea2a64736f6c634300080a0033 diff --git a/e2e/contracts/teststaking/TestStaking.go b/e2e/contracts/teststaking/TestStaking.go new file mode 100644 index 0000000000..b124d177dc --- /dev/null +++ b/e2e/contracts/teststaking/TestStaking.go @@ -0,0 +1,420 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package teststaking + +import ( + "errors" + "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 ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// Validator is an auto generated low-level Go binding around an user-defined struct. +type Validator struct { + OperatorAddress string + ConsensusPubKey string + Jailed bool + BondStatus uint8 +} + +// TestStakingMetaData contains all meta data concerning the TestStaking contract. +var TestStakingMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_wzeta\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"depositWZETA\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllValidators\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"operatorAddress\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"consensusPubKey\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"jailed\",\"type\":\"bool\"},{\"internalType\":\"enumBondStatus\",\"name\":\"bondStatus\",\"type\":\"uint8\"}],\"internalType\":\"structValidator[]\",\"name\":\"validators\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"validator\",\"type\":\"string\"}],\"name\":\"getShares\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"validatorSrc\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"validatorDst\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"moveStake\",\"outputs\":[{\"internalType\":\"int64\",\"name\":\"completionTime\",\"type\":\"int64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"validator\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"stake\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"validator\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"unstake\",\"outputs\":[{\"internalType\":\"int64\",\"name\":\"completionTime\",\"type\":\"int64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"withdrawWZETA\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", + Bin: "0x608060405260666000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503480156200005257600080fd5b50604051620014d3380380620014d383398181016040528101906200007891906200016b565b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555033600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506200019d565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620001338262000106565b9050919050565b620001458162000126565b81146200015157600080fd5b50565b60008151905062000165816200013a565b92915050565b60006020828403121562000184576200018362000101565b5b6000620001948482850162000154565b91505092915050565b61132680620001ad6000396000f3fe6080604052600436106100745760003560e01c806390b8436f1161004e57806390b8436f146101015780639a0fb6731461013e578063d11a93d014610167578063f3513a37146101a45761007b565b80630d1b3daf1461007d5780632c5d24ae146100ba57806357c6ea3e146100c45761007b565b3661007b57005b005b34801561008957600080fd5b506100a4600480360381019061009f91906109a4565b6101cf565b6040516100b19190610a19565b60405180910390f35b6100c2610276565b005b3480156100d057600080fd5b506100eb60048036038101906100e69190610a60565b610355565b6040516100f89190610aeb565b60405180910390f35b34801561010d57600080fd5b5061012860048036038101906101239190610a60565b61045a565b6040516101359190610b21565b60405180910390f35b34801561014a57600080fd5b5061016560048036038101906101609190610b3c565b61055f565b005b34801561017357600080fd5b5061018e60048036038101906101899190610b69565b610649565b60405161019b9190610aeb565b60405180910390f35b3480156101b057600080fd5b506101b9610751565b6040516101c69190610e42565b60405180910390f35b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630d1b3daf84846040518363ffffffff1660e01b815260040161022d929190610ebd565b602060405180830381865afa15801561024a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061026e9190610f02565b905092915050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146102d057600080fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561033a57600080fd5b505af115801561034e573d6000803e3d6000fd5b5050505050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103b157600080fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166357c6ea3e8585856040518463ffffffff1660e01b815260040161040e93929190610f2f565b6020604051808303816000875af115801561042d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104519190610f99565b90509392505050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104b657600080fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166390b8436f8585856040518463ffffffff1660e01b815260040161051393929190610f2f565b6020604051808303816000875af1158015610532573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105569190610ff2565b90509392505050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146105b957600080fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d826040518263ffffffff1660e01b81526004016106149190610a19565b600060405180830381600087803b15801561062e57600080fd5b505af1158015610642573d6000803e3d6000fd5b5050505050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106a557600080fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d11a93d0868686866040518563ffffffff1660e01b8152600401610704949392919061101f565b6020604051808303816000875af1158015610723573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107479190610f99565b9050949350505050565b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f3513a376040518163ffffffff1660e01b8152600401600060405180830381865afa1580156107be573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906107e791906112a7565b905090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061082b82610800565b9050919050565b61083b81610820565b811461084657600080fd5b50565b60008135905061085881610832565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6108b182610868565b810181811067ffffffffffffffff821117156108d0576108cf610879565b5b80604052505050565b60006108e36107ec565b90506108ef82826108a8565b919050565b600067ffffffffffffffff82111561090f5761090e610879565b5b61091882610868565b9050602081019050919050565b82818337600083830152505050565b6000610947610942846108f4565b6108d9565b90508281526020810184848401111561096357610962610863565b5b61096e848285610925565b509392505050565b600082601f83011261098b5761098a61085e565b5b813561099b848260208601610934565b91505092915050565b600080604083850312156109bb576109ba6107f6565b5b60006109c985828601610849565b925050602083013567ffffffffffffffff8111156109ea576109e96107fb565b5b6109f685828601610976565b9150509250929050565b6000819050919050565b610a1381610a00565b82525050565b6000602082019050610a2e6000830184610a0a565b92915050565b610a3d81610a00565b8114610a4857600080fd5b50565b600081359050610a5a81610a34565b92915050565b600080600060608486031215610a7957610a786107f6565b5b6000610a8786828701610849565b935050602084013567ffffffffffffffff811115610aa857610aa76107fb565b5b610ab486828701610976565b9250506040610ac586828701610a4b565b9150509250925092565b60008160070b9050919050565b610ae581610acf565b82525050565b6000602082019050610b006000830184610adc565b92915050565b60008115159050919050565b610b1b81610b06565b82525050565b6000602082019050610b366000830184610b12565b92915050565b600060208284031215610b5257610b516107f6565b5b6000610b6084828501610a4b565b91505092915050565b60008060008060808587031215610b8357610b826107f6565b5b6000610b9187828801610849565b945050602085013567ffffffffffffffff811115610bb257610bb16107fb565b5b610bbe87828801610976565b935050604085013567ffffffffffffffff811115610bdf57610bde6107fb565b5b610beb87828801610976565b9250506060610bfc87828801610a4b565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610c6e578082015181840152602081019050610c53565b83811115610c7d576000848401525b50505050565b6000610c8e82610c34565b610c988185610c3f565b9350610ca8818560208601610c50565b610cb181610868565b840191505092915050565b610cc581610b06565b82525050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60048110610d0b57610d0a610ccb565b5b50565b6000819050610d1c82610cfa565b919050565b6000610d2c82610d0e565b9050919050565b610d3c81610d21565b82525050565b60006080830160008301518482036000860152610d5f8282610c83565b91505060208301518482036020860152610d798282610c83565b9150506040830151610d8e6040860182610cbc565b506060830151610da16060860182610d33565b508091505092915050565b6000610db88383610d42565b905092915050565b6000602082019050919050565b6000610dd882610c08565b610de28185610c13565b935083602082028501610df485610c24565b8060005b85811015610e305784840389528151610e118582610dac565b9450610e1c83610dc0565b925060208a01995050600181019050610df8565b50829750879550505050505092915050565b60006020820190508181036000830152610e5c8184610dcd565b905092915050565b610e6d81610820565b82525050565b600082825260208201905092915050565b6000610e8f82610c34565b610e998185610e73565b9350610ea9818560208601610c50565b610eb281610868565b840191505092915050565b6000604082019050610ed26000830185610e64565b8181036020830152610ee48184610e84565b90509392505050565b600081519050610efc81610a34565b92915050565b600060208284031215610f1857610f176107f6565b5b6000610f2684828501610eed565b91505092915050565b6000606082019050610f446000830186610e64565b8181036020830152610f568185610e84565b9050610f656040830184610a0a565b949350505050565b610f7681610acf565b8114610f8157600080fd5b50565b600081519050610f9381610f6d565b92915050565b600060208284031215610faf57610fae6107f6565b5b6000610fbd84828501610f84565b91505092915050565b610fcf81610b06565b8114610fda57600080fd5b50565b600081519050610fec81610fc6565b92915050565b600060208284031215611008576110076107f6565b5b600061101684828501610fdd565b91505092915050565b60006080820190506110346000830187610e64565b81810360208301526110468186610e84565b9050818103604083015261105a8185610e84565b90506110696060830184610a0a565b95945050505050565b600067ffffffffffffffff82111561108d5761108c610879565b5b602082029050602081019050919050565b600080fd5b600080fd5b600080fd5b60006110c06110bb846108f4565b6108d9565b9050828152602081018484840111156110dc576110db610863565b5b6110e7848285610c50565b509392505050565b600082601f8301126111045761110361085e565b5b81516111148482602086016110ad565b91505092915050565b6004811061112a57600080fd5b50565b60008151905061113c8161111d565b92915050565b600060808284031215611158576111576110a3565b5b61116260806108d9565b9050600082015167ffffffffffffffff811115611182576111816110a8565b5b61118e848285016110ef565b600083015250602082015167ffffffffffffffff8111156111b2576111b16110a8565b5b6111be848285016110ef565b60208301525060406111d284828501610fdd565b60408301525060606111e68482850161112d565b60608301525092915050565b600061120561120084611072565b6108d9565b905080838252602082019050602084028301858111156112285761122761109e565b5b835b8181101561126f57805167ffffffffffffffff81111561124d5761124c61085e565b5b80860161125a8982611142565b8552602085019450505060208101905061122a565b5050509392505050565b600082601f83011261128e5761128d61085e565b5b815161129e8482602086016111f2565b91505092915050565b6000602082840312156112bd576112bc6107f6565b5b600082015167ffffffffffffffff8111156112db576112da6107fb565b5b6112e784828501611279565b9150509291505056fea26469706673582212209d34227b9c73d9c6eb2b67ca8fabedb28adcac235655b12df2a572847549ea2a64736f6c634300080a0033", +} + +// TestStakingABI is the input ABI used to generate the binding from. +// Deprecated: Use TestStakingMetaData.ABI instead. +var TestStakingABI = TestStakingMetaData.ABI + +// TestStakingBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use TestStakingMetaData.Bin instead. +var TestStakingBin = TestStakingMetaData.Bin + +// DeployTestStaking deploys a new Ethereum contract, binding an instance of TestStaking to it. +func DeployTestStaking(auth *bind.TransactOpts, backend bind.ContractBackend, _wzeta common.Address) (common.Address, *types.Transaction, *TestStaking, error) { + parsed, err := TestStakingMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(TestStakingBin), backend, _wzeta) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &TestStaking{TestStakingCaller: TestStakingCaller{contract: contract}, TestStakingTransactor: TestStakingTransactor{contract: contract}, TestStakingFilterer: TestStakingFilterer{contract: contract}}, nil +} + +// TestStaking is an auto generated Go binding around an Ethereum contract. +type TestStaking struct { + TestStakingCaller // Read-only binding to the contract + TestStakingTransactor // Write-only binding to the contract + TestStakingFilterer // Log filterer for contract events +} + +// TestStakingCaller is an auto generated read-only Go binding around an Ethereum contract. +type TestStakingCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// TestStakingTransactor is an auto generated write-only Go binding around an Ethereum contract. +type TestStakingTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// TestStakingFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type TestStakingFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// TestStakingSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type TestStakingSession struct { + Contract *TestStaking // 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 +} + +// TestStakingCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type TestStakingCallerSession struct { + Contract *TestStakingCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// TestStakingTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type TestStakingTransactorSession struct { + Contract *TestStakingTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// TestStakingRaw is an auto generated low-level Go binding around an Ethereum contract. +type TestStakingRaw struct { + Contract *TestStaking // Generic contract binding to access the raw methods on +} + +// TestStakingCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type TestStakingCallerRaw struct { + Contract *TestStakingCaller // Generic read-only contract binding to access the raw methods on +} + +// TestStakingTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type TestStakingTransactorRaw struct { + Contract *TestStakingTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewTestStaking creates a new instance of TestStaking, bound to a specific deployed contract. +func NewTestStaking(address common.Address, backend bind.ContractBackend) (*TestStaking, error) { + contract, err := bindTestStaking(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &TestStaking{TestStakingCaller: TestStakingCaller{contract: contract}, TestStakingTransactor: TestStakingTransactor{contract: contract}, TestStakingFilterer: TestStakingFilterer{contract: contract}}, nil +} + +// NewTestStakingCaller creates a new read-only instance of TestStaking, bound to a specific deployed contract. +func NewTestStakingCaller(address common.Address, caller bind.ContractCaller) (*TestStakingCaller, error) { + contract, err := bindTestStaking(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &TestStakingCaller{contract: contract}, nil +} + +// NewTestStakingTransactor creates a new write-only instance of TestStaking, bound to a specific deployed contract. +func NewTestStakingTransactor(address common.Address, transactor bind.ContractTransactor) (*TestStakingTransactor, error) { + contract, err := bindTestStaking(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &TestStakingTransactor{contract: contract}, nil +} + +// NewTestStakingFilterer creates a new log filterer instance of TestStaking, bound to a specific deployed contract. +func NewTestStakingFilterer(address common.Address, filterer bind.ContractFilterer) (*TestStakingFilterer, error) { + contract, err := bindTestStaking(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &TestStakingFilterer{contract: contract}, nil +} + +// bindTestStaking binds a generic wrapper to an already deployed contract. +func bindTestStaking(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := TestStakingMetaData.GetAbi() + 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 (_TestStaking *TestStakingRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _TestStaking.Contract.TestStakingCaller.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 (_TestStaking *TestStakingRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _TestStaking.Contract.TestStakingTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_TestStaking *TestStakingRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _TestStaking.Contract.TestStakingTransactor.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 (_TestStaking *TestStakingCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _TestStaking.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 (_TestStaking *TestStakingTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _TestStaking.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_TestStaking *TestStakingTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _TestStaking.Contract.contract.Transact(opts, method, params...) +} + +// GetAllValidators is a free data retrieval call binding the contract method 0xf3513a37. +// +// Solidity: function getAllValidators() view returns((string,string,bool,uint8)[] validators) +func (_TestStaking *TestStakingCaller) GetAllValidators(opts *bind.CallOpts) ([]Validator, error) { + var out []interface{} + err := _TestStaking.contract.Call(opts, &out, "getAllValidators") + + if err != nil { + return *new([]Validator), err + } + + out0 := *abi.ConvertType(out[0], new([]Validator)).(*[]Validator) + + return out0, err + +} + +// GetAllValidators is a free data retrieval call binding the contract method 0xf3513a37. +// +// Solidity: function getAllValidators() view returns((string,string,bool,uint8)[] validators) +func (_TestStaking *TestStakingSession) GetAllValidators() ([]Validator, error) { + return _TestStaking.Contract.GetAllValidators(&_TestStaking.CallOpts) +} + +// GetAllValidators is a free data retrieval call binding the contract method 0xf3513a37. +// +// Solidity: function getAllValidators() view returns((string,string,bool,uint8)[] validators) +func (_TestStaking *TestStakingCallerSession) GetAllValidators() ([]Validator, error) { + return _TestStaking.Contract.GetAllValidators(&_TestStaking.CallOpts) +} + +// GetShares is a free data retrieval call binding the contract method 0x0d1b3daf. +// +// Solidity: function getShares(address staker, string validator) view returns(uint256 shares) +func (_TestStaking *TestStakingCaller) GetShares(opts *bind.CallOpts, staker common.Address, validator string) (*big.Int, error) { + var out []interface{} + err := _TestStaking.contract.Call(opts, &out, "getShares", staker, validator) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetShares is a free data retrieval call binding the contract method 0x0d1b3daf. +// +// Solidity: function getShares(address staker, string validator) view returns(uint256 shares) +func (_TestStaking *TestStakingSession) GetShares(staker common.Address, validator string) (*big.Int, error) { + return _TestStaking.Contract.GetShares(&_TestStaking.CallOpts, staker, validator) +} + +// GetShares is a free data retrieval call binding the contract method 0x0d1b3daf. +// +// Solidity: function getShares(address staker, string validator) view returns(uint256 shares) +func (_TestStaking *TestStakingCallerSession) GetShares(staker common.Address, validator string) (*big.Int, error) { + return _TestStaking.Contract.GetShares(&_TestStaking.CallOpts, staker, validator) +} + +// DepositWZETA is a paid mutator transaction binding the contract method 0x2c5d24ae. +// +// Solidity: function depositWZETA() payable returns() +func (_TestStaking *TestStakingTransactor) DepositWZETA(opts *bind.TransactOpts) (*types.Transaction, error) { + return _TestStaking.contract.Transact(opts, "depositWZETA") +} + +// DepositWZETA is a paid mutator transaction binding the contract method 0x2c5d24ae. +// +// Solidity: function depositWZETA() payable returns() +func (_TestStaking *TestStakingSession) DepositWZETA() (*types.Transaction, error) { + return _TestStaking.Contract.DepositWZETA(&_TestStaking.TransactOpts) +} + +// DepositWZETA is a paid mutator transaction binding the contract method 0x2c5d24ae. +// +// Solidity: function depositWZETA() payable returns() +func (_TestStaking *TestStakingTransactorSession) DepositWZETA() (*types.Transaction, error) { + return _TestStaking.Contract.DepositWZETA(&_TestStaking.TransactOpts) +} + +// MoveStake is a paid mutator transaction binding the contract method 0xd11a93d0. +// +// Solidity: function moveStake(address staker, string validatorSrc, string validatorDst, uint256 amount) returns(int64 completionTime) +func (_TestStaking *TestStakingTransactor) MoveStake(opts *bind.TransactOpts, staker common.Address, validatorSrc string, validatorDst string, amount *big.Int) (*types.Transaction, error) { + return _TestStaking.contract.Transact(opts, "moveStake", staker, validatorSrc, validatorDst, amount) +} + +// MoveStake is a paid mutator transaction binding the contract method 0xd11a93d0. +// +// Solidity: function moveStake(address staker, string validatorSrc, string validatorDst, uint256 amount) returns(int64 completionTime) +func (_TestStaking *TestStakingSession) MoveStake(staker common.Address, validatorSrc string, validatorDst string, amount *big.Int) (*types.Transaction, error) { + return _TestStaking.Contract.MoveStake(&_TestStaking.TransactOpts, staker, validatorSrc, validatorDst, amount) +} + +// MoveStake is a paid mutator transaction binding the contract method 0xd11a93d0. +// +// Solidity: function moveStake(address staker, string validatorSrc, string validatorDst, uint256 amount) returns(int64 completionTime) +func (_TestStaking *TestStakingTransactorSession) MoveStake(staker common.Address, validatorSrc string, validatorDst string, amount *big.Int) (*types.Transaction, error) { + return _TestStaking.Contract.MoveStake(&_TestStaking.TransactOpts, staker, validatorSrc, validatorDst, amount) +} + +// Stake is a paid mutator transaction binding the contract method 0x90b8436f. +// +// Solidity: function stake(address staker, string validator, uint256 amount) returns(bool) +func (_TestStaking *TestStakingTransactor) Stake(opts *bind.TransactOpts, staker common.Address, validator string, amount *big.Int) (*types.Transaction, error) { + return _TestStaking.contract.Transact(opts, "stake", staker, validator, amount) +} + +// Stake is a paid mutator transaction binding the contract method 0x90b8436f. +// +// Solidity: function stake(address staker, string validator, uint256 amount) returns(bool) +func (_TestStaking *TestStakingSession) Stake(staker common.Address, validator string, amount *big.Int) (*types.Transaction, error) { + return _TestStaking.Contract.Stake(&_TestStaking.TransactOpts, staker, validator, amount) +} + +// Stake is a paid mutator transaction binding the contract method 0x90b8436f. +// +// Solidity: function stake(address staker, string validator, uint256 amount) returns(bool) +func (_TestStaking *TestStakingTransactorSession) Stake(staker common.Address, validator string, amount *big.Int) (*types.Transaction, error) { + return _TestStaking.Contract.Stake(&_TestStaking.TransactOpts, staker, validator, amount) +} + +// Unstake is a paid mutator transaction binding the contract method 0x57c6ea3e. +// +// Solidity: function unstake(address staker, string validator, uint256 amount) returns(int64 completionTime) +func (_TestStaking *TestStakingTransactor) Unstake(opts *bind.TransactOpts, staker common.Address, validator string, amount *big.Int) (*types.Transaction, error) { + return _TestStaking.contract.Transact(opts, "unstake", staker, validator, amount) +} + +// Unstake is a paid mutator transaction binding the contract method 0x57c6ea3e. +// +// Solidity: function unstake(address staker, string validator, uint256 amount) returns(int64 completionTime) +func (_TestStaking *TestStakingSession) Unstake(staker common.Address, validator string, amount *big.Int) (*types.Transaction, error) { + return _TestStaking.Contract.Unstake(&_TestStaking.TransactOpts, staker, validator, amount) +} + +// Unstake is a paid mutator transaction binding the contract method 0x57c6ea3e. +// +// Solidity: function unstake(address staker, string validator, uint256 amount) returns(int64 completionTime) +func (_TestStaking *TestStakingTransactorSession) Unstake(staker common.Address, validator string, amount *big.Int) (*types.Transaction, error) { + return _TestStaking.Contract.Unstake(&_TestStaking.TransactOpts, staker, validator, amount) +} + +// WithdrawWZETA is a paid mutator transaction binding the contract method 0x9a0fb673. +// +// Solidity: function withdrawWZETA(uint256 wad) returns() +func (_TestStaking *TestStakingTransactor) WithdrawWZETA(opts *bind.TransactOpts, wad *big.Int) (*types.Transaction, error) { + return _TestStaking.contract.Transact(opts, "withdrawWZETA", wad) +} + +// WithdrawWZETA is a paid mutator transaction binding the contract method 0x9a0fb673. +// +// Solidity: function withdrawWZETA(uint256 wad) returns() +func (_TestStaking *TestStakingSession) WithdrawWZETA(wad *big.Int) (*types.Transaction, error) { + return _TestStaking.Contract.WithdrawWZETA(&_TestStaking.TransactOpts, wad) +} + +// WithdrawWZETA is a paid mutator transaction binding the contract method 0x9a0fb673. +// +// Solidity: function withdrawWZETA(uint256 wad) returns() +func (_TestStaking *TestStakingTransactorSession) WithdrawWZETA(wad *big.Int) (*types.Transaction, error) { + return _TestStaking.Contract.WithdrawWZETA(&_TestStaking.TransactOpts, wad) +} + +// Fallback is a paid mutator transaction binding the contract fallback function. +// +// Solidity: fallback() payable returns() +func (_TestStaking *TestStakingTransactor) Fallback(opts *bind.TransactOpts, calldata []byte) (*types.Transaction, error) { + return _TestStaking.contract.RawTransact(opts, calldata) +} + +// Fallback is a paid mutator transaction binding the contract fallback function. +// +// Solidity: fallback() payable returns() +func (_TestStaking *TestStakingSession) Fallback(calldata []byte) (*types.Transaction, error) { + return _TestStaking.Contract.Fallback(&_TestStaking.TransactOpts, calldata) +} + +// Fallback is a paid mutator transaction binding the contract fallback function. +// +// Solidity: fallback() payable returns() +func (_TestStaking *TestStakingTransactorSession) Fallback(calldata []byte) (*types.Transaction, error) { + return _TestStaking.Contract.Fallback(&_TestStaking.TransactOpts, calldata) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_TestStaking *TestStakingTransactor) Receive(opts *bind.TransactOpts) (*types.Transaction, error) { + return _TestStaking.contract.RawTransact(opts, nil) // calldata is disallowed for receive function +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_TestStaking *TestStakingSession) Receive() (*types.Transaction, error) { + return _TestStaking.Contract.Receive(&_TestStaking.TransactOpts) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_TestStaking *TestStakingTransactorSession) Receive() (*types.Transaction, error) { + return _TestStaking.Contract.Receive(&_TestStaking.TransactOpts) +} diff --git a/e2e/contracts/teststaking/TestStaking.json b/e2e/contracts/teststaking/TestStaking.json new file mode 100644 index 0000000000..ebc45c196a --- /dev/null +++ b/e2e/contracts/teststaking/TestStaking.json @@ -0,0 +1,195 @@ +{ + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_wzeta", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "depositWZETA", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "getAllValidators", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "operatorAddress", + "type": "string" + }, + { + "internalType": "string", + "name": "consensusPubKey", + "type": "string" + }, + { + "internalType": "bool", + "name": "jailed", + "type": "bool" + }, + { + "internalType": "enum BondStatus", + "name": "bondStatus", + "type": "uint8" + } + ], + "internalType": "struct Validator[]", + "name": "validators", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "staker", + "type": "address" + }, + { + "internalType": "string", + "name": "validator", + "type": "string" + } + ], + "name": "getShares", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "staker", + "type": "address" + }, + { + "internalType": "string", + "name": "validatorSrc", + "type": "string" + }, + { + "internalType": "string", + "name": "validatorDst", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "moveStake", + "outputs": [ + { + "internalType": "int64", + "name": "completionTime", + "type": "int64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "staker", + "type": "address" + }, + { + "internalType": "string", + "name": "validator", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "stake", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "staker", + "type": "address" + }, + { + "internalType": "string", + "name": "validator", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "unstake", + "outputs": [ + { + "internalType": "int64", + "name": "completionTime", + "type": "int64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "withdrawWZETA", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bin": "608060405260666000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503480156200005257600080fd5b50604051620014d3380380620014d383398181016040528101906200007891906200016b565b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555033600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506200019d565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620001338262000106565b9050919050565b620001458162000126565b81146200015157600080fd5b50565b60008151905062000165816200013a565b92915050565b60006020828403121562000184576200018362000101565b5b6000620001948482850162000154565b91505092915050565b61132680620001ad6000396000f3fe6080604052600436106100745760003560e01c806390b8436f1161004e57806390b8436f146101015780639a0fb6731461013e578063d11a93d014610167578063f3513a37146101a45761007b565b80630d1b3daf1461007d5780632c5d24ae146100ba57806357c6ea3e146100c45761007b565b3661007b57005b005b34801561008957600080fd5b506100a4600480360381019061009f91906109a4565b6101cf565b6040516100b19190610a19565b60405180910390f35b6100c2610276565b005b3480156100d057600080fd5b506100eb60048036038101906100e69190610a60565b610355565b6040516100f89190610aeb565b60405180910390f35b34801561010d57600080fd5b5061012860048036038101906101239190610a60565b61045a565b6040516101359190610b21565b60405180910390f35b34801561014a57600080fd5b5061016560048036038101906101609190610b3c565b61055f565b005b34801561017357600080fd5b5061018e60048036038101906101899190610b69565b610649565b60405161019b9190610aeb565b60405180910390f35b3480156101b057600080fd5b506101b9610751565b6040516101c69190610e42565b60405180910390f35b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630d1b3daf84846040518363ffffffff1660e01b815260040161022d929190610ebd565b602060405180830381865afa15801561024a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061026e9190610f02565b905092915050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146102d057600080fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561033a57600080fd5b505af115801561034e573d6000803e3d6000fd5b5050505050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103b157600080fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166357c6ea3e8585856040518463ffffffff1660e01b815260040161040e93929190610f2f565b6020604051808303816000875af115801561042d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104519190610f99565b90509392505050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104b657600080fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166390b8436f8585856040518463ffffffff1660e01b815260040161051393929190610f2f565b6020604051808303816000875af1158015610532573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105569190610ff2565b90509392505050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146105b957600080fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d826040518263ffffffff1660e01b81526004016106149190610a19565b600060405180830381600087803b15801561062e57600080fd5b505af1158015610642573d6000803e3d6000fd5b5050505050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106a557600080fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d11a93d0868686866040518563ffffffff1660e01b8152600401610704949392919061101f565b6020604051808303816000875af1158015610723573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107479190610f99565b9050949350505050565b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f3513a376040518163ffffffff1660e01b8152600401600060405180830381865afa1580156107be573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906107e791906112a7565b905090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061082b82610800565b9050919050565b61083b81610820565b811461084657600080fd5b50565b60008135905061085881610832565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6108b182610868565b810181811067ffffffffffffffff821117156108d0576108cf610879565b5b80604052505050565b60006108e36107ec565b90506108ef82826108a8565b919050565b600067ffffffffffffffff82111561090f5761090e610879565b5b61091882610868565b9050602081019050919050565b82818337600083830152505050565b6000610947610942846108f4565b6108d9565b90508281526020810184848401111561096357610962610863565b5b61096e848285610925565b509392505050565b600082601f83011261098b5761098a61085e565b5b813561099b848260208601610934565b91505092915050565b600080604083850312156109bb576109ba6107f6565b5b60006109c985828601610849565b925050602083013567ffffffffffffffff8111156109ea576109e96107fb565b5b6109f685828601610976565b9150509250929050565b6000819050919050565b610a1381610a00565b82525050565b6000602082019050610a2e6000830184610a0a565b92915050565b610a3d81610a00565b8114610a4857600080fd5b50565b600081359050610a5a81610a34565b92915050565b600080600060608486031215610a7957610a786107f6565b5b6000610a8786828701610849565b935050602084013567ffffffffffffffff811115610aa857610aa76107fb565b5b610ab486828701610976565b9250506040610ac586828701610a4b565b9150509250925092565b60008160070b9050919050565b610ae581610acf565b82525050565b6000602082019050610b006000830184610adc565b92915050565b60008115159050919050565b610b1b81610b06565b82525050565b6000602082019050610b366000830184610b12565b92915050565b600060208284031215610b5257610b516107f6565b5b6000610b6084828501610a4b565b91505092915050565b60008060008060808587031215610b8357610b826107f6565b5b6000610b9187828801610849565b945050602085013567ffffffffffffffff811115610bb257610bb16107fb565b5b610bbe87828801610976565b935050604085013567ffffffffffffffff811115610bdf57610bde6107fb565b5b610beb87828801610976565b9250506060610bfc87828801610a4b565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610c6e578082015181840152602081019050610c53565b83811115610c7d576000848401525b50505050565b6000610c8e82610c34565b610c988185610c3f565b9350610ca8818560208601610c50565b610cb181610868565b840191505092915050565b610cc581610b06565b82525050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60048110610d0b57610d0a610ccb565b5b50565b6000819050610d1c82610cfa565b919050565b6000610d2c82610d0e565b9050919050565b610d3c81610d21565b82525050565b60006080830160008301518482036000860152610d5f8282610c83565b91505060208301518482036020860152610d798282610c83565b9150506040830151610d8e6040860182610cbc565b506060830151610da16060860182610d33565b508091505092915050565b6000610db88383610d42565b905092915050565b6000602082019050919050565b6000610dd882610c08565b610de28185610c13565b935083602082028501610df485610c24565b8060005b85811015610e305784840389528151610e118582610dac565b9450610e1c83610dc0565b925060208a01995050600181019050610df8565b50829750879550505050505092915050565b60006020820190508181036000830152610e5c8184610dcd565b905092915050565b610e6d81610820565b82525050565b600082825260208201905092915050565b6000610e8f82610c34565b610e998185610e73565b9350610ea9818560208601610c50565b610eb281610868565b840191505092915050565b6000604082019050610ed26000830185610e64565b8181036020830152610ee48184610e84565b90509392505050565b600081519050610efc81610a34565b92915050565b600060208284031215610f1857610f176107f6565b5b6000610f2684828501610eed565b91505092915050565b6000606082019050610f446000830186610e64565b8181036020830152610f568185610e84565b9050610f656040830184610a0a565b949350505050565b610f7681610acf565b8114610f8157600080fd5b50565b600081519050610f9381610f6d565b92915050565b600060208284031215610faf57610fae6107f6565b5b6000610fbd84828501610f84565b91505092915050565b610fcf81610b06565b8114610fda57600080fd5b50565b600081519050610fec81610fc6565b92915050565b600060208284031215611008576110076107f6565b5b600061101684828501610fdd565b91505092915050565b60006080820190506110346000830187610e64565b81810360208301526110468186610e84565b9050818103604083015261105a8185610e84565b90506110696060830184610a0a565b95945050505050565b600067ffffffffffffffff82111561108d5761108c610879565b5b602082029050602081019050919050565b600080fd5b600080fd5b600080fd5b60006110c06110bb846108f4565b6108d9565b9050828152602081018484840111156110dc576110db610863565b5b6110e7848285610c50565b509392505050565b600082601f8301126111045761110361085e565b5b81516111148482602086016110ad565b91505092915050565b6004811061112a57600080fd5b50565b60008151905061113c8161111d565b92915050565b600060808284031215611158576111576110a3565b5b61116260806108d9565b9050600082015167ffffffffffffffff811115611182576111816110a8565b5b61118e848285016110ef565b600083015250602082015167ffffffffffffffff8111156111b2576111b16110a8565b5b6111be848285016110ef565b60208301525060406111d284828501610fdd565b60408301525060606111e68482850161112d565b60608301525092915050565b600061120561120084611072565b6108d9565b905080838252602082019050602084028301858111156112285761122761109e565b5b835b8181101561126f57805167ffffffffffffffff81111561124d5761124c61085e565b5b80860161125a8982611142565b8552602085019450505060208101905061122a565b5050509392505050565b600082601f83011261128e5761128d61085e565b5b815161129e8482602086016111f2565b91505092915050565b6000602082840312156112bd576112bc6107f6565b5b600082015167ffffffffffffffff8111156112db576112da6107fb565b5b6112e784828501611279565b9150509291505056fea26469706673582212209d34227b9c73d9c6eb2b67ca8fabedb28adcac235655b12df2a572847549ea2a64736f6c634300080a0033" +} diff --git a/e2e/contracts/teststaking/TestStaking.sol b/e2e/contracts/teststaking/TestStaking.sol new file mode 100644 index 0000000000..f4d633ca38 --- /dev/null +++ b/e2e/contracts/teststaking/TestStaking.sol @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +// @dev Interface for IStaking precompile for easier import +enum BondStatus { + Unspecified, + Unbonded, + Unbonding, + Bonded +} + +struct Validator { + string operatorAddress; + string consensusPubKey; + bool jailed; + BondStatus bondStatus; +} + +interface IStaking { + function stake( + address staker, + string memory validator, + uint256 amount + ) external returns (bool success); + + function unstake( + address staker, + string memory validator, + uint256 amount + ) external returns (int64 completionTime); + + function moveStake( + address staker, + string memory validatorSrc, + string memory validatorDst, + uint256 amount + ) external returns (int64 completionTime); + + function getAllValidators() external view returns (Validator[] calldata validators); + + function getShares(address staker, string memory validator) external view returns (uint256 shares); +} + +interface WZETA { + function deposit() external payable; + function withdraw(uint256 wad) external; +} + +// @dev Purpose of this contract is to call staking precompile +contract TestStaking { + IStaking staking = IStaking(0x0000000000000000000000000000000000000066); + WZETA wzeta; + address owner; + + constructor(address _wzeta) { + wzeta = WZETA(_wzeta); + owner = msg.sender; + } + + // simple protection to not be able to call contract by anyone + // not relevant for e2e tests + modifier onlyOwner() { + require(msg.sender == owner); + _; + } + + function depositWZETA() external payable onlyOwner { + wzeta.deposit{value: msg.value}(); + } + + function withdrawWZETA(uint256 wad) external onlyOwner { + wzeta.withdraw(wad); + } + + function stake(address staker, string memory validator, uint256 amount) external onlyOwner returns (bool) { + return staking.stake(staker, validator, amount); + } + + function unstake( + address staker, + string memory validator, + uint256 amount + ) external onlyOwner returns (int64 completionTime) { + return staking.unstake(staker, validator, amount); + } + + function moveStake( + address staker, + string memory validatorSrc, + string memory validatorDst, + uint256 amount + ) external onlyOwner returns (int64 completionTime) { + return staking.moveStake(staker, validatorSrc, validatorDst, amount); + } + + function getShares(address staker, string memory validator) external view returns(uint256 shares) { + return staking.getShares(staker, validator); + } + + function getAllValidators() external view returns (Validator[] memory validators) { + return staking.getAllValidators(); + } + + fallback() external payable {} + + receive() external payable {} +} \ No newline at end of file diff --git a/e2e/contracts/teststaking/bindings.go b/e2e/contracts/teststaking/bindings.go new file mode 100644 index 0000000000..db835d3358 --- /dev/null +++ b/e2e/contracts/teststaking/bindings.go @@ -0,0 +1,8 @@ +//go:generate sh -c "solc TestStaking.sol --combined-json abi,bin | jq '.contracts.\"TestStaking.sol:TestStaking\"' > TestStaking.json" +//go:generate sh -c "cat TestStaking.json | jq .abi > TestStaking.abi" +//go:generate sh -c "cat TestStaking.json | jq .bin | tr -d '\"' > TestStaking.bin" +//go:generate sh -c "abigen --abi TestStaking.abi --bin TestStaking.bin --pkg teststaking --type TestStaking --out TestStaking.go" + +package teststaking + +var _ TestStaking diff --git a/e2e/e2etests/e2etests.go b/e2e/e2etests/e2etests.go index b2fbabeebf..e36ec034db 100644 --- a/e2e/e2etests/e2etests.go +++ b/e2e/e2etests/e2etests.go @@ -150,6 +150,7 @@ const ( TestPrecompilesPrototypeName = "precompile_contracts_prototype" TestPrecompilesPrototypeThroughContractName = "precompile_contracts_prototype_through_contract" TestPrecompilesStakingName = "precompile_contracts_staking" + TestPrecompilesStakingThroughContractName = "precompile_contracts_staking_through_contract" ) // AllE2ETests is an ordered list of all e2e tests @@ -833,4 +834,10 @@ var AllE2ETests = []runner.E2ETest{ []runner.ArgDefinition{}, TestPrecompilesStaking, ), + runner.NewE2ETest( + TestPrecompilesStakingThroughContractName, + "test stateful precompiled contracts staking through contract", + []runner.ArgDefinition{}, + TestPrecompilesStakingThroughContract, + ), } diff --git a/e2e/e2etests/test_precompiles_staking.go b/e2e/e2etests/test_precompiles_staking.go index 429c63932a..6b847d04c8 100644 --- a/e2e/e2etests/test_precompiles_staking.go +++ b/e2e/e2etests/test_precompiles_staking.go @@ -3,6 +3,8 @@ package e2etests import ( "math/big" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/stretchr/testify/require" @@ -46,6 +48,14 @@ func TestPrecompilesStaking(r *runner.E2ERunner, args []string) { require.NoError(r, err) require.Equal(r, big.NewInt(3e18).String(), sharesAfterVal1.String()) + // check delegation amount using staking keeper query client + delegationAfterVal1, err := r.StakingClient.Delegation(r.Ctx, &types.QueryDelegationRequest{ + DelegatorAddr: sdk.AccAddress(r.ZEVMAuth.From.Bytes()).String(), + ValidatorAddr: validators[0].OperatorAddress, + }) + require.NoError(r, err) + require.Equal(r, int64(3), delegationAfterVal1.DelegationResponse.Balance.Amount.Int64()) + // unstake 1 from validator1 tx, err = stakingContract.Unstake(r.ZEVMAuth, r.ZEVMAuth.From, validators[0].OperatorAddress, big.NewInt(1)) require.NoError(r, err) @@ -56,6 +66,14 @@ func TestPrecompilesStaking(r *runner.E2ERunner, args []string) { require.NoError(r, err) require.Equal(r, big.NewInt(2e18).String(), sharesAfterVal1.String()) + // check delegation amount using staking keeper query client + delegationAfterVal1, err = r.StakingClient.Delegation(r.Ctx, &types.QueryDelegationRequest{ + DelegatorAddr: sdk.AccAddress(r.ZEVMAuth.From.Bytes()).String(), + ValidatorAddr: validators[0].OperatorAddress, + }) + require.NoError(r, err) + require.Equal(r, int64(2), delegationAfterVal1.DelegationResponse.Balance.Amount.Int64()) + // move 1 stake from validator1 to validator2 tx, err = stakingContract.MoveStake( r.ZEVMAuth, @@ -65,7 +83,6 @@ func TestPrecompilesStaking(r *runner.E2ERunner, args []string) { big.NewInt(1), ) require.NoError(r, err) - utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) // check shares for both validator1 and validator2 are 1 @@ -76,4 +93,19 @@ func TestPrecompilesStaking(r *runner.E2ERunner, args []string) { sharesAfterVal2, err := stakingContract.GetShares(&bind.CallOpts{}, r.ZEVMAuth.From, validators[1].OperatorAddress) require.NoError(r, err) require.Equal(r, big.NewInt(1e18).String(), sharesAfterVal2.String()) + + // check delegation amount using staking keeper query client + delegationAfterVal1, err = r.StakingClient.Delegation(r.Ctx, &types.QueryDelegationRequest{ + DelegatorAddr: sdk.AccAddress(r.ZEVMAuth.From.Bytes()).String(), + ValidatorAddr: validators[0].OperatorAddress, + }) + require.NoError(r, err) + require.Equal(r, int64(1), delegationAfterVal1.DelegationResponse.Balance.Amount.Int64()) + + delegationAfterVal2, err := r.StakingClient.Delegation(r.Ctx, &types.QueryDelegationRequest{ + DelegatorAddr: sdk.AccAddress(r.ZEVMAuth.From.Bytes()).String(), + ValidatorAddr: validators[1].OperatorAddress, + }) + require.NoError(r, err) + require.Equal(r, int64(1), delegationAfterVal2.DelegationResponse.Balance.Amount.Int64()) } diff --git a/e2e/e2etests/test_precompiles_staking_through_contract.go b/e2e/e2etests/test_precompiles_staking_through_contract.go new file mode 100644 index 0000000000..ade60de7bf --- /dev/null +++ b/e2e/e2etests/test_precompiles_staking_through_contract.go @@ -0,0 +1,136 @@ +package e2etests + +import ( + "math/big" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/stretchr/testify/require" + + "github.com/zeta-chain/node/e2e/contracts/teststaking" + "github.com/zeta-chain/node/e2e/runner" + "github.com/zeta-chain/node/e2e/utils" +) + +func TestPrecompilesStakingThroughContract(r *runner.E2ERunner, args []string) { + require.Len(r, args, 0, "No arguments expected") + + testStakingAddr, testStakingTx, testStaking, err := teststaking.DeployTestStaking( + r.ZEVMAuth, + r.ZEVMClient, + r.WZetaAddr, + ) + require.NoError(r, err) + utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, testStakingTx, r.Logger, r.ReceiptTimeout) + + validators, err := testStaking.GetAllValidators(&bind.CallOpts{}) + require.NoError(r, err) + require.GreaterOrEqual(r, len(validators), 2) + + // shares are 0 for both validators at the start + sharesBeforeVal1, err := testStaking.GetShares(&bind.CallOpts{}, testStakingAddr, validators[0].OperatorAddress) + require.NoError(r, err) + require.Equal(r, int64(0), sharesBeforeVal1.Int64()) + + sharesBeforeVal2, err := testStaking.GetShares(&bind.CallOpts{}, testStakingAddr, validators[1].OperatorAddress) + require.NoError(r, err) + require.Equal(r, int64(0), sharesBeforeVal2.Int64()) + + // stake 3 to validator1 using user_precompile account should fail because sender is not provided staker + _, err = testStaking.Stake(r.ZEVMAuth, r.ZEVMAuth.From, validators[0].OperatorAddress, big.NewInt(3)) + require.Error(r, err) + + // stake 3 to validator1 using testStaking smart contract should fail because it doesn't have any balance yet + _, err = testStaking.Stake(r.ZEVMAuth, testStakingAddr, validators[0].OperatorAddress, big.NewInt(3)) + require.Error(r, err) + + r.ZEVMAuth.Value = big.NewInt(1000000000000) + previousGasLimit := r.ZEVMAuth.GasLimit + r.ZEVMAuth.GasLimit = 10000000 + defer func() { + r.ZEVMAuth.GasLimit = previousGasLimit + }() + + // fund testStaking contract with azeta + tx, err := testStaking.DepositWZETA(r.ZEVMAuth) + require.NoError(r, err) + utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) + r.ZEVMAuth.Value = big.NewInt(0) + + tx, err = testStaking.WithdrawWZETA(r.ZEVMAuth, big.NewInt(100000000000)) + require.NoError(r, err) + utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) + + // stake 3 to validator1 using testStaking smart contract + tx, err = testStaking.Stake(r.ZEVMAuth, testStakingAddr, validators[0].OperatorAddress, big.NewInt(3)) + require.NoError(r, err) + utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) + + // check shares are set to 3 + sharesAfterVal1, err := testStaking.GetShares(&bind.CallOpts{}, testStakingAddr, validators[0].OperatorAddress) + require.NoError(r, err) + require.Equal(r, big.NewInt(3e18).String(), sharesAfterVal1.String()) + + // check delegation amount using staking keeper query client + delegationAfterVal1, err := r.StakingClient.Delegation(r.Ctx, &types.QueryDelegationRequest{ + DelegatorAddr: sdk.AccAddress(testStakingAddr.Bytes()).String(), + ValidatorAddr: validators[0].OperatorAddress, + }) + require.NoError(r, err) + require.Equal(r, int64(3), delegationAfterVal1.DelegationResponse.Balance.Amount.Int64()) + + // unstake 1 from validator1 + tx, err = testStaking.Unstake(r.ZEVMAuth, testStakingAddr, validators[0].OperatorAddress, big.NewInt(1)) + require.NoError(r, err) + utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) + + // check shares are set to 2 + sharesAfterVal1, err = testStaking.GetShares(&bind.CallOpts{}, testStakingAddr, validators[0].OperatorAddress) + require.NoError(r, err) + require.Equal(r, big.NewInt(2e18).String(), sharesAfterVal1.String()) + + // check delegation amount using staking keeper query client + delegationAfterVal1, err = r.StakingClient.Delegation(r.Ctx, &types.QueryDelegationRequest{ + DelegatorAddr: sdk.AccAddress(testStakingAddr.Bytes()).String(), + ValidatorAddr: validators[0].OperatorAddress, + }) + require.NoError(r, err) + require.Equal(r, int64(2), delegationAfterVal1.DelegationResponse.Balance.Amount.Int64()) + + // move 1 stake from validator1 to validator2 + tx, err = testStaking.MoveStake( + r.ZEVMAuth, + testStakingAddr, + validators[0].OperatorAddress, + validators[1].OperatorAddress, + big.NewInt(1), + ) + require.NoError(r, err) + utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) + + // check shares for both validator1 and validator2 are 1 + sharesAfterVal1, err = testStaking.GetShares(&bind.CallOpts{}, testStakingAddr, validators[0].OperatorAddress) + require.NoError(r, err) + require.Equal(r, big.NewInt(1e18).String(), sharesAfterVal1.String()) + + // check delegation amount using staking keeper query client + delegationAfterVal1, err = r.StakingClient.Delegation(r.Ctx, &types.QueryDelegationRequest{ + DelegatorAddr: sdk.AccAddress(testStakingAddr.Bytes()).String(), + ValidatorAddr: validators[0].OperatorAddress, + }) + require.NoError(r, err) + require.Equal(r, int64(1), delegationAfterVal1.DelegationResponse.Balance.Amount.Int64()) + + sharesAfterVal2, err := testStaking.GetShares(&bind.CallOpts{}, testStakingAddr, validators[1].OperatorAddress) + require.NoError(r, err) + require.Equal(r, big.NewInt(1e18).String(), sharesAfterVal2.String()) + + // check delegation amount using staking keeper query client + delegationAfterVal2, err := r.StakingClient.Delegation(r.Ctx, &types.QueryDelegationRequest{ + DelegatorAddr: sdk.AccAddress(testStakingAddr.Bytes()).String(), + ValidatorAddr: validators[1].OperatorAddress, + }) + require.NoError(r, err) + require.Equal(r, int64(1), delegationAfterVal2.DelegationResponse.Balance.Amount.Int64()) +} diff --git a/e2e/runner/runner.go b/e2e/runner/runner.go index 38106a76b4..55e740ea5d 100644 --- a/e2e/runner/runner.go +++ b/e2e/runner/runner.go @@ -11,6 +11,7 @@ import ( "github.com/btcsuite/btcutil" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/ethereum/go-ethereum/accounts/abi/bind" ethcommon "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" @@ -86,6 +87,7 @@ type E2ERunner struct { FungibleClient fungibletypes.QueryClient AuthClient authtypes.QueryClient BankClient banktypes.QueryClient + StakingClient stakingtypes.QueryClient ObserverClient observertypes.QueryClient LightclientClient lightclienttypes.QueryClient @@ -188,6 +190,7 @@ func NewE2ERunner( FungibleClient: clients.Zetacore.Fungible, AuthClient: clients.Zetacore.Auth, BankClient: clients.Zetacore.Bank, + StakingClient: clients.Zetacore.Staking, ObserverClient: clients.Zetacore.Observer, LightclientClient: clients.Zetacore.Lightclient, diff --git a/pkg/rpc/clients.go b/pkg/rpc/clients.go index bafd6d44ab..26ecbe729f 100644 --- a/pkg/rpc/clients.go +++ b/pkg/rpc/clients.go @@ -8,6 +8,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/grpc/tmservice" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" feemarkettypes "github.com/zeta-chain/ethermint/x/feemarket/types" "google.golang.org/grpc" @@ -30,6 +31,8 @@ type Clients struct { Auth authtypes.QueryClient // Bank is a github.com/cosmos/cosmos-sdk/x/bank/types QueryClient Bank banktypes.QueryClient + // Bank is a github.com/cosmos/cosmos-sdk/x/staking/types QueryClient + Staking stakingtypes.QueryClient // Upgrade is a github.com/cosmos/cosmos-sdk/x/upgrade/types QueryClient Upgrade upgradetypes.QueryClient @@ -64,6 +67,7 @@ func newClients(ctx client.Context) (Clients, error) { // Cosmos SDK clients Auth: authtypes.NewQueryClient(ctx), Bank: banktypes.NewQueryClient(ctx), + Staking: stakingtypes.NewQueryClient(ctx), Upgrade: upgradetypes.NewQueryClient(ctx), Authority: authoritytypes.NewQueryClient(ctx), // ZetaCore specific clients diff --git a/precompiles/staking/staking.go b/precompiles/staking/staking.go index 308a1968f3..6ce344a344 100644 --- a/precompiles/staking/staking.go +++ b/precompiles/staking/staking.go @@ -166,17 +166,12 @@ func (c *Contract) GetShares( } } - staker, err := sdk.AccAddressFromBech32(sdk.AccAddress(stakerAddress.Bytes()).String()) - if err != nil { - return nil, err - } - validator, err := sdk.ValAddressFromBech32(validatorAddress) if err != nil { return nil, err } - delegation := c.stakingKeeper.Delegation(ctx, staker, validator) + delegation := c.stakingKeeper.Delegation(ctx, sdk.AccAddress(stakerAddress.Bytes()), validator) shares := big.NewInt(0) if delegation != nil { shares = delegation.GetShares().BigInt() @@ -187,7 +182,7 @@ func (c *Contract) GetShares( func (c *Contract) Stake( ctx sdk.Context, - origin common.Address, + contract *vm.Contract, method *abi.Method, args []interface{}, ) ([]byte, error) { @@ -205,8 +200,8 @@ func (c *Contract) Stake( } } - if origin != stakerAddress { - return nil, fmt.Errorf("origin is not staker address") + if contract.CallerAddress != stakerAddress { + return nil, fmt.Errorf("caller is not staker address") } validatorAddress, ok := args[1].(string) @@ -241,7 +236,7 @@ func (c *Contract) Stake( func (c *Contract) Unstake( ctx sdk.Context, - origin common.Address, + contract *vm.Contract, method *abi.Method, args []interface{}, ) ([]byte, error) { @@ -259,8 +254,8 @@ func (c *Contract) Unstake( } } - if origin != stakerAddress { - return nil, fmt.Errorf("origin is not staker address") + if contract.CallerAddress != stakerAddress { + return nil, fmt.Errorf("caller is not staker address") } validatorAddress, ok := args[1].(string) @@ -295,7 +290,7 @@ func (c *Contract) Unstake( func (c *Contract) MoveStake( ctx sdk.Context, - origin common.Address, + contract *vm.Contract, method *abi.Method, args []interface{}, ) ([]byte, error) { @@ -313,8 +308,8 @@ func (c *Contract) MoveStake( } } - if origin != stakerAddress { - return nil, fmt.Errorf("origin is not staker address") + if contract.CallerAddress != stakerAddress { + return nil, fmt.Errorf("caller is not staker address") } validatorSrcAddress, ok := args[1].(string) @@ -394,7 +389,7 @@ func (c *Contract) Run(evm *vm.EVM, contract *vm.Contract, _ bool) ([]byte, erro case StakeMethodName: var res []byte execErr := stateDB.ExecuteNativeAction(contract.Address(), nil, func(ctx sdk.Context) error { - res, err = c.Stake(ctx, evm.Origin, method, args) + res, err = c.Stake(ctx, contract, method, args) return err }) if execErr != nil { @@ -404,7 +399,7 @@ func (c *Contract) Run(evm *vm.EVM, contract *vm.Contract, _ bool) ([]byte, erro case UnstakeMethodName: var res []byte execErr := stateDB.ExecuteNativeAction(contract.Address(), nil, func(ctx sdk.Context) error { - res, err = c.Unstake(ctx, evm.Origin, method, args) + res, err = c.Unstake(ctx, contract, method, args) return err }) if execErr != nil { @@ -414,7 +409,7 @@ func (c *Contract) Run(evm *vm.EVM, contract *vm.Contract, _ bool) ([]byte, erro case MoveStakeMethodName: var res []byte execErr := stateDB.ExecuteNativeAction(contract.Address(), nil, func(ctx sdk.Context) error { - res, err = c.MoveStake(ctx, evm.Origin, method, args) + res, err = c.MoveStake(ctx, contract, method, args) return err }) if execErr != nil { diff --git a/precompiles/staking/staking_test.go b/precompiles/staking/staking_test.go index 6ae2f1fc3f..d7dfe933ac 100644 --- a/precompiles/staking/staking_test.go +++ b/precompiles/staking/staking_test.go @@ -16,15 +16,20 @@ import ( stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/params" "github.com/stretchr/testify/require" ethermint "github.com/zeta-chain/ethermint/types" + "github.com/zeta-chain/ethermint/x/evm/statedb" "github.com/zeta-chain/node/cmd/zetacored/config" + "github.com/zeta-chain/node/precompiles/prototype" "github.com/zeta-chain/node/testutil/keeper" + "github.com/zeta-chain/node/testutil/sample" fungibletypes "github.com/zeta-chain/node/x/fungible/types" ) -func setup(t *testing.T) (sdk.Context, *Contract, abi.ABI, keeper.SDKKeepers) { +func setup(t *testing.T) (sdk.Context, *Contract, abi.ABI, keeper.SDKKeepers, *vm.EVM, *vm.Contract) { var encoding ethermint.EncodingConfig appCodec := encoding.Codec @@ -32,9 +37,21 @@ func setup(t *testing.T) (sdk.Context, *Contract, abi.ABI, keeper.SDKKeepers) { db := tmdb.NewMemDB() stateStore := store.NewCommitMultiStore(db) - sdkKeepers := keeper.NewSDKKeepers(cdc, db, stateStore) + keys, memKeys, tkeys, allKeys := keeper.StoreKeys() + sdkKeepers := keeper.NewSDKKeepersWithKeys(cdc, keys, memKeys, tkeys, allKeys) + for _, key := range keys { + stateStore.MountStoreWithDB(key, storetypes.StoreTypeIAVL, db) + } + for _, key := range tkeys { + stateStore.MountStoreWithDB(key, storetypes.StoreTypeTransient, nil) + } + for _, key := range memKeys { + stateStore.MountStoreWithDB(key, storetypes.StoreTypeMemory, nil) + } + gasConfig := storetypes.TransientGasConfig() ctx := keeper.NewContext(stateStore) + require.NoError(t, stateStore.LoadLatestVersion()) stakingGenesisState := stakingtypes.DefaultGenesisState() @@ -50,11 +67,38 @@ func setup(t *testing.T) (sdk.Context, *Contract, abi.ABI, keeper.SDKKeepers) { address := contract.Address() require.NotNil(t, address, "contract address should not be nil") - return ctx, contract, abi, sdkKeepers + mockEVM := vm.NewEVM( + vm.BlockContext{}, + vm.TxContext{}, + statedb.New(ctx, sdkKeepers.EvmKeeper, statedb.TxConfig{}), + ¶ms.ChainConfig{}, + vm.Config{}, + ) + mockVMContract := vm.NewContract( + contractRef{address: common.Address{}}, + contractRef{address: ContractAddress}, + big.NewInt(0), + 0, + ) + return ctx, contract, abi, sdkKeepers, mockEVM, mockVMContract +} + +func packInputArgs(t *testing.T, methodID abi.Method, args ...interface{}) []byte { + input, err := methodID.Inputs.Pack(args...) + require.NoError(t, err) + return append(methodID.ID, input...) +} + +type contractRef struct { + address common.Address +} + +func (c contractRef) Address() common.Address { + return c.address } func Test_IStakingContract(t *testing.T) { - _, contract, abi, _ := setup(t) + _, contract, abi, _, _, _ := setup(t) gasConfig := storetypes.TransientGasConfig() t.Run("should check methods are present in ABI", func(t *testing.T) { @@ -176,7 +220,7 @@ func Test_IStakingContract(t *testing.T) { } func Test_InvalidMethod(t *testing.T) { - _, _, abi, _ := setup(t) + _, _, abi, _, _, _ := setup(t) _, doNotExist := abi.Methods["invalidMethod"] require.False(t, doNotExist, "invalidMethod should not be present in the ABI") @@ -194,11 +238,10 @@ func Test_InvalidABI(t *testing.T) { } func Test_Stake(t *testing.T) { - ctx, contract, abi, sdkKeepers := setup(t) - methodID := abi.Methods[StakeMethodName] - t.Run("should fail if validator doesn't exist", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, mockEVM, mockVMContract := setup(t) + methodID := abi.Methods[StakeMethodName] r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) @@ -211,11 +254,12 @@ func Test_Stake(t *testing.T) { require.NoError(t, err) stakerAddr := common.BytesToAddress(staker.Bytes()) - + mockVMContract.CallerAddress = stakerAddr args := []interface{}{stakerEthAddr, validator.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt()} + mockVMContract.Input = packInputArgs(t, methodID, args...) // ACT - _, err = contract.Stake(ctx, stakerAddr, &methodID, args) + _, err = contract.Run(mockEVM, mockVMContract, false) // ASSERT require.Error(t, err) @@ -223,6 +267,8 @@ func Test_Stake(t *testing.T) { t.Run("should stake", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, mockEVM, mockVMContract := setup(t) + methodID := abi.Methods[StakeMethodName] r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -236,18 +282,21 @@ func Test_Stake(t *testing.T) { require.NoError(t, err) stakerAddr := common.BytesToAddress(staker.Bytes()) - + mockVMContract.CallerAddress = stakerAddr args := []interface{}{stakerEthAddr, validator.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt()} + mockVMContract.Input = packInputArgs(t, methodID, args...) // ACT - _, err = contract.Stake(ctx, stakerAddr, &methodID, args) + _, err = contract.Run(mockEVM, mockVMContract, false) // ASSERT require.NoError(t, err) }) - t.Run("should fail if origin is not staker", func(t *testing.T) { + t.Run("should fail if no input args", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, mockEVM, mockVMContract := setup(t) + methodID := abi.Methods[StakeMethodName] r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -260,20 +309,49 @@ func Test_Stake(t *testing.T) { require.NoError(t, err) stakerAddr := common.BytesToAddress(staker.Bytes()) + mockVMContract.CallerAddress = stakerAddr + mockVMContract.Input = methodID.ID + + // ACT + _, err = contract.Run(mockEVM, mockVMContract, false) + + // ASSERT + require.Error(t, err) + }) + + t.Run("should fail if caller is not staker", func(t *testing.T) { + // ARRANGE + ctx, contract, abi, sdkKeepers, mockEVM, mockVMContract := setup(t) + methodID := abi.Methods[StakeMethodName] + r := rand.New(rand.NewSource(42)) + validator := sample.Validator(t, r) + sdkKeepers.StakingKeeper.SetValidator(ctx, validator) + + staker := sample.Bech32AccAddress() + coins := sample.Coins() + err := sdkKeepers.BankKeeper.MintCoins(ctx, fungibletypes.ModuleName, sample.Coins()) + require.NoError(t, err) + err = sdkKeepers.BankKeeper.SendCoinsFromModuleToAccount(ctx, fungibletypes.ModuleName, staker, coins) + require.NoError(t, err) - originEthAddr := common.BytesToAddress(sample.Bech32AccAddress().Bytes()) + stakerAddr := common.BytesToAddress(staker.Bytes()) + mockVMContract.CallerAddress = stakerAddr - args := []interface{}{originEthAddr, validator.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt()} + nonStakerAddr := common.BytesToAddress(sample.Bech32AccAddress().Bytes()) + args := []interface{}{nonStakerAddr, validator.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt()} + mockVMContract.Input = packInputArgs(t, methodID, args...) // ACT - _, err = contract.Stake(ctx, stakerAddr, &methodID, args) + _, err = contract.Run(mockEVM, mockVMContract, false) // ASSERT - require.ErrorContains(t, err, "origin is not staker address") + require.ErrorContains(t, err, "caller is not staker address") }) t.Run("should fail if staking fails", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, mockEVM, mockVMContract := setup(t) + methodID := abi.Methods[StakeMethodName] r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -281,13 +359,16 @@ func Test_Stake(t *testing.T) { // staker without funds staker := sample.Bech32AccAddress() stakerEthAddr := common.BytesToAddress(staker.Bytes()) + coins := sample.Coins() stakerAddr := common.BytesToAddress(staker.Bytes()) + mockVMContract.CallerAddress = stakerAddr - args := []interface{}{stakerEthAddr, validator.OperatorAddress, int64(42)} + args := []interface{}{stakerEthAddr, validator.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt()} + mockVMContract.Input = packInputArgs(t, methodID, args...) // ACT - _, err := contract.Stake(ctx, stakerAddr, &methodID, args) + _, err := contract.Run(mockEVM, mockVMContract, false) // ASSERT require.Error(t, err) @@ -295,6 +376,8 @@ func Test_Stake(t *testing.T) { t.Run("should fail if wrong args amount", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, _, _ := setup(t) + methodID := abi.Methods[StakeMethodName] r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -312,7 +395,7 @@ func Test_Stake(t *testing.T) { args := []interface{}{stakerEthAddr, validator.OperatorAddress} // ACT - _, err = contract.Stake(ctx, stakerAddr, &methodID, args) + _, err = contract.Stake(ctx, &vm.Contract{CallerAddress: stakerAddr}, &methodID, args) // ASSERT require.Error(t, err) @@ -320,6 +403,8 @@ func Test_Stake(t *testing.T) { t.Run("should fail if staker is not eth addr", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, _, _ := setup(t) + methodID := abi.Methods[StakeMethodName] r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -336,7 +421,7 @@ func Test_Stake(t *testing.T) { args := []interface{}{staker, validator.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt()} // ACT - _, err = contract.Stake(ctx, stakerAddr, &methodID, args) + _, err = contract.Stake(ctx, &vm.Contract{CallerAddress: stakerAddr}, &methodID, args) // ASSERT require.Error(t, err) @@ -344,6 +429,8 @@ func Test_Stake(t *testing.T) { t.Run("should fail if validator is not valid string", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, _, _ := setup(t) + methodID := abi.Methods[StakeMethodName] r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -361,7 +448,7 @@ func Test_Stake(t *testing.T) { args := []interface{}{stakerEthAddr, 42, coins.AmountOf(config.BaseDenom).BigInt()} // ACT - _, err = contract.Stake(ctx, stakerAddr, &methodID, args) + _, err = contract.Stake(ctx, &vm.Contract{CallerAddress: stakerAddr}, &methodID, args) // ASSERT require.Error(t, err) @@ -369,6 +456,8 @@ func Test_Stake(t *testing.T) { t.Run("should fail if amount is not int64", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, _, _ := setup(t) + methodID := abi.Methods[StakeMethodName] r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -386,7 +475,7 @@ func Test_Stake(t *testing.T) { args := []interface{}{stakerEthAddr, validator.OperatorAddress, coins.AmountOf(config.BaseDenom).Uint64()} // ACT - _, err = contract.Stake(ctx, stakerAddr, &methodID, args) + _, err = contract.Stake(ctx, &vm.Contract{CallerAddress: stakerAddr}, &methodID, args) // ASSERT require.Error(t, err) @@ -394,11 +483,10 @@ func Test_Stake(t *testing.T) { } func Test_Unstake(t *testing.T) { - ctx, contract, abi, sdkKeepers := setup(t) - methodID := abi.Methods[UnstakeMethodName] - t.Run("should fail if validator doesn't exist", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, mockEVM, mockVMContract := setup(t) + methodID := abi.Methods[UnstakeMethodName] r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) @@ -411,11 +499,13 @@ func Test_Unstake(t *testing.T) { require.NoError(t, err) stakerAddr := common.BytesToAddress(staker.Bytes()) + mockVMContract.CallerAddress = stakerAddr args := []interface{}{stakerEthAddr, validator.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt()} + mockVMContract.Input = packInputArgs(t, methodID, args...) // ACT - _, err = contract.Unstake(ctx, stakerAddr, &methodID, args) + _, err = contract.Run(mockEVM, mockVMContract, false) // ASSERT require.Error(t, err) @@ -423,6 +513,8 @@ func Test_Unstake(t *testing.T) { t.Run("should unstake", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, mockEVM, mockVMContract := setup(t) + methodID := abi.Methods[UnstakeMethodName] r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -436,23 +528,28 @@ func Test_Unstake(t *testing.T) { require.NoError(t, err) stakerAddr := common.BytesToAddress(staker.Bytes()) + mockVMContract.CallerAddress = stakerAddr args := []interface{}{stakerEthAddr, validator.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt()} // stake first stakeMethodID := abi.Methods[StakeMethodName] - _, err = contract.Stake(ctx, stakerAddr, &stakeMethodID, args) + mockVMContract.Input = packInputArgs(t, stakeMethodID, args...) + _, err = contract.Run(mockEVM, mockVMContract, false) require.NoError(t, err) // ACT - _, err = contract.Unstake(ctx, stakerAddr, &methodID, args) + mockVMContract.Input = packInputArgs(t, methodID, args...) + _, err = contract.Run(mockEVM, mockVMContract, false) // ASSERT require.NoError(t, err) }) - t.Run("should fail if origin is not staker", func(t *testing.T) { + t.Run("should fail if caller is not staker", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, mockEVM, mockVMContract := setup(t) + methodID := abi.Methods[UnstakeMethodName] r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -466,25 +563,30 @@ func Test_Unstake(t *testing.T) { require.NoError(t, err) stakerAddr := common.BytesToAddress(staker.Bytes()) + mockVMContract.CallerAddress = stakerAddr args := []interface{}{stakerEthAddr, validator.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt()} - // stake first stakeMethodID := abi.Methods[StakeMethodName] - _, err = contract.Stake(ctx, stakerAddr, &stakeMethodID, args) + mockVMContract.Input = packInputArgs(t, stakeMethodID, args...) + _, err = contract.Run(mockEVM, mockVMContract, false) require.NoError(t, err) - originEthAddr := common.BytesToAddress(sample.Bech32AccAddress().Bytes()) + callerEthAddr := common.BytesToAddress(sample.Bech32AccAddress().Bytes()) + mockVMContract.CallerAddress = callerEthAddr + mockVMContract.Input = packInputArgs(t, methodID, args...) // ACT - _, err = contract.Unstake(ctx, originEthAddr, &methodID, args) + _, err = contract.Run(mockEVM, mockVMContract, false) // ASSERT - require.ErrorContains(t, err, "origin is not staker address") + require.ErrorContains(t, err, "caller is not staker address") }) t.Run("should fail if no previous staking", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, mockEVM, mockVMContract := setup(t) + methodID := abi.Methods[UnstakeMethodName] r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -498,11 +600,13 @@ func Test_Unstake(t *testing.T) { require.NoError(t, err) stakerAddr := common.BytesToAddress(staker.Bytes()) + mockVMContract.CallerAddress = stakerAddr args := []interface{}{stakerEthAddr, validator.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt()} + mockVMContract.Input = packInputArgs(t, methodID, args...) // ACT - _, err = contract.Unstake(ctx, stakerAddr, &methodID, args) + _, err = contract.Run(mockEVM, mockVMContract, false) // ASSERT require.Error(t, err) @@ -510,6 +614,8 @@ func Test_Unstake(t *testing.T) { t.Run("should fail if wrong args amount", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, _, _ := setup(t) + methodID := abi.Methods[UnstakeMethodName] r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -527,7 +633,7 @@ func Test_Unstake(t *testing.T) { args := []interface{}{stakerEthAddr, validator.OperatorAddress} // ACT - _, err = contract.Unstake(ctx, stakerAddr, &methodID, args) + _, err = contract.Unstake(ctx, &vm.Contract{CallerAddress: stakerAddr}, &methodID, args) // ASSERT require.Error(t, err) @@ -535,6 +641,8 @@ func Test_Unstake(t *testing.T) { t.Run("should fail if staker is not eth addr", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, _, _ := setup(t) + methodID := abi.Methods[UnstakeMethodName] r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -551,7 +659,7 @@ func Test_Unstake(t *testing.T) { args := []interface{}{staker, validator.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt()} // ACT - _, err = contract.Unstake(ctx, stakerAddr, &methodID, args) + _, err = contract.Unstake(ctx, &vm.Contract{CallerAddress: stakerAddr}, &methodID, args) // ASSERT require.Error(t, err) @@ -559,6 +667,8 @@ func Test_Unstake(t *testing.T) { t.Run("should fail if validator is not valid string", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, _, _ := setup(t) + methodID := abi.Methods[UnstakeMethodName] r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -576,7 +686,7 @@ func Test_Unstake(t *testing.T) { args := []interface{}{stakerEthAddr, 42, coins.AmountOf(config.BaseDenom).BigInt()} // ACT - _, err = contract.Unstake(ctx, stakerAddr, &methodID, args) + _, err = contract.Unstake(ctx, &vm.Contract{CallerAddress: stakerAddr}, &methodID, args) // ASSERT require.Error(t, err) @@ -584,6 +694,8 @@ func Test_Unstake(t *testing.T) { t.Run("should fail if amount is not int64", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, _, _ := setup(t) + methodID := abi.Methods[UnstakeMethodName] r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -601,7 +713,7 @@ func Test_Unstake(t *testing.T) { args := []interface{}{stakerEthAddr, validator.OperatorAddress, coins.AmountOf(config.BaseDenom).Uint64()} // ACT - _, err = contract.Unstake(ctx, stakerAddr, &methodID, args) + _, err = contract.Unstake(ctx, &vm.Contract{CallerAddress: stakerAddr}, &methodID, args) // ASSERT require.Error(t, err) @@ -609,11 +721,10 @@ func Test_Unstake(t *testing.T) { } func Test_MoveStake(t *testing.T) { - ctx, contract, abi, sdkKeepers := setup(t) - methodID := abi.Methods[MoveStakeMethodName] - t.Run("should fail if validator dest doesn't exist", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, mockEVM, mockVMContract := setup(t) + methodID := abi.Methods[MoveStakeMethodName] r := rand.New(rand.NewSource(42)) validatorSrc := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validatorSrc) @@ -628,6 +739,7 @@ func Test_MoveStake(t *testing.T) { require.NoError(t, err) stakerAddr := common.BytesToAddress(staker.Bytes()) + mockVMContract.CallerAddress = stakerAddr argsStake := []interface{}{ stakerEthAddr, @@ -637,7 +749,8 @@ func Test_MoveStake(t *testing.T) { // stake to validator src stakeMethodID := abi.Methods[StakeMethodName] - _, err = contract.Stake(ctx, stakerAddr, &stakeMethodID, argsStake) + mockVMContract.Input = packInputArgs(t, stakeMethodID, argsStake...) + _, err = contract.Run(mockEVM, mockVMContract, false) require.NoError(t, err) argsMoveStake := []interface{}{ @@ -646,9 +759,10 @@ func Test_MoveStake(t *testing.T) { validatorDest.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt(), } + mockVMContract.Input = packInputArgs(t, methodID, argsMoveStake...) // ACT - _, err = contract.MoveStake(ctx, stakerAddr, &methodID, argsMoveStake) + _, err = contract.Run(mockEVM, mockVMContract, false) // ASSERT require.Error(t, err) @@ -656,6 +770,8 @@ func Test_MoveStake(t *testing.T) { t.Run("should move stake", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, mockEVM, mockVMContract := setup(t) + methodID := abi.Methods[MoveStakeMethodName] r := rand.New(rand.NewSource(42)) validatorSrc := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validatorSrc) @@ -671,7 +787,7 @@ func Test_MoveStake(t *testing.T) { require.NoError(t, err) stakerAddr := common.BytesToAddress(staker.Bytes()) - + mockVMContract.CallerAddress = stakerAddr argsStake := []interface{}{ stakerEthAddr, validatorSrc.OperatorAddress, @@ -680,7 +796,8 @@ func Test_MoveStake(t *testing.T) { // stake to validator src stakeMethodID := abi.Methods[StakeMethodName] - _, err = contract.Stake(ctx, stakerAddr, &stakeMethodID, argsStake) + mockVMContract.Input = packInputArgs(t, stakeMethodID, argsStake...) + _, err = contract.Run(mockEVM, mockVMContract, false) require.NoError(t, err) argsMoveStake := []interface{}{ @@ -689,10 +806,11 @@ func Test_MoveStake(t *testing.T) { validatorDest.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt(), } + mockVMContract.Input = packInputArgs(t, methodID, argsMoveStake...) // ACT // move stake to validator dest - _, err = contract.MoveStake(ctx, stakerAddr, &methodID, argsMoveStake) + _, err = contract.Run(mockEVM, mockVMContract, false) // ASSERT require.NoError(t, err) @@ -700,6 +818,8 @@ func Test_MoveStake(t *testing.T) { t.Run("should fail if staker is invalid arg", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, _, _ := setup(t) + methodID := abi.Methods[MoveStakeMethodName] r := rand.New(rand.NewSource(42)) validatorSrc := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validatorSrc) @@ -724,7 +844,7 @@ func Test_MoveStake(t *testing.T) { // stake to validator src stakeMethodID := abi.Methods[StakeMethodName] - _, err = contract.Stake(ctx, stakerAddr, &stakeMethodID, argsStake) + _, err = contract.Stake(ctx, &vm.Contract{CallerAddress: stakerAddr}, &stakeMethodID, argsStake) require.NoError(t, err) argsMoveStake := []interface{}{ @@ -735,7 +855,7 @@ func Test_MoveStake(t *testing.T) { } // ACT - _, err = contract.MoveStake(ctx, stakerAddr, &methodID, argsMoveStake) + _, err = contract.MoveStake(ctx, &vm.Contract{CallerAddress: stakerAddr}, &methodID, argsMoveStake) // ASSERT require.Error(t, err) @@ -743,6 +863,8 @@ func Test_MoveStake(t *testing.T) { t.Run("should fail if validator src is invalid arg", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, _, _ := setup(t) + methodID := abi.Methods[MoveStakeMethodName] r := rand.New(rand.NewSource(42)) validatorSrc := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validatorSrc) @@ -767,7 +889,7 @@ func Test_MoveStake(t *testing.T) { // stake to validator src stakeMethodID := abi.Methods[StakeMethodName] - _, err = contract.Stake(ctx, stakerAddr, &stakeMethodID, argsStake) + _, err = contract.Stake(ctx, &vm.Contract{CallerAddress: stakerAddr}, &stakeMethodID, argsStake) require.NoError(t, err) argsMoveStake := []interface{}{ @@ -778,7 +900,7 @@ func Test_MoveStake(t *testing.T) { } // ACT - _, err = contract.MoveStake(ctx, stakerAddr, &methodID, argsMoveStake) + _, err = contract.MoveStake(ctx, &vm.Contract{CallerAddress: stakerAddr}, &methodID, argsMoveStake) // ASSERT require.Error(t, err) @@ -786,6 +908,8 @@ func Test_MoveStake(t *testing.T) { t.Run("should fail if validator dest is invalid arg", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, _, _ := setup(t) + methodID := abi.Methods[MoveStakeMethodName] r := rand.New(rand.NewSource(42)) validatorSrc := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validatorSrc) @@ -810,7 +934,7 @@ func Test_MoveStake(t *testing.T) { // stake to validator src stakeMethodID := abi.Methods[StakeMethodName] - _, err = contract.Stake(ctx, stakerAddr, &stakeMethodID, argsStake) + _, err = contract.Stake(ctx, &vm.Contract{CallerAddress: stakerAddr}, &stakeMethodID, argsStake) require.NoError(t, err) argsMoveStake := []interface{}{ @@ -821,7 +945,7 @@ func Test_MoveStake(t *testing.T) { } // ACT - _, err = contract.MoveStake(ctx, stakerAddr, &methodID, argsMoveStake) + _, err = contract.MoveStake(ctx, &vm.Contract{CallerAddress: stakerAddr}, &methodID, argsMoveStake) // ASSERT require.Error(t, err) @@ -829,6 +953,8 @@ func Test_MoveStake(t *testing.T) { t.Run("should fail if amount is invalid arg", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, _, _ := setup(t) + methodID := abi.Methods[MoveStakeMethodName] r := rand.New(rand.NewSource(42)) validatorSrc := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validatorSrc) @@ -853,7 +979,7 @@ func Test_MoveStake(t *testing.T) { // stake to validator src stakeMethodID := abi.Methods[StakeMethodName] - _, err = contract.Stake(ctx, stakerAddr, &stakeMethodID, argsStake) + _, err = contract.Stake(ctx, &vm.Contract{CallerAddress: stakerAddr}, &stakeMethodID, argsStake) require.NoError(t, err) argsMoveStake := []interface{}{ @@ -864,7 +990,7 @@ func Test_MoveStake(t *testing.T) { } // ACT - _, err = contract.MoveStake(ctx, stakerAddr, &methodID, argsMoveStake) + _, err = contract.MoveStake(ctx, &vm.Contract{CallerAddress: stakerAddr}, &methodID, argsMoveStake) // ASSERT require.Error(t, err) @@ -872,6 +998,8 @@ func Test_MoveStake(t *testing.T) { t.Run("should fail if wrong args amount", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, _, _ := setup(t) + methodID := abi.Methods[MoveStakeMethodName] r := rand.New(rand.NewSource(42)) validatorSrc := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validatorSrc) @@ -896,20 +1024,22 @@ func Test_MoveStake(t *testing.T) { // stake to validator src stakeMethodID := abi.Methods[StakeMethodName] - _, err = contract.Stake(ctx, stakerAddr, &stakeMethodID, argsStake) + _, err = contract.Stake(ctx, &vm.Contract{CallerAddress: stakerAddr}, &stakeMethodID, argsStake) require.NoError(t, err) argsMoveStake := []interface{}{stakerEthAddr, validatorSrc.OperatorAddress, validatorDest.OperatorAddress} // ACT - _, err = contract.MoveStake(ctx, stakerAddr, &methodID, argsMoveStake) + _, err = contract.MoveStake(ctx, &vm.Contract{CallerAddress: stakerAddr}, &methodID, argsMoveStake) // ASSERT require.Error(t, err) }) - t.Run("should fail if origin is not staker", func(t *testing.T) { + t.Run("should fail if caller is not staker", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, mockEVM, mockVMContract := setup(t) + methodID := abi.Methods[MoveStakeMethodName] r := rand.New(rand.NewSource(42)) validatorSrc := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validatorSrc) @@ -925,7 +1055,7 @@ func Test_MoveStake(t *testing.T) { require.NoError(t, err) stakerAddr := common.BytesToAddress(staker.Bytes()) - + mockVMContract.CallerAddress = stakerAddr argsStake := []interface{}{ stakerEthAddr, validatorSrc.OperatorAddress, @@ -934,7 +1064,8 @@ func Test_MoveStake(t *testing.T) { // stake to validator src stakeMethodID := abi.Methods[StakeMethodName] - _, err = contract.Stake(ctx, stakerAddr, &stakeMethodID, argsStake) + mockVMContract.Input = packInputArgs(t, stakeMethodID, argsStake...) + _, err = contract.Run(mockEVM, mockVMContract, false) require.NoError(t, err) argsMoveStake := []interface{}{ @@ -943,24 +1074,28 @@ func Test_MoveStake(t *testing.T) { validatorDest.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt(), } + mockVMContract.Input = packInputArgs(t, methodID, argsMoveStake...) - originEthAddr := common.BytesToAddress(sample.Bech32AccAddress().Bytes()) + callerEthAddr := common.BytesToAddress(sample.Bech32AccAddress().Bytes()) + mockVMContract.CallerAddress = callerEthAddr // ACT - _, err = contract.MoveStake(ctx, originEthAddr, &methodID, argsMoveStake) + _, err = contract.Run(mockEVM, mockVMContract, false) // ASSERT - require.ErrorContains(t, err, "origin is not staker") + require.ErrorContains(t, err, "caller is not staker") }) } func Test_GetAllValidators(t *testing.T) { - ctx, contract, abi, sdkKeepers := setup(t) - methodID := abi.Methods[GetAllValidatorsMethodName] - t.Run("should return empty array if validators not set", func(t *testing.T) { + // ARRANGE + _, contract, abi, _, mockEVM, mockVMContract := setup(t) + methodID := abi.Methods[GetAllValidatorsMethodName] + mockVMContract.Input = methodID.ID + // ACT - validators, err := contract.GetAllValidators(ctx, &methodID) + validators, err := contract.Run(mockEVM, mockVMContract, false) // ASSERT require.NoError(t, err) @@ -973,12 +1108,15 @@ func Test_GetAllValidators(t *testing.T) { t.Run("should return validators if set", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, mockEVM, mockVMContract := setup(t) + methodID := abi.Methods[GetAllValidatorsMethodName] + mockVMContract.Input = methodID.ID r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) // ACT - validators, err := contract.GetAllValidators(ctx, &methodID) + validators, err := contract.Run(mockEVM, mockVMContract, false) // ASSERT require.NoError(t, err) @@ -991,11 +1129,10 @@ func Test_GetAllValidators(t *testing.T) { } func Test_GetShares(t *testing.T) { - ctx, contract, abi, sdkKeepers := setup(t) - methodID := abi.Methods[GetSharesMethodName] - t.Run("should return stakes", func(t *testing.T) { // ARRANGE + ctx, contract, abi, sdkKeepers, mockEVM, mockVMContract := setup(t) + methodID := abi.Methods[GetSharesMethodName] r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -1015,12 +1152,13 @@ func Test_GetShares(t *testing.T) { stakeMethodID := abi.Methods[StakeMethodName] // ACT - _, err = contract.Stake(ctx, stakerAddr, &stakeMethodID, stakeArgs) + _, err = contract.Stake(ctx, &vm.Contract{CallerAddress: stakerAddr}, &stakeMethodID, stakeArgs) require.NoError(t, err) // ASSERT args := []interface{}{stakerEthAddr, validator.OperatorAddress} - stakes, err := contract.GetShares(ctx, &methodID, args) + mockVMContract.Input = packInputArgs(t, methodID, args...) + stakes, err := contract.Run(mockEVM, mockVMContract, false) require.NoError(t, err) res, err := methodID.Outputs.Unpack(stakes) @@ -1034,6 +1172,8 @@ func Test_GetShares(t *testing.T) { t.Run("should fail if wrong args amount", func(t *testing.T) { // ARRANGE + ctx, contract, abi, _, _, _ := setup(t) + methodID := abi.Methods[GetSharesMethodName] staker := sample.Bech32AccAddress() stakerEthAddr := common.BytesToAddress(staker.Bytes()) args := []interface{}{stakerEthAddr} @@ -1047,6 +1187,8 @@ func Test_GetShares(t *testing.T) { t.Run("should fail if invalid staker arg", func(t *testing.T) { // ARRANGE + ctx, contract, abi, _, _, _ := setup(t) + methodID := abi.Methods[GetSharesMethodName] r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) args := []interface{}{42, validator.OperatorAddress} @@ -1060,6 +1202,8 @@ func Test_GetShares(t *testing.T) { t.Run("should fail if invalid val address", func(t *testing.T) { // ARRANGE + ctx, contract, abi, _, _, _ := setup(t) + methodID := abi.Methods[GetSharesMethodName] staker := sample.Bech32AccAddress() stakerEthAddr := common.BytesToAddress(staker.Bytes()) args := []interface{}{stakerEthAddr, staker.String()} @@ -1070,4 +1214,42 @@ func Test_GetShares(t *testing.T) { // ASSERT require.Error(t, err) }) + + t.Run("should fail if invalid val address format", func(t *testing.T) { + // ARRANGE + ctx, contract, abi, _, _, _ := setup(t) + methodID := abi.Methods[GetSharesMethodName] + staker := sample.Bech32AccAddress() + stakerEthAddr := common.BytesToAddress(staker.Bytes()) + args := []interface{}{stakerEthAddr, 42} + + // ACT + _, err := contract.GetShares(ctx, &methodID, args) + + // ASSERT + require.Error(t, err) + }) +} + +func Test_RunInvalidMethod(t *testing.T) { + // ARRANGE + _, contract, _, _, mockEVM, mockVMContract := setup(t) + k, _, _, _ := keeper.FungibleKeeper(t) + + var encoding ethermint.EncodingConfig + appCodec := encoding.Codec + gasConfig := storetypes.TransientGasConfig() + + prototype := prototype.NewIPrototypeContract(k, appCodec, gasConfig) + + prototypeAbi := prototype.Abi() + methodID := prototypeAbi.Methods["bech32ToHexAddr"] + args := []interface{}{"123"} + mockVMContract.Input = packInputArgs(t, methodID, args...) + + // ACT + _, err := contract.Run(mockEVM, mockVMContract, false) + + // ASSERT + require.Error(t, err) }