From 47c3797a57035cb17a6bec74d21290ab0147c10b Mon Sep 17 00:00:00 2001 From: zakir <80246097+zakir-code@users.noreply.github.com> Date: Wed, 6 Nov 2024 14:09:21 +0800 Subject: [PATCH] test: improve and fix integration tests (#805) --- api/fx/gravity/crosschain/v1/tx.pulsar.go | 18 +- client/grpc/grpc_client.go | 11 + contract/contract_test.go | 37 ++ contract/erc20_abi.go | 178 ------ contract/erc20_token.go | 5 - proto/fx/gravity/crosschain/v1/tx.proto | 2 + scripts/linter.sh | 6 +- tests/ante_test.go | 35 -- tests/contract_test.go | 48 -- tests/crosschain_test.go | 18 - tests/erc20_suite.go | 62 --- tests/evm_suite.go | 384 ------------- tests/evm_test.go | 314 ----------- tests/integration/ante_test.go | 28 + tests/{ => integration}/crosschain_suite.go | 288 ++++------ tests/integration/crosschain_test.go | 21 + tests/integration/erc20_token_suite.go | 183 ++++++ tests/integration/erc721_token_suite.go | 86 +++ tests/integration/eth_suite.go | 153 +++++ tests/integration/evm_test.go | 300 ++++++++++ tests/integration/fxcore_suite.go | 467 ++++++++++++++++ tests/integration/integration_test.go | 156 ++++++ tests/{ => integration}/migrate_test.go | 90 ++- .../staking_percompile_test.go} | 365 ++++++------ tests/integration/staking_precompile_suite.go | 112 ++++ tests/integration_test.go | 99 ---- tests/staking_suite.go | 284 ---------- tests/suite.go | 526 ------------------ testutil/helpers/tools.go | 11 + testutil/network.go | 5 +- testutil/network/network.go | 28 +- x/crosschain/types/tx.pb.go | 24 +- x/evm/keeper/msg_server_test.go | 4 +- x/migrate/keeper/distr_staking_test.go | 14 +- 34 files changed, 1963 insertions(+), 2399 deletions(-) delete mode 100644 contract/erc20_abi.go delete mode 100644 tests/ante_test.go delete mode 100644 tests/contract_test.go delete mode 100644 tests/crosschain_test.go delete mode 100644 tests/erc20_suite.go delete mode 100644 tests/evm_suite.go delete mode 100644 tests/evm_test.go create mode 100644 tests/integration/ante_test.go rename tests/{ => integration}/crosschain_suite.go (58%) create mode 100644 tests/integration/crosschain_test.go create mode 100644 tests/integration/erc20_token_suite.go create mode 100644 tests/integration/erc721_token_suite.go create mode 100644 tests/integration/eth_suite.go create mode 100644 tests/integration/evm_test.go create mode 100644 tests/integration/fxcore_suite.go create mode 100644 tests/integration/integration_test.go rename tests/{ => integration}/migrate_test.go (56%) rename tests/{staking_test.go => integration/staking_percompile_test.go} (53%) create mode 100644 tests/integration/staking_precompile_suite.go delete mode 100644 tests/integration_test.go delete mode 100644 tests/staking_suite.go delete mode 100644 tests/suite.go diff --git a/api/fx/gravity/crosschain/v1/tx.pulsar.go b/api/fx/gravity/crosschain/v1/tx.pulsar.go index 456dad08..960e8819 100644 --- a/api/fx/gravity/crosschain/v1/tx.pulsar.go +++ b/api/fx/gravity/crosschain/v1/tx.pulsar.go @@ -17259,12 +17259,13 @@ type MsgSendToFxClaim struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - EventNonce uint64 `protobuf:"varint,1,opt,name=event_nonce,json=eventNonce,proto3" json:"event_nonce,omitempty"` - BlockHeight uint64 `protobuf:"varint,2,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"` - TokenContract string `protobuf:"bytes,3,opt,name=token_contract,json=tokenContract,proto3" json:"token_contract,omitempty"` - Amount string `protobuf:"bytes,4,opt,name=amount,proto3" json:"amount,omitempty"` - Sender string `protobuf:"bytes,5,opt,name=sender,proto3" json:"sender,omitempty"` - Receiver string `protobuf:"bytes,6,opt,name=receiver,proto3" json:"receiver,omitempty"` + EventNonce uint64 `protobuf:"varint,1,opt,name=event_nonce,json=eventNonce,proto3" json:"event_nonce,omitempty"` + BlockHeight uint64 `protobuf:"varint,2,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"` + TokenContract string `protobuf:"bytes,3,opt,name=token_contract,json=tokenContract,proto3" json:"token_contract,omitempty"` + Amount string `protobuf:"bytes,4,opt,name=amount,proto3" json:"amount,omitempty"` + Sender string `protobuf:"bytes,5,opt,name=sender,proto3" json:"sender,omitempty"` + Receiver string `protobuf:"bytes,6,opt,name=receiver,proto3" json:"receiver,omitempty"` + // Deprecated: After the upgrade to v8 TargetIbc string `protobuf:"bytes,7,opt,name=target_ibc,json=targetIbc,proto3" json:"target_ibc,omitempty"` BridgerAddress string `protobuf:"bytes,8,opt,name=bridger_address,json=bridgerAddress,proto3" json:"bridger_address,omitempty"` ChainName string `protobuf:"bytes,9,opt,name=chain_name,json=chainName,proto3" json:"chain_name,omitempty"` @@ -17737,8 +17738,9 @@ type MsgBridgeTokenClaim struct { Symbol string `protobuf:"bytes,5,opt,name=symbol,proto3" json:"symbol,omitempty"` Decimals uint64 `protobuf:"varint,6,opt,name=decimals,proto3" json:"decimals,omitempty"` BridgerAddress string `protobuf:"bytes,7,opt,name=bridger_address,json=bridgerAddress,proto3" json:"bridger_address,omitempty"` - ChannelIbc string `protobuf:"bytes,8,opt,name=channel_ibc,json=channelIbc,proto3" json:"channel_ibc,omitempty"` // Bridge Token channel IBC - ChainName string `protobuf:"bytes,9,opt,name=chain_name,json=chainName,proto3" json:"chain_name,omitempty"` + // Deprecated: After the upgrade to v8 + ChannelIbc string `protobuf:"bytes,8,opt,name=channel_ibc,json=channelIbc,proto3" json:"channel_ibc,omitempty"` // Bridge Token channel IBC + ChainName string `protobuf:"bytes,9,opt,name=chain_name,json=chainName,proto3" json:"chain_name,omitempty"` } func (x *MsgBridgeTokenClaim) Reset() { diff --git a/client/grpc/grpc_client.go b/client/grpc/grpc_client.go index 256c4844..97ad906a 100644 --- a/client/grpc/grpc_client.go +++ b/client/grpc/grpc_client.go @@ -350,6 +350,17 @@ func (cli *Client) GetModuleAccounts() ([]sdk.AccountI, error) { return accounts, nil } +func (cli *Client) GetModuleAccountByName(moduleName string) (sdk.AccountI, error) { + response, err := cli.AuthQuery().ModuleAccountByName(cli.ctx, &authtypes.QueryModuleAccountByNameRequest{ + Name: moduleName, + }) + if err != nil { + return nil, err + } + var account sdk.AccountI + return account, client.NewAccountCodec().UnpackAny(response.Account, &account) +} + func (cli *Client) GetSyncing() (bool, error) { response, err := cli.TMServiceClient().GetSyncing(cli.ctx, &cmtservice.GetSyncingRequest{}) if err != nil { diff --git a/contract/contract_test.go b/contract/contract_test.go index b7beb824..9eb3ae92 100644 --- a/contract/contract_test.go +++ b/contract/contract_test.go @@ -1,6 +1,8 @@ package contract_test import ( + "bytes" + "encoding/base64" "encoding/hex" "math/big" "testing" @@ -64,3 +66,38 @@ func TestPackBridgeCallback(t *testing.T) { }) } } + +func TestFIP20Code(t *testing.T) { + codeAddr := "0x79172102144e0ef3dc372c3774f3225fbba20066" + codeBase64 := "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" + + code, codeNew := replayCodeAddress(codeBase64, codeAddr, contract.FIP20LogicAddress) + require.Equal(t, "60806040526004361061011f5760003560e01c8063715018a6116100a0578063b86d529811610064578063b86d52981461031c578063c5cb9b511461033a578063dd62ed3e1461035a578063de7ea79d146103a0578063f2fde38b146103c057600080fd5b8063715018a6146102805780638da5cb5b1461029557806395d89b41146102c75780639dc29fac146102dc578063a9059cbb146102fc57600080fd5b80633659cfe6116100e75780633659cfe6146101e057806340c10f19146102025780634f1ef2861461022257806352d1902d1461023557806370a082311461024a57600080fd5b806306fdde0314610124578063095ea7b31461014f57806318160ddd1461017f57806323b872dd1461019e578063313ce567146101be575b600080fd5b34801561013057600080fd5b506101396103e0565b6040516101469190611afa565b60405180910390f35b34801561015b57600080fd5b5061016f61016a36600461189a565b610472565b6040519015158152602001610146565b34801561018b57600080fd5b5060cc545b604051908152602001610146565b3480156101aa57600080fd5b5061016f6101b9366004611800565b6104c8565b3480156101ca57600080fd5b5060cb5460405160ff9091168152602001610146565b3480156101ec57600080fd5b506102006101fb3660046117b4565b610577565b005b34801561020e57600080fd5b5061020061021d36600461189a565b610657565b61020061023036600461183b565b61068f565b34801561024157600080fd5b5061019061075c565b34801561025657600080fd5b506101906102653660046117b4565b6001600160a01b0316600090815260cd602052604090205490565b34801561028c57600080fd5b5061020061080f565b3480156102a157600080fd5b506097546001600160a01b03165b6040516001600160a01b039091168152602001610146565b3480156102d357600080fd5b50610139610845565b3480156102e857600080fd5b506102006102f736600461189a565b610854565b34801561030857600080fd5b5061016f61031736600461189a565b610888565b34801561032857600080fd5b5060cf546001600160a01b03166102af565b34801561034657600080fd5b5061016f6103553660046119ce565b61089e565b34801561036657600080fd5b506101906103753660046117ce565b6001600160a01b03918216600090815260ce6020908152604080832093909416825291909152205490565b3480156103ac57600080fd5b506102006103bb366004611945565b610954565b3480156103cc57600080fd5b506102006103db3660046117b4565b610a73565b606060c980546103ef90611d08565b80601f016020809104026020016040519081016040528092919081815260200182805461041b90611d08565b80156104685780601f1061043d57610100808354040283529160200191610468565b820191906000526020600020905b81548152906001019060200180831161044b57829003601f168201915b5050505050905090565b600061047f338484610b0b565b6040518281526001600160a01b0384169033907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259060200160405180910390a350600192915050565b6001600160a01b038316600090815260ce602090815260408083203384529091528120548281101561054b5760405162461bcd60e51b815260206004820152602160248201527f7472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636044820152606560f81b60648201526084015b60405180910390fd5b61055f853361055a8685611cc5565b610b0b565b61056a858585610b8d565b60019150505b9392505050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614156105c05760405162461bcd60e51b815260040161054290611b3c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610609600080516020611d70833981519152546001600160a01b031690565b6001600160a01b03161461062f5760405162461bcd60e51b815260040161054290611b88565b61063881610d3c565b6040805160008082526020820190925261065491839190610d66565b50565b6097546001600160a01b031633146106815760405162461bcd60e51b815260040161054290611bd4565b61068b8282610ee5565b5050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614156106d85760405162461bcd60e51b815260040161054290611b3c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610721600080516020611d70833981519152546001600160a01b031690565b6001600160a01b0316146107475760405162461bcd60e51b815260040161054290611b88565b61075082610d3c565b61068b82826001610d66565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146107fc5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610542565b50600080516020611d7083398151915290565b6097546001600160a01b031633146108395760405162461bcd60e51b815260040161054290611bd4565b6108436000610fc4565b565b606060ca80546103ef90611d08565b6097546001600160a01b0316331461087e5760405162461bcd60e51b815260040161054290611bd4565b61068b8282611016565b6000610895338484610b8d565b50600192915050565b600063ffffffff333b16156108f55760405162461bcd60e51b815260206004820152601960248201527f63616c6c65722063616e6e6f7420626520636f6e7472616374000000000000006044820152606401610542565b6109023386868686611158565b336001600160a01b03167f282dd1817b996776123a00596764d4d54cc16460c9854f7a23f6be020ba0463d868686866040516109419493929190611b0d565b60405180910390a2506001949350505050565b600054610100900460ff1661096f5760005460ff1615610973565b303b155b6109d65760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610542565b600054610100900460ff161580156109f8576000805461ffff19166101011790555b8451610a0b9060c99060208801906116a2565b508351610a1f9060ca9060208701906116a2565b5060cb805460ff191660ff851617905560cf80546001600160a01b0319166001600160a01b038416179055610a5261131b565b610a5a61134a565b8015610a6c576000805461ff00191690555b5050505050565b6097546001600160a01b03163314610a9d5760405162461bcd60e51b815260040161054290611bd4565b6001600160a01b038116610b025760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610542565b61065481610fc4565b6001600160a01b038316610b615760405162461bcd60e51b815260206004820152601d60248201527f617070726f76652066726f6d20746865207a65726f20616464726573730000006044820152606401610542565b6001600160a01b03928316600090815260ce602090815260408083209490951682529290925291902055565b6001600160a01b038316610be35760405162461bcd60e51b815260206004820152601e60248201527f7472616e736665722066726f6d20746865207a65726f206164647265737300006044820152606401610542565b6001600160a01b038216610c395760405162461bcd60e51b815260206004820152601c60248201527f7472616e7366657220746f20746865207a65726f2061646472657373000000006044820152606401610542565b6001600160a01b038316600090815260cd602052604090205481811015610ca25760405162461bcd60e51b815260206004820152601f60248201527f7472616e7366657220616d6f756e7420657863656564732062616c616e6365006044820152606401610542565b610cac8282611cc5565b6001600160a01b03808616600090815260cd60205260408082209390935590851681529081208054849290610ce2908490611cad565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610d2e91815260200190565b60405180910390a350505050565b6097546001600160a01b031633146106545760405162461bcd60e51b815260040161054290611bd4565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615610d9e57610d9983611371565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b815260040160206040518083038186803b158015610dd757600080fd5b505afa925050508015610e07575060408051601f3d908101601f19168201909252610e04918101906118c3565b60015b610e6a5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610542565b600080516020611d708339815191528114610ed95760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610542565b50610d9983838361140d565b6001600160a01b038216610f3b5760405162461bcd60e51b815260206004820152601860248201527f6d696e7420746f20746865207a65726f206164647265737300000000000000006044820152606401610542565b8060cc6000828254610f4d9190611cad565b90915550506001600160a01b038216600090815260cd602052604081208054839290610f7a908490611cad565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b03821661106c5760405162461bcd60e51b815260206004820152601a60248201527f6275726e2066726f6d20746865207a65726f20616464726573730000000000006044820152606401610542565b6001600160a01b038216600090815260cd6020526040902054818110156110d55760405162461bcd60e51b815260206004820152601b60248201527f6275726e20616d6f756e7420657863656564732062616c616e636500000000006044820152606401610542565b6110df8282611cc5565b6001600160a01b038416600090815260cd602052604081209190915560cc805484929061110d908490611cc5565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6001600160a01b0385166111ae5760405162461bcd60e51b815260206004820152601e60248201527f7472616e736665722066726f6d20746865207a65726f206164647265737300006044820152606401610542565b60008451116111f35760405162461bcd60e51b81526020600482015260116024820152701a5b9d985b1a59081c9958da5c1a595b9d607a1b6044820152606401610542565b806112315760405162461bcd60e51b815260206004820152600e60248201526d1a5b9d985b1a59081d185c99d95d60921b6044820152606401610542565b60cf546112529086906001600160a01b031661124d8587611cad565b610b8d565b6000806110046001600160a01b031661127e888888888860405180602001604052806000815250611438565b60405161128b9190611a4c565b6000604051808303816000865af19150503d80600081146112c8576040519150601f19603f3d011682016040523d82523d6000602084013e6112cd565b606091505b509150915061131282826040518060400160405280601b81526020017f7472616e736665722063726f737320636861696e206661696c6564000000000081525061148b565b50505050505050565b600054610100900460ff166113425760405162461bcd60e51b815260040161054290611c09565b610843611505565b600054610100900460ff166108435760405162461bcd60e51b815260040161054290611c09565b6001600160a01b0381163b6113de5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610542565b600080516020611d7083398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b61141683611535565b6000825111806114235750805b15610d99576114328383611575565b50505050565b606086868686868660405160240161145596959493929190611aa5565b60408051601f198184030181529190526020810180516001600160e01b0316633c3e7d7760e01b17905290509695505050505050565b82610d99576000828060200190518101906114a691906118db565b90506001825110156114cc578060405162461bcd60e51b81526004016105429190611afa565b81816040516020016114df929190611a68565b60408051601f198184030181529082905262461bcd60e51b825261054291600401611afa565b600054610100900460ff1661152c5760405162461bcd60e51b815260040161054290611c09565b61084333610fc4565b61153e81611371565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b6115dd5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610542565b600080846001600160a01b0316846040516115f89190611a4c565b600060405180830381855af49150503d8060008114611633576040519150601f19603f3d011682016040523d82523d6000602084013e611638565b606091505b50915091506116608282604051806060016040528060278152602001611d9060279139611669565b95945050505050565b60608315611678575081610570565b8251156116885782518084602001fd5b8160405162461bcd60e51b81526004016105429190611afa565b8280546116ae90611d08565b90600052602060002090601f0160209004810192826116d05760008555611716565b82601f106116e957805160ff1916838001178555611716565b82800160010185558215611716579182015b828111156117165782518255916020019190600101906116fb565b50611722929150611726565b5090565b5b808211156117225760008155600101611727565b600061174e61174984611c85565b611c54565b905082815283838301111561176257600080fd5b828260208301376000602084830101529392505050565b80356001600160a01b038116811461179057600080fd5b919050565b600082601f8301126117a5578081fd5b6105708383356020850161173b565b6000602082840312156117c5578081fd5b61057082611779565b600080604083850312156117e0578081fd5b6117e983611779565b91506117f760208401611779565b90509250929050565b600080600060608486031215611814578081fd5b61181d84611779565b925061182b60208501611779565b9150604084013590509250925092565b6000806040838503121561184d578182fd5b61185683611779565b9150602083013567ffffffffffffffff811115611871578182fd5b8301601f81018513611881578182fd5b6118908582356020840161173b565b9150509250929050565b600080604083850312156118ac578182fd5b6118b583611779565b946020939093013593505050565b6000602082840312156118d4578081fd5b5051919050565b6000602082840312156118ec578081fd5b815167ffffffffffffffff811115611902578182fd5b8201601f81018413611912578182fd5b805161192061174982611c85565b818152856020838501011115611934578384fd5b611660826020830160208601611cdc565b6000806000806080858703121561195a578081fd5b843567ffffffffffffffff80821115611971578283fd5b61197d88838901611795565b95506020870135915080821115611992578283fd5b5061199f87828801611795565b935050604085013560ff811681146119b5578182fd5b91506119c360608601611779565b905092959194509250565b600080600080608085870312156119e3578384fd5b843567ffffffffffffffff8111156119f9578485fd5b611a0587828801611795565b97602087013597506040870135966060013595509350505050565b60008151808452611a38816020860160208601611cdc565b601f01601f19169290920160200192915050565b60008251611a5e818460208701611cdc565b9190910192915050565b60008351611a7a818460208801611cdc565b6101d160f51b9083019081528351611a99816002840160208801611cdc565b01600201949350505050565b6001600160a01b038716815260c060208201819052600090611ac990830188611a20565b86604084015285606084015284608084015282810360a0840152611aed8185611a20565b9998505050505050505050565b6020815260006105706020830184611a20565b608081526000611b206080830187611a20565b6020830195909552506040810192909252606090910152919050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c7d57611c7d611d59565b604052919050565b600067ffffffffffffffff821115611c9f57611c9f611d59565b50601f01601f191660200190565b60008219821115611cc057611cc0611d43565b500190565b600082821015611cd757611cd7611d43565b500390565b60005b83811015611cf7578181015183820152602001611cdf565b838111156114325750506000910152565b600181811c90821680611d1c57607f821691505b60208210811415611d3d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fdfe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212203b820696364250693508f4a7a5e7e57685a305efda3e6577e74dfee930ff276e64736f6c63430008040033", hex.EncodeToString(code)) + require.Equal(t, "60806040526004361061011f5760003560e01c8063715018a6116100a0578063b86d529811610064578063b86d52981461031c578063c5cb9b511461033a578063dd62ed3e1461035a578063de7ea79d146103a0578063f2fde38b146103c057600080fd5b8063715018a6146102805780638da5cb5b1461029557806395d89b41146102c75780639dc29fac146102dc578063a9059cbb146102fc57600080fd5b80633659cfe6116100e75780633659cfe6146101e057806340c10f19146102025780634f1ef2861461022257806352d1902d1461023557806370a082311461024a57600080fd5b806306fdde0314610124578063095ea7b31461014f57806318160ddd1461017f57806323b872dd1461019e578063313ce567146101be575b600080fd5b34801561013057600080fd5b506101396103e0565b6040516101469190611afa565b60405180910390f35b34801561015b57600080fd5b5061016f61016a36600461189a565b610472565b6040519015158152602001610146565b34801561018b57600080fd5b5060cc545b604051908152602001610146565b3480156101aa57600080fd5b5061016f6101b9366004611800565b6104c8565b3480156101ca57600080fd5b5060cb5460405160ff9091168152602001610146565b3480156101ec57600080fd5b506102006101fb3660046117b4565b610577565b005b34801561020e57600080fd5b5061020061021d36600461189a565b610657565b61020061023036600461183b565b61068f565b34801561024157600080fd5b5061019061075c565b34801561025657600080fd5b506101906102653660046117b4565b6001600160a01b0316600090815260cd602052604090205490565b34801561028c57600080fd5b5061020061080f565b3480156102a157600080fd5b506097546001600160a01b03165b6040516001600160a01b039091168152602001610146565b3480156102d357600080fd5b50610139610845565b3480156102e857600080fd5b506102006102f736600461189a565b610854565b34801561030857600080fd5b5061016f61031736600461189a565b610888565b34801561032857600080fd5b5060cf546001600160a01b03166102af565b34801561034657600080fd5b5061016f6103553660046119ce565b61089e565b34801561036657600080fd5b506101906103753660046117ce565b6001600160a01b03918216600090815260ce6020908152604080832093909416825291909152205490565b3480156103ac57600080fd5b506102006103bb366004611945565b610954565b3480156103cc57600080fd5b506102006103db3660046117b4565b610a73565b606060c980546103ef90611d08565b80601f016020809104026020016040519081016040528092919081815260200182805461041b90611d08565b80156104685780601f1061043d57610100808354040283529160200191610468565b820191906000526020600020905b81548152906001019060200180831161044b57829003601f168201915b5050505050905090565b600061047f338484610b0b565b6040518281526001600160a01b0384169033907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259060200160405180910390a350600192915050565b6001600160a01b038316600090815260ce602090815260408083203384529091528120548281101561054b5760405162461bcd60e51b815260206004820152602160248201527f7472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636044820152606560f81b60648201526084015b60405180910390fd5b61055f853361055a8685611cc5565b610b0b565b61056a858585610b8d565b60019150505b9392505050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000010011614156105c05760405162461bcd60e51b815260040161054290611b3c565b7f00000000000000000000000000000000000000000000000000000000000010016001600160a01b0316610609600080516020611d70833981519152546001600160a01b031690565b6001600160a01b03161461062f5760405162461bcd60e51b815260040161054290611b88565b61063881610d3c565b6040805160008082526020820190925261065491839190610d66565b50565b6097546001600160a01b031633146106815760405162461bcd60e51b815260040161054290611bd4565b61068b8282610ee5565b5050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000010011614156106d85760405162461bcd60e51b815260040161054290611b3c565b7f00000000000000000000000000000000000000000000000000000000000010016001600160a01b0316610721600080516020611d70833981519152546001600160a01b031690565b6001600160a01b0316146107475760405162461bcd60e51b815260040161054290611b88565b61075082610d3c565b61068b82826001610d66565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000100116146107fc5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610542565b50600080516020611d7083398151915290565b6097546001600160a01b031633146108395760405162461bcd60e51b815260040161054290611bd4565b6108436000610fc4565b565b606060ca80546103ef90611d08565b6097546001600160a01b0316331461087e5760405162461bcd60e51b815260040161054290611bd4565b61068b8282611016565b6000610895338484610b8d565b50600192915050565b600063ffffffff333b16156108f55760405162461bcd60e51b815260206004820152601960248201527f63616c6c65722063616e6e6f7420626520636f6e7472616374000000000000006044820152606401610542565b6109023386868686611158565b336001600160a01b03167f282dd1817b996776123a00596764d4d54cc16460c9854f7a23f6be020ba0463d868686866040516109419493929190611b0d565b60405180910390a2506001949350505050565b600054610100900460ff1661096f5760005460ff1615610973565b303b155b6109d65760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610542565b600054610100900460ff161580156109f8576000805461ffff19166101011790555b8451610a0b9060c99060208801906116a2565b508351610a1f9060ca9060208701906116a2565b5060cb805460ff191660ff851617905560cf80546001600160a01b0319166001600160a01b038416179055610a5261131b565b610a5a61134a565b8015610a6c576000805461ff00191690555b5050505050565b6097546001600160a01b03163314610a9d5760405162461bcd60e51b815260040161054290611bd4565b6001600160a01b038116610b025760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610542565b61065481610fc4565b6001600160a01b038316610b615760405162461bcd60e51b815260206004820152601d60248201527f617070726f76652066726f6d20746865207a65726f20616464726573730000006044820152606401610542565b6001600160a01b03928316600090815260ce602090815260408083209490951682529290925291902055565b6001600160a01b038316610be35760405162461bcd60e51b815260206004820152601e60248201527f7472616e736665722066726f6d20746865207a65726f206164647265737300006044820152606401610542565b6001600160a01b038216610c395760405162461bcd60e51b815260206004820152601c60248201527f7472616e7366657220746f20746865207a65726f2061646472657373000000006044820152606401610542565b6001600160a01b038316600090815260cd602052604090205481811015610ca25760405162461bcd60e51b815260206004820152601f60248201527f7472616e7366657220616d6f756e7420657863656564732062616c616e6365006044820152606401610542565b610cac8282611cc5565b6001600160a01b03808616600090815260cd60205260408082209390935590851681529081208054849290610ce2908490611cad565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610d2e91815260200190565b60405180910390a350505050565b6097546001600160a01b031633146106545760405162461bcd60e51b815260040161054290611bd4565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615610d9e57610d9983611371565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b815260040160206040518083038186803b158015610dd757600080fd5b505afa925050508015610e07575060408051601f3d908101601f19168201909252610e04918101906118c3565b60015b610e6a5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610542565b600080516020611d708339815191528114610ed95760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610542565b50610d9983838361140d565b6001600160a01b038216610f3b5760405162461bcd60e51b815260206004820152601860248201527f6d696e7420746f20746865207a65726f206164647265737300000000000000006044820152606401610542565b8060cc6000828254610f4d9190611cad565b90915550506001600160a01b038216600090815260cd602052604081208054839290610f7a908490611cad565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b03821661106c5760405162461bcd60e51b815260206004820152601a60248201527f6275726e2066726f6d20746865207a65726f20616464726573730000000000006044820152606401610542565b6001600160a01b038216600090815260cd6020526040902054818110156110d55760405162461bcd60e51b815260206004820152601b60248201527f6275726e20616d6f756e7420657863656564732062616c616e636500000000006044820152606401610542565b6110df8282611cc5565b6001600160a01b038416600090815260cd602052604081209190915560cc805484929061110d908490611cc5565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6001600160a01b0385166111ae5760405162461bcd60e51b815260206004820152601e60248201527f7472616e736665722066726f6d20746865207a65726f206164647265737300006044820152606401610542565b60008451116111f35760405162461bcd60e51b81526020600482015260116024820152701a5b9d985b1a59081c9958da5c1a595b9d607a1b6044820152606401610542565b806112315760405162461bcd60e51b815260206004820152600e60248201526d1a5b9d985b1a59081d185c99d95d60921b6044820152606401610542565b60cf546112529086906001600160a01b031661124d8587611cad565b610b8d565b6000806110046001600160a01b031661127e888888888860405180602001604052806000815250611438565b60405161128b9190611a4c565b6000604051808303816000865af19150503d80600081146112c8576040519150601f19603f3d011682016040523d82523d6000602084013e6112cd565b606091505b509150915061131282826040518060400160405280601b81526020017f7472616e736665722063726f737320636861696e206661696c6564000000000081525061148b565b50505050505050565b600054610100900460ff166113425760405162461bcd60e51b815260040161054290611c09565b610843611505565b600054610100900460ff166108435760405162461bcd60e51b815260040161054290611c09565b6001600160a01b0381163b6113de5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610542565b600080516020611d7083398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b61141683611535565b6000825111806114235750805b15610d99576114328383611575565b50505050565b606086868686868660405160240161145596959493929190611aa5565b60408051601f198184030181529190526020810180516001600160e01b0316633c3e7d7760e01b17905290509695505050505050565b82610d99576000828060200190518101906114a691906118db565b90506001825110156114cc578060405162461bcd60e51b81526004016105429190611afa565b81816040516020016114df929190611a68565b60408051601f198184030181529082905262461bcd60e51b825261054291600401611afa565b600054610100900460ff1661152c5760405162461bcd60e51b815260040161054290611c09565b61084333610fc4565b61153e81611371565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b6115dd5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610542565b600080846001600160a01b0316846040516115f89190611a4c565b600060405180830381855af49150503d8060008114611633576040519150601f19603f3d011682016040523d82523d6000602084013e611638565b606091505b50915091506116608282604051806060016040528060278152602001611d9060279139611669565b95945050505050565b60608315611678575081610570565b8251156116885782518084602001fd5b8160405162461bcd60e51b81526004016105429190611afa565b8280546116ae90611d08565b90600052602060002090601f0160209004810192826116d05760008555611716565b82601f106116e957805160ff1916838001178555611716565b82800160010185558215611716579182015b828111156117165782518255916020019190600101906116fb565b50611722929150611726565b5090565b5b808211156117225760008155600101611727565b600061174e61174984611c85565b611c54565b905082815283838301111561176257600080fd5b828260208301376000602084830101529392505050565b80356001600160a01b038116811461179057600080fd5b919050565b600082601f8301126117a5578081fd5b6105708383356020850161173b565b6000602082840312156117c5578081fd5b61057082611779565b600080604083850312156117e0578081fd5b6117e983611779565b91506117f760208401611779565b90509250929050565b600080600060608486031215611814578081fd5b61181d84611779565b925061182b60208501611779565b9150604084013590509250925092565b6000806040838503121561184d578182fd5b61185683611779565b9150602083013567ffffffffffffffff811115611871578182fd5b8301601f81018513611881578182fd5b6118908582356020840161173b565b9150509250929050565b600080604083850312156118ac578182fd5b6118b583611779565b946020939093013593505050565b6000602082840312156118d4578081fd5b5051919050565b6000602082840312156118ec578081fd5b815167ffffffffffffffff811115611902578182fd5b8201601f81018413611912578182fd5b805161192061174982611c85565b818152856020838501011115611934578384fd5b611660826020830160208601611cdc565b6000806000806080858703121561195a578081fd5b843567ffffffffffffffff80821115611971578283fd5b61197d88838901611795565b95506020870135915080821115611992578283fd5b5061199f87828801611795565b935050604085013560ff811681146119b5578182fd5b91506119c360608601611779565b905092959194509250565b600080600080608085870312156119e3578384fd5b843567ffffffffffffffff8111156119f9578485fd5b611a0587828801611795565b97602087013597506040870135966060013595509350505050565b60008151808452611a38816020860160208601611cdc565b601f01601f19169290920160200192915050565b60008251611a5e818460208701611cdc565b9190910192915050565b60008351611a7a818460208801611cdc565b6101d160f51b9083019081528351611a99816002840160208801611cdc565b01600201949350505050565b6001600160a01b038716815260c060208201819052600090611ac990830188611a20565b86604084015285606084015284608084015282810360a0840152611aed8185611a20565b9998505050505050505050565b6020815260006105706020830184611a20565b608081526000611b206080830187611a20565b6020830195909552506040810192909252606090910152919050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c7d57611c7d611d59565b604052919050565b600067ffffffffffffffff821115611c9f57611c9f611d59565b50601f01601f191660200190565b60008219821115611cc057611cc0611d43565b500190565b600082821015611cd757611cd7611d43565b500390565b60005b83811015611cf7578181015183820152602001611cdf565b838111156114325750506000910152565b600181811c90821680611d1c57607f821691505b60208210811415611d3d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fdfe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212203b820696364250693508f4a7a5e7e57685a305efda3e6577e74dfee930ff276e64736f6c63430008040033", hex.EncodeToString(codeNew)) + require.NotEqual(t, hex.EncodeToString(code), hex.EncodeToString(codeNew)) +} + +func TestWFXCode(t *testing.T) { + codeAddr := "0x0f40EeCB63928367dcbf5Db326fD5A2824c76926" + codeBase64 := "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" + + code, codeNew := replayCodeAddress(codeBase64, codeAddr, contract.WFXLogicAddress) + require.Equal(t, "6080604052600436106101395760003560e01c80638da5cb5b116100ab578063c5cb9b511161006f578063c5cb9b5114610364578063d0e30db014610148578063dd62ed3e14610377578063de7ea79d146103bd578063f2fde38b146103dd578063f3fef3a3146103fd57610148565b80638da5cb5b146102bf57806395d89b41146102f15780639dc29fac14610306578063a9059cbb14610326578063b86d52981461034657610148565b80633659cfe6116100fd5780633659cfe61461020c57806340c10f191461022c5780634f1ef2861461024c57806352d1902d1461025f57806370a0823114610274578063715018a6146102aa57610148565b806306fdde0314610150578063095ea7b31461017b57806318160ddd146101ab57806323b872dd146101ca578063313ce567146101ea57610148565b366101485761014661041d565b005b61014661041d565b34801561015c57600080fd5b5061016561045e565b6040516101729190611c0e565b60405180910390f35b34801561018757600080fd5b5061019b6101963660046119c3565b6104f0565b6040519015158152602001610172565b3480156101b757600080fd5b5060cc545b604051908152602001610172565b3480156101d657600080fd5b5061019b6101e5366004611922565b610546565b3480156101f657600080fd5b5060cb5460405160ff9091168152602001610172565b34801561021857600080fd5b506101466102273660046118a3565b6105f5565b34801561023857600080fd5b506101466102473660046119c3565b6106d5565b61014661025a366004611962565b61070d565b34801561026b57600080fd5b506101bc6107da565b34801561028057600080fd5b506101bc61028f3660046118a3565b6001600160a01b0316600090815260cd602052604090205490565b3480156102b657600080fd5b5061014661088d565b3480156102cb57600080fd5b506097546001600160a01b03165b6040516001600160a01b039091168152602001610172565b3480156102fd57600080fd5b506101656108c3565b34801561031257600080fd5b506101466103213660046119c3565b6108d2565b34801561033257600080fd5b5061019b6103413660046119c3565b610906565b34801561035257600080fd5b5060cf546001600160a01b03166102d9565b61019b610372366004611ae2565b61091c565b34801561038357600080fd5b506101bc6103923660046118ea565b6001600160a01b03918216600090815260ce6020908152604080832093909416825291909152205490565b3480156103c957600080fd5b506101466103d8366004611a57565b6109e0565b3480156103e957600080fd5b506101466103f83660046118a3565b610aff565b34801561040957600080fd5b506101466104183660046118bf565b610b97565b6104273334610c1d565b60405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b606060c9805461046d90611e1c565b80601f016020809104026020016040519081016040528092919081815260200182805461049990611e1c565b80156104e65780601f106104bb576101008083540402835291602001916104e6565b820191906000526020600020905b8154815290600101906020018083116104c957829003601f168201915b5050505050905090565b60006104fd338484610cf5565b6040518281526001600160a01b0384169033907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259060200160405180910390a350600192915050565b6001600160a01b038316600090815260ce60209081526040808320338452909152812054828110156105c95760405162461bcd60e51b815260206004820152602160248201527f7472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636044820152606560f81b60648201526084015b60405180910390fd5b6105dd85336105d88685611dd9565b610cf5565b6105e8858585610d77565b60019150505b9392505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016141561063e5760405162461bcd60e51b81526004016105c090611c50565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610687600080516020611e99833981519152546001600160a01b031690565b6001600160a01b0316146106ad5760405162461bcd60e51b81526004016105c090611c9c565b6106b681610f26565b604080516000808252602082019092526106d291839190610f50565b50565b6097546001600160a01b031633146106ff5760405162461bcd60e51b81526004016105c090611ce8565b6107098282610c1d565b5050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614156107565760405162461bcd60e51b81526004016105c090611c50565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661079f600080516020611e99833981519152546001600160a01b031690565b6001600160a01b0316146107c55760405162461bcd60e51b81526004016105c090611c9c565b6107ce82610f26565b61070982826001610f50565b6000306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461087a5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016105c0565b50600080516020611e9983398151915290565b6097546001600160a01b031633146108b75760405162461bcd60e51b81526004016105c090611ce8565b6108c160006110cf565b565b606060ca805461046d90611e1c565b6097546001600160a01b031633146108fc5760405162461bcd60e51b81526004016105c090611ce8565b6107098282611121565b6000610913338484610d77565b50600192915050565b600063ffffffff333b16156109735760405162461bcd60e51b815260206004820152601960248201527f63616c6c65722063616e6e6f7420626520636f6e74726163740000000000000060448201526064016105c0565b34156109815761098161041d565b61098e3386868686611263565b336001600160a01b03167f282dd1817b996776123a00596764d4d54cc16460c9854f7a23f6be020ba0463d868686866040516109cd9493929190611c21565b60405180910390a2506001949350505050565b600054610100900460ff166109fb5760005460ff16156109ff565b303b155b610a625760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016105c0565b600054610100900460ff16158015610a84576000805461ffff19166101011790555b8451610a979060c99060208801906117ad565b508351610aab9060ca9060208701906117ad565b5060cb805460ff191660ff851617905560cf80546001600160a01b0319166001600160a01b038416179055610ade611426565b610ae6611455565b8015610af8576000805461ff00191690555b5050505050565b6097546001600160a01b03163314610b295760405162461bcd60e51b81526004016105c090611ce8565b6001600160a01b038116610b8e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016105c0565b6106d2816110cf565b610ba13382611121565b6040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015610bd7573d6000803e3d6000fd5b506040518181526001600160a01b0383169033907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb906020015b60405180910390a35050565b6001600160a01b038216610c735760405162461bcd60e51b815260206004820152601860248201527f6d696e7420746f20746865207a65726f2061646472657373000000000000000060448201526064016105c0565b8060cc6000828254610c859190611dc1565b90915550506001600160a01b038216600090815260cd602052604081208054839290610cb2908490611dc1565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610c11565b6001600160a01b038316610d4b5760405162461bcd60e51b815260206004820152601d60248201527f617070726f76652066726f6d20746865207a65726f206164647265737300000060448201526064016105c0565b6001600160a01b03928316600090815260ce602090815260408083209490951682529290925291902055565b6001600160a01b038316610dcd5760405162461bcd60e51b815260206004820152601e60248201527f7472616e736665722066726f6d20746865207a65726f2061646472657373000060448201526064016105c0565b6001600160a01b038216610e235760405162461bcd60e51b815260206004820152601c60248201527f7472616e7366657220746f20746865207a65726f20616464726573730000000060448201526064016105c0565b6001600160a01b038316600090815260cd602052604090205481811015610e8c5760405162461bcd60e51b815260206004820152601f60248201527f7472616e7366657220616d6f756e7420657863656564732062616c616e63650060448201526064016105c0565b610e968282611dd9565b6001600160a01b03808616600090815260cd60205260408082209390935590851681529081208054849290610ecc908490611dc1565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610f1891815260200190565b60405180910390a350505050565b6097546001600160a01b031633146106d25760405162461bcd60e51b81526004016105c090611ce8565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615610f8857610f838361147c565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b815260040160206040518083038186803b158015610fc157600080fd5b505afa925050508015610ff1575060408051601f3d908101601f19168201909252610fee918101906119d5565b60015b6110545760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b60648201526084016105c0565b600080516020611e9983398151915281146110c35760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b60648201526084016105c0565b50610f83838383611518565b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0382166111775760405162461bcd60e51b815260206004820152601a60248201527f6275726e2066726f6d20746865207a65726f206164647265737300000000000060448201526064016105c0565b6001600160a01b038216600090815260cd6020526040902054818110156111e05760405162461bcd60e51b815260206004820152601b60248201527f6275726e20616d6f756e7420657863656564732062616c616e6365000000000060448201526064016105c0565b6111ea8282611dd9565b6001600160a01b038416600090815260cd602052604081209190915560cc8054849290611218908490611dd9565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6001600160a01b0385166112b95760405162461bcd60e51b815260206004820152601e60248201527f7472616e736665722066726f6d20746865207a65726f2061646472657373000060448201526064016105c0565b60008451116112fe5760405162461bcd60e51b81526020600482015260116024820152701a5b9d985b1a59081c9958da5c1a595b9d607a1b60448201526064016105c0565b8061133c5760405162461bcd60e51b815260206004820152600e60248201526d1a5b9d985b1a59081d185c99d95d60921b60448201526064016105c0565b60cf5461135d9086906001600160a01b03166113588587611dc1565b610d77565b6000806110046001600160a01b0316611389888888888860405180602001604052806000815250611543565b6040516113969190611b60565b6000604051808303816000865af19150503d80600081146113d3576040519150601f19603f3d011682016040523d82523d6000602084013e6113d8565b606091505b509150915061141d82826040518060400160405280601b81526020017f7472616e736665722063726f737320636861696e206661696c65640000000000815250611596565b50505050505050565b600054610100900460ff1661144d5760405162461bcd60e51b81526004016105c090611d1d565b6108c1611610565b600054610100900460ff166108c15760405162461bcd60e51b81526004016105c090611d1d565b6001600160a01b0381163b6114e95760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016105c0565b600080516020611e9983398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b61152183611640565b60008251118061152e5750805b15610f835761153d8383611680565b50505050565b606086868686868660405160240161156096959493929190611bb9565b60408051601f198184030181529190526020810180516001600160e01b0316633c3e7d7760e01b17905290509695505050505050565b82610f83576000828060200190518101906115b191906119ed565b90506001825110156115d7578060405162461bcd60e51b81526004016105c09190611c0e565b81816040516020016115ea929190611b7c565b60408051601f198184030181529082905262461bcd60e51b82526105c091600401611c0e565b600054610100900460ff166116375760405162461bcd60e51b81526004016105c090611d1d565b6108c1336110cf565b6116498161147c565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b6116e85760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016105c0565b600080846001600160a01b0316846040516117039190611b60565b600060405180830381855af49150503d806000811461173e576040519150601f19603f3d011682016040523d82523d6000602084013e611743565b606091505b509150915061176b8282604051806060016040528060278152602001611eb960279139611774565b95945050505050565b606083156117835750816105ee565b8251156117935782518084602001fd5b8160405162461bcd60e51b81526004016105c09190611c0e565b8280546117b990611e1c565b90600052602060002090601f0160209004810192826117db5760008555611821565b82601f106117f457805160ff1916838001178555611821565b82800160010185558215611821579182015b82811115611821578251825591602001919060010190611806565b5061182d929150611831565b5090565b5b8082111561182d5760008155600101611832565b600061185961185484611d99565b611d68565b905082815283838301111561186d57600080fd5b828260208301376000602084830101529392505050565b600082601f830112611894578081fd5b6105ee83833560208501611846565b6000602082840312156118b4578081fd5b81356105ee81611e83565b600080604083850312156118d1578081fd5b82356118dc81611e83565b946020939093013593505050565b600080604083850312156118fc578182fd5b823561190781611e83565b9150602083013561191781611e83565b809150509250929050565b600080600060608486031215611936578081fd5b833561194181611e83565b9250602084013561195181611e83565b929592945050506040919091013590565b60008060408385031215611974578182fd5b823561197f81611e83565b9150602083013567ffffffffffffffff81111561199a578182fd5b8301601f810185136119aa578182fd5b6119b985823560208401611846565b9150509250929050565b600080604083850312156118d1578182fd5b6000602082840312156119e6578081fd5b5051919050565b6000602082840312156119fe578081fd5b815167ffffffffffffffff811115611a14578182fd5b8201601f81018413611a24578182fd5b8051611a3261185482611d99565b818152856020838501011115611a46578384fd5b61176b826020830160208601611df0565b60008060008060808587031215611a6c578081fd5b843567ffffffffffffffff80821115611a83578283fd5b611a8f88838901611884565b95506020870135915080821115611aa4578283fd5b50611ab187828801611884565b935050604085013560ff81168114611ac7578182fd5b91506060850135611ad781611e83565b939692955090935050565b60008060008060808587031215611af7578384fd5b843567ffffffffffffffff811115611b0d578485fd5b611b1987828801611884565b97602087013597506040870135966060013595509350505050565b60008151808452611b4c816020860160208601611df0565b601f01601f19169290920160200192915050565b60008251611b72818460208701611df0565b9190910192915050565b60008351611b8e818460208801611df0565b6101d160f51b9083019081528351611bad816002840160208801611df0565b01600201949350505050565b6001600160a01b038716815260c060208201819052600090611bdd90830188611b34565b86604084015285606084015284608084015282810360a0840152611c018185611b34565b9998505050505050505050565b6020815260006105ee6020830184611b34565b608081526000611c346080830187611b34565b6020830195909552506040810192909252606090910152919050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b604051601f8201601f1916810167ffffffffffffffff81118282101715611d9157611d91611e6d565b604052919050565b600067ffffffffffffffff821115611db357611db3611e6d565b50601f01601f191660200190565b60008219821115611dd457611dd4611e57565b500190565b600082821015611deb57611deb611e57565b500390565b60005b83811015611e0b578181015183820152602001611df3565b8381111561153d5750506000910152565b600181811c90821680611e3057607f821691505b60208210811415611e5157634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146106d257600080fdfe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220c3b1cd913030a18195eba376a78d2ea5e6cb2500466d9f96635c54aa3829033164736f6c63430008040033", hex.EncodeToString(code)) + require.Equal(t, "6080604052600436106101395760003560e01c80638da5cb5b116100ab578063c5cb9b511161006f578063c5cb9b5114610364578063d0e30db014610148578063dd62ed3e14610377578063de7ea79d146103bd578063f2fde38b146103dd578063f3fef3a3146103fd57610148565b80638da5cb5b146102bf57806395d89b41146102f15780639dc29fac14610306578063a9059cbb14610326578063b86d52981461034657610148565b80633659cfe6116100fd5780633659cfe61461020c57806340c10f191461022c5780634f1ef2861461024c57806352d1902d1461025f57806370a0823114610274578063715018a6146102aa57610148565b806306fdde0314610150578063095ea7b31461017b57806318160ddd146101ab57806323b872dd146101ca578063313ce567146101ea57610148565b366101485761014661041d565b005b61014661041d565b34801561015c57600080fd5b5061016561045e565b6040516101729190611c0e565b60405180910390f35b34801561018757600080fd5b5061019b6101963660046119c3565b6104f0565b6040519015158152602001610172565b3480156101b757600080fd5b5060cc545b604051908152602001610172565b3480156101d657600080fd5b5061019b6101e5366004611922565b610546565b3480156101f657600080fd5b5060cb5460405160ff9091168152602001610172565b34801561021857600080fd5b506101466102273660046118a3565b6105f5565b34801561023857600080fd5b506101466102473660046119c3565b6106d5565b61014661025a366004611962565b61070d565b34801561026b57600080fd5b506101bc6107da565b34801561028057600080fd5b506101bc61028f3660046118a3565b6001600160a01b0316600090815260cd602052604090205490565b3480156102b657600080fd5b5061014661088d565b3480156102cb57600080fd5b506097546001600160a01b03165b6040516001600160a01b039091168152602001610172565b3480156102fd57600080fd5b506101656108c3565b34801561031257600080fd5b506101466103213660046119c3565b6108d2565b34801561033257600080fd5b5061019b6103413660046119c3565b610906565b34801561035257600080fd5b5060cf546001600160a01b03166102d9565b61019b610372366004611ae2565b61091c565b34801561038357600080fd5b506101bc6103923660046118ea565b6001600160a01b03918216600090815260ce6020908152604080832093909416825291909152205490565b3480156103c957600080fd5b506101466103d8366004611a57565b6109e0565b3480156103e957600080fd5b506101466103f83660046118a3565b610aff565b34801561040957600080fd5b506101466104183660046118bf565b610b97565b6104273334610c1d565b60405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b606060c9805461046d90611e1c565b80601f016020809104026020016040519081016040528092919081815260200182805461049990611e1c565b80156104e65780601f106104bb576101008083540402835291602001916104e6565b820191906000526020600020905b8154815290600101906020018083116104c957829003601f168201915b5050505050905090565b60006104fd338484610cf5565b6040518281526001600160a01b0384169033907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259060200160405180910390a350600192915050565b6001600160a01b038316600090815260ce60209081526040808320338452909152812054828110156105c95760405162461bcd60e51b815260206004820152602160248201527f7472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636044820152606560f81b60648201526084015b60405180910390fd5b6105dd85336105d88685611dd9565b610cf5565b6105e8858585610d77565b60019150505b9392505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000100216141561063e5760405162461bcd60e51b81526004016105c090611c50565b7f00000000000000000000000000000000000000000000000000000000000010026001600160a01b0316610687600080516020611e99833981519152546001600160a01b031690565b6001600160a01b0316146106ad5760405162461bcd60e51b81526004016105c090611c9c565b6106b681610f26565b604080516000808252602082019092526106d291839190610f50565b50565b6097546001600160a01b031633146106ff5760405162461bcd60e51b81526004016105c090611ce8565b6107098282610c1d565b5050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000010021614156107565760405162461bcd60e51b81526004016105c090611c50565b7f00000000000000000000000000000000000000000000000000000000000010026001600160a01b031661079f600080516020611e99833981519152546001600160a01b031690565b6001600160a01b0316146107c55760405162461bcd60e51b81526004016105c090611c9c565b6107ce82610f26565b61070982826001610f50565b6000306001600160a01b037f0000000000000000000000000000000000000000000000000000000000001002161461087a5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016105c0565b50600080516020611e9983398151915290565b6097546001600160a01b031633146108b75760405162461bcd60e51b81526004016105c090611ce8565b6108c160006110cf565b565b606060ca805461046d90611e1c565b6097546001600160a01b031633146108fc5760405162461bcd60e51b81526004016105c090611ce8565b6107098282611121565b6000610913338484610d77565b50600192915050565b600063ffffffff333b16156109735760405162461bcd60e51b815260206004820152601960248201527f63616c6c65722063616e6e6f7420626520636f6e74726163740000000000000060448201526064016105c0565b34156109815761098161041d565b61098e3386868686611263565b336001600160a01b03167f282dd1817b996776123a00596764d4d54cc16460c9854f7a23f6be020ba0463d868686866040516109cd9493929190611c21565b60405180910390a2506001949350505050565b600054610100900460ff166109fb5760005460ff16156109ff565b303b155b610a625760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016105c0565b600054610100900460ff16158015610a84576000805461ffff19166101011790555b8451610a979060c99060208801906117ad565b508351610aab9060ca9060208701906117ad565b5060cb805460ff191660ff851617905560cf80546001600160a01b0319166001600160a01b038416179055610ade611426565b610ae6611455565b8015610af8576000805461ff00191690555b5050505050565b6097546001600160a01b03163314610b295760405162461bcd60e51b81526004016105c090611ce8565b6001600160a01b038116610b8e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016105c0565b6106d2816110cf565b610ba13382611121565b6040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015610bd7573d6000803e3d6000fd5b506040518181526001600160a01b0383169033907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb906020015b60405180910390a35050565b6001600160a01b038216610c735760405162461bcd60e51b815260206004820152601860248201527f6d696e7420746f20746865207a65726f2061646472657373000000000000000060448201526064016105c0565b8060cc6000828254610c859190611dc1565b90915550506001600160a01b038216600090815260cd602052604081208054839290610cb2908490611dc1565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610c11565b6001600160a01b038316610d4b5760405162461bcd60e51b815260206004820152601d60248201527f617070726f76652066726f6d20746865207a65726f206164647265737300000060448201526064016105c0565b6001600160a01b03928316600090815260ce602090815260408083209490951682529290925291902055565b6001600160a01b038316610dcd5760405162461bcd60e51b815260206004820152601e60248201527f7472616e736665722066726f6d20746865207a65726f2061646472657373000060448201526064016105c0565b6001600160a01b038216610e235760405162461bcd60e51b815260206004820152601c60248201527f7472616e7366657220746f20746865207a65726f20616464726573730000000060448201526064016105c0565b6001600160a01b038316600090815260cd602052604090205481811015610e8c5760405162461bcd60e51b815260206004820152601f60248201527f7472616e7366657220616d6f756e7420657863656564732062616c616e63650060448201526064016105c0565b610e968282611dd9565b6001600160a01b03808616600090815260cd60205260408082209390935590851681529081208054849290610ecc908490611dc1565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610f1891815260200190565b60405180910390a350505050565b6097546001600160a01b031633146106d25760405162461bcd60e51b81526004016105c090611ce8565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615610f8857610f838361147c565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b815260040160206040518083038186803b158015610fc157600080fd5b505afa925050508015610ff1575060408051601f3d908101601f19168201909252610fee918101906119d5565b60015b6110545760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b60648201526084016105c0565b600080516020611e9983398151915281146110c35760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b60648201526084016105c0565b50610f83838383611518565b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0382166111775760405162461bcd60e51b815260206004820152601a60248201527f6275726e2066726f6d20746865207a65726f206164647265737300000000000060448201526064016105c0565b6001600160a01b038216600090815260cd6020526040902054818110156111e05760405162461bcd60e51b815260206004820152601b60248201527f6275726e20616d6f756e7420657863656564732062616c616e6365000000000060448201526064016105c0565b6111ea8282611dd9565b6001600160a01b038416600090815260cd602052604081209190915560cc8054849290611218908490611dd9565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6001600160a01b0385166112b95760405162461bcd60e51b815260206004820152601e60248201527f7472616e736665722066726f6d20746865207a65726f2061646472657373000060448201526064016105c0565b60008451116112fe5760405162461bcd60e51b81526020600482015260116024820152701a5b9d985b1a59081c9958da5c1a595b9d607a1b60448201526064016105c0565b8061133c5760405162461bcd60e51b815260206004820152600e60248201526d1a5b9d985b1a59081d185c99d95d60921b60448201526064016105c0565b60cf5461135d9086906001600160a01b03166113588587611dc1565b610d77565b6000806110046001600160a01b0316611389888888888860405180602001604052806000815250611543565b6040516113969190611b60565b6000604051808303816000865af19150503d80600081146113d3576040519150601f19603f3d011682016040523d82523d6000602084013e6113d8565b606091505b509150915061141d82826040518060400160405280601b81526020017f7472616e736665722063726f737320636861696e206661696c65640000000000815250611596565b50505050505050565b600054610100900460ff1661144d5760405162461bcd60e51b81526004016105c090611d1d565b6108c1611610565b600054610100900460ff166108c15760405162461bcd60e51b81526004016105c090611d1d565b6001600160a01b0381163b6114e95760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016105c0565b600080516020611e9983398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b61152183611640565b60008251118061152e5750805b15610f835761153d8383611680565b50505050565b606086868686868660405160240161156096959493929190611bb9565b60408051601f198184030181529190526020810180516001600160e01b0316633c3e7d7760e01b17905290509695505050505050565b82610f83576000828060200190518101906115b191906119ed565b90506001825110156115d7578060405162461bcd60e51b81526004016105c09190611c0e565b81816040516020016115ea929190611b7c565b60408051601f198184030181529082905262461bcd60e51b82526105c091600401611c0e565b600054610100900460ff166116375760405162461bcd60e51b81526004016105c090611d1d565b6108c1336110cf565b6116498161147c565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b6116e85760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016105c0565b600080846001600160a01b0316846040516117039190611b60565b600060405180830381855af49150503d806000811461173e576040519150601f19603f3d011682016040523d82523d6000602084013e611743565b606091505b509150915061176b8282604051806060016040528060278152602001611eb960279139611774565b95945050505050565b606083156117835750816105ee565b8251156117935782518084602001fd5b8160405162461bcd60e51b81526004016105c09190611c0e565b8280546117b990611e1c565b90600052602060002090601f0160209004810192826117db5760008555611821565b82601f106117f457805160ff1916838001178555611821565b82800160010185558215611821579182015b82811115611821578251825591602001919060010190611806565b5061182d929150611831565b5090565b5b8082111561182d5760008155600101611832565b600061185961185484611d99565b611d68565b905082815283838301111561186d57600080fd5b828260208301376000602084830101529392505050565b600082601f830112611894578081fd5b6105ee83833560208501611846565b6000602082840312156118b4578081fd5b81356105ee81611e83565b600080604083850312156118d1578081fd5b82356118dc81611e83565b946020939093013593505050565b600080604083850312156118fc578182fd5b823561190781611e83565b9150602083013561191781611e83565b809150509250929050565b600080600060608486031215611936578081fd5b833561194181611e83565b9250602084013561195181611e83565b929592945050506040919091013590565b60008060408385031215611974578182fd5b823561197f81611e83565b9150602083013567ffffffffffffffff81111561199a578182fd5b8301601f810185136119aa578182fd5b6119b985823560208401611846565b9150509250929050565b600080604083850312156118d1578182fd5b6000602082840312156119e6578081fd5b5051919050565b6000602082840312156119fe578081fd5b815167ffffffffffffffff811115611a14578182fd5b8201601f81018413611a24578182fd5b8051611a3261185482611d99565b818152856020838501011115611a46578384fd5b61176b826020830160208601611df0565b60008060008060808587031215611a6c578081fd5b843567ffffffffffffffff80821115611a83578283fd5b611a8f88838901611884565b95506020870135915080821115611aa4578283fd5b50611ab187828801611884565b935050604085013560ff81168114611ac7578182fd5b91506060850135611ad781611e83565b939692955090935050565b60008060008060808587031215611af7578384fd5b843567ffffffffffffffff811115611b0d578485fd5b611b1987828801611884565b97602087013597506040870135966060013595509350505050565b60008151808452611b4c816020860160208601611df0565b601f01601f19169290920160200192915050565b60008251611b72818460208701611df0565b9190910192915050565b60008351611b8e818460208801611df0565b6101d160f51b9083019081528351611bad816002840160208801611df0565b01600201949350505050565b6001600160a01b038716815260c060208201819052600090611bdd90830188611b34565b86604084015285606084015284608084015282810360a0840152611c018185611b34565b9998505050505050505050565b6020815260006105ee6020830184611b34565b608081526000611c346080830187611b34565b6020830195909552506040810192909252606090910152919050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b604051601f8201601f1916810167ffffffffffffffff81118282101715611d9157611d91611e6d565b604052919050565b600067ffffffffffffffff821115611db357611db3611e6d565b50601f01601f191660200190565b60008219821115611dd457611dd4611e57565b500190565b600082821015611deb57611deb611e57565b500390565b60005b83811015611e0b578181015183820152602001611df3565b8381111561153d5750506000910152565b600181811c90821680611e3057607f821691505b60208210811415611e5157634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146106d257600080fdfe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220c3b1cd913030a18195eba376a78d2ea5e6cb2500466d9f96635c54aa3829033164736f6c63430008040033", hex.EncodeToString(codeNew)) + require.NotEqual(t, hex.EncodeToString(code), hex.EncodeToString(codeNew)) +} + +func replayCodeAddress(codeBase64, addr, addrNew string) (code, codeNew []byte) { + bz, err := base64.StdEncoding.DecodeString(codeBase64) + if err != nil { + panic(err) + } + + addr1 := common.HexToAddress(addr) + addr2 := common.HexToAddress(addrNew) + + bzZero := bytes.ReplaceAll(bz, addr1.Bytes(), common.Address{}.Bytes()) + bzNew := bytes.ReplaceAll(bz, addr1.Bytes(), addr2.Bytes()) + + return bzZero, bzNew +} diff --git a/contract/erc20_abi.go b/contract/erc20_abi.go deleted file mode 100644 index 8acad6f4..00000000 --- a/contract/erc20_abi.go +++ /dev/null @@ -1,178 +0,0 @@ -package contract - -import ( - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" -) - -// Deprecated: please use ERC20TokenKeeper -type ERC20ABI struct { - abi abi.ABI -} - -func NewERC20ABI() ERC20ABI { - return ERC20ABI{} -} - -func (e ERC20ABI) PackName() (data []byte, err error) { - data, err = e.abi.Pack("name") - if err != nil { - return nil, fmt.Errorf("pack name: %s", err.Error()) - } - return data, err -} - -func (e ERC20ABI) UnpackName(ret []byte) (string, error) { - var unpackedRet struct{ Value string } - if err := e.abi.UnpackIntoInterface(&unpackedRet, "name", ret); err != nil { - return "", fmt.Errorf("unpack name: %s", err.Error()) - } - return unpackedRet.Value, nil -} - -func (e ERC20ABI) PackSymbol() (data []byte, err error) { - data, err = e.abi.Pack("symbol") - if err != nil { - return nil, fmt.Errorf("pack symbol: %s", err.Error()) - } - return data, err -} - -func (e ERC20ABI) UnpackSymbol(ret []byte) (string, error) { - var unpackedRet struct{ Value string } - if err := e.abi.UnpackIntoInterface(&unpackedRet, "symbol", ret); err != nil { - return "", fmt.Errorf("unpack symbol: %s", err.Error()) - } - return unpackedRet.Value, nil -} - -func (e ERC20ABI) PackDecimals() (data []byte, err error) { - data, err = e.abi.Pack("decimals") - if err != nil { - return nil, fmt.Errorf("pack decimals: %s", err.Error()) - } - return data, err -} - -func (e ERC20ABI) UnpackDecimals(ret []byte) (uint8, error) { - var unpackedRet struct{ Value uint8 } - if err := e.abi.UnpackIntoInterface(&unpackedRet, "decimals", ret); err != nil { - return 0, fmt.Errorf("unpack decimals: %s", err.Error()) - } - return unpackedRet.Value, nil -} - -func (e ERC20ABI) PackBalanceOf(account common.Address) (data []byte, err error) { - data, err = e.abi.Pack("balanceOf", account) - if err != nil { - return nil, fmt.Errorf("pack balanceOf: %s", err.Error()) - } - return data, err -} - -func (e ERC20ABI) UnpackBalanceOf(ret []byte) (*big.Int, error) { - var unpackedRet struct{ Value *big.Int } - if err := e.abi.UnpackIntoInterface(&unpackedRet, "balanceOf", ret); err != nil { - return nil, fmt.Errorf("unpack balanceOf: %s", err.Error()) - } - return unpackedRet.Value, nil -} - -func (e ERC20ABI) PackTotalSupply() (data []byte, err error) { - data, err = e.abi.Pack("totalSupply") - if err != nil { - return nil, fmt.Errorf("pack totalSupply: %s", err.Error()) - } - return data, err -} - -func (e ERC20ABI) UnpackTotalSupply(ret []byte) (*big.Int, error) { - var unpackedRet struct{ Value *big.Int } - if err := e.abi.UnpackIntoInterface(&unpackedRet, "totalSupply", ret); err != nil { - return nil, fmt.Errorf("unpack totalSupply: %s", err.Error()) - } - return unpackedRet.Value, nil -} - -func (e ERC20ABI) PackApprove(spender common.Address, amount *big.Int) (data []byte, err error) { - data, err = e.abi.Pack("approve", spender, amount) - if err != nil { - return nil, fmt.Errorf("pack approve: %s", err.Error()) - } - return data, err -} - -func (e ERC20ABI) PackAllowance(owner, spender common.Address) (data []byte, err error) { - data, err = e.abi.Pack("allowance", owner, spender) - if err != nil { - return nil, fmt.Errorf("pack allowance: %s", err.Error()) - } - return data, err -} - -func (e ERC20ABI) PackTransferFrom(sender, to common.Address, amount *big.Int) (data []byte, err error) { - data, err = e.abi.Pack("transferFrom", sender, to, amount) - if err != nil { - return nil, fmt.Errorf("pack transferFrom: %s", err.Error()) - } - return data, err -} - -func (e ERC20ABI) UnpackTransferFrom(ret []byte) (bool, error) { - var unpackedRet struct{ Value bool } - if err := e.abi.UnpackIntoInterface(&unpackedRet, "transferFrom", ret); err != nil { - return false, fmt.Errorf("unpack transferFrom: %s", err.Error()) - } - return unpackedRet.Value, nil -} - -func (e ERC20ABI) PackTransfer(to common.Address, amount *big.Int) (data []byte, err error) { - data, err = e.abi.Pack("transfer", to, amount) - if err != nil { - return nil, fmt.Errorf("pack transfer: %s", err.Error()) - } - return data, err -} - -func (e ERC20ABI) PackBurn(account common.Address, amount *big.Int) (data []byte, err error) { - data, err = e.abi.Pack("burn", account, amount) - if err != nil { - return nil, fmt.Errorf("pack burn: %s", err.Error()) - } - return data, err -} - -func (e ERC20ABI) PackMint(account common.Address, amount *big.Int) (data []byte, err error) { - data, err = e.abi.Pack("mint", account, amount) - if err != nil { - return nil, fmt.Errorf("pack mint: %s", err.Error()) - } - return data, err -} - -func (e ERC20ABI) PackDeposit() (data []byte, err error) { - data, err = e.abi.Pack("deposit") - if err != nil { - return nil, fmt.Errorf("pack deposit: %s", err.Error()) - } - return data, err -} - -func (e ERC20ABI) PackWithdraw(recipient common.Address, amount *big.Int) (data []byte, err error) { - data, err = e.abi.Pack("withdraw0", recipient, amount) - if err != nil { - return nil, fmt.Errorf("pack withdraw: %s", err.Error()) - } - return data, err -} - -func (e ERC20ABI) PackTransferOwnership(newOwner common.Address) (data []byte, err error) { - data, err = e.abi.Pack("transferOwnership", newOwner) - if err != nil { - return nil, fmt.Errorf("pack transferOwnership: %s", err.Error()) - } - return data, err -} diff --git a/contract/erc20_token.go b/contract/erc20_token.go index 195cd885..282a9315 100644 --- a/contract/erc20_token.go +++ b/contract/erc20_token.go @@ -87,11 +87,6 @@ func (k ERC20TokenKeeper) Approve(ctx context.Context, contractAddr, from, spend return unpackRetIsOk(k.abi, "approve", res) } -// PackMint only used for testing -func (k ERC20TokenKeeper) PackMint(receiver common.Address, amount *big.Int) ([]byte, error) { - return k.abi.Pack("mint", receiver, amount) -} - func (k ERC20TokenKeeper) Mint(ctx context.Context, contractAddr, from, receiver common.Address, amount *big.Int) (*types.MsgEthereumTxResponse, error) { return k.ApplyContract(ctx, from, contractAddr, nil, k.abi, "mint", receiver, amount) } diff --git a/proto/fx/gravity/crosschain/v1/tx.proto b/proto/fx/gravity/crosschain/v1/tx.proto index 8914dbe7..83181788 100644 --- a/proto/fx/gravity/crosschain/v1/tx.proto +++ b/proto/fx/gravity/crosschain/v1/tx.proto @@ -150,6 +150,7 @@ message MsgSendToFxClaim { ]; string sender = 5; string receiver = 6; + // Deprecated: After the upgrade to v8 string target_ibc = 7; string bridger_address = 8; string chain_name = 9; @@ -231,6 +232,7 @@ message MsgBridgeTokenClaim { string symbol = 5; uint64 decimals = 6; string bridger_address = 7; + // Deprecated: After the upgrade to v8 string channel_ibc = 8; // Bridge Token channel IBC string chain_name = 9; } diff --git a/scripts/linter.sh b/scripts/linter.sh index d478f218..d52c505a 100755 --- a/scripts/linter.sh +++ b/scripts/linter.sh @@ -5,11 +5,11 @@ set -eo pipefail patternLimits=( "nolint:20" "#nosec:5" - "CrossChain:3" + "CrossChain:4" "cross chain:0" "GetERC1967Proxy:4" - "GetWFX:9" - "GetFIP20:10" + "GetWFX:8" + "GetFIP20:11" ) if ! command -v rg &>/dev/null; then diff --git a/tests/ante_test.go b/tests/ante_test.go deleted file mode 100644 index 3423559a..00000000 --- a/tests/ante_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package tests - -import ( - sdkmath "cosmossdk.io/math" - tmrand "github.com/cometbft/cometbft/libs/rand" - distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types" - - "github.com/functionx/fx-core/v8/testutil/helpers" -) - -func (suite *IntegrationTest) ByPassFeeTest() { - userA := helpers.NewEthPrivKey() - userAAddr := userA.PubKey().Address().Bytes() - initBalance := suite.NewCoin(sdkmath.NewInt(100).MulRaw(1e18)) - txResponse := suite.Send(userAAddr, initBalance) - suite.Require().EqualValues(uint32(0), txResponse.Code) - - // 1. zero gasPrices for bypassing fee check - minGasPrices := suite.network.Config.MinGasPrices - config := suite.network.Config - config.MinGasPrices = suite.NewCoin(sdkmath.ZeroInt()).String() - suite.network.Config = config - - for i := 0; i < tmrand.Intn(5); i++ { - broadcastTx := suite.BroadcastTx(userA, distributiontypes.NewMsgSetWithdrawAddress(userAAddr, userAAddr)) - suite.Require().EqualValues(uint32(0), broadcastTx.Code) - } - - // check balance - suite.CheckBalance(userAAddr, initBalance) - - // ok. reset gasPrices - config.MinGasPrices = minGasPrices - suite.network.Config = config -} diff --git a/tests/contract_test.go b/tests/contract_test.go deleted file mode 100644 index 224ef449..00000000 --- a/tests/contract_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package tests - -import ( - "bytes" - "encoding/base64" - "encoding/hex" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" - - "github.com/functionx/fx-core/v8/contract" -) - -func TestFIP20Code(t *testing.T) { - codeAddr := "0x79172102144e0ef3dc372c3774f3225fbba20066" - codeBase64 := "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" - - code, codeNew := replayCodeAddress(codeBase64, codeAddr, contract.FIP20LogicAddress) - require.Equal(t, "60806040526004361061011f5760003560e01c8063715018a6116100a0578063b86d529811610064578063b86d52981461031c578063c5cb9b511461033a578063dd62ed3e1461035a578063de7ea79d146103a0578063f2fde38b146103c057600080fd5b8063715018a6146102805780638da5cb5b1461029557806395d89b41146102c75780639dc29fac146102dc578063a9059cbb146102fc57600080fd5b80633659cfe6116100e75780633659cfe6146101e057806340c10f19146102025780634f1ef2861461022257806352d1902d1461023557806370a082311461024a57600080fd5b806306fdde0314610124578063095ea7b31461014f57806318160ddd1461017f57806323b872dd1461019e578063313ce567146101be575b600080fd5b34801561013057600080fd5b506101396103e0565b6040516101469190611afa565b60405180910390f35b34801561015b57600080fd5b5061016f61016a36600461189a565b610472565b6040519015158152602001610146565b34801561018b57600080fd5b5060cc545b604051908152602001610146565b3480156101aa57600080fd5b5061016f6101b9366004611800565b6104c8565b3480156101ca57600080fd5b5060cb5460405160ff9091168152602001610146565b3480156101ec57600080fd5b506102006101fb3660046117b4565b610577565b005b34801561020e57600080fd5b5061020061021d36600461189a565b610657565b61020061023036600461183b565b61068f565b34801561024157600080fd5b5061019061075c565b34801561025657600080fd5b506101906102653660046117b4565b6001600160a01b0316600090815260cd602052604090205490565b34801561028c57600080fd5b5061020061080f565b3480156102a157600080fd5b506097546001600160a01b03165b6040516001600160a01b039091168152602001610146565b3480156102d357600080fd5b50610139610845565b3480156102e857600080fd5b506102006102f736600461189a565b610854565b34801561030857600080fd5b5061016f61031736600461189a565b610888565b34801561032857600080fd5b5060cf546001600160a01b03166102af565b34801561034657600080fd5b5061016f6103553660046119ce565b61089e565b34801561036657600080fd5b506101906103753660046117ce565b6001600160a01b03918216600090815260ce6020908152604080832093909416825291909152205490565b3480156103ac57600080fd5b506102006103bb366004611945565b610954565b3480156103cc57600080fd5b506102006103db3660046117b4565b610a73565b606060c980546103ef90611d08565b80601f016020809104026020016040519081016040528092919081815260200182805461041b90611d08565b80156104685780601f1061043d57610100808354040283529160200191610468565b820191906000526020600020905b81548152906001019060200180831161044b57829003601f168201915b5050505050905090565b600061047f338484610b0b565b6040518281526001600160a01b0384169033907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259060200160405180910390a350600192915050565b6001600160a01b038316600090815260ce602090815260408083203384529091528120548281101561054b5760405162461bcd60e51b815260206004820152602160248201527f7472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636044820152606560f81b60648201526084015b60405180910390fd5b61055f853361055a8685611cc5565b610b0b565b61056a858585610b8d565b60019150505b9392505050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614156105c05760405162461bcd60e51b815260040161054290611b3c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610609600080516020611d70833981519152546001600160a01b031690565b6001600160a01b03161461062f5760405162461bcd60e51b815260040161054290611b88565b61063881610d3c565b6040805160008082526020820190925261065491839190610d66565b50565b6097546001600160a01b031633146106815760405162461bcd60e51b815260040161054290611bd4565b61068b8282610ee5565b5050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614156106d85760405162461bcd60e51b815260040161054290611b3c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610721600080516020611d70833981519152546001600160a01b031690565b6001600160a01b0316146107475760405162461bcd60e51b815260040161054290611b88565b61075082610d3c565b61068b82826001610d66565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146107fc5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610542565b50600080516020611d7083398151915290565b6097546001600160a01b031633146108395760405162461bcd60e51b815260040161054290611bd4565b6108436000610fc4565b565b606060ca80546103ef90611d08565b6097546001600160a01b0316331461087e5760405162461bcd60e51b815260040161054290611bd4565b61068b8282611016565b6000610895338484610b8d565b50600192915050565b600063ffffffff333b16156108f55760405162461bcd60e51b815260206004820152601960248201527f63616c6c65722063616e6e6f7420626520636f6e7472616374000000000000006044820152606401610542565b6109023386868686611158565b336001600160a01b03167f282dd1817b996776123a00596764d4d54cc16460c9854f7a23f6be020ba0463d868686866040516109419493929190611b0d565b60405180910390a2506001949350505050565b600054610100900460ff1661096f5760005460ff1615610973565b303b155b6109d65760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610542565b600054610100900460ff161580156109f8576000805461ffff19166101011790555b8451610a0b9060c99060208801906116a2565b508351610a1f9060ca9060208701906116a2565b5060cb805460ff191660ff851617905560cf80546001600160a01b0319166001600160a01b038416179055610a5261131b565b610a5a61134a565b8015610a6c576000805461ff00191690555b5050505050565b6097546001600160a01b03163314610a9d5760405162461bcd60e51b815260040161054290611bd4565b6001600160a01b038116610b025760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610542565b61065481610fc4565b6001600160a01b038316610b615760405162461bcd60e51b815260206004820152601d60248201527f617070726f76652066726f6d20746865207a65726f20616464726573730000006044820152606401610542565b6001600160a01b03928316600090815260ce602090815260408083209490951682529290925291902055565b6001600160a01b038316610be35760405162461bcd60e51b815260206004820152601e60248201527f7472616e736665722066726f6d20746865207a65726f206164647265737300006044820152606401610542565b6001600160a01b038216610c395760405162461bcd60e51b815260206004820152601c60248201527f7472616e7366657220746f20746865207a65726f2061646472657373000000006044820152606401610542565b6001600160a01b038316600090815260cd602052604090205481811015610ca25760405162461bcd60e51b815260206004820152601f60248201527f7472616e7366657220616d6f756e7420657863656564732062616c616e6365006044820152606401610542565b610cac8282611cc5565b6001600160a01b03808616600090815260cd60205260408082209390935590851681529081208054849290610ce2908490611cad565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610d2e91815260200190565b60405180910390a350505050565b6097546001600160a01b031633146106545760405162461bcd60e51b815260040161054290611bd4565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615610d9e57610d9983611371565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b815260040160206040518083038186803b158015610dd757600080fd5b505afa925050508015610e07575060408051601f3d908101601f19168201909252610e04918101906118c3565b60015b610e6a5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610542565b600080516020611d708339815191528114610ed95760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610542565b50610d9983838361140d565b6001600160a01b038216610f3b5760405162461bcd60e51b815260206004820152601860248201527f6d696e7420746f20746865207a65726f206164647265737300000000000000006044820152606401610542565b8060cc6000828254610f4d9190611cad565b90915550506001600160a01b038216600090815260cd602052604081208054839290610f7a908490611cad565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b03821661106c5760405162461bcd60e51b815260206004820152601a60248201527f6275726e2066726f6d20746865207a65726f20616464726573730000000000006044820152606401610542565b6001600160a01b038216600090815260cd6020526040902054818110156110d55760405162461bcd60e51b815260206004820152601b60248201527f6275726e20616d6f756e7420657863656564732062616c616e636500000000006044820152606401610542565b6110df8282611cc5565b6001600160a01b038416600090815260cd602052604081209190915560cc805484929061110d908490611cc5565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6001600160a01b0385166111ae5760405162461bcd60e51b815260206004820152601e60248201527f7472616e736665722066726f6d20746865207a65726f206164647265737300006044820152606401610542565b60008451116111f35760405162461bcd60e51b81526020600482015260116024820152701a5b9d985b1a59081c9958da5c1a595b9d607a1b6044820152606401610542565b806112315760405162461bcd60e51b815260206004820152600e60248201526d1a5b9d985b1a59081d185c99d95d60921b6044820152606401610542565b60cf546112529086906001600160a01b031661124d8587611cad565b610b8d565b6000806110046001600160a01b031661127e888888888860405180602001604052806000815250611438565b60405161128b9190611a4c565b6000604051808303816000865af19150503d80600081146112c8576040519150601f19603f3d011682016040523d82523d6000602084013e6112cd565b606091505b509150915061131282826040518060400160405280601b81526020017f7472616e736665722063726f737320636861696e206661696c6564000000000081525061148b565b50505050505050565b600054610100900460ff166113425760405162461bcd60e51b815260040161054290611c09565b610843611505565b600054610100900460ff166108435760405162461bcd60e51b815260040161054290611c09565b6001600160a01b0381163b6113de5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610542565b600080516020611d7083398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b61141683611535565b6000825111806114235750805b15610d99576114328383611575565b50505050565b606086868686868660405160240161145596959493929190611aa5565b60408051601f198184030181529190526020810180516001600160e01b0316633c3e7d7760e01b17905290509695505050505050565b82610d99576000828060200190518101906114a691906118db565b90506001825110156114cc578060405162461bcd60e51b81526004016105429190611afa565b81816040516020016114df929190611a68565b60408051601f198184030181529082905262461bcd60e51b825261054291600401611afa565b600054610100900460ff1661152c5760405162461bcd60e51b815260040161054290611c09565b61084333610fc4565b61153e81611371565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b6115dd5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610542565b600080846001600160a01b0316846040516115f89190611a4c565b600060405180830381855af49150503d8060008114611633576040519150601f19603f3d011682016040523d82523d6000602084013e611638565b606091505b50915091506116608282604051806060016040528060278152602001611d9060279139611669565b95945050505050565b60608315611678575081610570565b8251156116885782518084602001fd5b8160405162461bcd60e51b81526004016105429190611afa565b8280546116ae90611d08565b90600052602060002090601f0160209004810192826116d05760008555611716565b82601f106116e957805160ff1916838001178555611716565b82800160010185558215611716579182015b828111156117165782518255916020019190600101906116fb565b50611722929150611726565b5090565b5b808211156117225760008155600101611727565b600061174e61174984611c85565b611c54565b905082815283838301111561176257600080fd5b828260208301376000602084830101529392505050565b80356001600160a01b038116811461179057600080fd5b919050565b600082601f8301126117a5578081fd5b6105708383356020850161173b565b6000602082840312156117c5578081fd5b61057082611779565b600080604083850312156117e0578081fd5b6117e983611779565b91506117f760208401611779565b90509250929050565b600080600060608486031215611814578081fd5b61181d84611779565b925061182b60208501611779565b9150604084013590509250925092565b6000806040838503121561184d578182fd5b61185683611779565b9150602083013567ffffffffffffffff811115611871578182fd5b8301601f81018513611881578182fd5b6118908582356020840161173b565b9150509250929050565b600080604083850312156118ac578182fd5b6118b583611779565b946020939093013593505050565b6000602082840312156118d4578081fd5b5051919050565b6000602082840312156118ec578081fd5b815167ffffffffffffffff811115611902578182fd5b8201601f81018413611912578182fd5b805161192061174982611c85565b818152856020838501011115611934578384fd5b611660826020830160208601611cdc565b6000806000806080858703121561195a578081fd5b843567ffffffffffffffff80821115611971578283fd5b61197d88838901611795565b95506020870135915080821115611992578283fd5b5061199f87828801611795565b935050604085013560ff811681146119b5578182fd5b91506119c360608601611779565b905092959194509250565b600080600080608085870312156119e3578384fd5b843567ffffffffffffffff8111156119f9578485fd5b611a0587828801611795565b97602087013597506040870135966060013595509350505050565b60008151808452611a38816020860160208601611cdc565b601f01601f19169290920160200192915050565b60008251611a5e818460208701611cdc565b9190910192915050565b60008351611a7a818460208801611cdc565b6101d160f51b9083019081528351611a99816002840160208801611cdc565b01600201949350505050565b6001600160a01b038716815260c060208201819052600090611ac990830188611a20565b86604084015285606084015284608084015282810360a0840152611aed8185611a20565b9998505050505050505050565b6020815260006105706020830184611a20565b608081526000611b206080830187611a20565b6020830195909552506040810192909252606090910152919050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c7d57611c7d611d59565b604052919050565b600067ffffffffffffffff821115611c9f57611c9f611d59565b50601f01601f191660200190565b60008219821115611cc057611cc0611d43565b500190565b600082821015611cd757611cd7611d43565b500390565b60005b83811015611cf7578181015183820152602001611cdf565b838111156114325750506000910152565b600181811c90821680611d1c57607f821691505b60208210811415611d3d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fdfe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212203b820696364250693508f4a7a5e7e57685a305efda3e6577e74dfee930ff276e64736f6c63430008040033", hex.EncodeToString(code)) - require.Equal(t, "60806040526004361061011f5760003560e01c8063715018a6116100a0578063b86d529811610064578063b86d52981461031c578063c5cb9b511461033a578063dd62ed3e1461035a578063de7ea79d146103a0578063f2fde38b146103c057600080fd5b8063715018a6146102805780638da5cb5b1461029557806395d89b41146102c75780639dc29fac146102dc578063a9059cbb146102fc57600080fd5b80633659cfe6116100e75780633659cfe6146101e057806340c10f19146102025780634f1ef2861461022257806352d1902d1461023557806370a082311461024a57600080fd5b806306fdde0314610124578063095ea7b31461014f57806318160ddd1461017f57806323b872dd1461019e578063313ce567146101be575b600080fd5b34801561013057600080fd5b506101396103e0565b6040516101469190611afa565b60405180910390f35b34801561015b57600080fd5b5061016f61016a36600461189a565b610472565b6040519015158152602001610146565b34801561018b57600080fd5b5060cc545b604051908152602001610146565b3480156101aa57600080fd5b5061016f6101b9366004611800565b6104c8565b3480156101ca57600080fd5b5060cb5460405160ff9091168152602001610146565b3480156101ec57600080fd5b506102006101fb3660046117b4565b610577565b005b34801561020e57600080fd5b5061020061021d36600461189a565b610657565b61020061023036600461183b565b61068f565b34801561024157600080fd5b5061019061075c565b34801561025657600080fd5b506101906102653660046117b4565b6001600160a01b0316600090815260cd602052604090205490565b34801561028c57600080fd5b5061020061080f565b3480156102a157600080fd5b506097546001600160a01b03165b6040516001600160a01b039091168152602001610146565b3480156102d357600080fd5b50610139610845565b3480156102e857600080fd5b506102006102f736600461189a565b610854565b34801561030857600080fd5b5061016f61031736600461189a565b610888565b34801561032857600080fd5b5060cf546001600160a01b03166102af565b34801561034657600080fd5b5061016f6103553660046119ce565b61089e565b34801561036657600080fd5b506101906103753660046117ce565b6001600160a01b03918216600090815260ce6020908152604080832093909416825291909152205490565b3480156103ac57600080fd5b506102006103bb366004611945565b610954565b3480156103cc57600080fd5b506102006103db3660046117b4565b610a73565b606060c980546103ef90611d08565b80601f016020809104026020016040519081016040528092919081815260200182805461041b90611d08565b80156104685780601f1061043d57610100808354040283529160200191610468565b820191906000526020600020905b81548152906001019060200180831161044b57829003601f168201915b5050505050905090565b600061047f338484610b0b565b6040518281526001600160a01b0384169033907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259060200160405180910390a350600192915050565b6001600160a01b038316600090815260ce602090815260408083203384529091528120548281101561054b5760405162461bcd60e51b815260206004820152602160248201527f7472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636044820152606560f81b60648201526084015b60405180910390fd5b61055f853361055a8685611cc5565b610b0b565b61056a858585610b8d565b60019150505b9392505050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000010011614156105c05760405162461bcd60e51b815260040161054290611b3c565b7f00000000000000000000000000000000000000000000000000000000000010016001600160a01b0316610609600080516020611d70833981519152546001600160a01b031690565b6001600160a01b03161461062f5760405162461bcd60e51b815260040161054290611b88565b61063881610d3c565b6040805160008082526020820190925261065491839190610d66565b50565b6097546001600160a01b031633146106815760405162461bcd60e51b815260040161054290611bd4565b61068b8282610ee5565b5050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000010011614156106d85760405162461bcd60e51b815260040161054290611b3c565b7f00000000000000000000000000000000000000000000000000000000000010016001600160a01b0316610721600080516020611d70833981519152546001600160a01b031690565b6001600160a01b0316146107475760405162461bcd60e51b815260040161054290611b88565b61075082610d3c565b61068b82826001610d66565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000100116146107fc5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610542565b50600080516020611d7083398151915290565b6097546001600160a01b031633146108395760405162461bcd60e51b815260040161054290611bd4565b6108436000610fc4565b565b606060ca80546103ef90611d08565b6097546001600160a01b0316331461087e5760405162461bcd60e51b815260040161054290611bd4565b61068b8282611016565b6000610895338484610b8d565b50600192915050565b600063ffffffff333b16156108f55760405162461bcd60e51b815260206004820152601960248201527f63616c6c65722063616e6e6f7420626520636f6e7472616374000000000000006044820152606401610542565b6109023386868686611158565b336001600160a01b03167f282dd1817b996776123a00596764d4d54cc16460c9854f7a23f6be020ba0463d868686866040516109419493929190611b0d565b60405180910390a2506001949350505050565b600054610100900460ff1661096f5760005460ff1615610973565b303b155b6109d65760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610542565b600054610100900460ff161580156109f8576000805461ffff19166101011790555b8451610a0b9060c99060208801906116a2565b508351610a1f9060ca9060208701906116a2565b5060cb805460ff191660ff851617905560cf80546001600160a01b0319166001600160a01b038416179055610a5261131b565b610a5a61134a565b8015610a6c576000805461ff00191690555b5050505050565b6097546001600160a01b03163314610a9d5760405162461bcd60e51b815260040161054290611bd4565b6001600160a01b038116610b025760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610542565b61065481610fc4565b6001600160a01b038316610b615760405162461bcd60e51b815260206004820152601d60248201527f617070726f76652066726f6d20746865207a65726f20616464726573730000006044820152606401610542565b6001600160a01b03928316600090815260ce602090815260408083209490951682529290925291902055565b6001600160a01b038316610be35760405162461bcd60e51b815260206004820152601e60248201527f7472616e736665722066726f6d20746865207a65726f206164647265737300006044820152606401610542565b6001600160a01b038216610c395760405162461bcd60e51b815260206004820152601c60248201527f7472616e7366657220746f20746865207a65726f2061646472657373000000006044820152606401610542565b6001600160a01b038316600090815260cd602052604090205481811015610ca25760405162461bcd60e51b815260206004820152601f60248201527f7472616e7366657220616d6f756e7420657863656564732062616c616e6365006044820152606401610542565b610cac8282611cc5565b6001600160a01b03808616600090815260cd60205260408082209390935590851681529081208054849290610ce2908490611cad565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610d2e91815260200190565b60405180910390a350505050565b6097546001600160a01b031633146106545760405162461bcd60e51b815260040161054290611bd4565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615610d9e57610d9983611371565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b815260040160206040518083038186803b158015610dd757600080fd5b505afa925050508015610e07575060408051601f3d908101601f19168201909252610e04918101906118c3565b60015b610e6a5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610542565b600080516020611d708339815191528114610ed95760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610542565b50610d9983838361140d565b6001600160a01b038216610f3b5760405162461bcd60e51b815260206004820152601860248201527f6d696e7420746f20746865207a65726f206164647265737300000000000000006044820152606401610542565b8060cc6000828254610f4d9190611cad565b90915550506001600160a01b038216600090815260cd602052604081208054839290610f7a908490611cad565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b03821661106c5760405162461bcd60e51b815260206004820152601a60248201527f6275726e2066726f6d20746865207a65726f20616464726573730000000000006044820152606401610542565b6001600160a01b038216600090815260cd6020526040902054818110156110d55760405162461bcd60e51b815260206004820152601b60248201527f6275726e20616d6f756e7420657863656564732062616c616e636500000000006044820152606401610542565b6110df8282611cc5565b6001600160a01b038416600090815260cd602052604081209190915560cc805484929061110d908490611cc5565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6001600160a01b0385166111ae5760405162461bcd60e51b815260206004820152601e60248201527f7472616e736665722066726f6d20746865207a65726f206164647265737300006044820152606401610542565b60008451116111f35760405162461bcd60e51b81526020600482015260116024820152701a5b9d985b1a59081c9958da5c1a595b9d607a1b6044820152606401610542565b806112315760405162461bcd60e51b815260206004820152600e60248201526d1a5b9d985b1a59081d185c99d95d60921b6044820152606401610542565b60cf546112529086906001600160a01b031661124d8587611cad565b610b8d565b6000806110046001600160a01b031661127e888888888860405180602001604052806000815250611438565b60405161128b9190611a4c565b6000604051808303816000865af19150503d80600081146112c8576040519150601f19603f3d011682016040523d82523d6000602084013e6112cd565b606091505b509150915061131282826040518060400160405280601b81526020017f7472616e736665722063726f737320636861696e206661696c6564000000000081525061148b565b50505050505050565b600054610100900460ff166113425760405162461bcd60e51b815260040161054290611c09565b610843611505565b600054610100900460ff166108435760405162461bcd60e51b815260040161054290611c09565b6001600160a01b0381163b6113de5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610542565b600080516020611d7083398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b61141683611535565b6000825111806114235750805b15610d99576114328383611575565b50505050565b606086868686868660405160240161145596959493929190611aa5565b60408051601f198184030181529190526020810180516001600160e01b0316633c3e7d7760e01b17905290509695505050505050565b82610d99576000828060200190518101906114a691906118db565b90506001825110156114cc578060405162461bcd60e51b81526004016105429190611afa565b81816040516020016114df929190611a68565b60408051601f198184030181529082905262461bcd60e51b825261054291600401611afa565b600054610100900460ff1661152c5760405162461bcd60e51b815260040161054290611c09565b61084333610fc4565b61153e81611371565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b6115dd5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610542565b600080846001600160a01b0316846040516115f89190611a4c565b600060405180830381855af49150503d8060008114611633576040519150601f19603f3d011682016040523d82523d6000602084013e611638565b606091505b50915091506116608282604051806060016040528060278152602001611d9060279139611669565b95945050505050565b60608315611678575081610570565b8251156116885782518084602001fd5b8160405162461bcd60e51b81526004016105429190611afa565b8280546116ae90611d08565b90600052602060002090601f0160209004810192826116d05760008555611716565b82601f106116e957805160ff1916838001178555611716565b82800160010185558215611716579182015b828111156117165782518255916020019190600101906116fb565b50611722929150611726565b5090565b5b808211156117225760008155600101611727565b600061174e61174984611c85565b611c54565b905082815283838301111561176257600080fd5b828260208301376000602084830101529392505050565b80356001600160a01b038116811461179057600080fd5b919050565b600082601f8301126117a5578081fd5b6105708383356020850161173b565b6000602082840312156117c5578081fd5b61057082611779565b600080604083850312156117e0578081fd5b6117e983611779565b91506117f760208401611779565b90509250929050565b600080600060608486031215611814578081fd5b61181d84611779565b925061182b60208501611779565b9150604084013590509250925092565b6000806040838503121561184d578182fd5b61185683611779565b9150602083013567ffffffffffffffff811115611871578182fd5b8301601f81018513611881578182fd5b6118908582356020840161173b565b9150509250929050565b600080604083850312156118ac578182fd5b6118b583611779565b946020939093013593505050565b6000602082840312156118d4578081fd5b5051919050565b6000602082840312156118ec578081fd5b815167ffffffffffffffff811115611902578182fd5b8201601f81018413611912578182fd5b805161192061174982611c85565b818152856020838501011115611934578384fd5b611660826020830160208601611cdc565b6000806000806080858703121561195a578081fd5b843567ffffffffffffffff80821115611971578283fd5b61197d88838901611795565b95506020870135915080821115611992578283fd5b5061199f87828801611795565b935050604085013560ff811681146119b5578182fd5b91506119c360608601611779565b905092959194509250565b600080600080608085870312156119e3578384fd5b843567ffffffffffffffff8111156119f9578485fd5b611a0587828801611795565b97602087013597506040870135966060013595509350505050565b60008151808452611a38816020860160208601611cdc565b601f01601f19169290920160200192915050565b60008251611a5e818460208701611cdc565b9190910192915050565b60008351611a7a818460208801611cdc565b6101d160f51b9083019081528351611a99816002840160208801611cdc565b01600201949350505050565b6001600160a01b038716815260c060208201819052600090611ac990830188611a20565b86604084015285606084015284608084015282810360a0840152611aed8185611a20565b9998505050505050505050565b6020815260006105706020830184611a20565b608081526000611b206080830187611a20565b6020830195909552506040810192909252606090910152919050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c7d57611c7d611d59565b604052919050565b600067ffffffffffffffff821115611c9f57611c9f611d59565b50601f01601f191660200190565b60008219821115611cc057611cc0611d43565b500190565b600082821015611cd757611cd7611d43565b500390565b60005b83811015611cf7578181015183820152602001611cdf565b838111156114325750506000910152565b600181811c90821680611d1c57607f821691505b60208210811415611d3d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fdfe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212203b820696364250693508f4a7a5e7e57685a305efda3e6577e74dfee930ff276e64736f6c63430008040033", hex.EncodeToString(codeNew)) - require.NotEqual(t, hex.EncodeToString(code), hex.EncodeToString(codeNew)) -} - -func TestWFXCode(t *testing.T) { - codeAddr := "0x0f40EeCB63928367dcbf5Db326fD5A2824c76926" - codeBase64 := "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" - - code, codeNew := replayCodeAddress(codeBase64, codeAddr, contract.WFXLogicAddress) - require.Equal(t, "6080604052600436106101395760003560e01c80638da5cb5b116100ab578063c5cb9b511161006f578063c5cb9b5114610364578063d0e30db014610148578063dd62ed3e14610377578063de7ea79d146103bd578063f2fde38b146103dd578063f3fef3a3146103fd57610148565b80638da5cb5b146102bf57806395d89b41146102f15780639dc29fac14610306578063a9059cbb14610326578063b86d52981461034657610148565b80633659cfe6116100fd5780633659cfe61461020c57806340c10f191461022c5780634f1ef2861461024c57806352d1902d1461025f57806370a0823114610274578063715018a6146102aa57610148565b806306fdde0314610150578063095ea7b31461017b57806318160ddd146101ab57806323b872dd146101ca578063313ce567146101ea57610148565b366101485761014661041d565b005b61014661041d565b34801561015c57600080fd5b5061016561045e565b6040516101729190611c0e565b60405180910390f35b34801561018757600080fd5b5061019b6101963660046119c3565b6104f0565b6040519015158152602001610172565b3480156101b757600080fd5b5060cc545b604051908152602001610172565b3480156101d657600080fd5b5061019b6101e5366004611922565b610546565b3480156101f657600080fd5b5060cb5460405160ff9091168152602001610172565b34801561021857600080fd5b506101466102273660046118a3565b6105f5565b34801561023857600080fd5b506101466102473660046119c3565b6106d5565b61014661025a366004611962565b61070d565b34801561026b57600080fd5b506101bc6107da565b34801561028057600080fd5b506101bc61028f3660046118a3565b6001600160a01b0316600090815260cd602052604090205490565b3480156102b657600080fd5b5061014661088d565b3480156102cb57600080fd5b506097546001600160a01b03165b6040516001600160a01b039091168152602001610172565b3480156102fd57600080fd5b506101656108c3565b34801561031257600080fd5b506101466103213660046119c3565b6108d2565b34801561033257600080fd5b5061019b6103413660046119c3565b610906565b34801561035257600080fd5b5060cf546001600160a01b03166102d9565b61019b610372366004611ae2565b61091c565b34801561038357600080fd5b506101bc6103923660046118ea565b6001600160a01b03918216600090815260ce6020908152604080832093909416825291909152205490565b3480156103c957600080fd5b506101466103d8366004611a57565b6109e0565b3480156103e957600080fd5b506101466103f83660046118a3565b610aff565b34801561040957600080fd5b506101466104183660046118bf565b610b97565b6104273334610c1d565b60405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b606060c9805461046d90611e1c565b80601f016020809104026020016040519081016040528092919081815260200182805461049990611e1c565b80156104e65780601f106104bb576101008083540402835291602001916104e6565b820191906000526020600020905b8154815290600101906020018083116104c957829003601f168201915b5050505050905090565b60006104fd338484610cf5565b6040518281526001600160a01b0384169033907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259060200160405180910390a350600192915050565b6001600160a01b038316600090815260ce60209081526040808320338452909152812054828110156105c95760405162461bcd60e51b815260206004820152602160248201527f7472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636044820152606560f81b60648201526084015b60405180910390fd5b6105dd85336105d88685611dd9565b610cf5565b6105e8858585610d77565b60019150505b9392505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016141561063e5760405162461bcd60e51b81526004016105c090611c50565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610687600080516020611e99833981519152546001600160a01b031690565b6001600160a01b0316146106ad5760405162461bcd60e51b81526004016105c090611c9c565b6106b681610f26565b604080516000808252602082019092526106d291839190610f50565b50565b6097546001600160a01b031633146106ff5760405162461bcd60e51b81526004016105c090611ce8565b6107098282610c1d565b5050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614156107565760405162461bcd60e51b81526004016105c090611c50565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661079f600080516020611e99833981519152546001600160a01b031690565b6001600160a01b0316146107c55760405162461bcd60e51b81526004016105c090611c9c565b6107ce82610f26565b61070982826001610f50565b6000306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461087a5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016105c0565b50600080516020611e9983398151915290565b6097546001600160a01b031633146108b75760405162461bcd60e51b81526004016105c090611ce8565b6108c160006110cf565b565b606060ca805461046d90611e1c565b6097546001600160a01b031633146108fc5760405162461bcd60e51b81526004016105c090611ce8565b6107098282611121565b6000610913338484610d77565b50600192915050565b600063ffffffff333b16156109735760405162461bcd60e51b815260206004820152601960248201527f63616c6c65722063616e6e6f7420626520636f6e74726163740000000000000060448201526064016105c0565b34156109815761098161041d565b61098e3386868686611263565b336001600160a01b03167f282dd1817b996776123a00596764d4d54cc16460c9854f7a23f6be020ba0463d868686866040516109cd9493929190611c21565b60405180910390a2506001949350505050565b600054610100900460ff166109fb5760005460ff16156109ff565b303b155b610a625760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016105c0565b600054610100900460ff16158015610a84576000805461ffff19166101011790555b8451610a979060c99060208801906117ad565b508351610aab9060ca9060208701906117ad565b5060cb805460ff191660ff851617905560cf80546001600160a01b0319166001600160a01b038416179055610ade611426565b610ae6611455565b8015610af8576000805461ff00191690555b5050505050565b6097546001600160a01b03163314610b295760405162461bcd60e51b81526004016105c090611ce8565b6001600160a01b038116610b8e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016105c0565b6106d2816110cf565b610ba13382611121565b6040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015610bd7573d6000803e3d6000fd5b506040518181526001600160a01b0383169033907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb906020015b60405180910390a35050565b6001600160a01b038216610c735760405162461bcd60e51b815260206004820152601860248201527f6d696e7420746f20746865207a65726f2061646472657373000000000000000060448201526064016105c0565b8060cc6000828254610c859190611dc1565b90915550506001600160a01b038216600090815260cd602052604081208054839290610cb2908490611dc1565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610c11565b6001600160a01b038316610d4b5760405162461bcd60e51b815260206004820152601d60248201527f617070726f76652066726f6d20746865207a65726f206164647265737300000060448201526064016105c0565b6001600160a01b03928316600090815260ce602090815260408083209490951682529290925291902055565b6001600160a01b038316610dcd5760405162461bcd60e51b815260206004820152601e60248201527f7472616e736665722066726f6d20746865207a65726f2061646472657373000060448201526064016105c0565b6001600160a01b038216610e235760405162461bcd60e51b815260206004820152601c60248201527f7472616e7366657220746f20746865207a65726f20616464726573730000000060448201526064016105c0565b6001600160a01b038316600090815260cd602052604090205481811015610e8c5760405162461bcd60e51b815260206004820152601f60248201527f7472616e7366657220616d6f756e7420657863656564732062616c616e63650060448201526064016105c0565b610e968282611dd9565b6001600160a01b03808616600090815260cd60205260408082209390935590851681529081208054849290610ecc908490611dc1565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610f1891815260200190565b60405180910390a350505050565b6097546001600160a01b031633146106d25760405162461bcd60e51b81526004016105c090611ce8565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615610f8857610f838361147c565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b815260040160206040518083038186803b158015610fc157600080fd5b505afa925050508015610ff1575060408051601f3d908101601f19168201909252610fee918101906119d5565b60015b6110545760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b60648201526084016105c0565b600080516020611e9983398151915281146110c35760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b60648201526084016105c0565b50610f83838383611518565b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0382166111775760405162461bcd60e51b815260206004820152601a60248201527f6275726e2066726f6d20746865207a65726f206164647265737300000000000060448201526064016105c0565b6001600160a01b038216600090815260cd6020526040902054818110156111e05760405162461bcd60e51b815260206004820152601b60248201527f6275726e20616d6f756e7420657863656564732062616c616e6365000000000060448201526064016105c0565b6111ea8282611dd9565b6001600160a01b038416600090815260cd602052604081209190915560cc8054849290611218908490611dd9565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6001600160a01b0385166112b95760405162461bcd60e51b815260206004820152601e60248201527f7472616e736665722066726f6d20746865207a65726f2061646472657373000060448201526064016105c0565b60008451116112fe5760405162461bcd60e51b81526020600482015260116024820152701a5b9d985b1a59081c9958da5c1a595b9d607a1b60448201526064016105c0565b8061133c5760405162461bcd60e51b815260206004820152600e60248201526d1a5b9d985b1a59081d185c99d95d60921b60448201526064016105c0565b60cf5461135d9086906001600160a01b03166113588587611dc1565b610d77565b6000806110046001600160a01b0316611389888888888860405180602001604052806000815250611543565b6040516113969190611b60565b6000604051808303816000865af19150503d80600081146113d3576040519150601f19603f3d011682016040523d82523d6000602084013e6113d8565b606091505b509150915061141d82826040518060400160405280601b81526020017f7472616e736665722063726f737320636861696e206661696c65640000000000815250611596565b50505050505050565b600054610100900460ff1661144d5760405162461bcd60e51b81526004016105c090611d1d565b6108c1611610565b600054610100900460ff166108c15760405162461bcd60e51b81526004016105c090611d1d565b6001600160a01b0381163b6114e95760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016105c0565b600080516020611e9983398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b61152183611640565b60008251118061152e5750805b15610f835761153d8383611680565b50505050565b606086868686868660405160240161156096959493929190611bb9565b60408051601f198184030181529190526020810180516001600160e01b0316633c3e7d7760e01b17905290509695505050505050565b82610f83576000828060200190518101906115b191906119ed565b90506001825110156115d7578060405162461bcd60e51b81526004016105c09190611c0e565b81816040516020016115ea929190611b7c565b60408051601f198184030181529082905262461bcd60e51b82526105c091600401611c0e565b600054610100900460ff166116375760405162461bcd60e51b81526004016105c090611d1d565b6108c1336110cf565b6116498161147c565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b6116e85760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016105c0565b600080846001600160a01b0316846040516117039190611b60565b600060405180830381855af49150503d806000811461173e576040519150601f19603f3d011682016040523d82523d6000602084013e611743565b606091505b509150915061176b8282604051806060016040528060278152602001611eb960279139611774565b95945050505050565b606083156117835750816105ee565b8251156117935782518084602001fd5b8160405162461bcd60e51b81526004016105c09190611c0e565b8280546117b990611e1c565b90600052602060002090601f0160209004810192826117db5760008555611821565b82601f106117f457805160ff1916838001178555611821565b82800160010185558215611821579182015b82811115611821578251825591602001919060010190611806565b5061182d929150611831565b5090565b5b8082111561182d5760008155600101611832565b600061185961185484611d99565b611d68565b905082815283838301111561186d57600080fd5b828260208301376000602084830101529392505050565b600082601f830112611894578081fd5b6105ee83833560208501611846565b6000602082840312156118b4578081fd5b81356105ee81611e83565b600080604083850312156118d1578081fd5b82356118dc81611e83565b946020939093013593505050565b600080604083850312156118fc578182fd5b823561190781611e83565b9150602083013561191781611e83565b809150509250929050565b600080600060608486031215611936578081fd5b833561194181611e83565b9250602084013561195181611e83565b929592945050506040919091013590565b60008060408385031215611974578182fd5b823561197f81611e83565b9150602083013567ffffffffffffffff81111561199a578182fd5b8301601f810185136119aa578182fd5b6119b985823560208401611846565b9150509250929050565b600080604083850312156118d1578182fd5b6000602082840312156119e6578081fd5b5051919050565b6000602082840312156119fe578081fd5b815167ffffffffffffffff811115611a14578182fd5b8201601f81018413611a24578182fd5b8051611a3261185482611d99565b818152856020838501011115611a46578384fd5b61176b826020830160208601611df0565b60008060008060808587031215611a6c578081fd5b843567ffffffffffffffff80821115611a83578283fd5b611a8f88838901611884565b95506020870135915080821115611aa4578283fd5b50611ab187828801611884565b935050604085013560ff81168114611ac7578182fd5b91506060850135611ad781611e83565b939692955090935050565b60008060008060808587031215611af7578384fd5b843567ffffffffffffffff811115611b0d578485fd5b611b1987828801611884565b97602087013597506040870135966060013595509350505050565b60008151808452611b4c816020860160208601611df0565b601f01601f19169290920160200192915050565b60008251611b72818460208701611df0565b9190910192915050565b60008351611b8e818460208801611df0565b6101d160f51b9083019081528351611bad816002840160208801611df0565b01600201949350505050565b6001600160a01b038716815260c060208201819052600090611bdd90830188611b34565b86604084015285606084015284608084015282810360a0840152611c018185611b34565b9998505050505050505050565b6020815260006105ee6020830184611b34565b608081526000611c346080830187611b34565b6020830195909552506040810192909252606090910152919050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b604051601f8201601f1916810167ffffffffffffffff81118282101715611d9157611d91611e6d565b604052919050565b600067ffffffffffffffff821115611db357611db3611e6d565b50601f01601f191660200190565b60008219821115611dd457611dd4611e57565b500190565b600082821015611deb57611deb611e57565b500390565b60005b83811015611e0b578181015183820152602001611df3565b8381111561153d5750506000910152565b600181811c90821680611e3057607f821691505b60208210811415611e5157634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146106d257600080fdfe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220c3b1cd913030a18195eba376a78d2ea5e6cb2500466d9f96635c54aa3829033164736f6c63430008040033", hex.EncodeToString(code)) - require.Equal(t, "6080604052600436106101395760003560e01c80638da5cb5b116100ab578063c5cb9b511161006f578063c5cb9b5114610364578063d0e30db014610148578063dd62ed3e14610377578063de7ea79d146103bd578063f2fde38b146103dd578063f3fef3a3146103fd57610148565b80638da5cb5b146102bf57806395d89b41146102f15780639dc29fac14610306578063a9059cbb14610326578063b86d52981461034657610148565b80633659cfe6116100fd5780633659cfe61461020c57806340c10f191461022c5780634f1ef2861461024c57806352d1902d1461025f57806370a0823114610274578063715018a6146102aa57610148565b806306fdde0314610150578063095ea7b31461017b57806318160ddd146101ab57806323b872dd146101ca578063313ce567146101ea57610148565b366101485761014661041d565b005b61014661041d565b34801561015c57600080fd5b5061016561045e565b6040516101729190611c0e565b60405180910390f35b34801561018757600080fd5b5061019b6101963660046119c3565b6104f0565b6040519015158152602001610172565b3480156101b757600080fd5b5060cc545b604051908152602001610172565b3480156101d657600080fd5b5061019b6101e5366004611922565b610546565b3480156101f657600080fd5b5060cb5460405160ff9091168152602001610172565b34801561021857600080fd5b506101466102273660046118a3565b6105f5565b34801561023857600080fd5b506101466102473660046119c3565b6106d5565b61014661025a366004611962565b61070d565b34801561026b57600080fd5b506101bc6107da565b34801561028057600080fd5b506101bc61028f3660046118a3565b6001600160a01b0316600090815260cd602052604090205490565b3480156102b657600080fd5b5061014661088d565b3480156102cb57600080fd5b506097546001600160a01b03165b6040516001600160a01b039091168152602001610172565b3480156102fd57600080fd5b506101656108c3565b34801561031257600080fd5b506101466103213660046119c3565b6108d2565b34801561033257600080fd5b5061019b6103413660046119c3565b610906565b34801561035257600080fd5b5060cf546001600160a01b03166102d9565b61019b610372366004611ae2565b61091c565b34801561038357600080fd5b506101bc6103923660046118ea565b6001600160a01b03918216600090815260ce6020908152604080832093909416825291909152205490565b3480156103c957600080fd5b506101466103d8366004611a57565b6109e0565b3480156103e957600080fd5b506101466103f83660046118a3565b610aff565b34801561040957600080fd5b506101466104183660046118bf565b610b97565b6104273334610c1d565b60405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b606060c9805461046d90611e1c565b80601f016020809104026020016040519081016040528092919081815260200182805461049990611e1c565b80156104e65780601f106104bb576101008083540402835291602001916104e6565b820191906000526020600020905b8154815290600101906020018083116104c957829003601f168201915b5050505050905090565b60006104fd338484610cf5565b6040518281526001600160a01b0384169033907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259060200160405180910390a350600192915050565b6001600160a01b038316600090815260ce60209081526040808320338452909152812054828110156105c95760405162461bcd60e51b815260206004820152602160248201527f7472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636044820152606560f81b60648201526084015b60405180910390fd5b6105dd85336105d88685611dd9565b610cf5565b6105e8858585610d77565b60019150505b9392505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000100216141561063e5760405162461bcd60e51b81526004016105c090611c50565b7f00000000000000000000000000000000000000000000000000000000000010026001600160a01b0316610687600080516020611e99833981519152546001600160a01b031690565b6001600160a01b0316146106ad5760405162461bcd60e51b81526004016105c090611c9c565b6106b681610f26565b604080516000808252602082019092526106d291839190610f50565b50565b6097546001600160a01b031633146106ff5760405162461bcd60e51b81526004016105c090611ce8565b6107098282610c1d565b5050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000010021614156107565760405162461bcd60e51b81526004016105c090611c50565b7f00000000000000000000000000000000000000000000000000000000000010026001600160a01b031661079f600080516020611e99833981519152546001600160a01b031690565b6001600160a01b0316146107c55760405162461bcd60e51b81526004016105c090611c9c565b6107ce82610f26565b61070982826001610f50565b6000306001600160a01b037f0000000000000000000000000000000000000000000000000000000000001002161461087a5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016105c0565b50600080516020611e9983398151915290565b6097546001600160a01b031633146108b75760405162461bcd60e51b81526004016105c090611ce8565b6108c160006110cf565b565b606060ca805461046d90611e1c565b6097546001600160a01b031633146108fc5760405162461bcd60e51b81526004016105c090611ce8565b6107098282611121565b6000610913338484610d77565b50600192915050565b600063ffffffff333b16156109735760405162461bcd60e51b815260206004820152601960248201527f63616c6c65722063616e6e6f7420626520636f6e74726163740000000000000060448201526064016105c0565b34156109815761098161041d565b61098e3386868686611263565b336001600160a01b03167f282dd1817b996776123a00596764d4d54cc16460c9854f7a23f6be020ba0463d868686866040516109cd9493929190611c21565b60405180910390a2506001949350505050565b600054610100900460ff166109fb5760005460ff16156109ff565b303b155b610a625760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016105c0565b600054610100900460ff16158015610a84576000805461ffff19166101011790555b8451610a979060c99060208801906117ad565b508351610aab9060ca9060208701906117ad565b5060cb805460ff191660ff851617905560cf80546001600160a01b0319166001600160a01b038416179055610ade611426565b610ae6611455565b8015610af8576000805461ff00191690555b5050505050565b6097546001600160a01b03163314610b295760405162461bcd60e51b81526004016105c090611ce8565b6001600160a01b038116610b8e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016105c0565b6106d2816110cf565b610ba13382611121565b6040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015610bd7573d6000803e3d6000fd5b506040518181526001600160a01b0383169033907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb906020015b60405180910390a35050565b6001600160a01b038216610c735760405162461bcd60e51b815260206004820152601860248201527f6d696e7420746f20746865207a65726f2061646472657373000000000000000060448201526064016105c0565b8060cc6000828254610c859190611dc1565b90915550506001600160a01b038216600090815260cd602052604081208054839290610cb2908490611dc1565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610c11565b6001600160a01b038316610d4b5760405162461bcd60e51b815260206004820152601d60248201527f617070726f76652066726f6d20746865207a65726f206164647265737300000060448201526064016105c0565b6001600160a01b03928316600090815260ce602090815260408083209490951682529290925291902055565b6001600160a01b038316610dcd5760405162461bcd60e51b815260206004820152601e60248201527f7472616e736665722066726f6d20746865207a65726f2061646472657373000060448201526064016105c0565b6001600160a01b038216610e235760405162461bcd60e51b815260206004820152601c60248201527f7472616e7366657220746f20746865207a65726f20616464726573730000000060448201526064016105c0565b6001600160a01b038316600090815260cd602052604090205481811015610e8c5760405162461bcd60e51b815260206004820152601f60248201527f7472616e7366657220616d6f756e7420657863656564732062616c616e63650060448201526064016105c0565b610e968282611dd9565b6001600160a01b03808616600090815260cd60205260408082209390935590851681529081208054849290610ecc908490611dc1565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610f1891815260200190565b60405180910390a350505050565b6097546001600160a01b031633146106d25760405162461bcd60e51b81526004016105c090611ce8565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615610f8857610f838361147c565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b815260040160206040518083038186803b158015610fc157600080fd5b505afa925050508015610ff1575060408051601f3d908101601f19168201909252610fee918101906119d5565b60015b6110545760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b60648201526084016105c0565b600080516020611e9983398151915281146110c35760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b60648201526084016105c0565b50610f83838383611518565b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0382166111775760405162461bcd60e51b815260206004820152601a60248201527f6275726e2066726f6d20746865207a65726f206164647265737300000000000060448201526064016105c0565b6001600160a01b038216600090815260cd6020526040902054818110156111e05760405162461bcd60e51b815260206004820152601b60248201527f6275726e20616d6f756e7420657863656564732062616c616e6365000000000060448201526064016105c0565b6111ea8282611dd9565b6001600160a01b038416600090815260cd602052604081209190915560cc8054849290611218908490611dd9565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6001600160a01b0385166112b95760405162461bcd60e51b815260206004820152601e60248201527f7472616e736665722066726f6d20746865207a65726f2061646472657373000060448201526064016105c0565b60008451116112fe5760405162461bcd60e51b81526020600482015260116024820152701a5b9d985b1a59081c9958da5c1a595b9d607a1b60448201526064016105c0565b8061133c5760405162461bcd60e51b815260206004820152600e60248201526d1a5b9d985b1a59081d185c99d95d60921b60448201526064016105c0565b60cf5461135d9086906001600160a01b03166113588587611dc1565b610d77565b6000806110046001600160a01b0316611389888888888860405180602001604052806000815250611543565b6040516113969190611b60565b6000604051808303816000865af19150503d80600081146113d3576040519150601f19603f3d011682016040523d82523d6000602084013e6113d8565b606091505b509150915061141d82826040518060400160405280601b81526020017f7472616e736665722063726f737320636861696e206661696c65640000000000815250611596565b50505050505050565b600054610100900460ff1661144d5760405162461bcd60e51b81526004016105c090611d1d565b6108c1611610565b600054610100900460ff166108c15760405162461bcd60e51b81526004016105c090611d1d565b6001600160a01b0381163b6114e95760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016105c0565b600080516020611e9983398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b61152183611640565b60008251118061152e5750805b15610f835761153d8383611680565b50505050565b606086868686868660405160240161156096959493929190611bb9565b60408051601f198184030181529190526020810180516001600160e01b0316633c3e7d7760e01b17905290509695505050505050565b82610f83576000828060200190518101906115b191906119ed565b90506001825110156115d7578060405162461bcd60e51b81526004016105c09190611c0e565b81816040516020016115ea929190611b7c565b60408051601f198184030181529082905262461bcd60e51b82526105c091600401611c0e565b600054610100900460ff166116375760405162461bcd60e51b81526004016105c090611d1d565b6108c1336110cf565b6116498161147c565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b6116e85760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016105c0565b600080846001600160a01b0316846040516117039190611b60565b600060405180830381855af49150503d806000811461173e576040519150601f19603f3d011682016040523d82523d6000602084013e611743565b606091505b509150915061176b8282604051806060016040528060278152602001611eb960279139611774565b95945050505050565b606083156117835750816105ee565b8251156117935782518084602001fd5b8160405162461bcd60e51b81526004016105c09190611c0e565b8280546117b990611e1c565b90600052602060002090601f0160209004810192826117db5760008555611821565b82601f106117f457805160ff1916838001178555611821565b82800160010185558215611821579182015b82811115611821578251825591602001919060010190611806565b5061182d929150611831565b5090565b5b8082111561182d5760008155600101611832565b600061185961185484611d99565b611d68565b905082815283838301111561186d57600080fd5b828260208301376000602084830101529392505050565b600082601f830112611894578081fd5b6105ee83833560208501611846565b6000602082840312156118b4578081fd5b81356105ee81611e83565b600080604083850312156118d1578081fd5b82356118dc81611e83565b946020939093013593505050565b600080604083850312156118fc578182fd5b823561190781611e83565b9150602083013561191781611e83565b809150509250929050565b600080600060608486031215611936578081fd5b833561194181611e83565b9250602084013561195181611e83565b929592945050506040919091013590565b60008060408385031215611974578182fd5b823561197f81611e83565b9150602083013567ffffffffffffffff81111561199a578182fd5b8301601f810185136119aa578182fd5b6119b985823560208401611846565b9150509250929050565b600080604083850312156118d1578182fd5b6000602082840312156119e6578081fd5b5051919050565b6000602082840312156119fe578081fd5b815167ffffffffffffffff811115611a14578182fd5b8201601f81018413611a24578182fd5b8051611a3261185482611d99565b818152856020838501011115611a46578384fd5b61176b826020830160208601611df0565b60008060008060808587031215611a6c578081fd5b843567ffffffffffffffff80821115611a83578283fd5b611a8f88838901611884565b95506020870135915080821115611aa4578283fd5b50611ab187828801611884565b935050604085013560ff81168114611ac7578182fd5b91506060850135611ad781611e83565b939692955090935050565b60008060008060808587031215611af7578384fd5b843567ffffffffffffffff811115611b0d578485fd5b611b1987828801611884565b97602087013597506040870135966060013595509350505050565b60008151808452611b4c816020860160208601611df0565b601f01601f19169290920160200192915050565b60008251611b72818460208701611df0565b9190910192915050565b60008351611b8e818460208801611df0565b6101d160f51b9083019081528351611bad816002840160208801611df0565b01600201949350505050565b6001600160a01b038716815260c060208201819052600090611bdd90830188611b34565b86604084015285606084015284608084015282810360a0840152611c018185611b34565b9998505050505050505050565b6020815260006105ee6020830184611b34565b608081526000611c346080830187611b34565b6020830195909552506040810192909252606090910152919050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b604051601f8201601f1916810167ffffffffffffffff81118282101715611d9157611d91611e6d565b604052919050565b600067ffffffffffffffff821115611db357611db3611e6d565b50601f01601f191660200190565b60008219821115611dd457611dd4611e57565b500190565b600082821015611deb57611deb611e57565b500390565b60005b83811015611e0b578181015183820152602001611df3565b8381111561153d5750506000910152565b600181811c90821680611e3057607f821691505b60208210811415611e5157634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146106d257600080fdfe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220c3b1cd913030a18195eba376a78d2ea5e6cb2500466d9f96635c54aa3829033164736f6c63430008040033", hex.EncodeToString(codeNew)) - require.NotEqual(t, hex.EncodeToString(code), hex.EncodeToString(codeNew)) -} - -func replayCodeAddress(codeBase64, addr, addrNew string) (code, codeNew []byte) { - bz, err := base64.StdEncoding.DecodeString(codeBase64) - if err != nil { - panic(err) - } - - addr1 := common.HexToAddress(addr) - addr2 := common.HexToAddress(addrNew) - - bzZero := bytes.ReplaceAll(bz, addr1.Bytes(), common.Address{}.Bytes()) - bzNew := bytes.ReplaceAll(bz, addr1.Bytes(), addr2.Bytes()) - - return bzZero, bzNew -} diff --git a/tests/crosschain_test.go b/tests/crosschain_test.go deleted file mode 100644 index 72dfff37..00000000 --- a/tests/crosschain_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package tests - -import ( - crosschaintypes "github.com/functionx/fx-core/v8/x/crosschain/types" -) - -func (suite *IntegrationTest) CrosschainTest() { -} - -func (suite *IntegrationTest) UpdateParamsTest() { - for _, chain := range suite.crosschain { - chain.UpdateParams(func(params *crosschaintypes.Params) { - params.DelegateMultiple = 100 - }) - params := chain.QueryParams() - suite.Require().Equal(params.DelegateMultiple, int64(100)) - } -} diff --git a/tests/erc20_suite.go b/tests/erc20_suite.go deleted file mode 100644 index fe88c84e..00000000 --- a/tests/erc20_suite.go +++ /dev/null @@ -1,62 +0,0 @@ -package tests - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - "github.com/ethereum/go-ethereum/common" - - erc20types "github.com/functionx/fx-core/v8/x/erc20/types" -) - -type Erc20TestSuite struct { - EvmTestSuite -} - -func NewErc20TestSuite(ts *TestSuite) Erc20TestSuite { - return Erc20TestSuite{ - EvmTestSuite: NewEvmTestSuite(ts), - } -} - -func (suite *Erc20TestSuite) AccAddress() sdk.AccAddress { - return sdk.AccAddress(suite.privKey.PubKey().Address()) -} - -func (suite *Erc20TestSuite) HexAddress() common.Address { - return common.BytesToAddress(suite.privKey.PubKey().Address()) -} - -func (suite *Erc20TestSuite) ERC20Query() erc20types.QueryClient { - return suite.GRPCClient().ERC20Query() -} - -func (suite *Erc20TestSuite) Erc20TokenAddress(denom string) common.Address { - // todo: implement me - return common.Address{} -} - -func (suite *Erc20TestSuite) ToggleTokenConversionProposal(denom string) (*sdk.TxResponse, uint64) { - msg := &erc20types.MsgToggleTokenConversion{ - Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(), - Token: denom, - } - return suite.BroadcastProposalTx2([]sdk.Msg{msg}, "ToggleTokenConversionProposal", "ToggleTokenConversionProposal") -} - -func (suite *Erc20TestSuite) ConvertCoin(recipient common.Address, coin sdk.Coin) *sdk.TxResponse { - fromAddress := sdk.AccAddress(suite.privKey.PubKey().Address()) - - beforeBalance := suite.QueryBalances(fromAddress).AmountOf(coin.Denom) - erc20TokenAddress := suite.Erc20TokenAddress(coin.Denom) - beforeBalanceOf := suite.BalanceOf(erc20TokenAddress, recipient) - - msg := erc20types.NewMsgConvertCoin(coin, recipient, sdk.AccAddress(suite.privKey.PubKey().Address())) - txResponse := suite.BroadcastTx(suite.privKey, msg) - - afterBalance := suite.QueryBalances(fromAddress).AmountOf(coin.Denom) - afterBalanceOf := suite.BalanceOf(erc20TokenAddress, recipient) - suite.Require().Equal(beforeBalance.Sub(afterBalance).String(), coin.Amount.String()) - suite.Require().Equal(afterBalanceOf.String(), beforeBalanceOf.String()) - return txResponse -} diff --git a/tests/evm_suite.go b/tests/evm_suite.go deleted file mode 100644 index ec963aff..00000000 --- a/tests/evm_suite.go +++ /dev/null @@ -1,384 +0,0 @@ -package tests - -import ( - "context" - "math/big" - "time" - - sdkmath "cosmossdk.io/math" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - ethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethclient" - evmtypes "github.com/evmos/ethermint/x/evm/types" - - "github.com/functionx/fx-core/v8/client" - "github.com/functionx/fx-core/v8/contract" - testscontract "github.com/functionx/fx-core/v8/tests/contract" - "github.com/functionx/fx-core/v8/testutil/helpers" - fxtypes "github.com/functionx/fx-core/v8/types" - erc20types "github.com/functionx/fx-core/v8/x/erc20/types" -) - -type EvmTestSuite struct { - *TestSuite - contract.ERC20ABI - privKey cryptotypes.PrivKey -} - -func NewEvmTestSuite(ts *TestSuite) EvmTestSuite { - return EvmTestSuite{ - TestSuite: ts, - ERC20ABI: contract.NewERC20ABI(), - privKey: helpers.NewEthPrivKey(), - } -} - -func (suite *EvmTestSuite) SetupSuite() { - suite.TestSuite.SetupSuite() - - // transfer to eth private key - suite.Send(suite.AccAddress(), suite.NewCoin(sdkmath.NewInt(100).MulRaw(1e18))) -} - -func (suite *EvmTestSuite) AccAddress() sdk.AccAddress { - return sdk.AccAddress(suite.privKey.PubKey().Address()) -} - -func (suite *EvmTestSuite) HexAddress() common.Address { - return common.BytesToAddress(suite.privKey.PubKey().Address()) -} - -func (suite *EvmTestSuite) EthClient() *ethclient.Client { - return suite.GetFirstValidator().JSONRPCClient -} - -func (suite *EvmTestSuite) TransactOpts() *bind.TransactOpts { - ecdsa, err := crypto.ToECDSA(suite.privKey.Bytes()) - suite.Require().NoError(err) - - transactOpts, err := bind.NewKeyedTransactorWithChainID(ecdsa, fxtypes.EIP155ChainID(suite.network.Config.ChainID)) - suite.Require().NoError(err) - - return transactOpts -} - -func (suite *EvmTestSuite) Balance(addr common.Address) *big.Int { - at, err := suite.EthClient().BalanceAt(suite.ctx, addr, nil) - suite.Require().NoError(err) - return at -} - -func (suite *EvmTestSuite) TotalSupply(contractAddr common.Address) *big.Int { - caller, err := contract.NewFIP20Upgradable(contractAddr, suite.EthClient()) - suite.Require().NoError(err) - totalSupply, err := caller.TotalSupply(nil) - suite.Require().NoError(err) - return totalSupply -} - -func (suite *EvmTestSuite) BalanceOf(contractAddr, address common.Address) *big.Int { - caller, err := contract.NewFIP20Upgradable(contractAddr, suite.EthClient()) - suite.Require().NoError(err) - balance, err := caller.BalanceOf(nil, address) - suite.Require().NoError(err) - return balance -} - -func (suite *EvmTestSuite) CheckBalanceOf(contractAddr, address common.Address, balance *big.Int) { - balAfter := suite.BalanceOf(contractAddr, address) - suite.Equal(balAfter.String(), balance.String()) -} - -func (suite *EvmTestSuite) Symbol(contractAddr common.Address) string { - caller, err := contract.NewFIP20Upgradable(contractAddr, suite.EthClient()) - suite.Require().NoError(err) - symbol, err := caller.Symbol(nil) - suite.Require().NoError(err) - return symbol -} - -func (suite *EvmTestSuite) HandleWithCheckBalance(contractAddr, address common.Address, addValue *big.Int, h func()) { - value := suite.BalanceOf(contractAddr, address) - h() - newValue := suite.BalanceOf(contractAddr, address) - suite.Equal(big.NewInt(0).Add(value, addValue).String(), newValue.String()) -} - -func (suite *EvmTestSuite) Allowance(contractAddr, owner, spender common.Address) *big.Int { - caller, err := contract.NewFIP20Upgradable(contractAddr, suite.EthClient()) - suite.Require().NoError(err) - allowance, err := caller.Allowance(nil, owner, spender) - suite.Require().NoError(err) - return allowance -} - -func (suite *EvmTestSuite) Owner(contractAddr common.Address) common.Address { - caller, err := contract.NewFIP20Upgradable(contractAddr, suite.EthClient()) - suite.Require().NoError(err) - owner, err := caller.Owner(nil) - suite.Require().NoError(err) - return owner -} - -func (suite *EvmTestSuite) CheckAllowance(contractAddr, owner, spender common.Address, value *big.Int) bool { - return suite.Allowance(contractAddr, owner, spender).Cmp(value) == 0 -} - -func (suite *EvmTestSuite) BlockHeight() uint64 { - number, err := suite.EthClient().BlockNumber(suite.ctx) - suite.Require().NoError(err) - return number -} - -func (suite *EvmTestSuite) Transfer(privateKey cryptotypes.PrivKey, recipient common.Address, value *big.Int) *ethtypes.Transaction { - ethTx, err := client.BuildEthTransaction(suite.ctx, suite.EthClient(), privateKey, &recipient, value, nil) - suite.Require().NoError(err) - - suite.SendTransaction(ethTx) - return ethTx -} - -func (suite *EvmTestSuite) WFXDeposit(privateKey cryptotypes.PrivKey, address common.Address, value *big.Int) *ethtypes.Transaction { - suite.True(suite.Balance(common.BytesToAddress(privateKey.PubKey().Address().Bytes())).Cmp(value) >= 0) - pack, err := suite.ERC20ABI.PackDeposit() - suite.Require().NoError(err) - - ethTx, err := client.BuildEthTransaction(suite.ctx, suite.EthClient(), privateKey, &address, value, pack) - suite.Require().NoError(err) - - suite.SendTransaction(ethTx) - suite.True(suite.BalanceOf(address, common.BytesToAddress(privateKey.PubKey().Address().Bytes())).Cmp(value) >= 0) - suite.True(suite.TotalSupply(address).Cmp(value) >= 0) - return ethTx -} - -func (suite *EvmTestSuite) WFXWithdraw(privateKey cryptotypes.PrivKey, address, recipient common.Address, value *big.Int) *ethtypes.Transaction { - suite.True(suite.TotalSupply(address).Cmp(value) >= 0) - suite.True(suite.BalanceOf(address, common.BytesToAddress(privateKey.PubKey().Address().Bytes())).Cmp(value) >= 0) - pack, err := suite.ERC20ABI.PackWithdraw(recipient, value) - suite.Require().NoError(err) - - ethTx, err := client.BuildEthTransaction(suite.ctx, suite.EthClient(), privateKey, &address, nil, pack) - suite.Require().NoError(err) - - suite.SendTransaction(ethTx) - - suite.True(suite.Balance(recipient).Cmp(value) >= 0) - return ethTx -} - -func (suite *EvmTestSuite) TransferERC20(privateKey cryptotypes.PrivKey, token, recipient common.Address, value *big.Int) *ethtypes.Transaction { - suite.True(suite.BalanceOf(token, common.BytesToAddress(privateKey.PubKey().Address().Bytes())).Cmp(value) >= 0) - - pack, err := suite.ERC20ABI.PackTransfer(recipient, value) - suite.Require().NoError(err) - - ethTx, err := client.BuildEthTransaction(suite.ctx, suite.EthClient(), privateKey, &token, nil, pack) - suite.Require().NoError(err) - - suite.SendTransaction(ethTx) - suite.True(suite.BalanceOf(token, recipient).Cmp(value) >= 0) - return ethTx -} - -func (suite *EvmTestSuite) ApproveERC20(privateKey cryptotypes.PrivKey, token, spender common.Address, value *big.Int) *ethtypes.Transaction { - pack, err := suite.ERC20ABI.PackApprove(spender, value) - suite.Require().NoError(err) - - ethTx, err := client.BuildEthTransaction(suite.ctx, suite.EthClient(), privateKey, &token, nil, pack) - suite.Require().NoError(err) - - suite.SendTransaction(ethTx) - suite.True(suite.Allowance(token, common.BytesToAddress(privateKey.PubKey().Address().Bytes()), spender).Cmp(value) >= 0) - return ethTx -} - -func (suite *EvmTestSuite) TransferOwnership(privateKey cryptotypes.PrivKey, token, newOwner common.Address) *ethtypes.Transaction { - pack, err := suite.ERC20ABI.PackTransferOwnership(newOwner) - suite.Require().NoError(err) - - ethTx, err := client.BuildEthTransaction(suite.ctx, suite.EthClient(), privateKey, &token, nil, pack) - suite.Require().NoError(err) - - suite.SendTransaction(ethTx) - suite.Require().Equal(suite.Owner(token).String(), newOwner.String()) - return ethTx -} - -func (suite *EvmTestSuite) TransferFromERC20(privateKey cryptotypes.PrivKey, token, sender, recipient common.Address, value *big.Int) *ethtypes.Transaction { - pack, err := suite.ERC20ABI.PackTransferFrom(sender, recipient, value) - suite.Require().NoError(err) - - ethTx, err := client.BuildEthTransaction(suite.ctx, suite.EthClient(), privateKey, &token, nil, pack) - suite.Require().NoError(err) - - suite.SendTransaction(ethTx) - suite.True(suite.BalanceOf(token, recipient).Cmp(value) >= 0) - return ethTx -} - -func (suite *EvmTestSuite) MintERC20(privateKey cryptotypes.PrivKey, token, account common.Address, value *big.Int) *ethtypes.Transaction { - pack, err := suite.ERC20ABI.PackMint(account, value) - suite.Require().NoError(err) - ethTx, err := client.BuildEthTransaction(suite.ctx, suite.EthClient(), privateKey, &token, nil, pack) - suite.Require().NoError(err) - suite.SendTransaction(ethTx) - suite.True(suite.BalanceOf(token, account).Cmp(value) >= 0) - suite.True(suite.TotalSupply(token).Cmp(value) >= 0) - return ethTx -} - -func (suite *EvmTestSuite) BurnERC20(privateKey cryptotypes.PrivKey, token, account common.Address, value *big.Int) *ethtypes.Transaction { - beforeBalance := suite.BalanceOf(token, account) - suite.True(beforeBalance.Cmp(value) >= 0) - beforeTotalSupply := suite.TotalSupply(token) - suite.True(beforeTotalSupply.Cmp(value) >= 0) - pack, err := suite.ERC20ABI.PackBurn(account, value) - suite.Require().NoError(err) - ethTx, err := client.BuildEthTransaction(suite.ctx, suite.EthClient(), privateKey, &token, nil, pack) - suite.Require().NoError(err) - suite.SendTransaction(ethTx) - suite.True(new(big.Int).Sub(beforeBalance, suite.BalanceOf(token, account)).Cmp(value) == 0) - suite.True(new(big.Int).Sub(beforeTotalSupply, suite.TotalSupply(token)).Cmp(value) == 0) - return ethTx -} - -func (suite *EvmTestSuite) BalanceOfERC721(contractAddr, account common.Address) *big.Int { - caller, err := testscontract.NewERC721TokenTest(contractAddr, suite.EthClient()) - suite.Require().NoError(err) - balanceOf, err := caller.BalanceOf(nil, account) - suite.Require().NoError(err) - return balanceOf -} - -func (suite *EvmTestSuite) CheckBalanceOfERC721(contractAddr, account common.Address, value *big.Int) bool { - return suite.BalanceOfERC721(contractAddr, account).Cmp(value) == 0 -} - -func (suite *EvmTestSuite) TokenURI(contractAddr common.Address, id *big.Int) string { - caller, err := testscontract.NewERC721TokenTest(contractAddr, suite.EthClient()) - suite.Require().NoError(err) - uri, err := caller.TokenURI(nil, id) - suite.Require().NoError(err) - return uri -} - -func (suite *EvmTestSuite) IsApprovedForAll(contractAddr, owner, operator common.Address) bool { - caller, err := testscontract.NewERC721TokenTest(contractAddr, suite.EthClient()) - suite.Require().NoError(err) - isApproved, err := caller.IsApprovedForAll(nil, owner, operator) - suite.Require().NoError(err) - return isApproved -} - -func (suite *EvmTestSuite) SafeMintERC721(privateKey cryptotypes.PrivKey, contractAddr, account common.Address) *ethtypes.Transaction { - pack, err := GetERC721().ABI.Pack("safeMint", account, "ipfs://test-url") - suite.Require().NoError(err) - ethTx, err := client.BuildEthTransaction(suite.ctx, suite.EthClient(), privateKey, &contractAddr, nil, pack) - suite.Require().NoError(err) - suite.SendTransaction(ethTx) - return ethTx -} - -func (suite *EvmTestSuite) ApproveERC721(privateKey cryptotypes.PrivKey, contractAddr, operator common.Address, id *big.Int) *ethtypes.Transaction { - pack, err := GetERC721().ABI.Pack("approve", operator, id) - suite.Require().NoError(err) - ethTx, err := client.BuildEthTransaction(suite.ctx, suite.EthClient(), privateKey, &contractAddr, nil, pack) - suite.Require().NoError(err) - suite.SendTransaction(ethTx) - return ethTx -} - -func (suite *EvmTestSuite) SetApprovalForAll(privateKey cryptotypes.PrivKey, contractAddr, operator common.Address, approved bool) *ethtypes.Transaction { - pack, err := GetERC721().ABI.Pack("setApprovalForAll", operator, approved) - suite.Require().NoError(err) - ethTx, err := client.BuildEthTransaction(suite.ctx, suite.EthClient(), privateKey, &contractAddr, nil, pack) - suite.Require().NoError(err) - suite.SendTransaction(ethTx) - return ethTx -} - -func (suite *EvmTestSuite) SafeTransferFrom(privateKey cryptotypes.PrivKey, contractAddr, from, to common.Address, id *big.Int) *ethtypes.Transaction { - pack, err := GetERC721().ABI.Pack("safeTransferFrom", from, to, id) - suite.Require().NoError(err) - ethTx, err := client.BuildEthTransaction(suite.ctx, suite.EthClient(), privateKey, &contractAddr, nil, pack) - suite.Require().NoError(err) - suite.SendTransaction(ethTx) - return ethTx -} - -func (suite *EvmTestSuite) SendTransaction(tx *ethtypes.Transaction) *ethtypes.Receipt { - err := suite.EthClient().SendTransaction(suite.ctx, tx) - suite.Require().NoError(err) - - ctx, cancel := context.WithTimeout(suite.ctx, 5*time.Second) - defer cancel() - receipt, err := bind.WaitMined(ctx, suite.EthClient(), tx) - suite.Require().NoError(err) - suite.Require().Equal(receipt.Status, ethtypes.ReceiptStatusSuccessful) - return receipt -} - -func (suite *EvmTestSuite) DeployContract(privKey cryptotypes.PrivKey, contractBin []byte) (common.Address, common.Hash) { - tx, err := client.BuildEthTransaction(suite.ctx, suite.EthClient(), privKey, nil, nil, contractBin) - suite.Require().NoError(err) - receipt := suite.SendTransaction(tx) - - suite.Require().False(contract.IsZeroEthAddress(receipt.ContractAddress)) - return receipt.ContractAddress, receipt.TxHash -} - -func (suite *EvmTestSuite) DeployProxy(privateKey cryptotypes.PrivKey, logic common.Address, initData []byte) common.Address { - erc1967Proxy := contract.GetERC1967Proxy() - input, err := erc1967Proxy.ABI.Pack("", logic, initData) - suite.Require().NoError(err) - tx, err := client.BuildEthTransaction(suite.ctx, suite.EthClient(), privateKey, nil, nil, append(erc1967Proxy.Bin, input...)) - suite.Require().NoError(err) - suite.SendTransaction(tx) - return crypto.CreateAddress(common.BytesToAddress(privateKey.PubKey().Address().Bytes()), tx.Nonce()) -} - -func (suite *EvmTestSuite) TxFee(hash common.Hash) *big.Int { - receipt, err := suite.EthClient().TransactionReceipt(suite.ctx, hash) - suite.Require().NoError(err) - - tx, pending, err := suite.EthClient().TransactionByHash(suite.ctx, hash) - suite.Require().NoError(err) - suite.Require().False(pending) - - block, err := suite.EthClient().BlockByNumber(suite.ctx, receipt.BlockNumber) - suite.Require().NoError(err) - baseFee := block.BaseFee() - - txData, err := evmtypes.NewTxDataFromTx(tx) - suite.Require().NoError(err) - effectiveGasPrice := txData.EffectiveGasPrice(baseFee) - return big.NewInt(0).Mul(effectiveGasPrice, big.NewInt(0).SetUint64(receipt.GasUsed)) -} - -func (suite *EvmTestSuite) DeployERC20Contract(privKey cryptotypes.PrivKey) common.Address { - fip20 := contract.GetFIP20() - tx, err := client.BuildEthTransaction(suite.ctx, suite.EthClient(), privKey, nil, nil, fip20.Bin) - suite.Require().NoError(err) - suite.SendTransaction(tx) - logic := crypto.CreateAddress(common.BytesToAddress(privKey.PubKey().Address().Bytes()), tx.Nonce()) - proxy := suite.DeployProxy(privKey, logic, []byte{}) - pack, err := fip20.ABI.Pack("initialize", "Test ERC20", helpers.NewRandSymbol(), uint8(18), common.BytesToAddress(authtypes.NewModuleAddress(erc20types.ModuleName).Bytes())) - suite.Require().NoError(err) - tx, err = client.BuildEthTransaction(suite.ctx, suite.EthClient(), privKey, &proxy, nil, pack) - suite.Require().NoError(err) - suite.SendTransaction(tx) - return proxy -} - -func GetERC721() contract.Contract { - return contract.Contract{ - ABI: contract.MustABIJson(testscontract.ERC721TokenTestMetaData.ABI), - Bin: contract.MustDecodeHex(testscontract.ERC721TokenTestMetaData.Bin), - } -} diff --git a/tests/evm_test.go b/tests/evm_test.go deleted file mode 100644 index 2a8d6467..00000000 --- a/tests/evm_test.go +++ /dev/null @@ -1,314 +0,0 @@ -package tests - -import ( - "bytes" - "fmt" - "math/big" - "reflect" - "strings" - - sdkmath "cosmossdk.io/math" - tmrand "github.com/cometbft/cometbft/libs/rand" - sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - evmtypes "github.com/evmos/ethermint/x/evm/types" - - "github.com/functionx/fx-core/v8/client" - "github.com/functionx/fx-core/v8/contract" - "github.com/functionx/fx-core/v8/testutil/helpers" - fxevmtypes "github.com/functionx/fx-core/v8/x/evm/types" -) - -func (suite *IntegrationTest) WFXTest() { - suite.Send(suite.evm.AccAddress(), suite.NewCoin(sdkmath.NewInt(100).MulRaw(1e18))) - wfx := contract.GetWFX() - tx, err := client.BuildEthTransaction(suite.ctx, suite.evm.EthClient(), suite.evm.privKey, nil, nil, wfx.Bin) - suite.Require().NoError(err) - suite.evm.SendTransaction(tx) - logic := crypto.CreateAddress(common.BytesToAddress(suite.evm.privKey.PubKey().Address().Bytes()), tx.Nonce()) - proxy := suite.evm.DeployProxy(suite.evm.privKey, logic, []byte{}) - pack, err := wfx.ABI.Pack("initialize", "Wrapped Function X", "WFX", uint8(18), common.BytesToAddress([]byte(evmtypes.ModuleName))) - suite.Require().NoError(err) - tx, err = client.BuildEthTransaction(suite.ctx, suite.evm.EthClient(), suite.evm.privKey, &proxy, nil, pack) - suite.Require().NoError(err) - suite.evm.SendTransaction(tx) - key := helpers.NewEthPrivKey() - suite.Send(key.PubKey().Address().Bytes(), suite.NewCoin(sdkmath.NewInt(100).MulRaw(1e18))) - suite.evm.WFXDeposit(key, proxy, new(big.Int).Mul(big.NewInt(tmrand.Int63n(19)+81), big.NewInt(1e18))) - suite.evm.WFXWithdraw(key, proxy, common.BytesToAddress(key.PubKey().Address().Bytes()), new(big.Int).Mul(big.NewInt(tmrand.Int63n(29)+1), big.NewInt(1e18))) - suite.evm.TransferERC20(key, proxy, helpers.GenHexAddress(), new(big.Int).Mul(big.NewInt(tmrand.Int63n(19)+1), big.NewInt(1e18))) - spenderKey := helpers.NewEthPrivKey() - suite.Send(spenderKey.PubKey().Address().Bytes(), suite.NewCoin(sdkmath.NewInt(100).MulRaw(1e18))) - suite.evm.ApproveERC20(key, proxy, common.BytesToAddress(spenderKey.PubKey().Address().Bytes()), new(big.Int).Mul(big.NewInt(tmrand.Int63n(10)+20), big.NewInt(1e18))) - suite.evm.TransferFromERC20(spenderKey, proxy, common.BytesToAddress(key.PubKey().Address().Bytes()), helpers.GenHexAddress(), new(big.Int).Mul(big.NewInt(tmrand.Int63n(19)+1), big.NewInt(1e18))) -} - -func (suite *IntegrationTest) ERC20TokenTest() { - suite.Send(suite.evm.AccAddress(), suite.NewCoin(sdkmath.NewInt(100).MulRaw(1e18))) - proxy := suite.evm.DeployERC20Contract(suite.evm.privKey) - - key := helpers.NewEthPrivKey() - suite.Send(key.PubKey().Address().Bytes(), suite.NewCoin(sdkmath.NewInt(100).MulRaw(1e18))) - suite.evm.MintERC20(suite.evm.privKey, proxy, common.BytesToAddress(key.PubKey().Address().Bytes()), new(big.Int).Mul(big.NewInt(100), big.NewInt(1e18))) - suite.evm.CheckBalanceOf(proxy, common.BytesToAddress(key.PubKey().Address().Bytes()), new(big.Int).Mul(big.NewInt(100), big.NewInt(1e18))) - - transferAmount := new(big.Int).Mul(big.NewInt(tmrand.Int63n(19)+1), big.NewInt(1e18)) - recipient := helpers.GenHexAddress() - - suite.evm.TransferERC20(key, proxy, recipient, transferAmount) - suite.evm.CheckBalanceOf(proxy, common.BytesToAddress(key.PubKey().Address().Bytes()), new(big.Int).Sub(new(big.Int).Mul(big.NewInt(100), big.NewInt(1e18)), transferAmount)) - suite.evm.CheckBalanceOf(proxy, recipient, transferAmount) - - spenderKey := helpers.NewEthPrivKey() - approveAmount := new(big.Int).Mul(big.NewInt(tmrand.Int63n(10)+20), big.NewInt(1e18)) - transferFromAmount := new(big.Int).Mul(big.NewInt(tmrand.Int63n(19)+1), big.NewInt(1e18)) - suite.Send(spenderKey.PubKey().Address().Bytes(), suite.NewCoin(sdkmath.NewInt(100).MulRaw(1e18))) - suite.evm.ApproveERC20(key, proxy, common.BytesToAddress(spenderKey.PubKey().Address().Bytes()), approveAmount) - suite.evm.CheckAllowance(proxy, common.BytesToAddress(key.PubKey().Address().Bytes()), common.BytesToAddress(spenderKey.PubKey().Address().Bytes()), approveAmount) - suite.evm.TransferFromERC20(spenderKey, proxy, common.BytesToAddress(key.PubKey().Address().Bytes()), helpers.GenHexAddress(), transferFromAmount) - suite.evm.CheckAllowance(proxy, common.BytesToAddress(key.PubKey().Address().Bytes()), common.BytesToAddress(spenderKey.PubKey().Address().Bytes()), new(big.Int).Sub(approveAmount, transferFromAmount)) -} - -func (suite *IntegrationTest) ERC721Test() { - suite.Send(suite.evm.AccAddress(), suite.NewCoin(sdkmath.NewInt(100).MulRaw(1e18))) - tx, err := client.BuildEthTransaction(suite.ctx, suite.evm.EthClient(), suite.evm.privKey, nil, nil, GetERC721().Bin) - suite.Require().NoError(err) - suite.evm.SendTransaction(tx) - logic := crypto.CreateAddress(common.BytesToAddress(suite.evm.privKey.PubKey().Address().Bytes()), tx.Nonce()) - proxy := suite.evm.DeployProxy(suite.evm.privKey, logic, []byte{}) - pack, err := GetERC721().ABI.Pack("initialize") - suite.Require().NoError(err) - tx, err = client.BuildEthTransaction(suite.ctx, suite.evm.EthClient(), suite.evm.privKey, &proxy, nil, pack) - suite.Require().NoError(err) - suite.evm.SendTransaction(tx) - - key := helpers.NewEthPrivKey() - suite.Send(key.PubKey().Address().Bytes(), suite.NewCoin(sdkmath.NewInt(100).MulRaw(1e18))) - suite.evm.SafeMintERC721(suite.evm.privKey, proxy, common.BytesToAddress(key.PubKey().Address().Bytes())) - suite.evm.CheckBalanceOfERC721(proxy, common.BytesToAddress(key.PubKey().Address().Bytes()), big.NewInt(1)) - approvekey := helpers.NewEthPrivKey() - suite.Send(approvekey.PubKey().Address().Bytes(), suite.NewCoin(sdkmath.NewInt(100).MulRaw(1e18))) - - suite.evm.ApproveERC721(key, proxy, common.BytesToAddress(approvekey.PubKey().Address().Bytes()), big.NewInt(0)) - suite.evm.SafeTransferFrom(approvekey, proxy, common.BytesToAddress(key.PubKey().Address().Bytes()), helpers.GenHexAddress(), big.NewInt(0)) - suite.evm.CheckBalanceOfERC721(proxy, common.BytesToAddress(key.PubKey().Address().Bytes()), big.NewInt(0)) - - suite.evm.SafeMintERC721(suite.evm.privKey, proxy, common.BytesToAddress(key.PubKey().Address().Bytes())) - suite.evm.CheckBalanceOfERC721(proxy, common.BytesToAddress(key.PubKey().Address().Bytes()), big.NewInt(1)) - suite.evm.SafeTransferFrom(key, proxy, common.BytesToAddress(key.PubKey().Address().Bytes()), helpers.GenHexAddress(), big.NewInt(1)) - suite.evm.CheckBalanceOfERC721(proxy, common.BytesToAddress(key.PubKey().Address().Bytes()), big.NewInt(0)) - - suite.evm.SafeMintERC721(suite.evm.privKey, proxy, common.BytesToAddress(key.PubKey().Address().Bytes())) - suite.evm.CheckBalanceOfERC721(proxy, common.BytesToAddress(key.PubKey().Address().Bytes()), big.NewInt(1)) - suite.evm.SetApprovalForAll(key, proxy, common.BytesToAddress(approvekey.PubKey().Address().Bytes()), true) - suite.True(suite.evm.IsApprovedForAll(proxy, common.BytesToAddress(key.PubKey().Address().Bytes()), common.BytesToAddress(approvekey.PubKey().Address().Bytes()))) - - suite.evm.SafeTransferFrom(key, proxy, common.BytesToAddress(key.PubKey().Address().Bytes()), helpers.GenHexAddress(), big.NewInt(2)) - suite.evm.CheckBalanceOfERC721(proxy, common.BytesToAddress(key.PubKey().Address().Bytes()), big.NewInt(0)) -} - -func (suite *IntegrationTest) EVMWeb3Test() { - suite.Send(suite.evm.AccAddress(), suite.NewCoin(sdkmath.NewInt(100).MulRaw(1e18))) - - tests := []struct { - name string - funcName string - params []interface{} - wantRes []interface{} - }{ - { - name: "eth_chainId", - funcName: "ChainID", - params: []interface{}{}, - wantRes: []interface{}{big.NewInt(530), nil}, - }, - { - name: "eth_getBlockByNumber", - funcName: "BlockByNumber", - params: []interface{}{big.NewInt(1)}, - wantRes: []interface{}{nil, nil}, - }, - { - name: "eth_getBlockByNumber latest", - funcName: "BlockByNumber", - params: []interface{}{nil}, - wantRes: []interface{}{nil, nil}, - }, - { - name: "eth_blockNumber", - funcName: "BlockNumber", - params: []interface{}{}, - wantRes: []interface{}{nil, nil}, - }, - { - name: "eth_getBlockByNumber", - funcName: "HeaderByNumber", - params: []interface{}{big.NewInt(1)}, - wantRes: []interface{}{nil, nil}, - }, - { - name: "eth_getBlockByNumber latest", - funcName: "HeaderByNumber", - params: []interface{}{nil}, - wantRes: []interface{}{nil, nil}, - }, - { - name: "eth_syncing", - funcName: "SyncProgress", - params: []interface{}{}, - wantRes: []interface{}{nil, nil}, - }, - { - name: "net_version", - funcName: "NetworkID", - params: []interface{}{}, - wantRes: []interface{}{big.NewInt(530), nil}, - }, - { - name: "eth_getBalance latest", - funcName: "BalanceAt", - params: []interface{}{suite.evm.HexAddress(), nil}, - wantRes: []interface{}{new(big.Int).Mul(big.NewInt(100), big.NewInt(1e18)), nil}, - }, - { - name: "eth_getBalance", - funcName: "BalanceAt", - params: []interface{}{suite.evm.HexAddress(), big.NewInt(1)}, - wantRes: []interface{}{big.NewInt(0), nil}, - }, - { - name: "eth_getStorageAt", - funcName: "StorageAt", - params: []interface{}{suite.evm.HexAddress(), common.Hash{}, nil}, - wantRes: []interface{}{[32]byte{}, nil}, - }, - { - name: "eth_getCode", - funcName: "CodeAt", - params: []interface{}{suite.evm.HexAddress(), nil}, - wantRes: []interface{}{[]byte{}, nil}, - }, - { - name: "eth_getTransactionCount", - funcName: "NonceAt", - params: []interface{}{suite.evm.HexAddress(), nil}, - wantRes: []interface{}{uint64(0), nil}, - }, - { - name: "eth_getBalance pending", - funcName: "PendingBalanceAt", - params: []interface{}{suite.evm.HexAddress()}, - wantRes: []interface{}{new(big.Int).Mul(big.NewInt(100), big.NewInt(1e18)), nil}, - }, - { - name: "eth_getStorageAt pending", - funcName: "PendingStorageAt", - params: []interface{}{suite.evm.HexAddress(), common.Hash{}}, - wantRes: []interface{}{[32]byte{}, nil}, - }, - { - name: "eth_getCode pending", - funcName: "PendingCodeAt", - params: []interface{}{suite.evm.HexAddress()}, - wantRes: []interface{}{[]byte{}, nil}, - }, - { - name: "eth_getTransactionCount pending", - funcName: "PendingNonceAt", - params: []interface{}{suite.evm.HexAddress()}, - wantRes: []interface{}{big.NewInt(0), nil}, - }, - { - name: "eth_getBlockTransactionCountByNumber pending", - funcName: "PendingTransactionCount", - params: []interface{}{}, - wantRes: []interface{}{uint64(0), nil}, - }, - { - name: "eth_gasPrice", - funcName: "SuggestGasPrice", - params: []interface{}{}, - wantRes: []interface{}{big.NewInt(562500000000), nil}, - }, - { - name: "eth_maxPriorityFeePerGas", - funcName: "SuggestGasTipCap", - params: []interface{}{}, - wantRes: []interface{}{big.NewInt(62500000000), nil}, - }, - } - ethClient := suite.evm.EthClient() - for _, tt := range tests { - suite.Run(tt.name, func() { - typeOf := reflect.TypeOf(ethClient) - method, is := typeOf.MethodByName(tt.funcName) - suite.True(is) - params := make([]reflect.Value, len(tt.params)+2) - params[0] = reflect.ValueOf(ethClient) - params[1] = reflect.ValueOf(suite.ctx) - for i := 2; i < len(params); i++ { - p := tt.params[i-2] - if p != nil { - params[i] = reflect.ValueOf(p) - } else { - params[i] = reflect.New(reflect.TypeOf(&big.Int{})).Elem() - } - } - results := method.Func.Call(params) - for i := 0; i < len(results); i++ { - if i == 0 && tt.wantRes[i] == nil { - continue - } - suite.EqualValues( - fmt.Sprintf("%v", tt.wantRes[i]), - fmt.Sprintf("%v", results[i]), - ) - } - }) - } -} - -func (suite *IntegrationTest) CallContractTest() { - suite.Send(suite.evm.AccAddress(), suite.NewCoin(sdkmath.NewInt(100).MulRaw(1e18))) - proxy := suite.evm.DeployERC20Contract(suite.evm.privKey) - - suite.evm.TransferOwnership(suite.evm.privKey, proxy, common.BytesToAddress(authtypes.NewModuleAddress(evmtypes.ModuleName))) - amount := new(big.Int).Exp(big.NewInt(10), big.NewInt(20), nil) - args, err := suite.evm.ERC20ABI.PackMint(suite.evm.HexAddress(), amount) - suite.Require().NoError(err) - response, proposalId := suite.BroadcastProposalTx2([]sdk.Msg{&fxevmtypes.MsgCallContract{ - Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(), - ContractAddress: proxy.String(), - Data: common.Bytes2Hex(args), - }}, "UpdateContractProposal", "UpdateContractProposal") - // suite.Require().EqualValues(amount, suite.evm.BalanceOf(proxy, suite.evm.HexAddress())) - suite.Require().EqualValues(response.Code, 0) - suite.Require().True(proposalId > 0) -} - -func (suite *IntegrationTest) FIP20CodeCheckTest() { - suite.Send(suite.evm.AccAddress(), suite.NewCoin(sdkmath.NewInt(100).MulRaw(1e18))) - fip20 := contract.GetFIP20() - fip20Addr, _ := suite.evm.DeployContract(suite.evm.privKey, fip20.Bin) - code, err := suite.evm.EthClient().CodeAt(suite.ctx, fip20Addr, nil) - suite.Require().NoError(err) - suite.Equal(fip20.Code, code, fmt.Sprintf("fip20 deployed code: %s", common.Bytes2Hex(code))) - - deployedCode := bytes.ReplaceAll(code, fip20.Address.Bytes(), common.Address{}.Bytes()) - suite.True(strings.HasSuffix(contract.FIP20UpgradableMetaData.Bin, common.Bytes2Hex(deployedCode))) -} - -func (suite *IntegrationTest) WFXCodeCheckTest() { - suite.Send(suite.evm.AccAddress(), suite.NewCoin(sdkmath.NewInt(100).MulRaw(1e18))) - wfx := contract.GetWFX() - wfxAddr, _ := suite.evm.DeployContract(suite.evm.privKey, wfx.Bin) - code, err := suite.evm.EthClient().CodeAt(suite.ctx, wfxAddr, nil) - suite.Require().NoError(err) - suite.Equal(wfx.Code, code, fmt.Sprintf("wfx deployed code: %s", common.Bytes2Hex(code))) - - deployedCode := bytes.ReplaceAll(code, wfx.Address.Bytes(), common.Address{}.Bytes()) - suite.True(strings.HasSuffix(contract.WFXUpgradableMetaData.Bin, common.Bytes2Hex(deployedCode))) -} diff --git a/tests/integration/ante_test.go b/tests/integration/ante_test.go new file mode 100644 index 00000000..6f9988f1 --- /dev/null +++ b/tests/integration/ante_test.go @@ -0,0 +1,28 @@ +package integration + +import ( + sdkmath "cosmossdk.io/math" + tmrand "github.com/cometbft/cometbft/libs/rand" + sdk "github.com/cosmos/cosmos-sdk/types" + distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types" + + "github.com/functionx/fx-core/v8/testutil/helpers" +) + +func (suite *IntegrationTest) ByPassFeeTest() { + userA := helpers.NewSigner(helpers.NewEthPrivKey()) + userAAddr := userA.AccAddress() + initBalance := suite.NewCoin(sdkmath.NewInt(100).MulRaw(1e18)) + txResponse := suite.Send(userAAddr, initBalance) + suite.Require().EqualValues(uint32(0), txResponse.Code) + + // zero gasPrices for bypassing fee check + zeroGasPrice := sdk.Coin{Amount: sdkmath.ZeroInt(), Denom: suite.defDenom} + for i := 0; i < tmrand.Intn(5); i++ { + suite.WithGasPrices(zeroGasPrice).BroadcastTx(userA, + distributiontypes.NewMsgSetWithdrawAddress(userAAddr, userAAddr)) + } + + // check balance + suite.EqualBalance(userAAddr, initBalance) +} diff --git a/tests/crosschain_suite.go b/tests/integration/crosschain_suite.go similarity index 58% rename from tests/crosschain_suite.go rename to tests/integration/crosschain_suite.go index d2461b2c..84872740 100644 --- a/tests/crosschain_suite.go +++ b/tests/integration/crosschain_suite.go @@ -1,4 +1,4 @@ -package tests +package integration import ( "crypto/ecdsa" @@ -7,7 +7,6 @@ import ( "strconv" sdkmath "cosmossdk.io/math" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -16,94 +15,81 @@ import ( ethtypes "github.com/ethereum/go-ethereum/core/types" ethcrypto "github.com/ethereum/go-ethereum/crypto" - "github.com/functionx/fx-core/v8/client" "github.com/functionx/fx-core/v8/contract" "github.com/functionx/fx-core/v8/testutil/helpers" fxtypes "github.com/functionx/fx-core/v8/types" - "github.com/functionx/fx-core/v8/x/crosschain/precompile" crosschaintypes "github.com/functionx/fx-core/v8/x/crosschain/types" trontypes "github.com/functionx/fx-core/v8/x/tron/types" ) -type CrosschainTestSuite struct { - EvmTestSuite - params crosschaintypes.Params - chainName string - oraclePrivKey cryptotypes.PrivKey - bridgerPrivKey cryptotypes.PrivKey - externalPrivKey *ecdsa.PrivateKey - privKey cryptotypes.PrivKey - executeClaimPrivKey cryptotypes.PrivKey +type CrosschainSuite struct { + *FxCoreSuite - crosschainAddr common.Address + chainName string + params crosschaintypes.Params + oracle *helpers.Signer + bridger *helpers.Signer + external *ecdsa.PrivateKey + + signer *helpers.Signer + + contractAddr common.Address + crosschain *contract.ICrosschain } -func NewCrosschainWithTestSuite(chainName string, ts *TestSuite) CrosschainTestSuite { +func NewCrosschainSuite(chainName string, suite *FxCoreSuite) *CrosschainSuite { externalPrivKey, err := ethcrypto.GenerateKey() - if err != nil { - panic(err.Error()) - } - return CrosschainTestSuite{ - EvmTestSuite: NewEvmTestSuite(ts), - chainName: chainName, - oraclePrivKey: helpers.NewPriKey(), - bridgerPrivKey: helpers.NewPriKey(), - externalPrivKey: externalPrivKey, - privKey: helpers.NewEthPrivKey(), - executeClaimPrivKey: helpers.NewEthPrivKey(), - crosschainAddr: common.HexToAddress(contract.CrosschainAddress), + suite.Require().NoError(err) + contractAddr := common.HexToAddress(contract.CrosschainAddress) + crosschain, err := contract.NewICrosschain(contractAddr, suite.ethCli) + suite.Require().NoError(err) + return &CrosschainSuite{ + FxCoreSuite: suite, + chainName: chainName, + oracle: helpers.NewSigner(helpers.NewEthPrivKey()), + bridger: helpers.NewSigner(helpers.NewEthPrivKey()), + external: externalPrivKey, + contractAddr: contractAddr, + crosschain: crosschain, } } -func (suite *CrosschainTestSuite) Init() { - suite.TestSuite.Send(suite.OracleAddr(), suite.NewCoin(sdkmath.NewInt(10_100).MulRaw(1e18))) - suite.TestSuite.Send(suite.BridgerAddr(), suite.NewCoin(sdkmath.NewInt(1_000).MulRaw(1e18))) - suite.TestSuite.Send(suite.AccAddress(), suite.NewCoin(sdkmath.NewInt(1_000).MulRaw(1e18))) - suite.TestSuite.Send(suite.ExecuteClaimAccAddress(), suite.NewCoin(sdkmath.NewInt(1_000).MulRaw(1e18))) +func (suite *CrosschainSuite) Init() { + suite.Send(suite.OracleAddr(), suite.NewCoin(sdkmath.NewInt(10_100).MulRaw(1e18))) + suite.Send(suite.BridgerAddr(), suite.NewCoin(sdkmath.NewInt(1_000).MulRaw(1e18))) + suite.Send(suite.signer.AccAddress(), suite.NewCoin(sdkmath.NewInt(1_000).MulRaw(1e18))) suite.params = suite.QueryParams() } -func (suite *CrosschainTestSuite) OracleAddr() sdk.AccAddress { - return suite.oraclePrivKey.PubKey().Address().Bytes() +func (suite *CrosschainSuite) OracleAddr() sdk.AccAddress { + return suite.oracle.AccAddress() } -func (suite *CrosschainTestSuite) ExternalAddr() string { - address := ethcrypto.PubkeyToAddress(suite.externalPrivKey.PublicKey) +func (suite *CrosschainSuite) ExternalAddr() string { + address := ethcrypto.PubkeyToAddress(suite.external.PublicKey) return crosschaintypes.ExternalAddrToStr(suite.chainName, address.Bytes()) } -func (suite *CrosschainTestSuite) BridgerAddr() sdk.AccAddress { - return suite.bridgerPrivKey.PubKey().Address().Bytes() -} - -func (suite *CrosschainTestSuite) AccAddress() sdk.AccAddress { - return suite.privKey.PubKey().Address().Bytes() -} - -func (suite *CrosschainTestSuite) ExecuteClaimAccAddress() sdk.AccAddress { - return suite.executeClaimPrivKey.PubKey().Address().Bytes() +func (suite *CrosschainSuite) BridgerAddr() sdk.AccAddress { + return suite.bridger.AccAddress() } -func (suite *CrosschainTestSuite) HexAddress() common.Address { - return common.BytesToAddress(suite.privKey.PubKey().Address()) +func (suite *CrosschainSuite) HexAddressString() string { + return crosschaintypes.ExternalAddrToStr(suite.chainName, suite.signer.Address().Bytes()) } -func (suite *CrosschainTestSuite) HexAddressString() string { - return crosschaintypes.ExternalAddrToStr(suite.chainName, suite.HexAddress().Bytes()) +func (suite *CrosschainSuite) CrosschainQuery() crosschaintypes.QueryClient { + return suite.grpcCli.CrosschainQuery() } -func (suite *CrosschainTestSuite) CrosschainQuery() crosschaintypes.QueryClient { - return suite.GRPCClient().CrosschainQuery() -} - -func (suite *CrosschainTestSuite) QueryParams() crosschaintypes.Params { +func (suite *CrosschainSuite) QueryParams() crosschaintypes.Params { response, err := suite.CrosschainQuery().Params(suite.ctx, &crosschaintypes.QueryParamsRequest{ChainName: suite.chainName}) suite.Require().NoError(err) return response.Params } -func (suite *CrosschainTestSuite) queryFxLastEventNonce() uint64 { +func (suite *CrosschainSuite) queryFxLastEventNonce() uint64 { lastEventNonce, err := suite.CrosschainQuery().LastEventNonceByAddr(suite.ctx, &crosschaintypes.QueryLastEventNonceByAddrRequest{ ChainName: suite.chainName, @@ -114,7 +100,7 @@ func (suite *CrosschainTestSuite) queryFxLastEventNonce() uint64 { return lastEventNonce.EventNonce + 1 } -func (suite *CrosschainTestSuite) queryObserverExternalBlockHeight() uint64 { +func (suite *CrosschainSuite) queryObserverExternalBlockHeight() uint64 { response, err := suite.CrosschainQuery().LastObservedBlockHeight(suite.ctx, &crosschaintypes.QueryLastObservedBlockHeightRequest{ ChainName: suite.chainName, @@ -124,7 +110,7 @@ func (suite *CrosschainTestSuite) queryObserverExternalBlockHeight() uint64 { return response.ExternalBlockHeight } -func (suite *CrosschainTestSuite) AddBridgeTokenClaim(name, symbol string, decimals uint64, token, channelIBCHex string) string { +func (suite *CrosschainSuite) AddBridgeTokenClaim(name, symbol string, decimals uint64, token string) string { response, err := suite.CrosschainQuery().TokenToDenom(suite.ctx, &crosschaintypes.QueryTokenToDenomRequest{ ChainName: suite.chainName, Token: token, @@ -132,7 +118,7 @@ func (suite *CrosschainTestSuite) AddBridgeTokenClaim(name, symbol string, decim suite.ErrorContains(err, "code = NotFound desc = bridge token") suite.Nil(response) - suite.BroadcastTx(suite.bridgerPrivKey, &crosschaintypes.MsgBridgeTokenClaim{ + suite.BroadcastTx(suite.bridger, &crosschaintypes.MsgBridgeTokenClaim{ EventNonce: suite.queryFxLastEventNonce(), BlockHeight: suite.queryObserverExternalBlockHeight() + 1, TokenContract: token, @@ -140,7 +126,6 @@ func (suite *CrosschainTestSuite) AddBridgeTokenClaim(name, symbol string, decim Symbol: symbol, Decimals: decimals, BridgerAddress: suite.BridgerAddr().String(), - ChannelIbc: channelIBCHex, ChainName: suite.chainName, }) @@ -156,7 +141,7 @@ func (suite *CrosschainTestSuite) AddBridgeTokenClaim(name, symbol string, decim return response.Denom } -func (suite *CrosschainTestSuite) GetBridgeTokens() (denoms []*crosschaintypes.BridgeToken) { +func (suite *CrosschainSuite) GetBridgeTokens() (denoms []*crosschaintypes.BridgeToken) { response, err := suite.CrosschainQuery().BridgeTokens(suite.ctx, &crosschaintypes.QueryBridgeTokensRequest{ ChainName: suite.chainName, }) @@ -164,7 +149,7 @@ func (suite *CrosschainTestSuite) GetBridgeTokens() (denoms []*crosschaintypes.B return response.BridgeTokens } -func (suite *CrosschainTestSuite) GetBridgeDenomByToken(token string) (denom string) { +func (suite *CrosschainSuite) GetBridgeDenomByToken(token string) (denom string) { response, err := suite.CrosschainQuery().TokenToDenom(suite.ctx, &crosschaintypes.QueryTokenToDenomRequest{ ChainName: suite.chainName, Token: token, @@ -174,7 +159,7 @@ func (suite *CrosschainTestSuite) GetBridgeDenomByToken(token string) (denom str return response.Denom } -func (suite *CrosschainTestSuite) GetBridgeTokenByDenom(denom string) (token string) { +func (suite *CrosschainSuite) GetBridgeTokenByDenom(denom string) (token string) { response, err := suite.CrosschainQuery().DenomToToken(suite.ctx, &crosschaintypes.QueryDenomToTokenRequest{ ChainName: suite.chainName, Denom: denom, @@ -184,13 +169,7 @@ func (suite *CrosschainTestSuite) GetBridgeTokenByDenom(denom string) (token str return response.Token } -func (suite *CrosschainTestSuite) Send(toAddress sdk.AccAddress, amount ...sdk.Coin) *sdk.TxResponse { - txResponse := suite.BroadcastTx(suite.privKey, banktypes.NewMsgSend(suite.privKey.PubKey().Address().Bytes(), toAddress, amount)) - suite.True(txResponse.GasUsed < 100_000, txResponse.GasUsed) - return txResponse -} - -func (suite *CrosschainTestSuite) BondedOracle() { +func (suite *CrosschainSuite) BondedOracle() { response, err := suite.CrosschainQuery().GetOracleByBridgerAddr(suite.ctx, &crosschaintypes.QueryOracleByBridgerAddrRequest{ BridgerAddress: suite.BridgerAddr().String(), @@ -200,11 +179,11 @@ func (suite *CrosschainTestSuite) BondedOracle() { suite.Require().Error(err, crosschaintypes.ErrNoFoundOracle) suite.Nil(response) - txResponse := suite.BroadcastTx(suite.oraclePrivKey, &crosschaintypes.MsgBondedOracle{ + txResponse := suite.BroadcastTx(suite.oracle, &crosschaintypes.MsgBondedOracle{ OracleAddress: suite.OracleAddr().String(), BridgerAddress: suite.BridgerAddr().String(), ExternalAddress: suite.ExternalAddr(), - ValidatorAddress: suite.GetFirstValAddr().String(), + ValidatorAddress: suite.GetValAddr().String(), DelegateAmount: suite.params.DelegateThreshold, ChainName: suite.chainName, }) @@ -223,21 +202,21 @@ func (suite *CrosschainTestSuite) BondedOracle() { DelegateAmount: suite.params.DelegateThreshold.Amount, StartHeight: txResponse.Height, Online: true, - DelegateValidator: suite.GetFirstValAddr().String(), + DelegateValidator: suite.GetValAddr().String(), SlashTimes: 0, }, *response.Oracle) } -func (suite *CrosschainTestSuite) SendUpdateChainOraclesProposal() (*sdk.TxResponse, uint64) { +func (suite *CrosschainSuite) SendUpdateChainOraclesProposal() (*sdk.TxResponse, uint64) { msg := &crosschaintypes.MsgUpdateChainOracles{ Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(), Oracles: []string{suite.OracleAddr().String()}, ChainName: suite.chainName, } - return suite.BroadcastProposalTx2([]sdk.Msg{msg}, "UpdateChainOraclesProposal", "UpdateChainOraclesProposal") + return suite.BroadcastProposalTxV1(msg) } -func (suite *CrosschainTestSuite) SendOracleSetConfirm() { +func (suite *CrosschainSuite) SendOracleSetConfirm() { queryResponse, err := suite.CrosschainQuery().LastPendingOracleSetRequestByAddr(suite.ctx, &crosschaintypes.QueryLastPendingOracleSetRequestByAddrRequest{ BridgerAddress: suite.BridgerAddr().String(), @@ -252,20 +231,20 @@ func (suite *CrosschainTestSuite) SendOracleSetConfirm() { if suite.chainName == trontypes.ModuleName { checkpoint, err := trontypes.GetCheckpointOracleSet(oracleSet, suite.params.GravityId) suite.Require().NoError(err) - signature, err = trontypes.NewTronSignature(checkpoint, suite.externalPrivKey) + signature, err = trontypes.NewTronSignature(checkpoint, suite.external) suite.Require().NoError(err) err = trontypes.ValidateTronSignature(checkpoint, signature, suite.ExternalAddr()) suite.Require().NoError(err) } else { checkpoint, err := oracleSet.GetCheckpoint(suite.params.GravityId) suite.Require().NoError(err) - signature, err = crosschaintypes.NewEthereumSignature(checkpoint, suite.externalPrivKey) + signature, err = crosschaintypes.NewEthereumSignature(checkpoint, suite.external) suite.Require().NoError(err) err = crosschaintypes.ValidateEthereumSignature(checkpoint, signature, suite.ExternalAddr()) suite.Require().NoError(err) } - suite.BroadcastTx(suite.bridgerPrivKey, &crosschaintypes.MsgOracleSetConfirm{ + suite.BroadcastTx(suite.bridger, &crosschaintypes.MsgOracleSetConfirm{ Nonce: oracleSet.Nonce, BridgerAddress: suite.BridgerAddr().String(), ExternalAddress: suite.ExternalAddr(), @@ -275,12 +254,8 @@ func (suite *CrosschainTestSuite) SendOracleSetConfirm() { } } -func (suite *CrosschainTestSuite) SendToFxClaim(token string, amount sdkmath.Int, targetIbc string) { - suite.SendToTxClaimWithReceiver(suite.AccAddress(), token, amount, targetIbc) -} - -func (suite *CrosschainTestSuite) BridgeCallClaim(to string, tokens []string, amounts []sdkmath.Int) { - suite.BroadcastTx(suite.bridgerPrivKey, &crosschaintypes.MsgBridgeCallClaim{ +func (suite *CrosschainSuite) BridgeCallClaim(to string, tokens []string, amounts []sdkmath.Int) { + suite.BroadcastTx(suite.bridger, &crosschaintypes.MsgBridgeCallClaim{ ChainName: suite.chainName, Sender: suite.HexAddressString(), Refund: suite.HexAddressString(), @@ -296,15 +271,16 @@ func (suite *CrosschainTestSuite) BridgeCallClaim(to string, tokens []string, am suite.ExecuteClaim() } -func (suite *CrosschainTestSuite) SendToTxClaimWithReceiver(receiver sdk.AccAddress, token string, amount sdkmath.Int, targetIbc string) { - suite.BroadcastTx(suite.bridgerPrivKey, &crosschaintypes.MsgSendToFxClaim{ +func (suite *CrosschainSuite) SendToFxClaim(receiver sdk.AccAddress, token string, amount sdkmath.Int) { + beforeBalance := suite.GetAllBalances(suite.signer.AccAddress()) + + suite.BroadcastTx(suite.bridger, &crosschaintypes.MsgSendToFxClaim{ EventNonce: suite.queryFxLastEventNonce(), BlockHeight: suite.queryObserverExternalBlockHeight() + 1, TokenContract: token, Amount: amount, Sender: suite.HexAddressString(), Receiver: receiver.String(), - TargetIbc: hex.EncodeToString([]byte(targetIbc)), BridgerAddress: suite.BridgerAddr().String(), ChainName: suite.chainName, }) @@ -314,34 +290,27 @@ func (suite *CrosschainTestSuite) SendToTxClaimWithReceiver(receiver sdk.AccAddr Token: token, }) suite.Require().NoError(err) - if bridgeToken.Denom == fxtypes.DefaultDenom && len(targetIbc) == 0 { - balances := suite.QueryBalances(receiver) - suite.True(balances.IsAllGTE(sdk.NewCoins(sdk.NewCoin(bridgeToken.Denom, amount)))) - } -} - -func (suite *CrosschainTestSuite) SendToFxClaimAndCheckBalance(token string, amount sdkmath.Int, targetIbc string, addCoins ...sdk.Coin) { - balance := suite.QueryBalances(suite.AccAddress()) - suite.SendToFxClaim(token, amount, targetIbc) - newBalance := suite.QueryBalances(suite.AccAddress()) - for _, coin := range addCoins { - balance = balance.Add(coin) + if bridgeToken.Denom == fxtypes.DefaultDenom { + balances := suite.GetAllBalances(receiver) + suite.Require().Equal(beforeBalance.Add(sdk.NewCoin(fxtypes.DefaultDenom, amount)), balances) + } else { + afterBalance := suite.GetAllBalances(suite.signer.AccAddress()) + suite.Equal(afterBalance, beforeBalance) } - suite.Equal(balance, newBalance) } -func (suite *CrosschainTestSuite) SendToExternalAndResponse(count int, amount sdk.Coin) (*sdk.TxResponse, uint64) { +func (suite *CrosschainSuite) SendToExternal(count int, amount sdk.Coin) (*sdk.TxResponse, uint64) { msgList := make([]sdk.Msg, 0, count) for i := 0; i < count; i++ { msgList = append(msgList, &crosschaintypes.MsgSendToExternal{ - Sender: suite.AccAddress().String(), + Sender: suite.signer.AccAddress().String(), Dest: suite.HexAddressString(), Amount: amount.SubAmount(sdkmath.NewInt(1)), BridgeFee: sdk.NewCoin(amount.Denom, sdkmath.NewInt(1)), ChainName: suite.chainName, }) } - txResponse := suite.BroadcastTx(suite.privKey, msgList...) + txResponse := suite.BroadcastTx(suite.signer, msgList...) for _, eventLog := range txResponse.Logs { for _, event := range eventLog.Events { if event.Type != crosschaintypes.EventTypeSendToExternal { @@ -361,44 +330,27 @@ func (suite *CrosschainTestSuite) SendToExternalAndResponse(count int, amount sd return txResponse, 0 } -func (suite *CrosschainTestSuite) SendToExternal(count int, amount sdk.Coin) uint64 { - _, txId := suite.SendToExternalAndResponse(count, amount) - return txId -} +func (suite *CrosschainSuite) SendToExternalAndCancel(coin sdk.Coin) { + balBefore := suite.GetAllBalances(suite.signer.AccAddress()) -func (suite *CrosschainTestSuite) SendToExternalAndCheckBalance(coin sdk.Coin) { - balance := suite.QueryBalances(suite.AccAddress()) - txRsp, txId1 := suite.SendToExternalAndResponse(1, coin) - suite.Greater(txId1, uint64(0)) - gasPrice, err := sdk.ParseCoinNormalized(suite.network.Config.MinGasPrices) - suite.Require().NoError(err) - gasFee := gasPrice.Amount.Mul(sdkmath.NewInt(txRsp.GasWanted)) - newBalance := suite.QueryBalances(suite.AccAddress()) - coins := sdk.NewCoins(coin).Add(sdk.NewCoin(fxtypes.DefaultDenom, gasFee)) - suite.Equal(balance, newBalance.Add(coins...)) -} - -func (suite *CrosschainTestSuite) SendToExternalAndCancel(coin sdk.Coin) { - balBefore := suite.QueryBalances(suite.AccAddress()) - - txId := suite.SendToExternal(1, coin) + _, txId := suite.SendToExternal(1, coin) suite.Greater(txId, uint64(0)) suite.SendCancelSendToExternal(txId) - balAfter := suite.QueryBalances(suite.AccAddress()) + balAfter := suite.GetAllBalances(suite.signer.AccAddress()) suite.Equal(balBefore.AmountOf(coin.Denom), balAfter.AmountOf(coin.Denom)) } -func (suite *CrosschainTestSuite) SendCancelSendToExternal(txId uint64) { - suite.BroadcastTx(suite.privKey, &crosschaintypes.MsgCancelSendToExternal{ +func (suite *CrosschainSuite) SendCancelSendToExternal(txId uint64) { + suite.BroadcastTx(suite.signer, &crosschaintypes.MsgCancelSendToExternal{ TransactionId: txId, - Sender: suite.AccAddress().String(), + Sender: suite.signer.AccAddress().String(), ChainName: suite.chainName, }) } -func (suite *CrosschainTestSuite) SendConfirmBatch() { +func (suite *CrosschainSuite) SendConfirmBatch() { response, err := suite.CrosschainQuery().LastPendingBatchRequestByAddr( suite.ctx, &crosschaintypes.QueryLastPendingBatchRequestByAddrRequest{ @@ -419,7 +371,7 @@ func (suite *CrosschainTestSuite) SendConfirmBatch() { suite.Require().NoError(err) signatureBytes := suite.SignatureCheckpoint(checkpoint) - suite.BroadcastTx(suite.bridgerPrivKey, + suite.BroadcastTx(suite.bridger, &crosschaintypes.MsgConfirmBatch{ Nonce: outgoingTxBatch.BatchNonce, TokenContract: outgoingTxBatch.TokenContract, @@ -439,14 +391,14 @@ func (suite *CrosschainTestSuite) SendConfirmBatch() { ) } -func (suite *CrosschainTestSuite) SendToExternalAndConfirm(coin sdk.Coin) { +func (suite *CrosschainSuite) SendToExternalAndConfirm(coin sdk.Coin) { suite.SendToExternal(1, coin) suite.SendConfirmBatch() } -func (suite *CrosschainTestSuite) AddBridgeToken(md banktypes.Metadata) (string, crosschaintypes.BridgeToken) { +func (suite *CrosschainSuite) AddBridgeToken(md banktypes.Metadata) (string, crosschaintypes.BridgeToken) { bridgeTokenAddr := helpers.GenExternalAddr(suite.chainName) - suite.AddBridgeTokenClaim(md.Name, md.Symbol, uint64(md.DenomUnits[1].Exponent), bridgeTokenAddr, "") + suite.AddBridgeTokenClaim(md.Name, md.Symbol, uint64(md.DenomUnits[1].Exponent), bridgeTokenAddr) bridgeTokenDenom := suite.GetBridgeDenomByToken(bridgeTokenAddr) return bridgeTokenDenom, crosschaintypes.BridgeToken{ Token: bridgeTokenAddr, @@ -454,11 +406,11 @@ func (suite *CrosschainTestSuite) AddBridgeToken(md banktypes.Metadata) (string, } } -func (suite *CrosschainTestSuite) FormatAddress(address common.Address) string { +func (suite *CrosschainSuite) FormatAddress(address common.Address) string { return crosschaintypes.ExternalAddrToStr(suite.chainName, address.Bytes()) } -func (suite *CrosschainTestSuite) BridgeCallConfirm(nonce uint64, isSuccess bool) { +func (suite *CrosschainSuite) BridgeCallConfirm(nonce uint64, isSuccess bool) { bridgeCall := suite.QueryBridgeCallByNonce(nonce) var checkpoint []byte var err error @@ -470,7 +422,7 @@ func (suite *CrosschainTestSuite) BridgeCallConfirm(nonce uint64, isSuccess bool suite.Require().NoError(err) signatureBytes := suite.SignatureCheckpoint(checkpoint) - suite.BroadcastTx(suite.bridgerPrivKey, + suite.BroadcastTx(suite.bridger, &crosschaintypes.MsgBridgeCallConfirm{ Nonce: nonce, BridgerAddress: suite.BridgerAddr().String(), @@ -479,7 +431,7 @@ func (suite *CrosschainTestSuite) BridgeCallConfirm(nonce uint64, isSuccess bool ChainName: suite.chainName, }, ) - suite.BroadcastTx(suite.bridgerPrivKey, + suite.BroadcastTx(suite.bridger, &crosschaintypes.MsgBridgeCallResultClaim{ ChainName: suite.chainName, BridgerAddress: suite.BridgerAddr().String(), @@ -494,22 +446,22 @@ func (suite *CrosschainTestSuite) BridgeCallConfirm(nonce uint64, isSuccess bool suite.ExecuteClaim() } -func (suite *CrosschainTestSuite) SignatureCheckpoint(checkpoint []byte) []byte { +func (suite *CrosschainSuite) SignatureCheckpoint(checkpoint []byte) []byte { var signatureBytes []byte var err error if suite.chainName == trontypes.ModuleName { - signatureBytes, err = trontypes.NewTronSignature(checkpoint, suite.externalPrivKey) + signatureBytes, err = trontypes.NewTronSignature(checkpoint, suite.external) suite.Require().NoError(err) suite.Require().NoError(trontypes.ValidateTronSignature(checkpoint, signatureBytes, suite.ExternalAddr())) } else { - signatureBytes, err = crosschaintypes.NewEthereumSignature(checkpoint, suite.externalPrivKey) + signatureBytes, err = crosschaintypes.NewEthereumSignature(checkpoint, suite.external) suite.Require().NoError(err) suite.Require().NoError(crosschaintypes.ValidateEthereumSignature(checkpoint, signatureBytes, suite.ExternalAddr())) } return signatureBytes } -func (suite *CrosschainTestSuite) QueryBridgeCallByNonce(nonce uint64) *crosschaintypes.OutgoingBridgeCall { +func (suite *CrosschainSuite) QueryBridgeCallByNonce(nonce uint64) *crosschaintypes.OutgoingBridgeCall { response, err := suite.CrosschainQuery().BridgeCallByNonce(suite.ctx, &crosschaintypes.QueryBridgeCallByNonceRequest{ ChainName: suite.chainName, Nonce: nonce, @@ -518,24 +470,19 @@ func (suite *CrosschainTestSuite) QueryBridgeCallByNonce(nonce uint64) *crosscha return response.GetBridgeCall() } -func (suite *CrosschainTestSuite) ExecuteClaim() *ethtypes.Transaction { +func (suite *CrosschainSuite) ExecuteClaim() *ethtypes.Transaction { externalClaims := suite.PendingExecuteClaim() suite.Require().True(len(externalClaims) > 0) - pack, err := precompile.NewExecuteClaimMethod(nil).PackInput(contract.ExecuteClaimArgs{ - Chain: suite.chainName, - EventNonce: new(big.Int).SetUint64(externalClaims[0].GetEventNonce()), - }) + ethTx, err := suite.crosschain.ExecuteClaim(suite.TransactOpts(suite.signer), + suite.chainName, new(big.Int).SetUint64(externalClaims[0].GetEventNonce())) suite.Require().NoError(err) + suite.WaitMined(ethTx) - ethTx, err := client.BuildEthTransaction(suite.ctx, suite.EthClient(), suite.executeClaimPrivKey, &suite.crosschainAddr, nil, pack) - suite.Require().NoError(err) - - suite.SendTransaction(ethTx) return ethTx } -func (suite *CrosschainTestSuite) PendingExecuteClaim() []crosschaintypes.ExternalClaim { +func (suite *CrosschainSuite) PendingExecuteClaim() []crosschaintypes.ExternalClaim { response, err := suite.CrosschainQuery().PendingExecuteClaim(suite.ctx, &crosschaintypes.QueryPendingExecuteClaimRequest{ ChainName: suite.chainName, }) @@ -543,14 +490,14 @@ func (suite *CrosschainTestSuite) PendingExecuteClaim() []crosschaintypes.Extern externalClaims := make([]crosschaintypes.ExternalClaim, 0, len(response.Claims)) for _, claim := range response.Claims { var externalClaim crosschaintypes.ExternalClaim - err = suite.network.Config.Codec.UnpackAny(claim, &externalClaim) + err = suite.codec.UnpackAny(claim, &externalClaim) suite.Require().NoError(err) externalClaims = append(externalClaims, externalClaim) } return externalClaims } -func (suite *CrosschainTestSuite) UpdateParams(opts ...func(params *crosschaintypes.Params)) (*sdk.TxResponse, uint64) { +func (suite *CrosschainSuite) UpdateParams(opts ...func(params *crosschaintypes.Params)) (*sdk.TxResponse, uint64) { params := suite.QueryParams() for _, opt := range opts { opt(¶ms) @@ -561,28 +508,21 @@ func (suite *CrosschainTestSuite) UpdateParams(opts ...func(params *crosschainty Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(), Params: params, } - return suite.BroadcastProposalTx2([]sdk.Msg{msg}, "UpdateParams", "UpdateParams") -} - -func (suite *CrosschainTestSuite) Crosschain(token common.Address, recipient string, amount, fee *big.Int, target string) *ethtypes.Transaction { - privateKey := suite.privKey - crosschainContract := suite.crosschainAddr - suite.ApproveERC20(privateKey, token, crosschainContract, big.NewInt(0).Add(amount, fee)) - - beforeBalanceOf := suite.BalanceOf(token, common.BytesToAddress(privateKey.PubKey().Address().Bytes())) - pack, err := precompile.NewCrosschainMethod(nil).PackInput(contract.CrosschainArgs{ - Token: token, - Receipt: recipient, - Amount: amount, - Fee: fee, - Target: fxtypes.MustStrToByte32(target), - Memo: "", - }) + return suite.BroadcastProposalTxV1(msg) +} + +func (suite *CrosschainSuite) Crosschain(token common.Address, recipient string, amount, fee *big.Int, target string) *ethtypes.Transaction { + erc20TokenSuite := NewERC20TokenSuite(suite.EthSuite, token, suite.signer) + + erc20TokenSuite.Approve(suite.contractAddr, big.NewInt(0).Add(amount, fee)) + + beforeBalanceOf := erc20TokenSuite.BalanceOf(suite.signer.Address()) + + ethTx, err := suite.crosschain.CrossChain(suite.TransactOpts(suite.signer), token, recipient, amount, fee, fxtypes.MustStrToByte32(target), "") suite.Require().NoError(err) - ethTx, err := client.BuildEthTransaction(suite.ctx, suite.EthClient(), privateKey, &crosschainContract, nil, pack) - suite.Require().NoError(err, target) - suite.SendTransaction(ethTx) - afterBalanceOf := suite.BalanceOf(token, common.BytesToAddress(privateKey.PubKey().Address().Bytes())) + suite.WaitMined(ethTx) + + afterBalanceOf := erc20TokenSuite.BalanceOf(suite.signer.Address()) suite.Require().True(new(big.Int).Sub(beforeBalanceOf, afterBalanceOf).Cmp(new(big.Int).Add(amount, fee)) == 0) return ethTx } diff --git a/tests/integration/crosschain_test.go b/tests/integration/crosschain_test.go new file mode 100644 index 00000000..3426c76c --- /dev/null +++ b/tests/integration/crosschain_test.go @@ -0,0 +1,21 @@ +package integration + +import ( + crosschaintypes "github.com/functionx/fx-core/v8/x/crosschain/types" +) + +func (suite *IntegrationTest) CrosschainTest() { + suite.updateParamsTest() +} + +func (suite *IntegrationTest) updateParamsTest() { + chains := crosschaintypes.GetSupportChains() + for _, chain := range chains { + crosschainSuite := NewCrosschainSuite(chain, suite.FxCoreSuite) + crosschainSuite.UpdateParams(func(params *crosschaintypes.Params) { + params.DelegateMultiple = 100 + }) + params := crosschainSuite.QueryParams() + suite.Require().Equal(params.DelegateMultiple, int64(100)) + } +} diff --git a/tests/integration/erc20_token_suite.go b/tests/integration/erc20_token_suite.go new file mode 100644 index 00000000..ccae11c3 --- /dev/null +++ b/tests/integration/erc20_token_suite.go @@ -0,0 +1,183 @@ +package integration + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + + "github.com/functionx/fx-core/v8/contract" + "github.com/functionx/fx-core/v8/testutil/helpers" +) + +type ERC20TokenSuite struct { + *EthSuite + + erc20Token *contract.WFXUpgradable + signer *helpers.Signer +} + +func NewERC20TokenSuite(suite *EthSuite, token common.Address, signer *helpers.Signer) *ERC20TokenSuite { + erc20Token, err := contract.NewWFXUpgradable(token, suite.ethCli) + suite.Require().NoError(err) + return &ERC20TokenSuite{ + EthSuite: suite, + erc20Token: erc20Token, + signer: signer, + } +} + +func (suite *ERC20TokenSuite) WithSigner(signer *helpers.Signer) *ERC20TokenSuite { + return &ERC20TokenSuite{ + EthSuite: suite.EthSuite, + erc20Token: suite.erc20Token, + signer: signer, + } +} + +func (suite *ERC20TokenSuite) Symbol() string { + symbol, err := suite.erc20Token.Symbol(nil) + suite.Require().NoError(err) + return symbol +} + +func (suite *ERC20TokenSuite) Name() string { + name, err := suite.erc20Token.Name(nil) + suite.Require().NoError(err) + return name +} + +func (suite *ERC20TokenSuite) Decimals() uint8 { + decimals, err := suite.erc20Token.Decimals(nil) + suite.Require().NoError(err) + return decimals +} + +func (suite *ERC20TokenSuite) BalanceOf(account common.Address) *big.Int { + balance, err := suite.erc20Token.BalanceOf(nil, account) + suite.Require().NoError(err) + return balance +} + +func (suite *ERC20TokenSuite) EqualBalanceOf(address common.Address, balance *big.Int) { + balAfter := suite.BalanceOf(address) + suite.Require().Equal(balAfter.String(), balance.String()) +} + +func (suite *ERC20TokenSuite) CheckBalance(address common.Address, addValue *big.Int, f func()) { + value := suite.BalanceOf(address) + f() + newValue := suite.BalanceOf(address) + suite.Require().Equal(big.NewInt(0).Add(value, addValue).String(), newValue.String()) +} + +func (suite *ERC20TokenSuite) TotalSupply() *big.Int { + totalSupply, err := suite.erc20Token.TotalSupply(nil) + suite.Require().NoError(err) + return totalSupply +} + +func (suite *ERC20TokenSuite) Allowance(owner, spender common.Address) *big.Int { + allowance, err := suite.erc20Token.Allowance(nil, owner, spender) + suite.Require().NoError(err) + return allowance +} + +func (suite *ERC20TokenSuite) EqualAllowance(owner, spender common.Address, value *big.Int) { + suite.Require().Equal(suite.Allowance(owner, spender).Cmp(value), 0) +} + +func (suite *ERC20TokenSuite) Owner() common.Address { + owner, err := suite.erc20Token.Owner(nil) + suite.Require().NoError(err) + return owner +} + +func (suite *ERC20TokenSuite) Deposit(value *big.Int) *ethtypes.Transaction { + suite.Require().True(suite.Balance(suite.signer.Address()).Cmp(value) >= 0) + + opts := suite.TransactOpts(suite.signer) + opts.Value = value + ethTx, err := suite.erc20Token.Deposit(opts) + suite.Require().NoError(err) + suite.WaitMined(ethTx) + + suite.Require().True(suite.BalanceOf(suite.signer.Address()).Cmp(value) >= 0) + suite.Require().True(suite.TotalSupply().Cmp(value) >= 0) + return ethTx +} + +func (suite *ERC20TokenSuite) Withdraw(recipient common.Address, value *big.Int) *ethtypes.Transaction { + suite.Require().True(suite.TotalSupply().Cmp(value) >= 0) + suite.Require().True(suite.BalanceOf(suite.signer.Address()).Cmp(value) >= 0) + + ethTx, err := suite.erc20Token.Withdraw0(suite.TransactOpts(suite.signer), recipient, value) + suite.Require().NoError(err) + suite.WaitMined(ethTx) + + suite.Require().True(suite.Balance(recipient).Cmp(value) >= 0) + return ethTx +} + +func (suite *ERC20TokenSuite) Transfer(recipient common.Address, value *big.Int) *ethtypes.Transaction { + suite.Require().True(suite.BalanceOf(suite.signer.Address()).Cmp(value) >= 0) + + ethTx, err := suite.erc20Token.Transfer(suite.TransactOpts(suite.signer), recipient, value) + suite.Require().NoError(err) + suite.WaitMined(ethTx) + + suite.Require().True(suite.BalanceOf(recipient).Cmp(value) >= 0) + return ethTx +} + +func (suite *ERC20TokenSuite) Approve(spender common.Address, value *big.Int) *ethtypes.Transaction { + ethTx, err := suite.erc20Token.Approve(suite.TransactOpts(suite.signer), spender, value) + suite.Require().NoError(err) + suite.WaitMined(ethTx) + + suite.Require().True(suite.Allowance(suite.signer.Address(), spender).Cmp(value) >= 0) + return ethTx +} + +func (suite *ERC20TokenSuite) TransferOwnership(newOwner common.Address) *ethtypes.Transaction { + ethTx, err := suite.erc20Token.TransferOwnership(suite.TransactOpts(suite.signer), newOwner) + suite.Require().NoError(err) + suite.WaitMined(ethTx) + + suite.Require().Equal(suite.Owner().String(), newOwner.String()) + return ethTx +} + +func (suite *ERC20TokenSuite) TransferFrom(sender, recipient common.Address, value *big.Int) *ethtypes.Transaction { + ethTx, err := suite.erc20Token.TransferFrom(suite.TransactOpts(suite.signer), sender, recipient, value) + suite.Require().NoError(err) + suite.WaitMined(ethTx) + + suite.Require().True(suite.BalanceOf(recipient).Cmp(value) >= 0) + return ethTx +} + +func (suite *ERC20TokenSuite) Mint(account common.Address, value *big.Int) *ethtypes.Transaction { + ethTx, err := suite.erc20Token.Mint(suite.TransactOpts(suite.signer), account, value) + suite.Require().NoError(err) + suite.WaitMined(ethTx) + + suite.Require().True(suite.BalanceOf(account).Cmp(value) >= 0) + suite.Require().True(suite.TotalSupply().Cmp(value) >= 0) + return ethTx +} + +func (suite *ERC20TokenSuite) Burn(account common.Address, value *big.Int) *ethtypes.Transaction { + beforeBalance := suite.BalanceOf(account) + suite.Require().True(beforeBalance.Cmp(value) >= 0) + beforeTotalSupply := suite.TotalSupply() + suite.Require().True(beforeTotalSupply.Cmp(value) >= 0) + + ethTx, err := suite.erc20Token.Burn(suite.TransactOpts(suite.signer), account, value) + suite.Require().NoError(err) + suite.WaitMined(ethTx) + + suite.Require().True(new(big.Int).Sub(beforeBalance, suite.BalanceOf(account)).Cmp(value) == 0) + suite.Require().True(new(big.Int).Sub(beforeTotalSupply, suite.TotalSupply()).Cmp(value) == 0) + return ethTx +} diff --git a/tests/integration/erc721_token_suite.go b/tests/integration/erc721_token_suite.go new file mode 100644 index 00000000..e6ad0754 --- /dev/null +++ b/tests/integration/erc721_token_suite.go @@ -0,0 +1,86 @@ +package integration + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + + "github.com/functionx/fx-core/v8/tests/contract" + "github.com/functionx/fx-core/v8/testutil/helpers" +) + +type ERC721TokenSuite struct { + *EthSuite + + erc721Token *contract.ERC721TokenTest + signer *helpers.Signer +} + +func NewERC721TokenSuite(suite *EthSuite, token common.Address, signer *helpers.Signer) *ERC721TokenSuite { + erc20Token, err := contract.NewERC721TokenTest(token, suite.ethCli) + suite.Require().NoError(err) + return &ERC721TokenSuite{ + EthSuite: suite, + erc721Token: erc20Token, + signer: signer, + } +} + +func (suite *ERC721TokenSuite) WithSigner(signer *helpers.Signer) *ERC721TokenSuite { + return &ERC721TokenSuite{ + EthSuite: suite.EthSuite, + erc721Token: suite.erc721Token, + signer: signer, + } +} + +func (suite *ERC721TokenSuite) BalanceOf(account common.Address) *big.Int { + balanceOf, err := suite.erc721Token.BalanceOf(nil, account) + suite.Require().NoError(err) + return balanceOf +} + +func (suite *ERC721TokenSuite) EqualBalanceOf(account common.Address, value *big.Int) { + suite.Require().Equal(suite.BalanceOf(account).Cmp(value), 0) +} + +func (suite *ERC721TokenSuite) TokenURI(id *big.Int) string { + uri, err := suite.erc721Token.TokenURI(nil, id) + suite.Require().NoError(err) + return uri +} + +func (suite *ERC721TokenSuite) IsApprovedForAll(owner, operator common.Address) bool { + isApproved, err := suite.erc721Token.IsApprovedForAll(nil, owner, operator) + suite.Require().NoError(err) + return isApproved +} + +func (suite *ERC721TokenSuite) SafeMint(account common.Address) *ethtypes.Transaction { + ethTx, err := suite.erc721Token.SafeMint(suite.TransactOpts(suite.signer), account, "ipfs://test-url") + suite.Require().NoError(err) + suite.WaitMined(ethTx) + return ethTx +} + +func (suite *ERC721TokenSuite) Approve(operator common.Address, id *big.Int) *ethtypes.Transaction { + ethTx, err := suite.erc721Token.Approve(suite.TransactOpts(suite.signer), operator, id) + suite.Require().NoError(err) + suite.WaitMined(ethTx) + return ethTx +} + +func (suite *ERC721TokenSuite) SetApprovalForAll(operator common.Address, approved bool) *ethtypes.Transaction { + ethTx, err := suite.erc721Token.SetApprovalForAll(suite.TransactOpts(suite.signer), operator, approved) + suite.Require().NoError(err) + suite.WaitMined(ethTx) + return ethTx +} + +func (suite *ERC721TokenSuite) SafeTransferFrom(from, to common.Address, id *big.Int) *ethtypes.Transaction { + ethTx, err := suite.erc721Token.SafeTransferFrom(suite.TransactOpts(suite.signer), from, to, id) + suite.Require().NoError(err) + suite.WaitMined(ethTx) + return ethTx +} diff --git a/tests/integration/eth_suite.go b/tests/integration/eth_suite.go new file mode 100644 index 00000000..deb3edec --- /dev/null +++ b/tests/integration/eth_suite.go @@ -0,0 +1,153 @@ +package integration + +import ( + "context" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" + evmtypes "github.com/evmos/ethermint/x/evm/types" + "github.com/stretchr/testify/suite" + + "github.com/functionx/fx-core/v8/client" + "github.com/functionx/fx-core/v8/contract" + testscontract "github.com/functionx/fx-core/v8/tests/contract" + "github.com/functionx/fx-core/v8/testutil/helpers" +) + +type EthSuite struct { + suite.Suite + ctx context.Context + ethCli *ethclient.Client +} + +func (suite *EthSuite) TransactOpts(signer *helpers.Signer) *bind.TransactOpts { + ecdsa, err := crypto.ToECDSA(signer.PrivKey().Bytes()) + suite.Require().NoError(err) + + chainId, err := suite.ethCli.ChainID(suite.ctx) + suite.Require().NoError(err) + + transactOpts, err := bind.NewKeyedTransactorWithChainID(ecdsa, chainId) + suite.Require().NoError(err) + + transactOpts.GasTipCap = big.NewInt(1e9) + transactOpts.GasFeeCap = big.NewInt(6e12) + transactOpts.GasLimit = 200_000 + return transactOpts +} + +func (suite *EthSuite) Balance(addr common.Address) *big.Int { + at, err := suite.ethCli.BalanceAt(suite.ctx, addr, nil) + suite.Require().NoError(err) + return at +} + +func (suite *EthSuite) BlockHeight() uint64 { + number, err := suite.ethCli.BlockNumber(suite.ctx) + suite.Require().NoError(err) + return number +} + +func (suite *EthSuite) SendTransaction(tx *ethtypes.Transaction) *ethtypes.Receipt { + err := suite.ethCli.SendTransaction(suite.ctx, tx) + suite.Require().NoError(err) + + return suite.WaitMined(tx) +} + +func (suite *EthSuite) WaitMined(tx *ethtypes.Transaction) *ethtypes.Receipt { + ctx, cancel := context.WithTimeout(suite.ctx, 5*time.Second) + defer cancel() + receipt, err := bind.WaitMined(ctx, suite.ethCli, tx) + suite.Require().NoError(err) + suite.T().Log("broadcast tx", "msg:", "ethermint.evm.v1.MsgEthereumTx", "height:", receipt.BlockNumber, "txHash:", receipt.TxHash) + suite.Require().Equal(ethtypes.ReceiptStatusSuccessful, receipt.Status) + return receipt +} + +func (suite *EthSuite) DeployERC20(signer *helpers.Signer, symbol string) common.Address { + erc20 := contract.GetFIP20() + tx, err := client.BuildEthTransaction(suite.ctx, suite.ethCli, signer.PrivKey(), nil, nil, erc20.Bin) + suite.Require().NoError(err) + suite.SendTransaction(tx) + + logicAddr := crypto.CreateAddress(signer.Address(), tx.Nonce()) + proxyAddr := suite.DeployProxy(signer, logicAddr, []byte{}) + + pack, err := erc20.ABI.Pack("initialize", "Test ERC20", symbol, uint8(18), signer.Address()) + suite.Require().NoError(err) + tx, err = client.BuildEthTransaction(suite.ctx, suite.ethCli, signer.PrivKey(), &proxyAddr, nil, pack) + suite.Require().NoError(err) + suite.SendTransaction(tx) + return proxyAddr +} + +func (suite *EthSuite) DeployERC721(signer *helpers.Signer) common.Address { + erc721ABI := contract.MustABIJson(testscontract.ERC721TokenTestMetaData.ABI) + erc721Bin := contract.MustDecodeHex(testscontract.ERC721TokenTestMetaData.Bin) + + tx, err := client.BuildEthTransaction(suite.ctx, suite.ethCli, signer.PrivKey(), nil, nil, erc721Bin) + suite.Require().NoError(err) + suite.SendTransaction(tx) + + logicAddr := crypto.CreateAddress(signer.Address(), tx.Nonce()) + proxyAddr := suite.DeployProxy(signer, logicAddr, []byte{}) + pack, err := erc721ABI.Pack("initialize") + suite.Require().NoError(err) + tx, err = client.BuildEthTransaction(suite.ctx, suite.ethCli, signer.PrivKey(), &proxyAddr, nil, pack) + suite.Require().NoError(err) + suite.SendTransaction(tx) + return proxyAddr +} + +func (suite *EthSuite) DeployStaking(signer *helpers.Signer) (common.Address, common.Hash) { + stakingBin := contract.MustDecodeHex(testscontract.StakingTestMetaData.Bin) + return suite.DeployContract(signer, stakingBin) +} + +func (suite *EthSuite) DeployCrosschain(signer *helpers.Signer) (common.Address, common.Hash) { + crosschainBin := contract.MustDecodeHex(testscontract.CrosschainTestMetaData.Bin) + return suite.DeployContract(signer, crosschainBin) +} + +func (suite *EthSuite) DeployContract(signer *helpers.Signer, contractBin []byte) (common.Address, common.Hash) { + tx, err := client.BuildEthTransaction(suite.ctx, suite.ethCli, signer.PrivKey(), nil, nil, contractBin) + suite.Require().NoError(err) + receipt := suite.SendTransaction(tx) + + suite.Require().False(contract.IsZeroEthAddress(receipt.ContractAddress)) + return receipt.ContractAddress, receipt.TxHash +} + +func (suite *EthSuite) DeployProxy(signer *helpers.Signer, logic common.Address, initData []byte) common.Address { + erc1967Proxy := contract.GetERC1967Proxy() + input, err := erc1967Proxy.ABI.Pack("", logic, initData) + suite.Require().NoError(err) + tx, err := client.BuildEthTransaction(suite.ctx, suite.ethCli, signer.PrivKey(), nil, nil, append(erc1967Proxy.Bin, input...)) + suite.Require().NoError(err) + suite.SendTransaction(tx) + return crypto.CreateAddress(signer.Address(), tx.Nonce()) +} + +func (suite *EthSuite) TxFee(hash common.Hash) *big.Int { + receipt, err := suite.ethCli.TransactionReceipt(suite.ctx, hash) + suite.Require().NoError(err) + + tx, pending, err := suite.ethCli.TransactionByHash(suite.ctx, hash) + suite.Require().NoError(err) + suite.Require().False(pending) + + block, err := suite.ethCli.BlockByNumber(suite.ctx, receipt.BlockNumber) + suite.Require().NoError(err) + baseFee := block.BaseFee() + + txData, err := evmtypes.NewTxDataFromTx(tx) + suite.Require().NoError(err) + effectiveGasPrice := txData.EffectiveGasPrice(baseFee) + return big.NewInt(0).Mul(effectiveGasPrice, big.NewInt(0).SetUint64(receipt.GasUsed)) +} diff --git a/tests/integration/evm_test.go b/tests/integration/evm_test.go new file mode 100644 index 00000000..d3a67b59 --- /dev/null +++ b/tests/integration/evm_test.go @@ -0,0 +1,300 @@ +package integration + +import ( + "bytes" + "fmt" + "math/big" + "reflect" + "strings" + + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/ethereum/go-ethereum/common" + evmtypes "github.com/evmos/ethermint/x/evm/types" + + "github.com/functionx/fx-core/v8/contract" + "github.com/functionx/fx-core/v8/testutil/helpers" + fxtypes "github.com/functionx/fx-core/v8/types" + fxevmtypes "github.com/functionx/fx-core/v8/x/evm/types" +) + +func (suite *IntegrationTest) WFXTest() { + signer := helpers.NewSigner(helpers.NewEthPrivKey()) + suite.Send(signer.AccAddress(), suite.NewStakingCoin(100, 18)) + + tokenAddr := suite.GetErc20TokenAddress(fxtypes.DefaultDenom) + wfxTokenSuite := NewERC20TokenSuite(suite.EthSuite, tokenAddr, signer) + + wfxTokenSuite.Deposit(helpers.NewBigInt(20, 18)) + wfxTokenSuite.Withdraw(signer.Address(), helpers.NewBigInt(10, 18)) + wfxTokenSuite.Transfer(helpers.GenHexAddress(), helpers.NewBigInt(5, 18)) + + newSigner := helpers.NewSigner(helpers.NewEthPrivKey()) + approveAmount := helpers.NewBigInt(5, 18) + wfxTokenSuite.Approve(newSigner.Address(), approveAmount) + + // send tx fee to signer + suite.Send(newSigner.AccAddress(), suite.NewStakingCoin(2, 18)) + + wfxTokenSuite.WithSigner(newSigner).TransferFrom(signer.Address(), helpers.GenHexAddress(), approveAmount) +} + +func (suite *IntegrationTest) ERC20TokenTest() { + signer := helpers.NewSigner(helpers.NewEthPrivKey()) + suite.Send(signer.AccAddress(), suite.NewStakingCoin(100, 18)) + + tokenAddr := suite.DeployERC20(signer, "TEST") + erc20TokenSuite := NewERC20TokenSuite(suite.EthSuite, tokenAddr, signer) + + erc20TokenSuite.Mint(signer.Address(), helpers.NewBigInt(100, 18)) + + erc20TokenSuite.Transfer(helpers.GenHexAddress(), helpers.NewBigInt(20, 18)) + + newSigner := helpers.NewSigner(helpers.NewEthPrivKey()) + approveAmount := helpers.NewBigInt(5, 18) + erc20TokenSuite.Approve(newSigner.Address(), approveAmount) + + // send tx fee to signer + suite.Send(newSigner.AccAddress(), suite.NewStakingCoin(100, 18)) + + erc20TokenSuite.WithSigner(newSigner).TransferFrom(signer.Address(), helpers.GenHexAddress(), approveAmount) +} + +func (suite *IntegrationTest) ERC721Test() { + signer := helpers.NewSigner(helpers.NewEthPrivKey()) + suite.Send(signer.AccAddress(), suite.NewStakingCoin(100, 18)) + + tokenAddr := suite.DeployERC721(signer) + erc721TokenSuite := NewERC721TokenSuite(suite.EthSuite, tokenAddr, signer) + + suite.Send(signer.AccAddress(), suite.NewStakingCoin(100, 18)) + + erc721TokenSuite.SafeMint(signer.Address()) + + newSigner := helpers.NewSigner(helpers.NewEthPrivKey()) + suite.Send(newSigner.AccAddress(), suite.NewStakingCoin(100, 18)) + + erc721TokenSuite.Approve(newSigner.Address(), big.NewInt(0)) + erc721TokenSuite.WithSigner(newSigner).SafeTransferFrom(signer.Address(), helpers.GenHexAddress(), big.NewInt(0)) + + erc721TokenSuite.SafeMint(signer.Address()) + erc721TokenSuite.SafeTransferFrom(signer.Address(), helpers.GenHexAddress(), big.NewInt(1)) + + erc721TokenSuite.SafeMint(signer.Address()) + erc721TokenSuite.SetApprovalForAll(newSigner.Address(), true) + erc721TokenSuite.WithSigner(newSigner).SafeTransferFrom(signer.Address(), helpers.GenHexAddress(), big.NewInt(2)) +} + +func (suite *IntegrationTest) EVMWeb3Test() { + signer := helpers.NewSigner(helpers.NewEthPrivKey()) + suite.Send(signer.AccAddress(), suite.NewStakingCoin(100, 18)) + + tests := []struct { + name string + funcName string + params []interface{} + wantRes []interface{} + }{ + { + name: "eth_chainId", + funcName: "ChainID", + params: []interface{}{}, + wantRes: []interface{}{big.NewInt(530), nil}, + }, + { + name: "eth_getBlockByNumber", + funcName: "BlockByNumber", + params: []interface{}{big.NewInt(1)}, + wantRes: []interface{}{nil, nil}, + }, + { + name: "eth_getBlockByNumber latest", + funcName: "BlockByNumber", + params: []interface{}{nil}, + wantRes: []interface{}{nil, nil}, + }, + { + name: "eth_blockNumber", + funcName: "BlockNumber", + params: []interface{}{}, + wantRes: []interface{}{nil, nil}, + }, + { + name: "eth_getBlockByNumber", + funcName: "HeaderByNumber", + params: []interface{}{big.NewInt(1)}, + wantRes: []interface{}{nil, nil}, + }, + { + name: "eth_getBlockByNumber latest", + funcName: "HeaderByNumber", + params: []interface{}{nil}, + wantRes: []interface{}{nil, nil}, + }, + { + name: "eth_syncing", + funcName: "SyncProgress", + params: []interface{}{}, + wantRes: []interface{}{nil, nil}, + }, + { + name: "net_version", + funcName: "NetworkID", + params: []interface{}{}, + wantRes: []interface{}{big.NewInt(530), nil}, + }, + { + name: "eth_getBalance latest", + funcName: "BalanceAt", + params: []interface{}{signer.Address(), nil}, + wantRes: []interface{}{new(big.Int).Mul(big.NewInt(100), big.NewInt(1e18)), nil}, + }, + { + name: "eth_getBalance", + funcName: "BalanceAt", + params: []interface{}{signer.Address(), big.NewInt(1)}, + wantRes: []interface{}{big.NewInt(0), nil}, + }, + { + name: "eth_getStorageAt", + funcName: "StorageAt", + params: []interface{}{signer.Address(), common.Hash{}, nil}, + wantRes: []interface{}{[32]byte{}, nil}, + }, + { + name: "eth_getCode", + funcName: "CodeAt", + params: []interface{}{signer.Address(), nil}, + wantRes: []interface{}{[]byte{}, nil}, + }, + { + name: "eth_getTransactionCount", + funcName: "NonceAt", + params: []interface{}{signer.Address(), nil}, + wantRes: []interface{}{uint64(0), nil}, + }, + { + name: "eth_getBalance pending", + funcName: "PendingBalanceAt", + params: []interface{}{signer.Address()}, + wantRes: []interface{}{new(big.Int).Mul(big.NewInt(100), big.NewInt(1e18)), nil}, + }, + { + name: "eth_getStorageAt pending", + funcName: "PendingStorageAt", + params: []interface{}{signer.Address(), common.Hash{}}, + wantRes: []interface{}{[32]byte{}, nil}, + }, + { + name: "eth_getCode pending", + funcName: "PendingCodeAt", + params: []interface{}{signer.Address()}, + wantRes: []interface{}{[]byte{}, nil}, + }, + { + name: "eth_getTransactionCount pending", + funcName: "PendingNonceAt", + params: []interface{}{signer.Address()}, + wantRes: []interface{}{big.NewInt(0), nil}, + }, + { + name: "eth_getBlockTransactionCountByNumber pending", + funcName: "PendingTransactionCount", + params: []interface{}{}, + wantRes: []interface{}{uint64(0), nil}, + }, + { + name: "eth_gasPrice", + funcName: "SuggestGasPrice", + params: []interface{}{}, + wantRes: []interface{}{big.NewInt(562500000000), nil}, + }, + { + name: "eth_maxPriorityFeePerGas", + funcName: "SuggestGasTipCap", + params: []interface{}{}, + wantRes: []interface{}{big.NewInt(62500000000), nil}, + }, + } + ethClient := suite.EthSuite.ethCli + for _, tt := range tests { + suite.Run(tt.name, func() { + typeOf := reflect.TypeOf(ethClient) + method, is := typeOf.MethodByName(tt.funcName) + suite.True(is) + params := make([]reflect.Value, len(tt.params)+2) + params[0] = reflect.ValueOf(ethClient) + params[1] = reflect.ValueOf(suite.ctx) + for i := 2; i < len(params); i++ { + p := tt.params[i-2] + if p != nil { + params[i] = reflect.ValueOf(p) + } else { + params[i] = reflect.New(reflect.TypeOf(&big.Int{})).Elem() + } + } + results := method.Func.Call(params) + for i := 0; i < len(results); i++ { + if i == 0 && tt.wantRes[i] == nil { + continue + } + suite.EqualValues( + fmt.Sprintf("%v", tt.wantRes[i]), + fmt.Sprintf("%v", results[i]), + ) + } + }) + } +} + +func (suite *IntegrationTest) CallContractTest() { + signer := helpers.NewSigner(helpers.NewEthPrivKey()) + suite.Send(signer.AccAddress(), suite.NewStakingCoin(100, 18)) + + tokenAddr := suite.DeployERC20(signer, "TEST") + erc20TokenSuite := NewERC20TokenSuite(suite.EthSuite, tokenAddr, signer) + + evmModuleAddr := common.BytesToAddress(authtypes.NewModuleAddress(evmtypes.ModuleName)) + erc20TokenSuite.TransferOwnership(evmModuleAddr) + + args, err := helpers.PackERC20Mint(signer.Address(), helpers.NewBigInt(100, 18)) + suite.Require().NoError(err) + + response, proposalId := suite.BroadcastProposalTxV1( + &fxevmtypes.MsgCallContract{ + Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(), + ContractAddress: tokenAddr.String(), + Data: common.Bytes2Hex(args), + }, + ) + suite.Require().EqualValues(response.Code, 0) + suite.Require().True(proposalId > 0) +} + +func (suite *IntegrationTest) ERC20CodeTest() { + signer := helpers.NewSigner(helpers.NewEthPrivKey()) + suite.Send(signer.AccAddress(), suite.NewStakingCoin(100, 18)) + + erc20 := contract.GetFIP20() + erc20Addr, _ := suite.DeployContract(signer, erc20.Bin) + code, err := suite.EthSuite.ethCli.CodeAt(suite.ctx, erc20Addr, nil) + suite.Require().NoError(err) + suite.Equal(erc20.Code, code, fmt.Sprintf("erc20 deployed code: %s", common.Bytes2Hex(code))) + + deployedCode := bytes.ReplaceAll(code, erc20.Address.Bytes(), common.Address{}.Bytes()) + suite.True(strings.HasSuffix(contract.FIP20UpgradableMetaData.Bin, common.Bytes2Hex(deployedCode))) +} + +func (suite *IntegrationTest) WFXCodeTest() { + signer := helpers.NewSigner(helpers.NewEthPrivKey()) + suite.Send(signer.AccAddress(), suite.NewStakingCoin(100, 18)) + + wfx := contract.GetWFX() + wfxAddr, _ := suite.DeployContract(signer, wfx.Bin) + code, err := suite.EthSuite.ethCli.CodeAt(suite.ctx, wfxAddr, nil) + suite.Require().NoError(err) + suite.Equal(wfx.Code, code, fmt.Sprintf("wfx deployed code: %s", common.Bytes2Hex(code))) + + deployedCode := bytes.ReplaceAll(code, wfx.Address.Bytes(), common.Address{}.Bytes()) + suite.True(strings.HasSuffix(contract.WFXUpgradableMetaData.Bin, common.Bytes2Hex(deployedCode))) +} diff --git a/tests/integration/fxcore_suite.go b/tests/integration/fxcore_suite.go new file mode 100644 index 00000000..4022d4f6 --- /dev/null +++ b/tests/integration/fxcore_suite.go @@ -0,0 +1,467 @@ +package integration + +import ( + "sort" + "strconv" + "time" + + sdkmath "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/client/grpc/cmtservice" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" + govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/ethereum/go-ethereum/common" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/functionx/fx-core/v8/client/grpc" + "github.com/functionx/fx-core/v8/testutil/helpers" + erc20types "github.com/functionx/fx-core/v8/x/erc20/types" +) + +type FxCoreSuite struct { + *EthSuite + + codec codec.Codec + validators []*helpers.Signer + grpcCli *grpc.Client + gasPrices sdk.Coins + defDenom string + timeoutCommit time.Duration + waitForHeightFunc func(height int64) (int64, error) + + proposalId uint64 + proposalStatus govv1.ProposalStatus +} + +func (suite *FxCoreSuite) WithGasPrices(gasPrices ...sdk.Coin) *FxCoreSuite { + newSuite := *suite + newSuite.gasPrices = gasPrices + return &newSuite +} + +func (suite *FxCoreSuite) GetValSigner() *helpers.Signer { + return suite.validators[0] +} + +func (suite *FxCoreSuite) GetValAddr() sdk.ValAddress { + return suite.GetValSigner().AccAddress().Bytes() +} + +func (suite *FxCoreSuite) FindValSigner(addr sdk.AccAddress) *helpers.Signer { + for _, validator := range suite.validators { + if addr.Equals(validator.AccAddress()) { + return validator + } + } + return nil +} + +func (suite *FxCoreSuite) getNextProposalId() uint64 { + suite.proposalId = suite.proposalId + 1 + return suite.proposalId +} + +// Deprecated: Use NewStakingCoin +func (suite *FxCoreSuite) NewCoin(amount sdkmath.Int) sdk.Coin { + return sdk.NewCoin(suite.defDenom, amount) +} + +func (suite *FxCoreSuite) NewStakingCoin(amount, power int64) sdk.Coin { + coin := helpers.NewStakingCoin(amount, power) + suite.Require().Equal(coin.Denom, suite.defDenom) + return coin +} + +func (suite *FxCoreSuite) BlockNumber() int64 { + height, err := suite.grpcCli.GetBlockHeight() + suite.Require().NoError(err) + return height +} + +func (suite *FxCoreSuite) QueryTx(txHash string) *sdk.TxResponse { + txResponse, err := suite.grpcCli.TxByHash(txHash) + suite.Require().NoError(err) + return txResponse +} + +func (suite *FxCoreSuite) QueryBlock(blockHeight int64) *cmtservice.Block { + txResponse, err := suite.grpcCli.GetBlockByHeight(blockHeight) + suite.Require().NoError(err) + return txResponse +} + +func (suite *FxCoreSuite) QueryBlockByTxHash(txHash string) *cmtservice.Block { + txResponse := suite.QueryTx(txHash) + return suite.QueryBlock(txResponse.Height) +} + +func (suite *FxCoreSuite) BroadcastTx(signer *helpers.Signer, msgList ...sdk.Msg) *sdk.TxResponse { + balances, err := suite.grpcCli.QueryBalances(signer.AccAddress().String()) + suite.Require().NoError(err) + suite.Require().True(balances.AmountOf(suite.defDenom).GT(sdkmath.NewInt(2).MulRaw(1e18))) + + txRaw, err := suite.grpcCli.WithGasPrices(suite.gasPrices). + BuildTxRaw(signer.PrivKey(), msgList, 500000, 0, "") + suite.Require().NoError(err) + + txResponse, err := suite.grpcCli.BroadcastTx(txRaw) + suite.Require().NoError(err) + suite.Require().NotNil(txResponse) // txResponse might be nil, but error is also nil + suite.Require().EqualValues(0, txResponse.Code) + txResponse, err = suite.grpcCli.WaitMined(txResponse.TxHash, 200*suite.timeoutCommit, 10*suite.timeoutCommit) + suite.Require().NoError(err) + msgTypeURL := sdk.MsgTypeURL(msgList[0]) + suite.T().Log("broadcast tx", "msg:", msgTypeURL, "height:", txResponse.Height, "txHash:", txResponse.TxHash) + waitBlock := txResponse.Height + 1 + if msgTypeURL == sdk.MsgTypeURL(&govv1beta1.MsgSubmitProposal{}) || + msgTypeURL == sdk.MsgTypeURL(&govv1.MsgSubmitProposal{}) { + waitBlock += 2 + } + _, err = suite.waitForHeightFunc(waitBlock) + suite.Require().NoError(err) + return txResponse +} + +func (suite *FxCoreSuite) Send(toAddress sdk.AccAddress, amount ...sdk.Coin) *sdk.TxResponse { + signer := suite.GetValSigner() + txResponse := suite.BroadcastTx(signer, banktypes.NewMsgSend(signer.AccAddress(), toAddress, amount)) + suite.Require().Less(txResponse.GasUsed, int64(100_000)) + return txResponse +} + +// --- Bank Module + +func (suite *FxCoreSuite) GetAllBalances(accAddress sdk.AccAddress) sdk.Coins { + balances, err := suite.grpcCli.QueryBalances(accAddress.String()) + suite.Require().NoError(err) + return balances +} + +func (suite *FxCoreSuite) EqualBalance(accAddress sdk.AccAddress, balance sdk.Coin) { + queryBalance, err := suite.grpcCli.QueryBalance(accAddress.String(), balance.Denom) + suite.Require().NoError(err) + suite.Require().Equal(balance.String(), queryBalance.String()) +} + +func (suite *FxCoreSuite) GetDenomsMetadata() []banktypes.Metadata { + resp, err := suite.grpcCli.BankQuery().DenomsMetadata(suite.ctx, &banktypes.QueryDenomsMetadataRequest{}) + suite.Require().NoError(err) + return resp.Metadatas +} + +func (suite *FxCoreSuite) GetMetadata(denom string) banktypes.Metadata { + response, err := suite.grpcCli.BankQuery().DenomMetadata(suite.ctx, &banktypes.QueryDenomMetadataRequest{Denom: denom}) + suite.Require().NoError(err) + return response.Metadata +} + +// --- Auth Module + +func (suite *FxCoreSuite) QueryModuleAccountByName(moduleName string) sdk.AccAddress { + moduleAccount, err := suite.grpcCli.GetModuleAccountByName(moduleName) + suite.Require().NoError(err) + return moduleAccount.GetAddress() +} + +// --- Gov Module + +func (suite *FxCoreSuite) WithProposalStatus(status govv1.ProposalStatus) *FxCoreSuite { + newSuite := *suite + newSuite.proposalStatus = status + return &newSuite +} + +func (suite *FxCoreSuite) BroadcastProposalTxV1(msgs ...sdk.Msg) (*sdk.TxResponse, uint64) { + proposalMsg, err := govv1.NewMsgSubmitProposal( + msgs, + sdk.NewCoins(suite.NewCoin(sdkmath.NewInt(10_000).MulRaw(1e18))), + suite.GetValSigner().AccAddress().String(), + "", + sdk.MsgTypeURL(msgs[0]), + sdk.MsgTypeURL(msgs[0]), + false, + ) + suite.Require().NoError(err) + proposalId := suite.getNextProposalId() + voteMsg := govv1.NewMsgVote(suite.GetValSigner().AccAddress(), proposalId, govv1.OptionYes, "") + txResponse := suite.BroadcastTx(suite.GetValSigner(), proposalMsg, voteMsg) + for _, log := range txResponse.Logs { + for _, event := range log.Events { + if event.Type != "proposal_deposit" { + continue + } + for _, attribute := range event.Attributes { + if attribute.Key != "proposal_id" { + continue + } + id, err := strconv.ParseUint(attribute.Value, 10, 64) + suite.Require().NoError(err) + suite.Require().Equal(proposalId, id) + break + } + } + } + suite.Require().NoError(err) + + if suite.proposalStatus > 0 { + suite.EqualProposal(proposalId, suite.proposalStatus) + } + return txResponse, proposalId +} + +func (suite *FxCoreSuite) GetProposals(depositor sdk.AccAddress) govv1.Proposals { + proposalsResp, err := suite.grpcCli.GovQuery().Proposals(suite.ctx, &govv1.QueryProposalsRequest{ + ProposalStatus: govv1.StatusDepositPeriod, + Depositor: depositor.String(), + }) + suite.Require().NoError(err) + return proposalsResp.Proposals +} + +func (suite *FxCoreSuite) ProposalDeposit(signer *helpers.Signer, proposalID uint64, amount sdk.Coin) *sdk.TxResponse { + coins := sdk.NewCoins(amount) + txResponse := suite.BroadcastTx(signer, govv1beta1.NewMsgDeposit(signer.AccAddress(), proposalID, coins)) + + depositResp, err := suite.grpcCli.GovQuery().Deposit(suite.ctx, &govv1.QueryDepositRequest{ + ProposalId: proposalID, + Depositor: signer.AccAddress().String(), + }) + suite.Require().NoError(err) + suite.Require().Equal(depositResp.Deposit.Amount, coins) + return txResponse +} + +func (suite *FxCoreSuite) ProposalVote(signer *helpers.Signer, proposalID uint64, option govv1beta1.VoteOption) *sdk.TxResponse { + return suite.BroadcastTx(signer, govv1beta1.NewMsgVote(signer.AccAddress(), proposalID, option)) +} + +func (suite *FxCoreSuite) EqualProposal(proposalId uint64, _ govv1.ProposalStatus) govv1.Proposal { + proposalResp, err := suite.grpcCli.GovQuery().Proposal(suite.ctx, &govv1.QueryProposalRequest{ + ProposalId: proposalId, + }) + suite.Require().NoError(err) + + suite.Require().Greater(proposalResp.Proposal.Status, govv1.StatusDepositPeriod) + return *proposalResp.Proposal +} + +// --- Distribution Module + +func (suite *FxCoreSuite) DistrQuery() distrtypes.QueryClient { + return suite.grpcCli.DistrQuery() +} + +func (suite *FxCoreSuite) EqualWithdrawAddr(delegatorAddr, withdrawAddr sdk.AccAddress) { + withdrawAddressResp, err := suite.DistrQuery().DelegatorWithdrawAddress(suite.ctx, + &distrtypes.QueryDelegatorWithdrawAddressRequest{ + DelegatorAddress: delegatorAddr.String(), + }) + suite.Require().NoError(err) + suite.Require().Equal(withdrawAddressResp.WithdrawAddress, withdrawAddr.String()) +} + +func (suite *FxCoreSuite) WithdrawReward(signer *helpers.Signer, valAddress sdk.ValAddress) *sdk.TxResponse { + return suite.BroadcastTx(signer, distrtypes.NewMsgWithdrawDelegatorReward(signer.AccAddress().String(), valAddress.String())) +} + +func (suite *FxCoreSuite) DelegationRewards(delAddr, valAddr string) sdk.DecCoins { + response, err := suite.DistrQuery().DelegationRewards(suite.ctx, + &distrtypes.QueryDelegationRewardsRequest{ + DelegatorAddress: delAddr, ValidatorAddress: valAddr, + }) + suite.Require().NoError(err) + return response.Rewards +} + +func (suite *FxCoreSuite) SetWithdrawAddress(signer *helpers.Signer, withdrawAddr sdk.AccAddress) *sdk.TxResponse { + delAddr := signer.AccAddress() + setWithdrawAddress := distrtypes.NewMsgSetWithdrawAddress(delAddr, withdrawAddr) + txResponse := suite.BroadcastTx(signer, setWithdrawAddress) + + suite.EqualWithdrawAddr(delAddr, withdrawAddr) + return txResponse +} + +// --- Staking Module + +func (suite *FxCoreSuite) StakingQuery() stakingtypes.QueryClient { + return suite.grpcCli.StakingQuery() +} + +func (suite *FxCoreSuite) GetDelegation(delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress) *stakingtypes.DelegationResponse { + delegationResp, err := suite.StakingQuery().Delegation(suite.ctx, &stakingtypes.QueryDelegationRequest{ + DelegatorAddr: delegatorAddr.String(), + ValidatorAddr: validatorAddr.String(), + }) + if status.Code(err) == codes.NotFound { + return nil + } + suite.Require().NoError(err) + return delegationResp.DelegationResponse +} + +func (suite *FxCoreSuite) CreateValidator(signer *helpers.Signer, toBondedVal bool) *sdk.TxResponse { + valAddr := sdk.ValAddress(signer.AccAddress().Bytes()) + minSelfDelegate := sdkmath.NewInt(1) + stakingDenom := suite.defDenom + selfDelegate := sdk.NewCoin(stakingDenom, minSelfDelegate) + if toBondedVal { + selfDelegate = sdk.NewCoin(stakingDenom, sdkmath.NewIntFromUint64(1e18).Mul(sdkmath.NewInt(100))) + } + description := stakingtypes.Description{ + Moniker: "val2", + Identity: "", + Website: "", + SecurityContact: "", + Details: "", + } + rates := stakingtypes.CommissionRates{ + Rate: sdkmath.LegacyNewDecWithPrec(2, 2), // 2% + MaxRate: sdkmath.LegacyNewDecWithPrec(50, 2), // 5% + MaxChangeRate: sdkmath.LegacyNewDecWithPrec(2, 2), // 2% + } + ed25519PrivKey := ed25519.GenPrivKeyFromSecret(valAddr.Bytes()) + msg, err := stakingtypes.NewMsgCreateValidator(valAddr.String(), ed25519PrivKey.PubKey(), selfDelegate, description, rates, minSelfDelegate) + suite.Require().NoError(err) + return suite.BroadcastTx(signer, msg) +} + +func (suite *FxCoreSuite) GetValSortByToken() sdk.ValAddress { + response, err := suite.StakingQuery().Validators(suite.ctx, + &stakingtypes.QueryValidatorsRequest{Status: stakingtypes.Bonded.String()}) + suite.Require().NoError(err) + suite.Require().NotEmpty(response.Validators) + validators := response.Validators + sort.Slice(validators, func(i, j int) bool { + return validators[i].Tokens.LT(validators[j].Tokens) + }) + valAddr, err := sdk.ValAddressFromBech32(validators[0].OperatorAddress) + suite.Require().NoError(err) + return valAddr +} + +func (suite *FxCoreSuite) Delegate(signer *helpers.Signer, valAddress sdk.ValAddress, amount sdk.Coin) *sdk.TxResponse { + delegation := suite.GetDelegation(signer.AccAddress(), valAddress) + + txResponse := suite.BroadcastTx(signer, stakingtypes.NewMsgDelegate(signer.AccAddress().String(), valAddress.String(), amount)) + + if delegation != nil { + amount = amount.Add(delegation.Balance) + } + suite.EqualDelegate(signer.AccAddress(), valAddress, amount) + return txResponse +} + +func (suite *FxCoreSuite) EqualDelegate(delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress, delegation sdk.Coin) { + delegationResp, err := suite.StakingQuery().Delegation(suite.ctx, &stakingtypes.QueryDelegationRequest{ + DelegatorAddr: delegatorAddr.String(), + ValidatorAddr: validatorAddr.String(), + }) + if delegation.IsZero() { + suite.Require().Error(sdkerrors.ErrNotFound) + } else { + suite.Require().NoError(err) + suite.Require().Equal(delegation.String(), delegationResp.DelegationResponse.Balance.String()) + } +} + +func (suite *FxCoreSuite) Undelegate(signer *helpers.Signer, valAddress sdk.ValAddress, amount sdk.Coin) *sdk.TxResponse { + if amount.IsZero() { + delegation, err := suite.StakingQuery().Delegation(suite.ctx, &stakingtypes.QueryDelegationRequest{ + DelegatorAddr: signer.AccAddress().String(), + ValidatorAddr: valAddress.String(), + }) + suite.Require().NoError(err) + amount = delegation.DelegationResponse.Balance + } + txResponse := suite.BroadcastTx(signer, stakingtypes.NewMsgUndelegate(signer.AccAddress().String(), valAddress.String(), amount)) + return txResponse +} + +func (suite *FxCoreSuite) EqualUndelegate(delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress, entries ...stakingtypes.UnbondingDelegationEntry) { + response, err := suite.StakingQuery().UnbondingDelegation(suite.ctx, &stakingtypes.QueryUnbondingDelegationRequest{ + DelegatorAddr: delegatorAddr.String(), + ValidatorAddr: validatorAddr.String(), + }) + suite.Require().NoError(err) + suite.Require().Equal(len(response.Unbond.Entries), len(entries)) + for i, entry := range response.Unbond.Entries { + entry.UnbondingId = 0 + suite.Require().Equal(entry.String(), entries[i].String()) + } +} + +func (suite *FxCoreSuite) Redelegate(signer *helpers.Signer, valSrc, valDest sdk.ValAddress, all bool) *sdk.TxResponse { + amt := sdkmath.NewInt(1) + if all { + delegation, err := suite.StakingQuery().Delegation(suite.ctx, &stakingtypes.QueryDelegationRequest{ + DelegatorAddr: signer.AccAddress().String(), + ValidatorAddr: valSrc.String(), + }) + suite.Require().NoError(err) + amt = delegation.DelegationResponse.Balance.Amount + } + msg := stakingtypes.NewMsgBeginRedelegate(signer.AccAddress().String(), valSrc.String(), valDest.String(), sdk.NewCoin(suite.defDenom, amt)) + return suite.BroadcastTx(signer, msg) +} + +func (suite *FxCoreSuite) EqualRedelegate(delegatorAddr sdk.AccAddress, redelegationResponses stakingtypes.RedelegationResponses) { + redelegationResp, err := suite.StakingQuery().Redelegations(suite.ctx, &stakingtypes.QueryRedelegationsRequest{DelegatorAddr: delegatorAddr.String()}) + suite.Require().NoError(err) + suite.Require().Equal(len(redelegationResp.RedelegationResponses), len(redelegationResponses)) + for i, item := range redelegationResp.RedelegationResponses { + suite.Require().Equal(item.Redelegation.String(), redelegationResponses[i].Redelegation.String()) + for j, entry := range item.Entries { + suite.Require().Equal(entry.RedelegationEntry.String(), redelegationResponses[i].Entries[j].RedelegationEntry.String()) + suite.Require().Equal(entry.Balance.String(), redelegationResponses[i].Entries[j].Balance.String()) + } + } +} + +// --- ERC20 Module + +func (suite *FxCoreSuite) ERC20Query() erc20types.QueryClient { + return suite.grpcCli.ERC20Query() +} + +func (suite *FxCoreSuite) GetErc20TokenAddress(denom string) common.Address { + pair, err := suite.ERC20Query().TokenPair(suite.ctx, &erc20types.QueryTokenPairRequest{Token: denom}) + suite.Require().NoError(err) + return common.HexToAddress(pair.Erc20Token.Erc20Address) +} + +func (suite *FxCoreSuite) ToggleTokenConversionProposal(denom string) (*sdk.TxResponse, uint64) { + msg := &erc20types.MsgToggleTokenConversion{ + Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(), + Token: denom, + } + return suite.BroadcastProposalTxV1(msg) +} + +func (suite *FxCoreSuite) ConvertCoin(signer *helpers.Signer, recipient common.Address, coin sdk.Coin) *sdk.TxResponse { + fromAddress := signer.AccAddress() + + beforeBalance := suite.GetAllBalances(fromAddress).AmountOf(coin.Denom) + erc20TokenAddress := suite.GetErc20TokenAddress(coin.Denom) + + erc20TokenSuite := NewERC20TokenSuite(suite.EthSuite, erc20TokenAddress, signer) + beforeBalanceOf := erc20TokenSuite.BalanceOf(recipient) + + msg := erc20types.NewMsgConvertCoin(coin, recipient, fromAddress) + txResponse := suite.BroadcastTx(signer, msg) + + afterBalance := suite.GetAllBalances(fromAddress).AmountOf(coin.Denom) + afterBalanceOf := erc20TokenSuite.BalanceOf(recipient) + suite.Require().Equal(beforeBalance.Sub(afterBalance).String(), coin.Amount.String()) + suite.Require().Equal(afterBalanceOf.String(), beforeBalanceOf.String()) + return txResponse +} diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go new file mode 100644 index 00000000..ac8b3165 --- /dev/null +++ b/tests/integration/integration_test.go @@ -0,0 +1,156 @@ +package integration + +import ( + "context" + "fmt" + "os" + "testing" + "time" + + sdkmath "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/crypto/hd" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/suite" + + "github.com/functionx/fx-core/v8/client/grpc" + "github.com/functionx/fx-core/v8/testutil" + "github.com/functionx/fx-core/v8/testutil/helpers" + "github.com/functionx/fx-core/v8/testutil/network" +) + +type IntegrationTest struct { + network *network.Network + numValidator int + enableLogging bool + + *FxCoreSuite +} + +func TestIntegrationTest(t *testing.T) { + if os.Getenv("TEST_INTEGRATION") != "true" { + t.Skip("skip integration test") + } + + suite.Run(t, &IntegrationTest{FxCoreSuite: &FxCoreSuite{EthSuite: &EthSuite{}}}) +} + +func (suite *IntegrationTest) SetupSuite() { + suite.T().Log("setting up integration test suite") + + suite.numValidator = 1 + suite.enableLogging = false + + timeoutCommit := 50 * time.Millisecond + if suite.numValidator > 1 { + timeoutCommit = 500 * time.Millisecond + } + + ibcGenesisOpt := func(config *network.Config) { + config.GenesisState = testutil.IbcGenesisState(config.Codec, config.GenesisState) + } + bankGenesisOpt := func(config *network.Config) { + config.GenesisState = testutil.BankGenesisState(config.Codec, config.GenesisState) + } + govGenesisOpt := func(config *network.Config) { + votingPeriod := time.Millisecond + if suite.numValidator > 1 { + votingPeriod = time.Duration(suite.numValidator*5) * timeoutCommit + } + config.GenesisState = testutil.GovGenesisState(config.Codec, config.GenesisState, votingPeriod) + } + slashingGenesisOpt := func(config *network.Config) { + signedBlocksWindow := int64(10) + minSignedPerWindow := sdkmath.LegacyNewDecWithPrec(2, 1) + downtimeJailDuration := 5 * time.Second + config.GenesisState = testutil.SlashingGenesisState(config.Codec, config.GenesisState, signedBlocksWindow, minSignedPerWindow, downtimeJailDuration) + } + + cfg := testutil.DefaultNetworkConfig(ibcGenesisOpt, bankGenesisOpt, govGenesisOpt, slashingGenesisOpt) + cfg.TimeoutCommit = timeoutCommit + cfg.NumValidators = suite.numValidator + cfg.EnableJSONRPC = true + if suite.enableLogging { + cfg.EnableTMLogging = true + } + + suite.network = network.New(suite.T(), cfg) + + _, err := suite.network.WaitForHeight(3) + suite.Require().NoError(err) + + suite.FxCoreSuite.EthSuite.ctx = suite.network.GetContext() + suite.FxCoreSuite.EthSuite.ethCli = suite.network.Validators[0].JSONRPCClient + + suite.FxCoreSuite.codec = suite.network.Config.Codec + suite.FxCoreSuite.validators = suite.GetAllValSigners() + suite.FxCoreSuite.grpcCli = suite.GRPCClient(suite.ctx) + suite.FxCoreSuite.gasPrices = suite.GetGasPrices() + suite.FxCoreSuite.defDenom = suite.network.Config.BondDenom + suite.FxCoreSuite.timeoutCommit = timeoutCommit + suite.FxCoreSuite.waitForHeightFunc = suite.network.WaitForHeight +} + +func (suite *IntegrationTest) TearDownSuite() { + suite.T().Log("tearing down integration test suite") + + // This is important and must be called to ensure other tests can create + // a network! + suite.network.Cleanup() +} + +func (suite *IntegrationTest) TestRun() { + suite.CrosschainTest() + + suite.StakingTest() + suite.StakingSharesTest() + suite.StakingPrecompileRedelegateTest() + suite.StakingPrecompileV2() + + // suite.StakingContractTest() + // suite.StakingSharesContractTest() + // suite.StakingPrecompileRedelegateByContractTest() + + suite.MigrateTestDelegate() + suite.MigrateTestUnDelegate() + + suite.EVMWeb3Test() + suite.WFXTest() + suite.ERC20TokenTest() + suite.ERC721Test() + suite.CallContractTest() + suite.ERC20CodeTest() + suite.WFXCodeTest() + + suite.ByPassFeeTest() +} + +func (suite *IntegrationTest) GetAllValSigners() []*helpers.Signer { + signers := make([]*helpers.Signer, 0, len(suite.network.Config.Mnemonics)) + for _, mnemonics := range suite.network.Config.Mnemonics { + privKey, err := helpers.PrivKeyFromMnemonic(mnemonics, hd.Secp256k1Type, 0, 0) + suite.Require().NoError(err) + signers = append(signers, helpers.NewSigner(privKey)) + } + return signers +} + +func (suite *IntegrationTest) GetGasPrices() sdk.Coins { + gasPrices, err := sdk.ParseCoinsNormalized(suite.network.Config.MinGasPrices) + suite.Require().NoError(err) + if gasPrices.Len() <= 0 { + // Let me know if you use sdk.newCoins sanitizeCoins will remove all zero coins + gasPrices = sdk.Coins{suite.NewCoin(sdkmath.ZeroInt())} + } + return gasPrices +} + +func (suite *IntegrationTest) GRPCClient(ctx context.Context) *grpc.Client { + validator := suite.network.Validators[0] + if validator.ClientCtx.GRPCClient != nil { + return grpc.NewClient(validator.ClientCtx) + } + grpcUrl := fmt.Sprintf("http://%s", validator.AppConfig.GRPC.Address) + client, err := grpc.DailClient(grpcUrl, ctx) + suite.Require().NoError(err) + return client +} diff --git a/tests/migrate_test.go b/tests/integration/migrate_test.go similarity index 56% rename from tests/migrate_test.go rename to tests/integration/migrate_test.go index 9c239a0f..e7744ad8 100644 --- a/tests/migrate_test.go +++ b/tests/integration/migrate_test.go @@ -1,4 +1,4 @@ -package tests +package integration import ( "encoding/hex" @@ -6,14 +6,11 @@ import ( "time" sdkmath "cosmossdk.io/math" - "github.com/cosmos/cosmos-sdk/crypto/hd" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/evmos/ethermint/crypto/ethsecp256k1" - hd2 "github.com/evmos/ethermint/crypto/hd" "github.com/stretchr/testify/require" "github.com/functionx/fx-core/v8/testutil/helpers" @@ -21,83 +18,79 @@ import ( migratetypes "github.com/functionx/fx-core/v8/x/migrate/types" ) -func (suite *IntegrationTest) migrateAccount(fromPrivateKey, toPrivateKey cryptotypes.PrivKey) { - fromAddr := sdk.AccAddress(fromPrivateKey.PubKey().Address().Bytes()) - toAddress := common.BytesToAddress(toPrivateKey.PubKey().Address()) +func (suite *IntegrationTest) migrateAccount(fromSigner, toSigner *helpers.Signer) { + fromAddr := fromSigner.AccAddress() + toAddress := toSigner.Address() - migrateSign, err := toPrivateKey.Sign(migratetypes.MigrateAccountSignatureHash(fromAddr, toAddress.Bytes())) + migrateSign, err := toSigner.PrivKey().Sign(migratetypes.MigrateAccountSignatureHash(fromAddr, toAddress.Bytes())) suite.Require().NoError(err) msg := migratetypes.NewMsgMigrateAccount(fromAddr, toAddress, hex.EncodeToString(migrateSign)) - suite.BroadcastTx(fromPrivateKey, msg) + suite.BroadcastTx(fromSigner, msg) } func (suite *IntegrationTest) MigrateTestDelegate() { - fromPrivKey, err := helpers.PrivKeyFromMnemonic(helpers.NewMnemonic(), hd.Secp256k1Type, 0, 0) - suite.Require().NoError(err) - fromAccAddress := fromPrivKey.PubKey().Address().Bytes() + fromSigner := helpers.NewSigner(helpers.NewPriKey()) + fromAccAddress := fromSigner.AccAddress() amount := sdkmath.NewInt(20).MulRaw(1e18) suite.Send(fromAccAddress, suite.NewCoin(amount)) - suite.CheckBalance(fromAccAddress, suite.NewCoin(amount)) + suite.EqualBalance(fromAccAddress, suite.NewCoin(amount)) - valAddress := suite.QueryValidatorByToken() + valAddress := suite.GetValSortByToken() delegateAmount := suite.NewCoin(sdkmath.NewInt(1).MulRaw(1e18)) - suite.Delegate(fromPrivKey, valAddress, delegateAmount) + suite.Delegate(fromSigner, valAddress, delegateAmount) amount = amount.Sub(sdkmath.NewInt(3).MulRaw(1e18)) - suite.CheckBalance(fromAccAddress, suite.NewCoin(amount)) - suite.CheckDelegate(fromAccAddress, valAddress, delegateAmount) + suite.EqualBalance(fromAccAddress, suite.NewCoin(amount)) + suite.EqualDelegate(fromAccAddress, valAddress, delegateAmount) withdrawAddr := sdk.AccAddress(helpers.NewPriKey().PubKey().Address().Bytes()) - suite.SetWithdrawAddr(fromPrivKey, withdrawAddr) + suite.SetWithdrawAddress(fromSigner, withdrawAddr) amount = amount.Sub(sdkmath.NewInt(2).MulRaw(1e18)) - suite.CheckBalance(fromAccAddress, suite.NewCoin(amount)) - suite.CheckWithdrawAddr(fromAccAddress, withdrawAddr) + suite.EqualBalance(fromAccAddress, suite.NewCoin(amount)) // ===> migration - toPrivKey, err := helpers.PrivKeyFromMnemonic(helpers.NewMnemonic(), hd2.EthSecp256k1Type, 0, 0) - suite.Require().NoError(err) - toAccAddress := sdk.AccAddress(toPrivKey.PubKey().Address().Bytes()) - suite.CheckBalance(toAccAddress, suite.NewCoin(sdkmath.ZeroInt())) + toSigner := helpers.NewSigner(helpers.NewEthPrivKey()) + toAccAddress := toSigner.AccAddress() + suite.EqualBalance(toAccAddress, suite.NewCoin(sdkmath.ZeroInt())) - suite.migrateAccount(fromPrivKey, toPrivKey) + suite.migrateAccount(fromSigner, toSigner) amount = amount.Sub(sdkmath.NewInt(2).MulRaw(1e18)) - suite.CheckBalance(fromAccAddress, suite.NewCoin(sdkmath.ZeroInt())) - suite.CheckDelegate(fromAccAddress, valAddress, suite.NewCoin(sdkmath.ZeroInt())) + suite.EqualBalance(fromAccAddress, suite.NewCoin(sdkmath.ZeroInt())) + suite.EqualDelegate(fromAccAddress, valAddress, suite.NewCoin(sdkmath.ZeroInt())) - suite.CheckBalance(toAccAddress, suite.NewCoin(amount)) - suite.CheckDelegate(toAccAddress, valAddress, delegateAmount) - suite.CheckWithdrawAddr(toAccAddress, toAccAddress) + suite.EqualBalance(toAccAddress, suite.NewCoin(amount)) + suite.EqualDelegate(toAccAddress, valAddress, delegateAmount) + suite.EqualWithdrawAddr(toAccAddress, toAccAddress) - suite.Delegate(toPrivKey, valAddress, suite.NewCoin(sdkmath.NewInt(1).MulRaw(1e18))) + suite.Delegate(toSigner, valAddress, suite.NewCoin(sdkmath.NewInt(1).MulRaw(1e18))) amount = amount.Sub(sdkmath.NewInt(3).MulRaw(1e18)) - balances := suite.QueryBalances(toAccAddress) + balances := suite.GetAllBalances(toAccAddress) suite.True(balances.AmountOf(fxtypes.DefaultDenom).GT(amount)) delegateAmount = delegateAmount.Add(suite.NewCoin(sdkmath.NewInt(1).MulRaw(1e18))) - suite.CheckDelegate(toAccAddress, valAddress, delegateAmount) + suite.EqualDelegate(toAccAddress, valAddress, delegateAmount) - suite.WithdrawReward(toPrivKey, valAddress) + suite.WithdrawReward(toSigner, valAddress) amount = amount.Sub(sdkmath.NewInt(2).MulRaw(1e18)) - balances2 := suite.QueryBalances(toAccAddress) + balances2 := suite.GetAllBalances(toAccAddress) suite.True(balances2.AmountOf(fxtypes.DefaultDenom).GT(amount)) } func (suite *IntegrationTest) MigrateTestUnDelegate() { - fromPrivKey, err := helpers.PrivKeyFromMnemonic(helpers.NewMnemonic(), hd.Secp256k1Type, 0, 0) - suite.Require().NoError(err) - fromAccAddress := fromPrivKey.PubKey().Address().Bytes() + fromSigner := helpers.NewSigner(helpers.NewPriKey()) + fromAccAddress := fromSigner.AccAddress() amount := sdkmath.NewInt(20).MulRaw(1e18) suite.Send(fromAccAddress, suite.NewCoin(amount)) - valAddress := suite.QueryValidatorByToken() + valAddress := suite.GetValSortByToken() delegateAmount := suite.NewCoin(sdkmath.NewInt(2).MulRaw(1e18)) - suite.Delegate(fromPrivKey, valAddress, delegateAmount) + suite.Delegate(fromSigner, valAddress, delegateAmount) amount = amount.Sub(sdkmath.NewInt(2 + 2).MulRaw(1e18)) delegateAmount = delegateAmount.Sub(suite.NewCoin(sdkmath.NewInt(1).MulRaw(1e18))) - txResponse := suite.Undelegate(fromPrivKey, valAddress, delegateAmount) + txResponse := suite.Undelegate(fromSigner, valAddress, delegateAmount) amount = amount.Sub(sdkmath.NewInt(2).MulRaw(1e18)) block := suite.QueryBlockByTxHash(txResponse.TxHash) @@ -107,21 +100,20 @@ func (suite *IntegrationTest) MigrateTestUnDelegate() { InitialBalance: delegateAmount.Amount, Balance: delegateAmount.Amount, } - suite.CheckUndelegate(fromAccAddress, valAddress, unbondingDelegationEntry) + suite.EqualUndelegate(fromAccAddress, valAddress, unbondingDelegationEntry) // ===> migration - toPrivKey, err := helpers.PrivKeyFromMnemonic(helpers.NewMnemonic(), hd2.EthSecp256k1Type, 0, 0) - suite.Require().NoError(err) - toAccAddress := sdk.AccAddress(toPrivKey.PubKey().Address().Bytes()) + toSigner := helpers.NewSigner(helpers.NewEthPrivKey()) + toAccAddress := toSigner.AccAddress() - suite.migrateAccount(fromPrivKey, toPrivKey) + suite.migrateAccount(fromSigner, toSigner) amount = amount.Sub(sdkmath.NewInt(2).MulRaw(1e18)) - balances2 := suite.QueryBalances(toAccAddress) + balances2 := suite.GetAllBalances(toAccAddress) suite.True(balances2.AmountOf(fxtypes.DefaultDenom).GT(amount)) - suite.CheckDelegate(toAccAddress, valAddress, delegateAmount) - suite.CheckUndelegate(toAccAddress, valAddress, unbondingDelegationEntry) + suite.EqualDelegate(toAccAddress, valAddress, delegateAmount) + suite.EqualUndelegate(toAccAddress, valAddress, unbondingDelegationEntry) } func TestSignature(t *testing.T) { diff --git a/tests/staking_test.go b/tests/integration/staking_percompile_test.go similarity index 53% rename from tests/staking_test.go rename to tests/integration/staking_percompile_test.go index 087d613d..839313b1 100644 --- a/tests/staking_test.go +++ b/tests/integration/staking_percompile_test.go @@ -1,4 +1,4 @@ -package tests +package integration import ( "math/big" @@ -8,58 +8,54 @@ import ( stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/ethereum/go-ethereum/common" + "github.com/functionx/fx-core/v8/contract" "github.com/functionx/fx-core/v8/testutil/helpers" fxtypes "github.com/functionx/fx-core/v8/types" - stakingprecompile "github.com/functionx/fx-core/v8/x/staking/precompile" ) func (suite *IntegrationTest) StakingTest() { + signer := helpers.NewSigner(helpers.NewEthPrivKey()) + var ( - delAddr = suite.staking.AccAddress() - valAddr = suite.staking.GetFirstValAddr() - initBalance = sdkmath.NewInt(2000).MulRaw(1e18) - delBalance = sdkmath.NewInt(1000).MulRaw(1e18) + valAddr = suite.GetValAddr() + delBalance = sdkmath.NewInt(1000).MulRaw(1e18) ) - suite.Send(delAddr, sdk.NewCoin(fxtypes.DefaultDenom, initBalance)) + suite.Send(signer.AccAddress(), suite.NewStakingCoin(2000, 18)) - // delegate - suite.staking.DelegateV2(suite.staking.privKey, valAddr.String(), delBalance.BigInt()) + stakingSuite := NewStakingSuite(suite.EthSuite, common.HexToAddress(contract.StakingAddress), signer) + stakingSuite.DelegateV2(valAddr.String(), delBalance.BigInt()) - // query delegate - share, delegateAmount := suite.staking.Delegation(valAddr.String(), suite.staking.Address()) - query, err := suite.staking.StakingQuery().Delegation(suite.ctx, &stakingtypes.QueryDelegationRequest{DelegatorAddr: delAddr.String(), ValidatorAddr: valAddr.String()}) - suite.Require().NoError(err) + share, delegateAmount := stakingSuite.Delegation(valAddr.String(), signer.Address()) + + delegation := suite.GetDelegation(signer.AccAddress(), valAddr) suite.Require().EqualValues(delegateAmount.String(), delegateAmount.String()) - suite.Require().EqualValues(share.String(), query.DelegationResponse.Delegation.GetShares().TruncateInt().BigInt().String()) - suite.Require().EqualValues(delegateAmount.String(), query.DelegationResponse.GetBalance().Amount.String()) + suite.Require().EqualValues(share.String(), delegation.Delegation.GetShares().TruncateInt().BigInt().String()) + suite.Require().EqualValues(delegateAmount.String(), delegation.GetBalance().Amount.String()) - // set WithdrawAddress - rewardAddress := sdk.AccAddress(helpers.NewEthPrivKey().Bytes()) - suite.staking.SetWithdrawAddress(rewardAddress) + rewardAddress := helpers.GenAccAddress() + suite.SetWithdrawAddress(stakingSuite.signer, rewardAddress) // delegation rewards - rewards := suite.staking.Rewards(valAddr.String(), suite.staking.Address()) + rewards := stakingSuite.Rewards(valAddr.String(), signer.Address()) suite.Require().EqualValues(1, rewards.Cmp(big.NewInt(0))) - delegationRewards := suite.staking.DelegationRewards(delAddr.String(), valAddr.String()) + delegationRewards := suite.DelegationRewards(signer.AccAddress().String(), valAddr.String()) suite.Require().EqualValues(1, delegationRewards.AmountOf(fxtypes.DefaultDenom).TruncateInt().BigInt().Cmp(big.NewInt(0))) - beforeBalance := suite.QueryBalances(rewardAddress) + beforeBalance := suite.GetAllBalances(rewardAddress) suite.Require().True(beforeBalance.IsZero()) - // withdrawReward - suite.staking.WithdrawReward(suite.staking.privKey, valAddr.String()) - afterBalance := suite.QueryBalances(rewardAddress) + suite.WithdrawReward(stakingSuite.signer, valAddr) + afterBalance := suite.GetAllBalances(rewardAddress) suite.Require().True(afterBalance.IsAllGTE(beforeBalance)) - // undelegate - suite.staking.UnDelegateV2(suite.staking.privKey, valAddr.String(), delBalance.BigInt()) - afterBalance2 := suite.QueryBalances(rewardAddress) + stakingSuite.UnDelegateV2(valAddr.String(), delBalance.BigInt()) + afterBalance2 := suite.GetAllBalances(rewardAddress) suite.Require().True(afterBalance2.IsAllGTE(beforeBalance)) } func (suite *IntegrationTest) StakingContractTest() { var ( delSigner = helpers.NewSigner(helpers.NewEthPrivKey()) - valAddr = suite.staking.GetFirstValAddr() + valAddr = suite.GetValAddr() initBalance = sdkmath.NewInt(2000).MulRaw(1e18) delBalance = sdkmath.NewInt(1000).MulRaw(1e18) ) @@ -67,58 +63,49 @@ func (suite *IntegrationTest) StakingContractTest() { suite.Send(delSigner.AccAddress(), sdk.NewCoin(fxtypes.DefaultDenom, initBalance)) // deploy contract to staking - contract, txHash := suite.staking.DeployStakingContract(delSigner.PrivKey()) - txFee1 := suite.evm.TxFee(txHash) + contractAddr, txHash := suite.DeployStaking(delSigner) + txFee1 := suite.TxFee(txHash) + + stakingSuite := NewStakingSuite(suite.EthSuite, contractAddr, delSigner) // delegate by contract - receipt := suite.staking.DelegateV2(delSigner.PrivKey(), valAddr.String(), delBalance.BigInt()) - txFee2 := suite.evm.TxFee(receipt.TxHash) + receipt := stakingSuite.DelegateV2(valAddr.String(), delBalance.BigInt()) + txFee2 := suite.TxFee(receipt.TxHash) - delBal := suite.QueryBalances(delSigner.AccAddress()) + delBal := suite.GetAllBalances(delSigner.AccAddress()) total := delBalance.Add(sdkmath.NewIntFromBigInt(txFee1)).Add(sdkmath.NewIntFromBigInt(txFee2)).Add(delBal.AmountOf(fxtypes.DefaultDenom)) suite.Require().Equal(initBalance.String(), total.String()) // query delegate by contract - shares, amount := suite.staking.Delegation(valAddr.String(), contract) + shares, amount := stakingSuite.Delegation(valAddr.String(), contractAddr) suite.Require().Equal(delBalance.BigInt().String(), amount.String()) // withdraw by contract - delBal = suite.QueryBalances(contract.Bytes()) + delBal = suite.GetAllBalances(contractAddr.Bytes()) suite.Require().True(delBal.IsZero()) - receipt = suite.staking.WithdrawByContract(delSigner.PrivKey(), contract, valAddr.String()) - txFee3 := suite.evm.TxFee(receipt.TxHash) - - withdrawMethod := stakingprecompile.NewWithdrawMethod(nil) - for _, log := range receipt.Logs { - if log.Address == suite.staking.stakingContract && log.Topics[0] == withdrawMethod.Event.ID { - unpack, err := withdrawMethod.Event.Inputs.NonIndexed().Unpack(log.Data) - suite.Require().NoError(err) - reward := unpack[1].(*big.Int) - delBal = suite.QueryBalances(contract.Bytes()) - suite.Require().Equal(reward.String(), delBal.AmountOf(fxtypes.DefaultDenom).BigInt().String()) - } - } + receipt = stakingSuite.Withdraw(valAddr.String()) + txFee3 := suite.TxFee(receipt.TxHash) - delBal = suite.QueryBalances(contract.Bytes()) + delBal = suite.GetAllBalances(contractAddr.Bytes()) suite.Require().True(delBal.AmountOf(fxtypes.DefaultDenom).GT(sdkmath.NewInt(0))) // undelegate by contract - receipt = suite.staking.UnDelegateV2(delSigner.PrivKey(), valAddr.String(), shares) - txFee4 := suite.evm.TxFee(receipt.TxHash) + receipt = stakingSuite.UnDelegateV2(valAddr.String(), shares) + txFee4 := suite.TxFee(receipt.TxHash) - delBal = suite.QueryBalances(delSigner.AccAddress()) + delBal = suite.GetAllBalances(delSigner.AccAddress()) txFee := sdkmath.NewIntFromBigInt(txFee1).Add(sdkmath.NewIntFromBigInt(txFee2).Add( sdkmath.NewIntFromBigInt(txFee3).Add(sdkmath.NewIntFromBigInt(txFee4)))) total = delBalance.Add(txFee).Add(delBal.AmountOf(fxtypes.DefaultDenom)) suite.Require().Equal(initBalance.String(), total.String()) // query delegate by contract - shares, amount = suite.staking.Delegation(valAddr.String(), contract) + shares, amount = stakingSuite.Delegation(valAddr.String(), contractAddr) suite.Require().Equal(amount.String(), big.NewInt(0).String()) suite.Require().Equal(shares.String(), big.NewInt(0).String()) - resp, err := suite.GRPCClient().StakingQuery().UnbondingDelegation(suite.ctx, &stakingtypes.QueryUnbondingDelegationRequest{ - DelegatorAddr: sdk.AccAddress(contract.Bytes()).String(), + resp, err := suite.StakingQuery().UnbondingDelegation(suite.ctx, &stakingtypes.QueryUnbondingDelegationRequest{ + DelegatorAddr: sdk.AccAddress(contractAddr.Bytes()).String(), ValidatorAddr: valAddr.String(), }) suite.Require().NoError(err) @@ -130,152 +117,154 @@ func (suite *IntegrationTest) StakingSharesTest() { var ( delSigner = helpers.NewSigner(helpers.NewEthPrivKey()) receiptSigner = helpers.NewSigner(helpers.NewEthPrivKey()) - valAddr = suite.staking.GetFirstValAddr() + valAddr = suite.GetValAddr() initBalance = sdkmath.NewInt(2000).MulRaw(1e18) delBalance = sdkmath.NewInt(1000).MulRaw(1e18) receiptInitBalance = sdkmath.NewInt(100).MulRaw(1e18) ) + stakingSuite := NewStakingSuite(suite.EthSuite, common.HexToAddress(contract.StakingAddress), delSigner) suite.Send(delSigner.AccAddress(), sdk.NewCoin(fxtypes.DefaultDenom, initBalance)) + receiptAccAddr := receiptSigner.AccAddress() receiptEthAddr := receiptSigner.Address() suite.Send(receiptAccAddr, sdk.NewCoin(fxtypes.DefaultDenom, receiptInitBalance)) // delegate - receipt := suite.staking.DelegateV2(delSigner.PrivKey(), valAddr.String(), delBalance.BigInt()) - txFee1 := suite.evm.TxFee(receipt.TxHash) + receipt := stakingSuite.DelegateV2(valAddr.String(), delBalance.BigInt()) + txFee1 := suite.TxFee(receipt.TxHash) // check receipt delegate - _, amount := suite.staking.Delegation(valAddr.String(), receiptEthAddr) + _, amount := stakingSuite.Delegation(valAddr.String(), receiptEthAddr) suite.Require().Equal(big.NewInt(0).String(), amount.String()) // check del delegate delSignerAddr := delSigner.Address() - shares, amount := suite.staking.Delegation(valAddr.String(), delSignerAddr) + shares, amount := stakingSuite.Delegation(valAddr.String(), delSignerAddr) suite.Require().Equal(delBalance.BigInt().String(), amount.String()) halfShares := big.NewInt(0).Div(shares, big.NewInt(2)) // transfer shares - receipt = suite.staking.TransferShares(delSigner.PrivKey(), valAddr.String(), receiptEthAddr, halfShares) - txFee2 := suite.evm.TxFee(receipt.TxHash) + receipt = stakingSuite.TransferShares(valAddr.String(), receiptEthAddr, halfShares) + txFee2 := suite.TxFee(receipt.TxHash) - reward1 := suite.staking.LogReward(receipt.Logs, valAddr.String(), delSignerAddr) + reward1 := stakingSuite.LogReward(receipt.Logs, valAddr.String(), delSignerAddr) // check del delegate - shares, _ = suite.staking.Delegation(valAddr.String(), delSignerAddr) + shares, _ = stakingSuite.Delegation(valAddr.String(), delSignerAddr) suite.Require().Equal(shares, halfShares) // check receipt delegate - shares, _ = suite.staking.Delegation(valAddr.String(), receiptEthAddr) + shares, _ = stakingSuite.Delegation(valAddr.String(), receiptEthAddr) suite.Require().Equal(shares, halfShares) // check del balance - delBal := suite.QueryBalances(delSigner.AccAddress()) + delBal := suite.GetAllBalances(delSigner.AccAddress()) txFee := sdkmath.NewIntFromBigInt(txFee1).Add(sdkmath.NewIntFromBigInt(txFee2)) total := delBalance.Add(txFee).Add(delBal.AmountOf(fxtypes.DefaultDenom)).Sub(sdkmath.NewIntFromBigInt(reward1)) suite.Require().Equal(initBalance.String(), total.String()) // transfer shares - receipt = suite.staking.TransferShares(delSigner.PrivKey(), valAddr.String(), receiptEthAddr, halfShares) - txFee3 := suite.evm.TxFee(receipt.TxHash) + receipt = stakingSuite.TransferShares(valAddr.String(), receiptEthAddr, halfShares) + txFee3 := suite.TxFee(receipt.TxHash) - reward2 := suite.staking.LogReward(receipt.Logs, valAddr.String(), delSignerAddr) - reward3 := suite.staking.LogReward(receipt.Logs, valAddr.String(), receiptEthAddr) + reward2 := stakingSuite.LogReward(receipt.Logs, valAddr.String(), delSignerAddr) + reward3 := stakingSuite.LogReward(receipt.Logs, valAddr.String(), receiptEthAddr) // check del delegate - shares, _ = suite.staking.Delegation(valAddr.String(), delSignerAddr) + shares, _ = stakingSuite.Delegation(valAddr.String(), delSignerAddr) suite.Require().Equal(shares.String(), big.NewInt(0).String()) // check receipt delegate - shares, _ = suite.staking.Delegation(valAddr.String(), receiptEthAddr) + shares, _ = stakingSuite.Delegation(valAddr.String(), receiptEthAddr) suite.Require().Equal(shares.String(), big.NewInt(0).Mul(big.NewInt(2), halfShares).String()) // check del balance - delBal = suite.QueryBalances(delSigner.AccAddress()) + delBal = suite.GetAllBalances(delSigner.AccAddress()) txFee = sdkmath.NewIntFromBigInt(txFee1).Add(sdkmath.NewIntFromBigInt(txFee2).Add(sdkmath.NewIntFromBigInt(txFee3))) total = delBalance.Add(txFee).Add(delBal.AmountOf(fxtypes.DefaultDenom)).Sub(sdkmath.NewIntFromBigInt(reward1)).Sub(sdkmath.NewIntFromBigInt(reward2)) suite.Require().Equal(initBalance.String(), total.String()) // check receipt balance receiptExpectBalance := receiptInitBalance.Add(sdkmath.NewIntFromBigInt(reward3)) - suite.CheckBalance(receiptAccAddr, sdk.NewCoin(fxtypes.DefaultDenom, receiptExpectBalance)) + suite.EqualBalance(receiptAccAddr, sdk.NewCoin(fxtypes.DefaultDenom, receiptExpectBalance)) // approve - receipt = suite.staking.ApproveShares(receiptSigner.PrivKey(), valAddr.String(), delSignerAddr, big.NewInt(0).Mul(big.NewInt(3), halfShares)) - txFee4 := suite.evm.TxFee(receipt.TxHash) + receipt = stakingSuite.WithSigner(receiptSigner).ApproveShares(valAddr.String(), delSignerAddr, big.NewInt(0).Mul(big.NewInt(3), halfShares)) + txFee4 := suite.TxFee(receipt.TxHash) // check approve - allowance := suite.staking.AllowanceShares(valAddr.String(), receiptEthAddr, delSignerAddr) + allowance := stakingSuite.AllowanceShares(valAddr.String(), receiptEthAddr, delSignerAddr) suite.Require().Equal(big.NewInt(0).Mul(big.NewInt(3), halfShares).String(), allowance.String()) // check receipt balance receiptExpectBalance = receiptExpectBalance.Sub(sdkmath.NewIntFromBigInt(txFee4)) - suite.CheckBalance(receiptAccAddr, sdk.NewCoin(fxtypes.DefaultDenom, receiptExpectBalance)) + suite.EqualBalance(receiptAccAddr, sdk.NewCoin(fxtypes.DefaultDenom, receiptExpectBalance)) // transfer from - receipt = suite.staking.TransferFromShares(delSigner.PrivKey(), valAddr.String(), receiptEthAddr, delSignerAddr, halfShares) - txFee5 := suite.evm.TxFee(receipt.TxHash) + receipt = stakingSuite.TransferFromShares(valAddr.String(), receiptEthAddr, delSignerAddr, halfShares) + txFee5 := suite.TxFee(receipt.TxHash) - reward4 := suite.staking.LogReward(receipt.Logs, valAddr.String(), receiptEthAddr) + reward4 := stakingSuite.LogReward(receipt.Logs, valAddr.String(), receiptEthAddr) receiptExpectBalance = receiptExpectBalance.Add(sdkmath.NewIntFromBigInt(reward4)) // check del delegate - shares, _ = suite.staking.Delegation(valAddr.String(), delSignerAddr) + shares, _ = stakingSuite.Delegation(valAddr.String(), delSignerAddr) suite.Require().Equal(shares.String(), halfShares.String()) // check receipt delegate - shares, _ = suite.staking.Delegation(valAddr.String(), receiptEthAddr) + shares, _ = stakingSuite.Delegation(valAddr.String(), receiptEthAddr) suite.Require().Equal(shares.String(), halfShares.String()) // check del balance - delBal = suite.QueryBalances(delSigner.AccAddress()) + delBal = suite.GetAllBalances(delSigner.AccAddress()) txFee = sdkmath.NewIntFromBigInt(txFee1).Add(sdkmath.NewIntFromBigInt(txFee2).Add(sdkmath.NewIntFromBigInt(txFee3).Add(sdkmath.NewIntFromBigInt(txFee5)))) total = delBalance.Add(txFee).Add(delBal.AmountOf(fxtypes.DefaultDenom)).Sub(sdkmath.NewIntFromBigInt(reward1)).Sub(sdkmath.NewIntFromBigInt(reward2)) suite.Require().Equal(initBalance.String(), total.String()) // check receipt balance - suite.CheckBalance(receiptAccAddr, sdk.NewCoin(fxtypes.DefaultDenom, receiptExpectBalance)) + suite.EqualBalance(receiptAccAddr, sdk.NewCoin(fxtypes.DefaultDenom, receiptExpectBalance)) // check approve - allowance = suite.staking.AllowanceShares(valAddr.String(), receiptEthAddr, delSignerAddr) + allowance = stakingSuite.AllowanceShares(valAddr.String(), receiptEthAddr, delSignerAddr) suite.Require().Equal(big.NewInt(0).Mul(big.NewInt(2), halfShares).String(), allowance.String()) // transfer from - receipt = suite.staking.TransferFromShares(delSigner.PrivKey(), valAddr.String(), receiptEthAddr, delSignerAddr, halfShares) - txFee6 := suite.evm.TxFee(receipt.TxHash) + receipt = stakingSuite.TransferFromShares(valAddr.String(), receiptEthAddr, delSignerAddr, halfShares) + txFee6 := suite.TxFee(receipt.TxHash) - reward5 := suite.staking.LogReward(receipt.Logs, valAddr.String(), delSignerAddr) - reward6 := suite.staking.LogReward(receipt.Logs, valAddr.String(), receiptEthAddr) + reward5 := stakingSuite.LogReward(receipt.Logs, valAddr.String(), delSignerAddr) + reward6 := stakingSuite.LogReward(receipt.Logs, valAddr.String(), receiptEthAddr) receiptExpectBalance = receiptExpectBalance.Add(sdkmath.NewIntFromBigInt(reward6)) // check del delegate - shares, _ = suite.staking.Delegation(valAddr.String(), delSignerAddr) + shares, _ = stakingSuite.Delegation(valAddr.String(), delSignerAddr) suite.Require().Equal(shares.String(), big.NewInt(0).Mul(big.NewInt(2), halfShares).String()) // check receipt delegate - shares, _ = suite.staking.Delegation(valAddr.String(), receiptEthAddr) + shares, _ = stakingSuite.Delegation(valAddr.String(), receiptEthAddr) suite.Require().Equal(shares.String(), big.NewInt(0).String()) // check del balance - delBal = suite.QueryBalances(delSigner.AccAddress()) + delBal = suite.GetAllBalances(delSigner.AccAddress()) txFee = sdkmath.NewIntFromBigInt(txFee1).Add(sdkmath.NewIntFromBigInt(txFee2).Add(sdkmath.NewIntFromBigInt(txFee3).Add(sdkmath.NewIntFromBigInt(txFee5).Add(sdkmath.NewIntFromBigInt(txFee6))))) totalReward := big.NewInt(0).Add(big.NewInt(0).Add(reward1, reward2), reward5) total = delBalance.Add(txFee).Add(delBal.AmountOf(fxtypes.DefaultDenom)).Sub(sdkmath.NewIntFromBigInt(totalReward)) suite.Require().Equal(initBalance.String(), total.String()) // check receipt balance - suite.CheckBalance(receiptAccAddr, sdk.NewCoin(fxtypes.DefaultDenom, receiptExpectBalance)) + suite.EqualBalance(receiptAccAddr, sdk.NewCoin(fxtypes.DefaultDenom, receiptExpectBalance)) // check approve - allowance = suite.staking.AllowanceShares(valAddr.String(), receiptEthAddr, delSignerAddr) + allowance = stakingSuite.AllowanceShares(valAddr.String(), receiptEthAddr, delSignerAddr) suite.Require().Equal(halfShares.String(), allowance.String()) } func (suite *IntegrationTest) StakingSharesContractTest() { var ( delSigner = helpers.NewSigner(helpers.NewEthPrivKey()) - valAddr = suite.staking.GetFirstValAddr() + valAddr = suite.GetValAddr() initBalance = sdkmath.NewInt(2000).MulRaw(1e18) delBalance = sdkmath.NewInt(1000).MulRaw(1e18) ) @@ -283,109 +272,111 @@ func (suite *IntegrationTest) StakingSharesContractTest() { suite.Send(delSigner.AccAddress(), sdk.NewCoin(fxtypes.DefaultDenom, initBalance)) // deploy contract to staking - contract, txHash := suite.staking.DeployStakingContract(delSigner.PrivKey()) - txFee1 := suite.evm.TxFee(txHash) + contractAddr, txHash := suite.DeployStaking(delSigner) + txFee1 := suite.TxFee(txHash) + + stakingSuite := NewStakingSuite(suite.EthSuite, contractAddr, delSigner) // delegate - receipt := suite.staking.DelegateV2(delSigner.PrivKey(), valAddr.String(), delBalance.BigInt()) - txFee2 := suite.evm.TxFee(receipt.TxHash) + receipt := stakingSuite.DelegateV2(valAddr.String(), delBalance.BigInt()) + txFee2 := suite.TxFee(receipt.TxHash) // check del balance - delBal := suite.QueryBalances(delSigner.AccAddress()) + delBal := suite.GetAllBalances(delSigner.AccAddress()) txFee := sdkmath.NewIntFromBigInt(txFee1).Add(sdkmath.NewIntFromBigInt(txFee2)) total := delBalance.Add(txFee).Add(delBal.AmountOf(fxtypes.DefaultDenom)) suite.Require().Equal(initBalance.String(), total.String()) // check contract delegate - _, amount := suite.staking.Delegation(valAddr.String(), contract) + _, amount := stakingSuite.Delegation(valAddr.String(), contractAddr) suite.Require().Equal(big.NewInt(0).String(), amount.String()) // check del delegate - shares, amount := suite.staking.Delegation(valAddr.String(), delSigner.Address()) + shares, amount := stakingSuite.Delegation(valAddr.String(), delSigner.Address()) suite.Require().Equal(delBalance.BigInt().String(), amount.String()) halfShares := big.NewInt(0).Div(shares, big.NewInt(2)) // approve - receipt = suite.staking.ApproveShares(delSigner.PrivKey(), valAddr.String(), contract, big.NewInt(0).Mul(big.NewInt(3), halfShares)) - txFee3 := suite.evm.TxFee(receipt.TxHash) + receipt = stakingSuite.ApproveShares(valAddr.String(), contractAddr, big.NewInt(0).Mul(big.NewInt(3), halfShares)) + txFee3 := suite.TxFee(receipt.TxHash) // check approve - allowance := suite.staking.AllowanceShares(valAddr.String(), delSigner.Address(), contract) + allowance := stakingSuite.AllowanceShares(valAddr.String(), delSigner.Address(), contractAddr) suite.Require().Equal(big.NewInt(0).Mul(big.NewInt(3), halfShares).String(), allowance.String()) // transferFromShares - receipt = suite.staking.TransferFromSharesByContract(delSigner.PrivKey(), valAddr.String(), contract, delSigner.Address(), contract, halfShares) - txFee4 := suite.evm.TxFee(receipt.TxHash) + receipt = stakingSuite.TransferFromShares(valAddr.String(), delSigner.Address(), contractAddr, halfShares) + txFee4 := suite.TxFee(receipt.TxHash) - reward1 := suite.staking.LogReward(receipt.Logs, valAddr.String(), delSigner.Address()) + reward1 := stakingSuite.LogReward(receipt.Logs, valAddr.String(), delSigner.Address()) // check del delegate - shares, _ = suite.staking.Delegation(valAddr.String(), delSigner.Address()) + shares, _ = stakingSuite.Delegation(valAddr.String(), delSigner.Address()) suite.Require().Equal(shares.String(), halfShares.String()) // check contract delegate - shares, _ = suite.staking.Delegation(valAddr.String(), contract) + shares, _ = stakingSuite.Delegation(valAddr.String(), contractAddr) suite.Require().Equal(shares.String(), halfShares.String()) // check del balance - delBal = suite.QueryBalances(delSigner.AccAddress()) + delBal = suite.GetAllBalances(delSigner.AccAddress()) txFee = sdkmath.NewIntFromBigInt(txFee1).Add(sdkmath.NewIntFromBigInt(txFee2).Add(sdkmath.NewIntFromBigInt(txFee3).Add(sdkmath.NewIntFromBigInt(txFee4)))) total = delBalance.Add(txFee).Add(delBal.AmountOf(fxtypes.DefaultDenom)).Sub(sdkmath.NewIntFromBigInt(reward1)) suite.Require().Equal(initBalance.String(), total.String()) // check contract balance - contractBal := suite.QueryBalances(contract.Bytes()) + contractBal := suite.GetAllBalances(contractAddr.Bytes()) suite.Require().Equal(contractBal.AmountOf(fxtypes.DefaultDenom).String(), big.NewInt(0).String()) // check approve - allowance = suite.staking.AllowanceShares(valAddr.String(), delSigner.Address(), contract) + allowance = stakingSuite.AllowanceShares(valAddr.String(), delSigner.Address(), contractAddr) suite.Require().Equal(big.NewInt(0).Mul(big.NewInt(2), halfShares).String(), allowance.String()) // transferFromShares - receipt = suite.staking.TransferFromSharesByContract(delSigner.PrivKey(), valAddr.String(), contract, delSigner.Address(), contract, halfShares) - txFee5 := suite.evm.TxFee(receipt.TxHash) - reward2 := suite.staking.LogReward(receipt.Logs, valAddr.String(), delSigner.Address()) - reward3 := suite.staking.LogReward(receipt.Logs, valAddr.String(), contract) + receipt = stakingSuite.TransferFromShares(valAddr.String(), delSigner.Address(), contractAddr, halfShares) + txFee5 := suite.TxFee(receipt.TxHash) + reward2 := stakingSuite.LogReward(receipt.Logs, valAddr.String(), delSigner.Address()) + reward3 := stakingSuite.LogReward(receipt.Logs, valAddr.String(), contractAddr) // check del delegate - shares, _ = suite.staking.Delegation(valAddr.String(), delSigner.Address()) + shares, _ = stakingSuite.Delegation(valAddr.String(), delSigner.Address()) suite.Require().Equal(shares.String(), big.NewInt(0).String()) // check contract delegate - shares, _ = suite.staking.Delegation(valAddr.String(), contract) + shares, _ = stakingSuite.Delegation(valAddr.String(), contractAddr) suite.Require().Equal(shares.String(), big.NewInt(0).Mul(big.NewInt(2), halfShares).String()) // check del balance - delBal = suite.QueryBalances(delSigner.AccAddress()) + delBal = suite.GetAllBalances(delSigner.AccAddress()) txFee = sdkmath.NewIntFromBigInt(txFee1).Add(sdkmath.NewIntFromBigInt(txFee2).Add(sdkmath.NewIntFromBigInt(txFee3).Add(sdkmath.NewIntFromBigInt(txFee4).Add(sdkmath.NewIntFromBigInt(txFee5))))) totalReward := sdkmath.NewIntFromBigInt(reward1).Add(sdkmath.NewIntFromBigInt(reward2)) total = delBalance.Add(txFee).Add(delBal.AmountOf(fxtypes.DefaultDenom)).Sub(totalReward) suite.Require().Equal(initBalance.String(), total.String()) // check contract balance - contractBal = suite.QueryBalances(contract.Bytes()) + contractBal = suite.GetAllBalances(contractAddr.Bytes()) suite.Require().Equal(contractBal.AmountOf(fxtypes.DefaultDenom).String(), reward3.String()) // check approve - allowance = suite.staking.AllowanceShares(valAddr.String(), delSigner.Address(), contract) + allowance = stakingSuite.AllowanceShares(valAddr.String(), delSigner.Address(), contractAddr) suite.Require().Equal(halfShares.String(), allowance.String()) // contract transfer - receipt = suite.staking.TransferSharesByContract(delSigner.PrivKey(), valAddr.String(), contract, delSigner.Address(), halfShares) - txFee6 := suite.evm.TxFee(receipt.TxHash) - reward4 := suite.staking.LogReward(receipt.Logs, valAddr.String(), contract) + receipt = stakingSuite.TransferShares(valAddr.String(), delSigner.Address(), halfShares) + txFee6 := suite.TxFee(receipt.TxHash) + reward4 := stakingSuite.LogReward(receipt.Logs, valAddr.String(), contractAddr) // check del delegate - shares, _ = suite.staking.Delegation(valAddr.String(), delSigner.Address()) + shares, _ = stakingSuite.Delegation(valAddr.String(), delSigner.Address()) suite.Require().Equal(shares.String(), halfShares.String()) // check contract delegate - shares, _ = suite.staking.Delegation(valAddr.String(), contract) + shares, _ = stakingSuite.Delegation(valAddr.String(), contractAddr) suite.Require().Equal(shares.String(), halfShares.String()) // check del balance - delBal = suite.QueryBalances(delSigner.AccAddress()) + delBal = suite.GetAllBalances(delSigner.AccAddress()) txFee = sdkmath.NewIntFromBigInt(txFee1).Add(sdkmath.NewIntFromBigInt(txFee2).Add(sdkmath.NewIntFromBigInt(txFee3). Add(sdkmath.NewIntFromBigInt(txFee4).Add(sdkmath.NewIntFromBigInt(txFee5).Add(sdkmath.NewIntFromBigInt(txFee6)))))) totalReward = sdkmath.NewIntFromBigInt(reward1).Add(sdkmath.NewIntFromBigInt(reward2)) @@ -393,25 +384,25 @@ func (suite *IntegrationTest) StakingSharesContractTest() { suite.Require().Equal(initBalance.String(), total.String()) // check contract balance - contractBal = suite.QueryBalances(contract.Bytes()) + contractBal = suite.GetAllBalances(contractAddr.Bytes()) suite.Require().Equal(contractBal.AmountOf(fxtypes.DefaultDenom).String(), big.NewInt(0).Add(reward3, reward4).String()) // contract transfer - receipt = suite.staking.TransferSharesByContract(delSigner.PrivKey(), valAddr.String(), contract, delSigner.Address(), halfShares) - txFee7 := suite.evm.TxFee(receipt.TxHash) - reward5 := suite.staking.LogReward(receipt.Logs, valAddr.String(), delSigner.Address()) - reward6 := suite.staking.LogReward(receipt.Logs, valAddr.String(), contract) + receipt = stakingSuite.TransferShares(valAddr.String(), delSigner.Address(), halfShares) + txFee7 := suite.TxFee(receipt.TxHash) + reward5 := stakingSuite.LogReward(receipt.Logs, valAddr.String(), delSigner.Address()) + reward6 := stakingSuite.LogReward(receipt.Logs, valAddr.String(), contractAddr) // check del delegate - shares, _ = suite.staking.Delegation(valAddr.String(), delSigner.Address()) + shares, _ = stakingSuite.Delegation(valAddr.String(), delSigner.Address()) suite.Require().Equal(shares.String(), big.NewInt(0).Mul(big.NewInt(2), halfShares).String()) // check contract delegate - shares, _ = suite.staking.Delegation(valAddr.String(), contract) + shares, _ = stakingSuite.Delegation(valAddr.String(), contractAddr) suite.Require().Equal(shares.String(), big.NewInt(0).String()) // check del balance - delBal = suite.QueryBalances(delSigner.AccAddress()) + delBal = suite.GetAllBalances(delSigner.AccAddress()) txFee = sdkmath.NewIntFromBigInt(txFee1).Add(sdkmath.NewIntFromBigInt(txFee2).Add(sdkmath.NewIntFromBigInt(txFee3). Add(sdkmath.NewIntFromBigInt(txFee4).Add(sdkmath.NewIntFromBigInt(txFee5).Add(sdkmath.NewIntFromBigInt(txFee6).Add(sdkmath.NewIntFromBigInt(txFee7))))))) totalReward = sdkmath.NewIntFromBigInt(reward1).Add(sdkmath.NewIntFromBigInt(reward2).Add(sdkmath.NewIntFromBigInt(reward5))) @@ -419,55 +410,57 @@ func (suite *IntegrationTest) StakingSharesContractTest() { suite.Require().Equal(initBalance.String(), total.String()) // check contract balance - contractBal = suite.QueryBalances(contract.Bytes()) + contractBal = suite.GetAllBalances(contractAddr.Bytes()) totalReward = sdkmath.NewIntFromBigInt(reward3).Add(sdkmath.NewIntFromBigInt(reward4).Add(sdkmath.NewIntFromBigInt(reward6))) suite.Require().Equal(contractBal.AmountOf(fxtypes.DefaultDenom).String(), totalReward.String()) } func (suite *IntegrationTest) StakingPrecompileRedelegateTest() { var ( - delSigner = helpers.NewSigner(helpers.NewEthPrivKey()) - valAddr = suite.staking.GetFirstValAddr() - valNew = helpers.NewSigner(helpers.NewEthPrivKey()) - initBalance = sdkmath.NewInt(2000).MulRaw(1e18) - delBalance = sdkmath.NewInt(1000).MulRaw(1e18) + delSigner = helpers.NewSigner(helpers.NewEthPrivKey()) + valAddr = suite.GetValAddr() + valNewSigner = helpers.NewSigner(helpers.NewEthPrivKey()) + initBalance = sdkmath.NewInt(2000).MulRaw(1e18) + delBalance = sdkmath.NewInt(1000).MulRaw(1e18) ) + stakingSuite := NewStakingSuite(suite.EthSuite, common.HexToAddress(contract.StakingAddress), delSigner) + suite.Send(delSigner.AccAddress(), sdk.NewCoin(fxtypes.DefaultDenom, initBalance)) - suite.Send(valNew.AccAddress(), sdk.NewCoin(fxtypes.DefaultDenom, initBalance)) + suite.Send(valNewSigner.AccAddress(), sdk.NewCoin(fxtypes.DefaultDenom, initBalance)) // delegate - receipt := suite.staking.DelegateV2(delSigner.PrivKey(), valAddr.String(), delBalance.BigInt()) - txFee1 := suite.evm.TxFee(receipt.TxHash) + receipt := stakingSuite.DelegateV2(valAddr.String(), delBalance.BigInt()) + txFee1 := suite.TxFee(receipt.TxHash) - delBal := suite.QueryBalances(delSigner.AccAddress()) + delBal := suite.GetAllBalances(delSigner.AccAddress()) total := delBalance.Add(sdkmath.NewIntFromBigInt(txFee1)).Add(delBal.AmountOf(fxtypes.DefaultDenom)) suite.Equal(initBalance.String(), total.String()) // set WithdrawAddress rewardAddress := sdk.AccAddress(helpers.NewEthPrivKey().PubKey().Address().Bytes()) - txRsp := suite.staking.SetWithdrawAddressWithResponse(delSigner.PrivKey(), rewardAddress) + txRsp := suite.SetWithdrawAddress(stakingSuite.signer, rewardAddress) gasPrice, err := sdk.ParseCoinNormalized(suite.network.Config.MinGasPrices) suite.Require().NoError(err) gasFee := gasPrice.Amount.Mul(sdkmath.NewInt(txRsp.GasWanted)) hexAddr := common.BytesToAddress(delSigner.AccAddress().Bytes()) // query delegate - valAddrShares1, _ := suite.staking.Delegation(valAddr.String(), hexAddr) + valAddrShares1, _ := stakingSuite.Delegation(valAddr.String(), hexAddr) - resp := suite.staking.CreateValidator(valNew.PrivKey(), false) + resp := suite.CreateValidator(valNewSigner, false) suite.Equal(resp.Code, uint32(0)) - receipt = suite.staking.RedelegateV2(delSigner.PrivKey(), valAddr.String(), sdk.ValAddress(valNew.AccAddress()).String(), valAddrShares1) - txFee2 := suite.evm.TxFee(receipt.TxHash) + receipt = stakingSuite.RedelegateV2(valAddr.String(), sdk.ValAddress(valNewSigner.AccAddress()).String(), valAddrShares1) + txFee2 := suite.TxFee(receipt.TxHash) - valAddrShares2, _ := suite.staking.Delegation(valAddr.String(), hexAddr) + valAddrShares2, _ := stakingSuite.Delegation(valAddr.String(), hexAddr) suite.Equal(big.NewInt(0).String(), valAddrShares2.String()) - valNewShares, _ := suite.staking.Delegation(sdk.ValAddress(valNew.AccAddress()).String(), hexAddr) + valNewShares, _ := stakingSuite.Delegation(sdk.ValAddress(valNewSigner.AccAddress()).String(), hexAddr) suite.Equal(valAddrShares1, valNewShares) - delBal = suite.QueryBalances(delSigner.AccAddress()) + delBal = suite.GetAllBalances(delSigner.AccAddress()) total = delBalance.Add(sdkmath.NewIntFromBigInt(txFee1)). Add(gasFee). Add(sdkmath.NewIntFromBigInt(txFee2)). @@ -478,7 +471,7 @@ func (suite *IntegrationTest) StakingPrecompileRedelegateTest() { func (suite *IntegrationTest) StakingPrecompileRedelegateByContractTest() { var ( delSigner = helpers.NewSigner(helpers.NewEthPrivKey()) - valAddr = suite.staking.GetFirstValAddr() + valAddr = suite.GetValAddr() valNew = helpers.NewSigner(helpers.NewEthPrivKey()) initBalance = sdkmath.NewInt(2000).MulRaw(1e18) delBalance = sdkmath.NewInt(1000).MulRaw(1e18) @@ -488,33 +481,35 @@ func (suite *IntegrationTest) StakingPrecompileRedelegateByContractTest() { suite.Send(valNew.AccAddress(), sdk.NewCoin(fxtypes.DefaultDenom, initBalance)) // deploy contract to staking - contract, txHash := suite.staking.DeployStakingContract(delSigner.PrivKey()) - txFee1 := suite.evm.TxFee(txHash) + contractAddr, txHash := suite.DeployStaking(delSigner) + txFee1 := suite.TxFee(txHash) + + stakingSuite := NewStakingSuite(suite.EthSuite, contractAddr, delSigner) // delegate by contract - receipt := suite.staking.DelegateV2(delSigner.PrivKey(), valAddr.String(), delBalance.BigInt()) - txFee2 := suite.evm.TxFee(receipt.TxHash) + receipt := stakingSuite.DelegateV2(valAddr.String(), delBalance.BigInt()) + txFee2 := suite.TxFee(receipt.TxHash) - delBal := suite.QueryBalances(delSigner.AccAddress()) + delBal := suite.GetAllBalances(delSigner.AccAddress()) total := delBalance.Add(sdkmath.NewIntFromBigInt(txFee1)).Add(sdkmath.NewIntFromBigInt(txFee2)).Add(delBal.AmountOf(fxtypes.DefaultDenom)) suite.Equal(initBalance.String(), total.String()) // query delegate - valAddrShares1, _ := suite.staking.Delegation(valAddr.String(), contract) + valAddrShares1, _ := stakingSuite.Delegation(valAddr.String(), contractAddr) - resp := suite.staking.CreateValidator(valNew.PrivKey(), false) + resp := suite.CreateValidator(valNew, false) suite.Equal(resp.Code, uint32(0)) - receipt = suite.staking.RedelegateV2(delSigner.PrivKey(), valAddr.String(), sdk.ValAddress(valNew.AccAddress()).String(), valAddrShares1) - txFee3 := suite.evm.TxFee(receipt.TxHash) + receipt = stakingSuite.RedelegateV2(valAddr.String(), sdk.ValAddress(valNew.AccAddress()).String(), valAddrShares1) + txFee3 := suite.TxFee(receipt.TxHash) - valAddrShares2, _ := suite.staking.Delegation(valAddr.String(), contract) + valAddrShares2, _ := stakingSuite.Delegation(valAddr.String(), contractAddr) suite.Equal(big.NewInt(0).String(), valAddrShares2.String()) - valNewShares, _ := suite.staking.Delegation(sdk.ValAddress(valNew.AccAddress()).String(), contract) + valNewShares, _ := stakingSuite.Delegation(sdk.ValAddress(valNew.AccAddress()).String(), contractAddr) suite.Equal(valAddrShares1, valNewShares) - delBal = suite.QueryBalances(delSigner.AccAddress()) + delBal = suite.GetAllBalances(delSigner.AccAddress()) total = delBalance.Add(sdkmath.NewIntFromBigInt(txFee1)). Add(sdkmath.NewIntFromBigInt(txFee2)). Add(sdkmath.NewIntFromBigInt(txFee3)). @@ -528,47 +523,49 @@ func (suite *IntegrationTest) StakingPrecompileV2() { initBalance := sdkmath.NewInt(2000).MulRaw(1e18) suite.Send(delSigner.AccAddress(), sdk.NewCoin(fxtypes.DefaultDenom, initBalance)) + stakingSuite := NewStakingSuite(suite.EthSuite, common.HexToAddress(contract.StakingAddress), delSigner) + // 2. delegate to first validator - valAddr := suite.staking.GetFirstValAddr() + valAddr := suite.GetValAddr() delBalance := sdkmath.NewInt(1000) - receipt := suite.staking.DelegateV2(delSigner.PrivKey(), valAddr.String(), delBalance.BigInt()) - txFee1 := suite.evm.TxFee(receipt.TxHash) + receipt := stakingSuite.DelegateV2(valAddr.String(), delBalance.BigInt()) + txFee1 := suite.TxFee(receipt.TxHash) - delBal := suite.QueryBalances(delSigner.AccAddress()) + delBal := suite.GetAllBalances(delSigner.AccAddress()) total := delBalance.Add(sdkmath.NewIntFromBigInt(txFee1)).Add(delBal.AmountOf(fxtypes.DefaultDenom)) suite.Equal(initBalance.String(), total.String()) hexAddr := common.BytesToAddress(delSigner.AccAddress().Bytes()) - _, delAmt1 := suite.staking.Delegation(valAddr.String(), hexAddr) + _, delAmt1 := stakingSuite.Delegation(valAddr.String(), hexAddr) suite.Equal(delAmt1.String(), delBalance.String()) halfDelegateAmount := big.NewInt(0).Div(delBalance.BigInt(), big.NewInt(2)) // 2. undelegate half of the first validator amount - suite.staking.UnDelegateV2(delSigner.PrivKey(), valAddr.String(), halfDelegateAmount) - _, delAmt2 := suite.staking.Delegation(valAddr.String(), hexAddr) + stakingSuite.UnDelegateV2(valAddr.String(), halfDelegateAmount) + _, delAmt2 := stakingSuite.Delegation(valAddr.String(), hexAddr) suite.Equal(halfDelegateAmount.String(), delAmt2.String()) // 3. create a new validator, and redelegate half of the first validator amount to it(new validator is not bonded) - valNew := helpers.NewSigner(helpers.NewEthPrivKey()) - suite.Send(valNew.AccAddress(), sdk.NewCoin(fxtypes.DefaultDenom, initBalance)) - resp := suite.staking.CreateValidator(valNew.PrivKey(), false) + valNewSigner := helpers.NewSigner(helpers.NewEthPrivKey()) + suite.Send(valNewSigner.AccAddress(), sdk.NewCoin(fxtypes.DefaultDenom, initBalance)) + resp := suite.CreateValidator(valNewSigner, false) suite.Equal(resp.Code, uint32(0)) // 4. redelegate half of the first validator amount to new validator - suite.staking.RedelegateV2(delSigner.PrivKey(), valAddr.String(), sdk.ValAddress(valNew.AccAddress()).String(), halfDelegateAmount) + stakingSuite.RedelegateV2(valAddr.String(), sdk.ValAddress(valNewSigner.AccAddress()).String(), halfDelegateAmount) - delShare, _ := suite.staking.Delegation(valAddr.String(), hexAddr) + delShare, _ := stakingSuite.Delegation(valAddr.String(), hexAddr) suite.Equal(int64(0), delShare.Int64()) // 5. check new validator's delegation amount, expecting half of the first validator amount - _, delAmt3 := suite.staking.Delegation(sdk.ValAddress(valNew.AccAddress()).String(), hexAddr) + _, delAmt3 := stakingSuite.Delegation(sdk.ValAddress(valNewSigner.AccAddress()).String(), hexAddr) suite.Equal(halfDelegateAmount.String(), delAmt3.String()) { // finally, clear the new validator - suite.staking.UnDelegateV2(delSigner.PrivKey(), sdk.ValAddress(valNew.AccAddress()).String(), halfDelegateAmount) - _, valSelfDelegation := suite.staking.Delegation(sdk.ValAddress(valNew.AccAddress()).String(), valNew.Address()) - suite.staking.UnDelegateV2(valNew.PrivKey(), sdk.ValAddress(valNew.AccAddress()).String(), valSelfDelegation) + stakingSuite.UnDelegateV2(sdk.ValAddress(valNewSigner.AccAddress()).String(), halfDelegateAmount) + _, valSelfDelegation := stakingSuite.Delegation(sdk.ValAddress(valNewSigner.AccAddress()).String(), valNewSigner.Address()) + stakingSuite.WithSigner(valNewSigner).UnDelegateV2(sdk.ValAddress(valNewSigner.AccAddress()).String(), valSelfDelegation) } } diff --git a/tests/integration/staking_precompile_suite.go b/tests/integration/staking_precompile_suite.go new file mode 100644 index 00000000..413f000a --- /dev/null +++ b/tests/integration/staking_precompile_suite.go @@ -0,0 +1,112 @@ +package integration + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + + "github.com/functionx/fx-core/v8/contract" + "github.com/functionx/fx-core/v8/testutil/helpers" + "github.com/functionx/fx-core/v8/x/staking/precompile" +) + +type StakingPrecompileSuite struct { + *EthSuite + + staking *contract.IStaking + signer *helpers.Signer +} + +func NewStakingSuite(suite *EthSuite, contractAddr common.Address, signer *helpers.Signer) *StakingPrecompileSuite { + staking, err := contract.NewIStaking(contractAddr, suite.ethCli) + suite.Require().NoError(err) + return &StakingPrecompileSuite{ + EthSuite: suite, + staking: staking, + signer: signer, + } +} + +func (suite *StakingPrecompileSuite) WithSigner(signer *helpers.Signer) *StakingPrecompileSuite { + return &StakingPrecompileSuite{ + EthSuite: suite.EthSuite, + staking: suite.staking, + signer: signer, + } +} + +func (suite *StakingPrecompileSuite) DelegateV2(valAddr string, delAmount *big.Int) *ethtypes.Receipt { + ethTx, err := suite.staking.DelegateV2(suite.TransactOpts(suite.signer), valAddr, delAmount) + suite.Require().NoError(err) + return suite.WaitMined(ethTx) +} + +func (suite *StakingPrecompileSuite) RedelegateV2(valSrc, valDst string, amount *big.Int) *ethtypes.Receipt { + ethTx, err := suite.staking.RedelegateV2(suite.TransactOpts(suite.signer), valSrc, valDst, amount) + suite.Require().NoError(err) + return suite.WaitMined(ethTx) +} + +func (suite *StakingPrecompileSuite) UnDelegateV2(valAddr string, amount *big.Int) *ethtypes.Receipt { + ethTx, err := suite.staking.UndelegateV2(suite.TransactOpts(suite.signer), valAddr, amount) + suite.Require().NoError(err) + return suite.WaitMined(ethTx) +} + +func (suite *StakingPrecompileSuite) Withdraw(valAddr string) *ethtypes.Receipt { + ethTx, err := suite.staking.Withdraw(suite.TransactOpts(suite.signer), valAddr) + suite.Require().NoError(err) + return suite.WaitMined(ethTx) +} + +func (suite *StakingPrecompileSuite) Delegation(valAddr string, delAddr common.Address) (*big.Int, *big.Int) { + delegation, err := suite.staking.Delegation(nil, valAddr, delAddr) + suite.Require().NoError(err) + return delegation.Shares, delegation.DelegateAmount +} + +func (suite *StakingPrecompileSuite) Rewards(valAddr string, delAddr common.Address) *big.Int { + rewards, err := suite.staking.DelegationRewards(nil, valAddr, delAddr) + suite.Require().NoError(err) + return rewards +} + +func (suite *StakingPrecompileSuite) TransferShares(valAddr string, receipt common.Address, shares *big.Int) *ethtypes.Receipt { + ethTx, err := suite.staking.TransferShares(suite.TransactOpts(suite.signer), valAddr, receipt, shares) + suite.Require().NoError(err) + return suite.WaitMined(ethTx) +} + +func (suite *StakingPrecompileSuite) TransferFromShares(valAddr string, from, receipt common.Address, shares *big.Int) *ethtypes.Receipt { + ethTx, err := suite.staking.TransferFromShares(suite.TransactOpts(suite.signer), valAddr, from, receipt, shares) + suite.Require().NoError(err) + return suite.WaitMined(ethTx) +} + +func (suite *StakingPrecompileSuite) ApproveShares(valAddr string, spender common.Address, shares *big.Int) *ethtypes.Receipt { + ethTx, err := suite.staking.ApproveShares(suite.TransactOpts(suite.signer), valAddr, spender, shares) + suite.Require().NoError(err) + return suite.WaitMined(ethTx) +} + +func (suite *StakingPrecompileSuite) AllowanceShares(valAddr string, owner, spender common.Address) *big.Int { + allowance, err := suite.staking.AllowanceShares(nil, valAddr, owner, spender) + suite.Require().NoError(err) + return allowance +} + +func (suite *StakingPrecompileSuite) LogReward(logs []*ethtypes.Log, valAddr string, addr common.Address) *big.Int { + withdrawABI := precompile.NewWithdrawABI() + for _, log := range logs { + if log.Address.String() == contract.StakingAddress && + log.Topics[0] == withdrawABI.Event.ID && + log.Topics[1] == addr.Hash() { + unpack, err := withdrawABI.Event.Inputs.NonIndexed().Unpack(log.Data) + suite.Require().NoError(err) + suite.Require().Equal(unpack[0].(string), valAddr) + return unpack[1].(*big.Int) + } + } + return big.NewInt(0) +} diff --git a/tests/integration_test.go b/tests/integration_test.go deleted file mode 100644 index 0438e093..00000000 --- a/tests/integration_test.go +++ /dev/null @@ -1,99 +0,0 @@ -package tests - -import ( - "fmt" - "os" - "runtime" - "testing" - - "github.com/stretchr/testify/suite" - - arbitrumtypes "github.com/functionx/fx-core/v8/x/arbitrum/types" - avalanchetypes "github.com/functionx/fx-core/v8/x/avalanche/types" - bsctypes "github.com/functionx/fx-core/v8/x/bsc/types" - ethtypes "github.com/functionx/fx-core/v8/x/eth/types" - layer2types "github.com/functionx/fx-core/v8/x/layer2/types" - optimismtypes "github.com/functionx/fx-core/v8/x/optimism/types" - polygontypes "github.com/functionx/fx-core/v8/x/polygon/types" - trontypes "github.com/functionx/fx-core/v8/x/tron/types" -) - -type IntegrationTest struct { - *TestSuite - crosschain []CrosschainTestSuite - // erc20 Erc20TestSuite - evm EvmTestSuite - staking StakingSuite - // precompile PrecompileTestSuite -} - -func TestIntegrationTest(t *testing.T) { - if os.Getenv("TEST_INTEGRATION") != "true" { - t.Skip("skip integration test") - } - - testSuite := NewTestSuite() - testingSuite := &IntegrationTest{ - TestSuite: testSuite, - crosschain: []CrosschainTestSuite{ - NewCrosschainWithTestSuite(ethtypes.ModuleName, testSuite), - NewCrosschainWithTestSuite(bsctypes.ModuleName, testSuite), - NewCrosschainWithTestSuite(trontypes.ModuleName, testSuite), - }, - // erc20: NewErc20TestSuite(testSuite), - evm: NewEvmTestSuite(testSuite), - staking: NewStakingSuite(testSuite), - // precompile: NewPrecompileTestSuite(testSuite), - } - if runtime.GOOS == "linux" { - evmChainModules := []string{ - polygontypes.ModuleName, - avalanchetypes.ModuleName, - arbitrumtypes.ModuleName, - optimismtypes.ModuleName, - layer2types.ModuleName, - } - for _, module := range evmChainModules { - testingSuite.crosschain = append( - testingSuite.crosschain, - NewCrosschainWithTestSuite(module, testSuite), - ) - } - } - - suite.Run(t, testingSuite) -} - -func (suite *IntegrationTest) TestRun() { - suite.CrosschainTest() - - suite.StakingTest() - suite.StakingContractTest() - suite.StakingSharesTest() - suite.StakingSharesContractTest() - suite.StakingPrecompileRedelegateTest() - suite.StakingPrecompileRedelegateByContractTest() - suite.StakingPrecompileV2() - - suite.MigrateTestDelegate() - suite.MigrateTestUnDelegate() - - suite.EVMWeb3Test() - suite.WFXTest() - suite.ERC20TokenTest() - suite.ERC721Test() - suite.CallContractTest() - suite.FIP20CodeCheckTest() - suite.WFXCodeCheckTest() - - suite.ByPassFeeTest() -} - -func (suite *IntegrationTest) GetByName(chainName string) CrosschainTestSuite { - for _, c := range suite.crosschain { - if c.chainName == chainName { - return c - } - } - panic(fmt.Sprintf("chain not found %s", chainName)) -} diff --git a/tests/staking_suite.go b/tests/staking_suite.go deleted file mode 100644 index 13798e2e..00000000 --- a/tests/staking_suite.go +++ /dev/null @@ -1,284 +0,0 @@ -package tests - -import ( - "context" - "math/big" - "time" - - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/authz" - distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" - slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - ethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - - "github.com/functionx/fx-core/v8/client" - "github.com/functionx/fx-core/v8/contract" - testscontract "github.com/functionx/fx-core/v8/tests/contract" - "github.com/functionx/fx-core/v8/testutil/helpers" - "github.com/functionx/fx-core/v8/x/staking/precompile" -) - -type StakingSuite struct { - Erc20TestSuite - grantKey cryptotypes.PrivKey - stakingContract common.Address -} - -func NewStakingSuite(ts *TestSuite) StakingSuite { - key := helpers.NewEthPrivKey() - return StakingSuite{ - Erc20TestSuite: NewErc20TestSuite(ts), - grantKey: key, - stakingContract: common.HexToAddress(contract.StakingAddress), - } -} - -func (suite *StakingSuite) AccAddress() sdk.AccAddress { - return sdk.AccAddress(suite.privKey.PubKey().Address()) -} - -func (suite *StakingSuite) Address() common.Address { - return common.BytesToAddress(suite.privKey.PubKey().Address()) -} - -func (suite *StakingSuite) GrantPrivKey() cryptotypes.PrivKey { - return suite.grantKey -} - -func (suite *StakingSuite) GrantAddress() sdk.AccAddress { - return sdk.AccAddress(suite.grantKey.PubKey().Address()) -} - -func (suite *StakingSuite) StakingQuery() stakingtypes.QueryClient { - return suite.GRPCClient().StakingQuery() -} - -func (suite *StakingSuite) TransactionOpts(privateKey cryptotypes.PrivKey) *bind.TransactOpts { - ecdsa, err := crypto.ToECDSA(privateKey.Bytes()) - suite.Require().NoError(err) - - chainId, err := suite.EthClient().ChainID(suite.ctx) - suite.Require().NoError(err) - - auth, err := bind.NewKeyedTransactorWithChainID(ecdsa, chainId) - suite.Require().NoError(err) - - auth.GasTipCap = big.NewInt(1e9) - auth.GasFeeCap = big.NewInt(6e12) - return auth -} - -func (suite *StakingSuite) DeployStakingContract(privKey cryptotypes.PrivKey) (common.Address, common.Hash) { - stakingBin := contract.MustDecodeHex(testscontract.StakingTestMetaData.Bin) - return suite.DeployContract(privKey, stakingBin) -} - -// DelegationRewards Get delegatorAddress rewards -func (suite *StakingSuite) DelegationRewards(delAddr, valAddr string) sdk.DecCoins { - response, err := suite.GRPCClient().DistrQuery().DelegationRewards(suite.ctx, &distrtypes.QueryDelegationRewardsRequest{DelegatorAddress: delAddr, ValidatorAddress: valAddr}) - suite.Require().NoError(err) - return response.Rewards -} - -func (suite *StakingSuite) SetWithdrawAddress(withdrawAddr sdk.AccAddress) { - suite.SetWithdrawAddressWithResponse(suite.privKey, withdrawAddr) -} - -func (suite *StakingSuite) SetWithdrawAddressWithResponse(privKey cryptotypes.PrivKey, withdrawAddr sdk.AccAddress) *sdk.TxResponse { - delAddr := sdk.AccAddress(privKey.PubKey().Address()) - setWithdrawAddress := distrtypes.NewMsgSetWithdrawAddress(delAddr, withdrawAddr) - txResponse := suite.BroadcastTx(privKey, setWithdrawAddress) - suite.Require().True(txResponse.Code == 0) - response, err := suite.GRPCClient().DistrQuery().DelegatorWithdrawAddress(suite.ctx, - &distrtypes.QueryDelegatorWithdrawAddressRequest{DelegatorAddress: delAddr.String()}) - suite.Require().NoError(err) - suite.Require().EqualValues(response.WithdrawAddress, withdrawAddr.String()) - return txResponse -} - -func (suite *StakingSuite) send(privateKey cryptotypes.PrivKey, value *big.Int, data []byte) *ethtypes.Receipt { - if value == nil { - value = big.NewInt(0) - } - transaction, err := client.BuildEthTransaction(suite.ctx, suite.EthClient(), privateKey, &suite.stakingContract, value, data) - suite.Require().NoError(err) - return suite.SendTransaction(transaction) -} - -func (suite *StakingSuite) DelegateV2(privateKey cryptotypes.PrivKey, valAddr string, delAmount *big.Int) *ethtypes.Receipt { - method := precompile.NewDelegateV2Method(nil) - pack, err := method.PackInput(contract.DelegateV2Args{Validator: valAddr, Amount: delAmount}) - suite.Require().NoError(err) - return suite.send(privateKey, big.NewInt(0), pack) -} - -func (suite *StakingSuite) RedelegateV2(privateKey cryptotypes.PrivKey, valSrc, valDst string, amount *big.Int) *ethtypes.Receipt { - method := precompile.NewRedelegateV2Method(nil) - pack, err := method.PackInput(contract.RedelegateV2Args{ValidatorSrc: valSrc, ValidatorDst: valDst, Amount: amount}) - suite.Require().NoError(err) - return suite.send(privateKey, nil, pack) -} - -func (suite *StakingSuite) WithdrawByContract(privateKey cryptotypes.PrivKey, contract common.Address, valAddr string) *ethtypes.Receipt { - stakingContract, err := testscontract.NewStakingTest(contract, suite.EthClient()) - suite.Require().NoError(err) - - auth := suite.TransactionOpts(privateKey) - - tx, err := stakingContract.Withdraw(auth, valAddr) - suite.Require().NoError(err) - - ctx, cancel := context.WithTimeout(suite.ctx, 5*time.Second) - defer cancel() - receipt, err := bind.WaitMined(ctx, suite.EthClient(), tx) - suite.Require().NoError(err) - suite.Require().Equal(receipt.Status, ethtypes.ReceiptStatusSuccessful) - return receipt -} - -func (suite *StakingSuite) UnDelegateV2(privateKey cryptotypes.PrivKey, valAddr string, amount *big.Int) *ethtypes.Receipt { - method := precompile.NewUndelegateV2Method(nil) - pack, err := method.PackInput(contract.UndelegateV2Args{Validator: valAddr, Amount: amount}) - suite.Require().NoError(err) - return suite.send(privateKey, nil, pack) -} - -func (suite *StakingSuite) WithdrawReward(privateKey cryptotypes.PrivKey, valAddr string) *ethtypes.Receipt { - method := precompile.NewWithdrawMethod(nil) - pack, err := method.PackInput(contract.WithdrawArgs{Validator: valAddr}) - suite.Require().NoError(err) - return suite.send(privateKey, nil, pack) -} - -func (suite *StakingSuite) Delegation(valAddr string, delAddr common.Address) (*big.Int, *big.Int) { - method := precompile.NewDelegationMethod(nil) - pack, err := method.PackInput(contract.DelegationArgs{Validator: valAddr, Delegator: delAddr}) - suite.Require().NoError(err) - output, err := suite.EthClient().CallContract(suite.ctx, ethereum.CallMsg{To: &suite.stakingContract, Data: pack}, nil) - suite.Require().NoError(err) - shares, amount, err := method.UnpackOutput(output) - suite.Require().NoError(err) - return shares, amount -} - -func (suite *StakingSuite) Rewards(valAddr string, delAddr common.Address) *big.Int { - method := precompile.NewDelegationRewardsMethod(nil) - pack, err := method.PackInput(contract.DelegationRewardsArgs{Validator: valAddr, Delegator: delAddr}) - suite.Require().NoError(err) - output, err := suite.EthClient().CallContract(suite.ctx, ethereum.CallMsg{To: &suite.stakingContract, Data: pack}, nil) - suite.Require().NoError(err) - amount, err := method.UnpackOutput(output) - suite.Require().NoError(err) - return amount -} - -func (suite *StakingSuite) TransferShares(privateKey cryptotypes.PrivKey, valAddr string, receipt common.Address, shares *big.Int) *ethtypes.Receipt { - method := precompile.NewTransferSharesMethod(nil) - pack, err := method.PackInput(contract.TransferSharesArgs{Validator: valAddr, To: receipt, Shares: shares}) - suite.Require().NoError(err) - return suite.send(privateKey, nil, pack) -} - -func (suite *StakingSuite) TransferSharesByContract(privateKey cryptotypes.PrivKey, valAddr string, contract, to common.Address, shares *big.Int) *ethtypes.Receipt { - stakingContract, err := testscontract.NewStakingTest(contract, suite.EthClient()) - suite.Require().NoError(err) - - auth := suite.TransactionOpts(privateKey) - - tx, err := stakingContract.TransferShares(auth, valAddr, to, shares) - suite.Require().NoError(err) - - ctx, cancel := context.WithTimeout(suite.ctx, 5*time.Second) - defer cancel() - receipt, err := bind.WaitMined(ctx, suite.EthClient(), tx) - suite.Require().NoError(err) - suite.Require().Equal(receipt.Status, ethtypes.ReceiptStatusSuccessful) - return receipt -} - -func (suite *StakingSuite) TransferFromShares(privateKey cryptotypes.PrivKey, valAddr string, from, receipt common.Address, shares *big.Int) *ethtypes.Receipt { - method := precompile.NewTransferFromSharesMethod(nil) - pack, err := method.PackInput(contract.TransferFromSharesArgs{Validator: valAddr, From: from, To: receipt, Shares: shares}) - suite.Require().NoError(err) - return suite.send(privateKey, nil, pack) -} - -func (suite *StakingSuite) TransferFromSharesByContract(privateKey cryptotypes.PrivKey, valAddr string, contract, from, to common.Address, shares *big.Int) *ethtypes.Receipt { - stakingContract, err := testscontract.NewStakingTest(contract, suite.EthClient()) - suite.Require().NoError(err) - - auth := suite.TransactionOpts(privateKey) - - tx, err := stakingContract.TransferFromShares(auth, valAddr, from, to, shares) - suite.Require().NoError(err) - - ctx, cancel := context.WithTimeout(suite.ctx, 5*time.Second) - defer cancel() - receipt, err := bind.WaitMined(ctx, suite.EthClient(), tx) - suite.Require().NoError(err) - suite.Require().Equal(receipt.Status, ethtypes.ReceiptStatusSuccessful) - return receipt -} - -func (suite *StakingSuite) ApproveShares(privateKey cryptotypes.PrivKey, valAddr string, spender common.Address, shares *big.Int) *ethtypes.Receipt { - method := precompile.NewApproveSharesMethod(nil) - pack, err := method.PackInput(contract.ApproveSharesArgs{Validator: valAddr, Spender: spender, Shares: shares}) - suite.Require().NoError(err) - return suite.send(privateKey, nil, pack) -} - -func (suite *StakingSuite) AllowanceShares(valAddr string, owner, spender common.Address) *big.Int { - method := precompile.NewAllowanceSharesMethod(nil) - pack, err := method.PackInput(contract.AllowanceSharesArgs{Validator: valAddr, Owner: owner, Spender: spender}) - suite.Require().NoError(err) - output, err := suite.EthClient().CallContract(suite.ctx, ethereum.CallMsg{To: &suite.stakingContract, Data: pack}, nil) - suite.Require().NoError(err) - amount, err := method.UnpackOutput(output) - suite.Require().NoError(err) - return amount -} - -func (suite *StakingSuite) LogReward(logs []*ethtypes.Log, valAddr string, addr common.Address) *big.Int { - method := precompile.NewWithdrawMethod(nil) - for _, log := range logs { - if log.Address == suite.stakingContract && - log.Topics[0] == method.Event.ID && - log.Topics[1] == addr.Hash() { - unpack, err := method.Event.Inputs.NonIndexed().Unpack(log.Data) - suite.Require().NoError(err) - suite.Require().Equal(unpack[0].(string), valAddr) - return unpack[1].(*big.Int) - } - } - return big.NewInt(0) -} - -type AuthzSuite struct { - *TestSuite -} - -func NewAuthzSuite(ts *TestSuite) AuthzSuite { - return AuthzSuite{TestSuite: ts} -} - -func (suite *AuthzSuite) AuthzQuery() authz.QueryClient { - return suite.GRPCClient().AuthzQuery() -} - -type SlashingSuite struct { - *TestSuite -} - -func NewSlashingSuite(ts *TestSuite) SlashingSuite { - return SlashingSuite{TestSuite: ts} -} - -func (suite *SlashingSuite) SlashingQuery() slashingtypes.QueryClient { - return suite.GRPCClient().SlashingQuery() -} diff --git a/tests/suite.go b/tests/suite.go deleted file mode 100644 index dd0fe5f5..00000000 --- a/tests/suite.go +++ /dev/null @@ -1,526 +0,0 @@ -package tests - -import ( - "context" - "fmt" - "sort" - "strconv" - "strings" - "time" - - sdkmath "cosmossdk.io/math" - "github.com/cosmos/cosmos-sdk/client/grpc/cmtservice" - "github.com/cosmos/cosmos-sdk/crypto/hd" - "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/cosmos/cosmos-sdk/x/auth/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - distritypes "github.com/cosmos/cosmos-sdk/x/distribution/types" - govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" - govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/stretchr/testify/suite" - - "github.com/functionx/fx-core/v8/client/grpc" - "github.com/functionx/fx-core/v8/client/jsonrpc" - "github.com/functionx/fx-core/v8/testutil" - "github.com/functionx/fx-core/v8/testutil/helpers" - "github.com/functionx/fx-core/v8/testutil/network" - fxtypes "github.com/functionx/fx-core/v8/types" - bsctypes "github.com/functionx/fx-core/v8/x/bsc/types" - ethtypes "github.com/functionx/fx-core/v8/x/eth/types" -) - -type TestSuite struct { - suite.Suite - network *network.Network - ctx context.Context - proposalId uint64 - numValidator int - timeoutCommit time.Duration - enableTMLogging bool -} - -func NewTestSuite() *TestSuite { - return &TestSuite{ - Suite: suite.Suite{}, - proposalId: 0, - ctx: context.Background(), - numValidator: 1, - } -} - -func (suite *TestSuite) SetupSuite() { - suite.T().Log("setting up integration test suite") - - numValidators := suite.numValidator - suite.timeoutCommit = 50 * time.Millisecond - if numValidators > 1 { - suite.timeoutCommit = 500 * time.Millisecond - } - - ibcGenesisOpt := func(config *network.Config) { - config.GenesisState = testutil.IbcGenesisState(config.Codec, config.GenesisState) - } - bankGenesisOpt := func(config *network.Config) { - config.GenesisState = testutil.BankGenesisState(config.Codec, config.GenesisState) - } - govGenesisOpt := func(config *network.Config) { - votingPeriod := time.Millisecond - if numValidators > 1 { - votingPeriod = time.Duration(numValidators*5) * suite.timeoutCommit - } - config.GenesisState = testutil.GovGenesisState(config.Codec, config.GenesisState, votingPeriod) - } - slashingGenesisOpt := func(config *network.Config) { - signedBlocksWindow := int64(10) - minSignedPerWindow := sdkmath.LegacyNewDecWithPrec(2, 1) - downtimeJailDuration := 5 * time.Second - config.GenesisState = testutil.SlashingGenesisState(config.Codec, config.GenesisState, signedBlocksWindow, minSignedPerWindow, downtimeJailDuration) - } - - cfg := testutil.DefaultNetworkConfig(ibcGenesisOpt, bankGenesisOpt, govGenesisOpt, slashingGenesisOpt) - cfg.TimeoutCommit = suite.timeoutCommit - cfg.NumValidators = numValidators - cfg.EnableJSONRPC = true - if suite.enableTMLogging { - cfg.EnableTMLogging = true - } - - suite.network = network.New(suite.T(), cfg) - - _, err := suite.network.WaitForHeight(3) - suite.Require().NoError(err) -} - -func (suite *TestSuite) TearDownSuite() { - suite.T().Log("tearing down integration test suite") - - // This is important and must be called to ensure other tests can create - // a network! - suite.network.Cleanup() -} - -func (suite *TestSuite) GetNetwork() *network.Network { - return suite.network -} - -func (suite *TestSuite) Context() context.Context { - return suite.ctx -} - -func (suite *TestSuite) getNextProposalId() uint64 { - suite.proposalId = suite.proposalId + 1 - return suite.proposalId -} - -func (suite *TestSuite) GetFirstValidator() *network.Validator { - return suite.network.Validators[0] -} - -func (suite *TestSuite) GetAllValidators() []*network.Validator { - return suite.network.Validators -} - -func (suite *TestSuite) GetFirstValPrivKey() cryptotypes.PrivKey { - privKey, err := helpers.PrivKeyFromMnemonic(suite.network.Config.Mnemonics[0], hd.Secp256k1Type, 0, 0) - suite.Require().NoError(err) - return privKey -} - -func (suite *TestSuite) GetAllValPrivKeys() []cryptotypes.PrivKey { - privKeys := make([]cryptotypes.PrivKey, 0, len(suite.network.Config.Mnemonics)) - for _, mnemonics := range suite.network.Config.Mnemonics { - privKey, err := helpers.PrivKeyFromMnemonic(mnemonics, hd.Secp256k1Type, 0, 0) - suite.Require().NoError(err) - privKeys = append(privKeys, privKey) - } - return privKeys -} - -func (suite *TestSuite) GetValidatorPrivKeys(addr sdk.AccAddress) cryptotypes.PrivKey { - for _, mnemonics := range suite.network.Config.Mnemonics { - privKey, err := helpers.PrivKeyFromMnemonic(mnemonics, hd.Secp256k1Type, 0, 0) - suite.Require().NoError(err) - if addr.Equals(sdk.AccAddress(privKey.PubKey().Address())) { - return privKey - } - } - return nil -} - -func (suite *TestSuite) GRPCClient() *grpc.Client { - if suite.GetFirstValidator().ClientCtx.GRPCClient != nil { - return grpc.NewClient(suite.GetFirstValidator().ClientCtx) - } - grpcUrl := fmt.Sprintf("http://%s", suite.GetFirstValidator().AppConfig.GRPC.Address) - client, err := grpc.DailClient(grpcUrl, suite.ctx) - suite.Require().NoError(err) - return client -} - -func (suite *TestSuite) NodeClient() *jsonrpc.NodeRPC { - nodeUrl := suite.GetFirstValidator().Ctx.Config.RPC.ListenAddress - return jsonrpc.NewNodeRPC(jsonrpc.NewClient(nodeUrl), suite.ctx) -} - -func (suite *TestSuite) GetFirstValAddr() sdk.ValAddress { - return suite.GetFirstValPrivKey().PubKey().Address().Bytes() -} - -func (suite *TestSuite) GetStakingDenom() string { - return suite.network.Config.BondDenom -} - -func (suite *TestSuite) NewCoin(amount sdkmath.Int) sdk.Coin { - return sdk.NewCoin(suite.GetStakingDenom(), amount) -} - -func (suite *TestSuite) GetMetadata(denom string) banktypes.Metadata { - response, err := suite.GRPCClient().BankQuery().DenomMetadata(suite.ctx, &banktypes.QueryDenomMetadataRequest{Denom: denom}) - suite.Require().NoError(err) - return response.Metadata -} - -func (suite *TestSuite) BlockNumber() int64 { - height, err := suite.GRPCClient().GetBlockHeight() - suite.Require().NoError(err) - return height -} - -func (suite *TestSuite) QueryTx(txHash string) *sdk.TxResponse { - txResponse, err := suite.GRPCClient().TxByHash(txHash) - suite.Require().NoError(err) - return txResponse -} - -func (suite *TestSuite) QueryBlock(blockHeight int64) *cmtservice.Block { - txResponse, err := suite.GRPCClient().GetBlockByHeight(blockHeight) - suite.Require().NoError(err) - return txResponse -} - -func (suite *TestSuite) QueryBlockByTxHash(txHash string) *cmtservice.Block { - txResponse := suite.QueryTx(txHash) - return suite.QueryBlock(txResponse.Height) -} - -func (suite *TestSuite) BroadcastTx(privKey cryptotypes.PrivKey, msgList ...sdk.Msg) *sdk.TxResponse { - grpcClient := suite.GRPCClient() - balances, err := grpcClient.QueryBalances(sdk.AccAddress(privKey.PubKey().Address().Bytes()).String()) - suite.Require().NoError(err) - suite.True(balances.AmountOf(suite.GetStakingDenom()).GT(sdkmath.NewInt(2).MulRaw(1e18))) - - gasPrices, err := sdk.ParseCoinsNormalized(suite.network.Config.MinGasPrices) - suite.Require().NoError(err) - if gasPrices.Len() <= 0 { - // Let me know if you use sdk.newCoins sanitizeCoins will remove all zero coins - gasPrices = sdk.Coins{suite.NewCoin(sdkmath.ZeroInt())} - } - grpcClient = grpcClient.WithGasPrices(gasPrices) - txRaw, err := grpcClient.BuildTxRaw(privKey, msgList, 500000, 0, "") - suite.Require().NoError(err) - - txResponse, err := grpcClient.BroadcastTx(txRaw) - suite.Require().NoError(err) - suite.NotNil(txResponse) // txResponse might be nil, but error is also nil - suite.EqualValues(0, txResponse.Code) - txResponse, err = grpcClient.WaitMined(txResponse.TxHash, 200*suite.timeoutCommit, 10*suite.timeoutCommit) - suite.Require().NoError(err) - suite.T().Log("broadcast tx", "msg:", sdk.MsgTypeURL(msgList[0]), "height:", txResponse.Height, "txHash:", txResponse.TxHash) - suite.Require().NoError(suite.network.WaitForNextBlock()) - return txResponse -} - -func (suite *TestSuite) BroadcastProposalTx(content govv1beta1.Content, expectedStatus ...govv1.ProposalStatus) (*sdk.TxResponse, uint64) { - proposalMsg, err := govv1beta1.NewMsgSubmitProposal( - content, - sdk.NewCoins(suite.NewCoin(sdkmath.NewInt(10_000).MulRaw(1e18))), - suite.GetFirstValAddr().Bytes(), - ) - suite.Require().NoError(err) - proposalId := suite.getNextProposalId() - voteMsg := govv1beta1.NewMsgVote(suite.GetFirstValAddr().Bytes(), proposalId, govv1beta1.OptionYes) - txResponse := suite.BroadcastTx(suite.GetFirstValPrivKey(), proposalMsg, voteMsg) - for _, log := range txResponse.Logs { - for _, event := range log.Events { - if event.Type != "proposal_deposit" { - continue - } - for _, attribute := range event.Attributes { - if attribute.Key != "proposal_id" { - continue - } - id, err := strconv.ParseUint(attribute.Value, 10, 64) - suite.Require().NoError(err) - suite.Require().Equal(proposalId, id) - break - } - } - } - _, err = suite.network.WaitForHeight(txResponse.Height + 2) - suite.Require().NoError(err) - status := govv1.StatusPassed - if len(expectedStatus) > 0 { - status = expectedStatus[0] - } - suite.CheckProposal(proposalId, status) - return txResponse, proposalId -} - -func (suite *TestSuite) BroadcastProposalTx2(msgs []sdk.Msg, title, summary string, expectedStatus ...govv1.ProposalStatus) (*sdk.TxResponse, uint64) { - proposalMsg, err := govv1.NewMsgSubmitProposal( - msgs, - sdk.NewCoins(suite.NewCoin(sdkmath.NewInt(10_000).MulRaw(1e18))), - sdk.AccAddress(suite.GetFirstValAddr().Bytes()).String(), - "", - title, - summary, - false, - ) - suite.Require().NoError(err) - proposalId := suite.getNextProposalId() - voteMsg := govv1.NewMsgVote(suite.GetFirstValAddr().Bytes(), proposalId, govv1.OptionYes, "") - txResponse := suite.BroadcastTx(suite.GetFirstValPrivKey(), proposalMsg, voteMsg) - for _, log := range txResponse.Logs { - for _, event := range log.Events { - if event.Type != "proposal_deposit" { - continue - } - for _, attribute := range event.Attributes { - if attribute.Key != "proposal_id" { - continue - } - id, err := strconv.ParseUint(attribute.Value, 10, 64) - suite.Require().NoError(err) - suite.Require().Equal(proposalId, id) - break - } - } - } - _, err = suite.network.WaitForHeight(txResponse.Height + 2) - suite.Require().NoError(err) - status := govv1.StatusPassed - if len(expectedStatus) > 0 { - status = expectedStatus[0] - } - suite.CheckProposal(proposalId, status) - return txResponse, proposalId -} - -func (suite *TestSuite) CreateValidator(valPriv cryptotypes.PrivKey, toBondedVal bool) *sdk.TxResponse { - valAddr := sdk.ValAddress(valPriv.PubKey().Address()) - minSelfDelegate := sdkmath.NewInt(1) - stakingDenom := suite.GetStakingDenom() - selfDelegate := sdk.NewCoin(stakingDenom, minSelfDelegate) - if toBondedVal { - selfDelegate = sdk.NewCoin(stakingDenom, sdkmath.NewIntFromUint64(1e18).Mul(sdkmath.NewInt(100))) - } - description := stakingtypes.Description{ - Moniker: "val2", - Identity: "", - Website: "", - SecurityContact: "", - Details: "", - } - rates := stakingtypes.CommissionRates{ - Rate: sdkmath.LegacyNewDecWithPrec(2, 2), // 2% - MaxRate: sdkmath.LegacyNewDecWithPrec(50, 2), // 5% - MaxChangeRate: sdkmath.LegacyNewDecWithPrec(2, 2), // 2% - } - ed25519PrivKey := ed25519.GenPrivKeyFromSecret(valAddr.Bytes()) - msg, err := stakingtypes.NewMsgCreateValidator(valAddr.String(), ed25519PrivKey.PubKey(), selfDelegate, description, rates, minSelfDelegate) - suite.Require().NoError(err) - return suite.BroadcastTx(valPriv, msg) -} - -func (suite *TestSuite) QueryValidatorByToken() sdk.ValAddress { - response, err := suite.GRPCClient().StakingQuery().Validators(suite.ctx, &stakingtypes.QueryValidatorsRequest{Status: stakingtypes.Bonded.String()}) - suite.Require().NoError(err) - suite.NotEmpty(response.Validators) - validators := response.Validators - sort.Slice(validators, func(i, j int) bool { - return validators[i].Tokens.LT(validators[j].Tokens) - }) - valAddr, err := sdk.ValAddressFromBech32(validators[0].OperatorAddress) - suite.Require().NoError(err) - return valAddr -} - -func (suite *TestSuite) Send(toAddress sdk.AccAddress, amount ...sdk.Coin) *sdk.TxResponse { - priv := suite.GetFirstValPrivKey() - txResponse := suite.BroadcastTx(priv, banktypes.NewMsgSend(priv.PubKey().Address().Bytes(), toAddress, amount)) - suite.Len(txResponse.GasUsed, 100_000) - return txResponse -} - -func (suite *TestSuite) QueryBalances(accAddress sdk.AccAddress) sdk.Coins { - balances, err := suite.GRPCClient().QueryBalances(accAddress.String()) - suite.Require().NoError(err) - return balances -} - -func (suite *TestSuite) CheckBalance(accAddress sdk.AccAddress, balance sdk.Coin) { - queryBalance, err := suite.GRPCClient().QueryBalance(accAddress.String(), balance.Denom) - suite.Require().NoError(err) - suite.Equal(balance.String(), queryBalance.String()) -} - -func (suite *TestSuite) SetWithdrawAddr(priv cryptotypes.PrivKey, withdrawAddr sdk.AccAddress) *sdk.TxResponse { - fromAddr := sdk.AccAddress(priv.PubKey().Address().Bytes()) - return suite.BroadcastTx(priv, distritypes.NewMsgSetWithdrawAddress(fromAddr, withdrawAddr)) -} - -func (suite *TestSuite) CheckWithdrawAddr(delegatorAddr, withdrawAddr sdk.AccAddress) { - withdrawAddressResp, err := suite.GRPCClient().DistrQuery().DelegatorWithdrawAddress(suite.ctx, &distritypes.QueryDelegatorWithdrawAddressRequest{ - DelegatorAddress: delegatorAddr.String(), - }) - suite.Require().NoError(err) - suite.Equal(withdrawAddressResp.WithdrawAddress, withdrawAddr.String()) -} - -func (suite *TestSuite) Delegate(priv cryptotypes.PrivKey, valAddress sdk.ValAddress, amount sdk.Coin) *sdk.TxResponse { - return suite.BroadcastTx(priv, stakingtypes.NewMsgDelegate(sdk.AccAddress(priv.PubKey().Address().Bytes()).String(), valAddress.String(), amount)) -} - -func (suite *TestSuite) CheckDelegate(delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress, delegation sdk.Coin) { - delegationResp, err := suite.GRPCClient().StakingQuery().Delegation(suite.ctx, &stakingtypes.QueryDelegationRequest{ - DelegatorAddr: delegatorAddr.String(), - ValidatorAddr: validatorAddr.String(), - }) - if delegation.IsZero() { - suite.Error(sdkerrors.ErrNotFound) - } else { - suite.Require().NoError(err) - suite.Equal(delegation.String(), delegationResp.DelegationResponse.Balance.String()) - } -} - -func (suite *TestSuite) WithdrawReward(priv cryptotypes.PrivKey, valAddress sdk.ValAddress) *sdk.TxResponse { - return suite.BroadcastTx(priv, distritypes.NewMsgWithdrawDelegatorReward(sdk.AccAddress(priv.PubKey().Address().Bytes()).String(), valAddress.String())) -} - -func (suite *TestSuite) Undelegate(priv cryptotypes.PrivKey, valAddress sdk.ValAddress, amount sdk.Coin) *sdk.TxResponse { - if amount.IsZero() { - delegation, err := suite.GRPCClient().StakingQuery().Delegation(suite.ctx, &stakingtypes.QueryDelegationRequest{ - DelegatorAddr: sdk.AccAddress(priv.PubKey().Address().Bytes()).String(), - ValidatorAddr: valAddress.String(), - }) - suite.Require().NoError(err) - amount = delegation.DelegationResponse.Balance - } - return suite.BroadcastTx(priv, stakingtypes.NewMsgUndelegate(sdk.AccAddress(priv.PubKey().Address().Bytes()).String(), valAddress.String(), amount)) -} - -func (suite *TestSuite) CheckUndelegate(delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress, entries ...stakingtypes.UnbondingDelegationEntry) { - response, err := suite.GRPCClient().StakingQuery().UnbondingDelegation(suite.ctx, &stakingtypes.QueryUnbondingDelegationRequest{ - DelegatorAddr: delegatorAddr.String(), - ValidatorAddr: validatorAddr.String(), - }) - suite.Require().NoError(err) - suite.Equal(len(response.Unbond.Entries), len(entries)) - for i, entry := range response.Unbond.Entries { - entry.UnbondingId = 0 - suite.Equal(entry.String(), entries[i].String()) - } -} - -func (suite *TestSuite) Redelegate(priv cryptotypes.PrivKey, valSrc, valDest sdk.ValAddress, all bool) *sdk.TxResponse { - amt := sdkmath.NewInt(1) - if all { - delegation, err := suite.GRPCClient().StakingQuery().Delegation(suite.ctx, &stakingtypes.QueryDelegationRequest{ - DelegatorAddr: sdk.AccAddress(priv.PubKey().Address().Bytes()).String(), - ValidatorAddr: valSrc.String(), - }) - suite.Require().NoError(err) - amt = delegation.DelegationResponse.Balance.Amount - } - msg := stakingtypes.NewMsgBeginRedelegate(sdk.AccAddress(priv.PubKey().Address().Bytes()).String(), valSrc.String(), valDest.String(), sdk.NewCoin(suite.GetStakingDenom(), amt)) - return suite.BroadcastTx(priv, msg) -} - -func (suite *TestSuite) CheckRedelegate(delegatorAddr sdk.AccAddress, redelegationResponses stakingtypes.RedelegationResponses) { - redelegationResp, err := suite.GRPCClient().StakingQuery().Redelegations(suite.ctx, &stakingtypes.QueryRedelegationsRequest{DelegatorAddr: delegatorAddr.String()}) - suite.Require().NoError(err) - suite.Equal(len(redelegationResp.RedelegationResponses), len(redelegationResponses)) - for i, item := range redelegationResp.RedelegationResponses { - suite.Equal(item.Redelegation.String(), redelegationResponses[i].Redelegation.String()) - for j, entry := range item.Entries { - suite.Equal(entry.RedelegationEntry.String(), redelegationResponses[i].Entries[j].RedelegationEntry.String()) - suite.Equal(entry.Balance.String(), redelegationResponses[i].Entries[j].Balance.String()) - } - } -} - -func (suite *TestSuite) CheckProposals(depositor sdk.AccAddress) govv1.Proposals { - proposalsResp, err := suite.GRPCClient().GovQuery().Proposals(suite.ctx, &govv1.QueryProposalsRequest{ - ProposalStatus: govv1.StatusDepositPeriod, - Depositor: depositor.String(), - }) - suite.Require().NoError(err) - return proposalsResp.Proposals -} - -func (suite *TestSuite) ProposalDeposit(priv cryptotypes.PrivKey, proposalID uint64, amount sdk.Coin) *sdk.TxResponse { - return suite.BroadcastTx(priv, govv1beta1.NewMsgDeposit(priv.PubKey().Address().Bytes(), proposalID, sdk.NewCoins(amount))) -} - -func (suite *TestSuite) CheckDeposit(proposalId uint64, depositor sdk.AccAddress, amount sdk.Coin) { - depositResp, err := suite.GRPCClient().GovQuery().Deposit(suite.ctx, &govv1.QueryDepositRequest{ - ProposalId: proposalId, - Depositor: depositor.String(), - }) - suite.Require().NoError(err) - suite.Equal(depositResp.Deposit.Amount, amount) -} - -func (suite *TestSuite) ProposalVote(priv cryptotypes.PrivKey, proposalID uint64, option govv1beta1.VoteOption) *sdk.TxResponse { - return suite.BroadcastTx(priv, govv1beta1.NewMsgVote(priv.PubKey().Address().Bytes(), proposalID, option)) -} - -func (suite *TestSuite) CheckProposal(proposalId uint64, _ govv1.ProposalStatus) govv1.Proposal { - proposalResp, err := suite.GRPCClient().GovQuery().Proposal(suite.ctx, &govv1.QueryProposalRequest{ - ProposalId: proposalId, - }) - suite.Require().NoError(err) - - suite.Require().Greater(proposalResp.Proposal.Status, govv1.StatusDepositPeriod) - return *proposalResp.Proposal -} - -func (suite *TestSuite) ChainTokens(chainName string) []banktypes.Metadata { - resp, err := suite.GRPCClient().BankQuery().DenomsMetadata(suite.ctx, &banktypes.QueryDenomsMetadataRequest{}) - suite.Require().NoError(err) - - chainMetadata := make([]banktypes.Metadata, 0) - for _, md := range resp.Metadatas { - // FX or PURSE or PUNDIX - if md.Base == fxtypes.DefaultDenom && chainName == ethtypes.ModuleName || - strings.HasPrefix(md.Base, "ibc/") && chainName == bsctypes.ModuleName || - strings.HasPrefix(md.Base, chainName) { - chainMetadata = append(chainMetadata, md) - continue - } - if len(md.DenomUnits[0].Aliases) > 0 { - for _, alias := range md.DenomUnits[0].Aliases { - if strings.HasPrefix(alias, chainName) { - chainMetadata = append(chainMetadata, md) - } - } - } - } - return chainMetadata -} - -func (suite *TestSuite) QueryModuleAccountByName(moduleName string) sdk.AccAddress { - moduleAddress, err := suite.GRPCClient().AuthQuery().ModuleAccountByName(suite.ctx, &types.QueryModuleAccountByNameRequest{ - Name: moduleName, - }) - suite.Require().NoError(err) - var account sdk.AccountI - err = suite.network.Config.Codec.UnpackAny(moduleAddress.Account, &account) - suite.Require().NoError(err) - return account.GetAddress() -} diff --git a/testutil/helpers/tools.go b/testutil/helpers/tools.go index 53003541..f4f11417 100644 --- a/testutil/helpers/tools.go +++ b/testutil/helpers/tools.go @@ -11,9 +11,11 @@ import ( sdkmath "cosmossdk.io/math" tmrand "github.com/cometbft/cometbft/libs/rand" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/functionx/fx-core/v8/contract" fxtypes "github.com/functionx/fx-core/v8/types" ) @@ -61,3 +63,12 @@ func NewStakingCoin(amount, power int64) sdk.Coin { func NewStakingCoins(amount, power int64) sdk.Coins { return sdk.NewCoins(NewStakingCoin(amount, power)) } + +func NewBigInt(amount, power int64) *big.Int { + powerBig := new(big.Int).Exp(big.NewInt(10), big.NewInt(power), nil) + return new(big.Int).Mul(big.NewInt(amount), powerBig) +} + +func PackERC20Mint(receiver common.Address, amount *big.Int) ([]byte, error) { + return contract.GetFIP20().ABI.Pack("mint", receiver, amount) +} diff --git a/testutil/network.go b/testutil/network.go index c528cb6b..b2e35119 100644 --- a/testutil/network.go +++ b/testutil/network.go @@ -45,6 +45,7 @@ import ( // testing requirements. func DefaultNetworkConfig(opts ...func(config *network.Config)) network.Config { newApp := helpers.NewApp() + chainID := fxtypes.MainnetChainId cfg := network.Config{ Codec: newApp.AppCodec(), InterfaceRegistry: newApp.InterfaceRegistry(), @@ -61,7 +62,7 @@ func DefaultNetworkConfig(opts ...func(config *network.Config)) network.Config { ctx.Viper, baseapp.SetPruning(pruningtypes.NewPruningOptionsFromString(appConfig.Pruning)), baseapp.SetMinGasPrices(appConfig.MinGasPrices), - baseapp.SetChainID(fxtypes.MainnetChainId), + baseapp.SetChainID(chainID), ) }, GenesisState: NoSupplyGenesisState(newApp.AppCodec(), newApp.ModuleBasics), @@ -69,7 +70,7 @@ func DefaultNetworkConfig(opts ...func(config *network.Config)) network.Config { StakingTokens: sdk.TokensFromConsensusPower(5000, sdk.DefaultPowerReduction), // 500_000 BondedTokens: sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction), // 10_000 NumValidators: 4, - ChainID: fxtypes.MainnetChainId, + ChainID: chainID, BondDenom: fxtypes.DefaultDenom, MinGasPrices: fxtypes.GetDefGasPrice().String(), PruningStrategy: pruningtypes.PruningOptionNothing, diff --git a/testutil/network/network.go b/testutil/network/network.go index 1fe7e09a..efdded50 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -10,6 +10,7 @@ import ( "os/signal" "path/filepath" "strings" + "sync" "syscall" "testing" "time" @@ -45,6 +46,9 @@ import ( fxcfg "github.com/functionx/fx-core/v8/server/config" ) +// package-wide network lock to only allow one test network at a time +var lock = new(sync.Mutex) + // AppConstructor defines a function which accepts a network configuration and // creates an ABCI Application to provide to Tendermint. type AppConstructor = func(appConfig *fxcfg.Config, ctx *server.Context) servertypes.Application @@ -95,6 +99,7 @@ type Network struct { BaseDir string Config Config Validators []*Validator + ctx context.Context cancel context.CancelFunc } @@ -121,6 +126,9 @@ type Validator struct { // New creates a new Network for integration tests or in-process testnets run via the CLI func New(t *testing.T, cfg Config) *Network { t.Helper() + // only one caller/test can create and use a network at a time + t.Log("acquiring test network lock") + lock.Lock() baseDir := t.TempDir() @@ -136,15 +144,15 @@ func New(t *testing.T, cfg Config) *Network { require.NoError(t, err) network := &Network{ + ctx: context.Background(), logger: logger, BaseDir: baseDir, Config: cfg, Validators: validators, } - ctx := context.Background() - ctx, network.cancel = context.WithCancel(ctx) - errGroup, ctx := errgroup.WithContext(ctx) + network.ctx, network.cancel = context.WithCancel(network.ctx) + errGroup, ctx := errgroup.WithContext(network.ctx) t.Log("starting test network...") for _, val := range network.Validators { @@ -409,6 +417,10 @@ func GenerateGenesisAndValidators(baseDir string, cfg *Config, logger log.Logger return validators, nil } +func (n *Network) GetContext() context.Context { + return n.ctx +} + // LatestHeight returns the latest height of the network or an error if the // query fails or no validators exist. func (n *Network) LatestHeight() (int64, error) { @@ -416,7 +428,7 @@ func (n *Network) LatestHeight() (int64, error) { return 0, errors.New("no validators available") } - status, err := n.Validators[0].RPCClient.Status(context.Background()) + status, err := n.Validators[0].RPCClient.Status(n.ctx) if err != nil { return 0, err } @@ -458,7 +470,7 @@ func (n *Network) WaitForHeightWithTimeout(h int64, t time.Duration) (int64, err ticker.Stop() return latestHeight, errors.New("timeout exceeded waiting for block") case <-ticker.C: - status, err := val.RPCClient.Status(context.Background()) + status, err := val.RPCClient.Status(n.ctx) if err == nil && status != nil { latestHeight = status.SyncInfo.LatestBlockHeight if latestHeight >= h { @@ -490,9 +502,13 @@ func (n *Network) WaitForNextBlock() error { // test networks. This method must be called when a test is finished, typically // in a defer. func (n *Network) Cleanup() { + defer func() { + lock.Unlock() + n.logger.Info("released test network lock") + }() n.logger.Info("cleaning up test network...") startTime := time.Now() - shutdownCtx, cancelFn := context.WithTimeout(context.Background(), 5*time.Second) + shutdownCtx, cancelFn := context.WithTimeout(n.ctx, 5*time.Second) defer cancelFn() n.cancel() for _, v := range n.Validators { diff --git a/x/crosschain/types/tx.pb.go b/x/crosschain/types/tx.pb.go index 602f8752..4cec4188 100644 --- a/x/crosschain/types/tx.pb.go +++ b/x/crosschain/types/tx.pb.go @@ -779,15 +779,16 @@ func (m *MsgOracleSetUpdatedClaim) GetChainName() string { } type MsgSendToFxClaim struct { - EventNonce uint64 `protobuf:"varint,1,opt,name=event_nonce,json=eventNonce,proto3" json:"event_nonce,omitempty"` - BlockHeight uint64 `protobuf:"varint,2,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"` - TokenContract string `protobuf:"bytes,3,opt,name=token_contract,json=tokenContract,proto3" json:"token_contract,omitempty"` - Amount cosmossdk_io_math.Int `protobuf:"bytes,4,opt,name=amount,proto3,customtype=cosmossdk.io/math.Int" json:"amount"` - Sender string `protobuf:"bytes,5,opt,name=sender,proto3" json:"sender,omitempty"` - Receiver string `protobuf:"bytes,6,opt,name=receiver,proto3" json:"receiver,omitempty"` - TargetIbc string `protobuf:"bytes,7,opt,name=target_ibc,json=targetIbc,proto3" json:"target_ibc,omitempty"` - BridgerAddress string `protobuf:"bytes,8,opt,name=bridger_address,json=bridgerAddress,proto3" json:"bridger_address,omitempty"` - ChainName string `protobuf:"bytes,9,opt,name=chain_name,json=chainName,proto3" json:"chain_name,omitempty"` + EventNonce uint64 `protobuf:"varint,1,opt,name=event_nonce,json=eventNonce,proto3" json:"event_nonce,omitempty"` + BlockHeight uint64 `protobuf:"varint,2,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"` + TokenContract string `protobuf:"bytes,3,opt,name=token_contract,json=tokenContract,proto3" json:"token_contract,omitempty"` + Amount cosmossdk_io_math.Int `protobuf:"bytes,4,opt,name=amount,proto3,customtype=cosmossdk.io/math.Int" json:"amount"` + Sender string `protobuf:"bytes,5,opt,name=sender,proto3" json:"sender,omitempty"` + Receiver string `protobuf:"bytes,6,opt,name=receiver,proto3" json:"receiver,omitempty"` + // Deprecated: After the upgrade to v8 + TargetIbc string `protobuf:"bytes,7,opt,name=target_ibc,json=targetIbc,proto3" json:"target_ibc,omitempty"` + BridgerAddress string `protobuf:"bytes,8,opt,name=bridger_address,json=bridgerAddress,proto3" json:"bridger_address,omitempty"` + ChainName string `protobuf:"bytes,9,opt,name=chain_name,json=chainName,proto3" json:"chain_name,omitempty"` } func (m *MsgSendToFxClaim) Reset() { *m = MsgSendToFxClaim{} } @@ -1281,8 +1282,9 @@ type MsgBridgeTokenClaim struct { Symbol string `protobuf:"bytes,5,opt,name=symbol,proto3" json:"symbol,omitempty"` Decimals uint64 `protobuf:"varint,6,opt,name=decimals,proto3" json:"decimals,omitempty"` BridgerAddress string `protobuf:"bytes,7,opt,name=bridger_address,json=bridgerAddress,proto3" json:"bridger_address,omitempty"` - ChannelIbc string `protobuf:"bytes,8,opt,name=channel_ibc,json=channelIbc,proto3" json:"channel_ibc,omitempty"` - ChainName string `protobuf:"bytes,9,opt,name=chain_name,json=chainName,proto3" json:"chain_name,omitempty"` + // Deprecated: After the upgrade to v8 + ChannelIbc string `protobuf:"bytes,8,opt,name=channel_ibc,json=channelIbc,proto3" json:"channel_ibc,omitempty"` + ChainName string `protobuf:"bytes,9,opt,name=chain_name,json=chainName,proto3" json:"chain_name,omitempty"` } func (m *MsgBridgeTokenClaim) Reset() { *m = MsgBridgeTokenClaim{} } diff --git a/x/evm/keeper/msg_server_test.go b/x/evm/keeper/msg_server_test.go index 3784af15..56d0bda5 100644 --- a/x/evm/keeper/msg_server_test.go +++ b/x/evm/keeper/msg_server_test.go @@ -60,7 +60,7 @@ func (s *KeeperTestSuite) TestKeeper_EthereumTx_Data() { recipient := helpers.GenHexAddress() amount := big.NewInt(10) - data, err := erc20Suite.ERC20TokenKeeper.PackMint(recipient, amount) + data, err := helpers.PackERC20Mint(recipient, amount) s.Require().NoError(err) res, err := s.ethereumTx(signer, &contractAddr, data, nil, gasLimit) @@ -117,7 +117,7 @@ func (s *KeeperTestSuite) TestKeeper_CallContract() { amount := big.NewInt(100) recipient := erc20Suite.HexAddress() - data, err := erc20Suite.ERC20TokenKeeper.PackMint(recipient, amount) + data, err := helpers.PackERC20Mint(recipient, amount) s.Require().NoError(err) // failed: not authorized diff --git a/x/migrate/keeper/distr_staking_test.go b/x/migrate/keeper/distr_staking_test.go index 53dd1031..5c2fbc7b 100644 --- a/x/migrate/keeper/distr_staking_test.go +++ b/x/migrate/keeper/distr_staking_test.go @@ -10,7 +10,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/distribution" distributionkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" - distritypes "github.com/cosmos/cosmos-sdk/x/distribution/types" + distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" "github.com/cosmos/cosmos-sdk/x/mint" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -61,7 +61,7 @@ func (suite *KeeperTestSuite) TestMigrateStakingDelegate() { suite.Require().EqualError(err, "no delegation for (address, validator) tuple") // migrate - m := migratekeeper.NewDistrStakingMigrate(suite.App.GetKey(distritypes.StoreKey), suite.App.GetKey(stakingtypes.StoreKey), suite.App.StakingKeeper) + m := migratekeeper.NewDistrStakingMigrate(suite.App.GetKey(distrtypes.StoreKey), suite.App.GetKey(stakingtypes.StoreKey), suite.App.StakingKeeper) err = m.Validate(suite.Ctx, suite.App.AppCodec(), acc, ethAcc) suite.Require().NoError(err) err = m.Execute(suite.Ctx, suite.App.AppCodec(), acc, ethAcc) @@ -129,7 +129,7 @@ func (suite *KeeperTestSuite) TestMigrateStakingUnbonding() { suite.Require().Len(slice, 1) suite.Require().Equal(acc.String(), slice[0].DelegatorAddress) - m := migratekeeper.NewDistrStakingMigrate(suite.App.GetKey(distritypes.StoreKey), suite.App.GetKey(stakingtypes.StoreKey), suite.App.StakingKeeper) + m := migratekeeper.NewDistrStakingMigrate(suite.App.GetKey(distrtypes.StoreKey), suite.App.GetKey(stakingtypes.StoreKey), suite.App.StakingKeeper) err = m.Validate(suite.Ctx, suite.App.AppCodec(), acc, ethAcc) suite.Require().NoError(err) err = m.Execute(suite.Ctx, suite.App.AppCodec(), acc, ethAcc) @@ -214,7 +214,7 @@ func (suite *KeeperTestSuite) TestMigrateStakingRedelegate() { suite.Require().Len(queue, int(entries)) suite.Require().Equal(queue[0].DelegatorAddress, acc.String()) - m := migratekeeper.NewDistrStakingMigrate(suite.App.GetKey(distritypes.StoreKey), suite.App.GetKey(stakingtypes.StoreKey), suite.App.StakingKeeper) + m := migratekeeper.NewDistrStakingMigrate(suite.App.GetKey(distrtypes.StoreKey), suite.App.GetKey(stakingtypes.StoreKey), suite.App.StakingKeeper) err = m.Validate(suite.Ctx, suite.App.AppCodec(), acc, ethAcc) suite.Require().NoError(err) err = m.Execute(suite.Ctx, suite.App.AppCodec(), acc, ethAcc) @@ -239,9 +239,9 @@ func (suite *KeeperTestSuite) TestMigrateStakingRedelegate() { func GetDelegateRewards(ctx sdk.Context, app *app.App, delegate []byte, validator string) (sdk.DecCoins, error) { queryHelper := baseapp.NewQueryServerTestHelper(ctx, app.InterfaceRegistry()) - distritypes.RegisterQueryServer(queryHelper, distributionkeeper.NewQuerier(app.DistrKeeper)) - queryClient := distritypes.NewQueryClient(queryHelper) - rewards, err := queryClient.DelegationRewards(context.Background(), &distritypes.QueryDelegationRewardsRequest{ + distrtypes.RegisterQueryServer(queryHelper, distributionkeeper.NewQuerier(app.DistrKeeper)) + queryClient := distrtypes.NewQueryClient(queryHelper) + rewards, err := queryClient.DelegationRewards(context.Background(), &distrtypes.QueryDelegationRewardsRequest{ DelegatorAddress: sdk.AccAddress(delegate).String(), ValidatorAddress: validator, })