From 8628885bbeba3b499765e792afa243892cdf07f3 Mon Sep 17 00:00:00 2001 From: zsystm Date: Wed, 4 Jun 2025 21:43:10 +0900 Subject: [PATCH 01/21] test refactoring evmd as separate package - we can make sure more clean dependency: only evmd -> evmd allows. not vice versa. test re-structuring - tests using network + evmd moved into evm/tests/integration - test file names are changed from *_test.go to test_*.go, so any client chains can leverage cosmos/evm's test suites with their own application refactoring - all integration tests in evm uses EvmApp interface. so it allows other client application can leverage cosmos/evm's test suites. - evmd implements methods of EvmApp - separate Erc20Keeper interface to avoid cyclic import between erc20/keeper and precompiles/erc20 - change backend member variables to public. this is for making testing refactoring easier. if there are some security concern, we should consider introducing getters. removed un-used files --- ante/cosmos/authz_test.go | 496 --- ante/cosmos/setup_test.go | 21 - ante/evm/fee_checker_test.go | 11 +- ante/evm/setup_test.go | 30 - ante/evm/signverify_test.go | 88 - ante/evm/sigs_test.go | 49 - ante/evm/suite_test.go | 36 - ante/evm/utils_test.go | 580 --- ante/testutils/testutil.go | 178 - cmd/evmd/cmd/root.go | 8 +- cmd/evmd/main.go | 5 +- evmd/activators.go | 3 +- evmd/ante/integration_test.go | 175 - evmd/app.go | 75 +- evmd/eips/eips_test.go | 438 --- evmd/go.mod | 280 ++ evmd/go.sum | 2605 +++++++++++++ evmd/precompiles.go | 2 +- evmd/tests/ante/authz_test.go | 277 ++ {tests => evmd/tests}/ibc/helper.go | 2 +- .../tests}/ibc/ibc_middleware_test.go | 2 +- .../ibc/ics20_precompile_transfer_test.go | 2 +- {tests => evmd/tests}/ibc/transfer_test.go | 2 +- .../tests}/ibc/v2_ibc_middleware_test.go | 2 +- .../ibc/v2_ics20_precompile_transfer_test.go | 2 +- {tests => evmd/tests}/ibc/v2_transfer_test.go | 2 +- evmd/tests/integration/ante_test.go | 11 + evmd/tests/integration/backend_test.go | 14 + evmd/tests/integration/create_app.go | 34 + evmd/tests/integration/eip712_test.go | 19 + evmd/tests/integration/eips_test.go | 11 + evmd/tests/integration/evm_ante_bench_test.go | 15 + evmd/tests/integration/evm_ante_test.go | 45 + evmd/tests/integration/ibc_test.go | 14 + evmd/tests/integration/indexer_test.go | 11 + .../tests/integration/precompile_bank_test.go | 18 + .../integration/precompile_bech32_test.go | 14 + .../precompile_distribution_test.go | 18 + .../integration/precompile_erc20_test.go | 18 + .../integration/precompile_evidence_test.go | 14 + evmd/tests/integration/precompile_gov_test.go | 18 + .../tests/integration/precompile_p256_test.go | 18 + .../integration/precompile_slashing_test.go | 14 + .../integration/precompile_staking_test.go | 18 + .../integration/precompile_werc20_test.go | 18 + evmd/tests/integration/testutil_test.go | 14 + evmd/tests/integration/wallets_test.go | 14 + evmd/tests/integration/x_erc20_test.go | 22 + evmd/tests/integration/x_feemarket_test.go | 14 + evmd/tests/integration/x_precisebank_test.go | 19 + evmd/tests/integration/x_vm_test.go | 31 + evmd/testutil/abci.go | 31 +- evmd/testutil/app.go | 5 - evmd/testutil/eth_setup.go | 75 +- evmd/testutil/fund.go | 42 - evmd/testutil/integration.go | 14 +- go.mod | 6 +- ibc/testing/chain.go | 2 +- ibc/testing/coordinator.go | 2 +- ibc/testing/testing_app.go | 3 +- interfaces.go | 145 + precompiles/bank/bank.go | 6 +- precompiles/bank/integration_test.go | 431 --- precompiles/distribution/integration_test.go | 3205 ---------------- precompiles/erc20/integration_test.go | 2789 -------------- precompiles/gov/integration_test.go | 2068 ---------- precompiles/p256/integration_test.go | 201 - precompiles/staking/integration_test.go | 3354 ----------------- precompiles/testutil/contracts/contracts.go | 29 +- precompiles/werc20/integration_test.go | 605 --- rpc/backend/account_info.go | 20 +- rpc/backend/backend.go | 36 +- rpc/backend/blocks.go | 90 +- rpc/backend/call_tx.go | 38 +- rpc/backend/chain_info.go | 30 +- rpc/backend/filters.go | 2 +- rpc/backend/node_info.go | 96 +- rpc/backend/sign_tx.go | 52 +- rpc/backend/tracing.go | 36 +- rpc/backend/tx_info.go | 100 +- rpc/backend/utils.go | 10 +- tests/integration/README.md | 16 + tests/integration/ante/ante_test_suite.go | 192 + .../ante/benchmark_evm_antehandler.go | 39 +- tests/integration/ante/evm_ante_test_suite.go | 707 ++++ .../ante/evm_unit_ante_test_suite.go | 29 + .../integration/ante/test_bench_evm_ante.go | 25 +- .../integration/ante/test_evm_01_setup_ctx.go | 18 +- .../integration/ante/test_evm_ante.go | 553 +-- .../integration/ante/test_evm_fee_market.go | 29 +- .../ante/test_evm_unit_02_mempool_fee.go | 4 +- .../ante/test_evm_unit_03_global_fee.go | 4 +- .../ante/test_evm_unit_04_validate.go | 8 +- .../test_evm_unit_06_account_verification.go | 31 +- .../ante/test_evm_unit_07_can_transfer.go | 23 +- .../ante/test_evm_unit_08_gas_consume.go | 30 +- .../test_evm_unit_09_increment_sequence.go | 17 +- .../ante/test_evm_unit_10_gas_wanted.go | 29 +- tests/integration/ante/test_integration.go | 237 ++ .../integration/ante/test_min_gas_price.go | 88 +- .../ante/test_validate_handler_options.go | 74 +- .../integration/eip712/test_eip712.go | 26 +- .../integration/eip712/test_eip712_fuzzer.go | 194 + tests/integration/eips/test_eips.go | 445 +++ .../integration/indexer/test_kv_indexer.go | 8 +- tests/integration/ledger/evmosd_suite_test.go | 2 +- .../precompiles/bank/test_integration.go | 447 +++ .../precompiles/bank/test_query.go | 4 +- .../precompiles/bank/test_setup.go | 41 +- .../precompiles/bank/test_utils.go | 24 +- .../precompiles/bech32/test_bech32.go | 6 +- .../precompiles/bech32/test_methods.go | 2 +- .../precompiles/bech32/test_setup.go | 24 +- .../distribution/test_distribution.go | 34 +- .../precompiles/distribution/test_event.go | 6 +- .../distribution/test_integration.go | 3205 ++++++++++++++++ .../precompiles/distribution/test_query.go | 14 +- .../precompiles/distribution/test_setup.go | 38 +- .../precompiles/distribution/test_tx.go | 40 +- .../precompiles/distribution/test_utils.go | 16 +- .../precompiles/erc20/test_approve.go | 2 +- .../precompiles/erc20/test_erc20.go | 2 +- .../precompiles/erc20/test_errors.go | 6 +- .../precompiles/erc20/test_events.go | 16 +- .../precompiles/erc20/test_integration.go | 2802 ++++++++++++++ .../precompiles/erc20/test_query.go | 109 +- .../precompiles/erc20/test_setup.go | 36 +- .../integration/precompiles/erc20/test_tx.go | 35 +- .../precompiles/erc20/test_types.go | 2 +- .../precompiles/erc20/test_utils.go | 64 +- .../precompiles/evidence/test_query.go | 10 +- .../precompiles/evidence/test_setup.go | 31 +- .../precompiles/evidence/test_tx.go | 4 +- .../precompiles/gov/test_events.go | 2 +- .../integration/precompiles/gov/test_gov.go | 16 +- .../precompiles/gov/test_integration.go | 2068 ++++++++++ .../integration/precompiles/gov/test_query.go | 16 +- .../integration/precompiles/gov/test_setup.go | 28 +- .../integration/precompiles/gov/test_tx.go | 10 +- .../integration/precompiles/gov/test_utils.go | 8 +- .../precompiles/p256/test_integration.go | 211 ++ .../integration/precompiles/p256/test_p256.go | 2 +- .../precompiles/p256/test_setup.go | 28 +- .../precompiles/slashing/test_events.go | 6 +- .../precompiles/slashing/test_query.go | 9 +- .../precompiles/slashing/test_setup.go | 30 +- .../precompiles/slashing/test_tx.go | 10 +- .../precompiles/staking/test_events.go | 4 +- .../precompiles/staking/test_integration.go | 3353 ++++++++++++++++ .../precompiles/staking/test_query.go | 4 +- .../precompiles/staking/test_setup.go | 30 +- .../precompiles/staking/test_staking.go | 116 +- .../precompiles/staking/test_tx.go | 24 +- .../precompiles/staking/test_utils.go | 4 +- .../precompiles/werc20/test_events.go | 41 +- .../precompiles/werc20/test_integration.go | 605 +++ .../precompiles/werc20/test_utils.go | 10 +- .../rpc/backend/test_account_info.go | 158 +- .../rpc/backend/test_backend_suite.go | 99 +- .../integration/rpc/backend/test_blocks.go | 554 +-- .../integration/rpc/backend/test_call_tx.go | 244 +- .../rpc/backend/test_chain_info.go | 178 +- .../integration/rpc/backend/test_client.go | 0 .../rpc/backend/test_evm_query_client.go | 0 .../backend/test_feemarket_query_client.go | 0 .../integration/rpc/backend/test_filters.go | 42 +- .../integration/rpc/backend/test_node_info.go | 132 +- .../integration/rpc/backend/test_sign_tx.go | 106 +- .../integration/rpc/backend/test_tracing.go | 78 +- .../integration/rpc/backend/test_tx_info.go | 286 +- .../integration/rpc/backend/test_utils.go | 8 +- tests/integration/testutil/test_bank.go | 71 + tests/integration/testutil/test_config.go | 135 + tests/integration/testutil/test_evm.go | 69 + tests/integration/testutil/test_suite.go | 23 + .../integration/wallets/test_ledger_suite.go | 49 +- .../integration/wallets/test_legder.go | 2 +- .../integration/wallets/test_wallet.go | 2 +- .../integration/x/erc20/test_allowance.go | 146 +- .../x/erc20/test_dynamic_precompiles.go | 44 +- .../integration/x/erc20/test_erc20_utils.go | 32 +- .../integration/x/erc20/test_evm.go | 81 +- .../integration/x/erc20/test_genesis.go | 111 +- .../integration/x/erc20/test_grpc_query.go | 63 +- .../integration/x/erc20/test_ibc_callback.go | 214 +- tests/integration/x/erc20/test_integration.go | 194 + tests/integration/x/erc20/test_mint.go | 109 + .../integration/x/erc20/test_msg_server.go | 323 +- .../integration/x/erc20/test_params.go | 28 +- .../integration/x/erc20/test_precompiles.go | 34 +- .../integration/x/erc20/test_proposals.go | 170 +- .../integration/x/erc20/test_setup.go | 43 +- .../integration/x/erc20/test_token_pairs.go | 148 +- tests/integration/x/erc20/test_util.go | 80 + .../integration/x/feemarket/test_abci.go | 30 +- .../integration/x/feemarket/test_eip1559.go | 34 +- .../x/feemarket/test_grpc_query.go | 54 +- .../x/feemarket/test_integration.go | 691 ++++ .../integration/x/feemarket/test_keeper.go | 32 +- .../x/feemarket/test_msg_server.go | 20 +- .../integration/x/feemarket/test_params.go | 51 +- tests/integration/x/feemarket/test_setup.go | 64 + .../integration/x/ibc/test_keeper.go | 74 +- .../integration/x/ibc/test_msg_server.go | 46 +- .../x/precisebank/test_burn_integration.go | 204 +- .../integration/x/precisebank/test_genesis.go | 116 +- .../x/precisebank/test_grpc_query.go | 36 +- .../x/precisebank/test_integration.go | 150 +- .../x/precisebank/test_mint_integration.go | 102 +- .../x/precisebank/test_send_integration.go | 256 +- tests/integration/x/precisebank/test_setup.go | 50 + .../integration/x/precisebank/test_utils.go | 52 +- .../x/precisebank/test_view_integration.go | 46 +- tests/integration/x/vm/ante_test_suite.go | 21 + .../integration/x/vm/benchmark_params.go | 6 +- .../integration/x/vm/benchmark_statedb.go | 16 +- tests/integration/x/vm/genesis_test_suite.go | 44 + .../integration/x/vm/keeper_test_suite.go | 75 +- .../x/vm/nested_evm_extension_test_suite.go | 158 + .../x/vm/state_transition_benchmark.go | 68 +- tests/integration/x/vm/test_abci.go | 26 + .../integration/x/vm/test_benchmark.go | 48 +- .../integration/x/vm/test_call_evm.go | 34 +- .../integration/x/vm/test_ctx.go | 6 +- .../integration/x/vm/test_fees.go | 152 +- .../x/vm/test_flash_loan_exploit.go | 103 + tests/integration/x/vm/test_genesis.go | 212 ++ .../integration/x/vm/test_grpc_query.go | 651 ++-- .../integration/x/vm/test_hooks.go | 22 +- .../integration/x/vm/test_keeper.go | 56 +- .../integration/x/vm/test_msg_server.go | 68 +- .../integration/x/vm/test_params.go | 41 +- .../integration/x/vm/test_state_transition.go | 343 +- .../integration/x/vm/test_statedb.go | 524 ++- .../integration/x/vm/utils.go | 66 +- {evmd/testutil => testutil}/gas.go | 0 .../{common => base}/factory/base.go | 4 +- .../{common => base}/factory/distribution.go | 0 .../{common => base}/factory/factory.go | 4 +- .../{common => base}/factory/fund.go | 2 +- .../{common => base}/factory/helper.go | 0 .../{common => base}/factory/sign.go | 0 .../{common => base}/factory/staking.go | 0 .../{common => base}/factory/types.go | 0 .../{common => base}/grpc/account.go | 0 .../{common => base}/grpc/authz.go | 0 .../integration/{common => base}/grpc/bank.go | 0 .../{common => base}/grpc/distribution.go | 0 .../integration/{common => base}/grpc/grpc.go | 2 +- .../{common => base}/grpc/staking.go | 0 .../{common => base}/network/network.go | 0 .../integration}/contract.go | 14 +- .../{os => evm}/factory/broadcast.go | 7 +- .../integration/{os => evm}/factory/build.go | 5 +- .../{os => evm}/factory/factory.go | 23 +- .../{os => evm}/factory/helpers.go | 0 .../integration/{os => evm}/factory/sign.go | 0 testutil/integration/{os => evm}/grpc/evm.go | 0 .../integration/{os => evm}/grpc/feemarket.go | 0 testutil/integration/{os => evm}/grpc/gov.go | 0 testutil/integration/{os => evm}/grpc/grpc.go | 10 +- .../integration/{os => evm}/network/abci.go | 2 +- .../{os => evm}/network/amounts.go | 0 .../{os => evm}/network/chain_id_modifiers.go | 0 .../{os => evm}/network/clients.go | 23 +- .../integration/{os => evm}/network/coins.go | 0 .../integration/{os => evm}/network/config.go | 4 + .../{os => evm}/network/example_contracts.go | 0 .../integration/{os => evm}/network/ibc.go | 0 .../{os => evm}/network/network.go | 70 +- .../integration/{os => evm}/network/setup.go | 66 +- .../{os => evm}/network/unit_network.go | 14 +- .../integration/{os => evm}/utils/bank.go | 6 +- .../{os => evm}/utils/contracts.go | 4 +- .../integration/{os => evm}/utils/erc20.go | 4 +- .../integration/{os => evm}/utils/events.go | 0 testutil/integration/{os => evm}/utils/evm.go | 2 +- .../integration/{os => evm}/utils/genesis.go | 20 +- testutil/integration/{os => evm}/utils/gov.go | 6 +- .../integration/{os => evm}/utils/params.go | 4 +- .../integration/{os => evm}/utils/staking.go | 4 +- .../integration/{os => evm}/utils/types.go | 0 .../integration/{os => evm}/utils/unit.go | 28 +- .../integration/os/network/config_test.go | 136 - testutil/integration/os/utils/bank_test.go | 74 - testutil/integration/os/utils/evm_test.go | 65 - testutil/integration/params.go | 27 + testutil/integration/utils.go | 67 + .../{integration/os => }/keyring/keyring.go | 0 testutil/network/network.go | 2 +- testutil/staking_rewards.go | 126 - testutil/tx/cosmos.go | 12 +- testutil/tx/eip712.go | 18 +- testutil/tx/eth.go | 8 +- .../os/factory => types}/types.go | 2 +- ante/cosmos/utils_test.go => testutil/util.go | 65 +- utils/utils.go | 28 + wallets/usbwallet/ledger.go | 2 +- x/erc20/ibc_middleware.go | 4 +- x/erc20/keeper/integration_test.go | 193 - x/erc20/keeper/mint_test.go | 109 - x/erc20/keeper/token_pairs.go | 4 +- x/erc20/keeper/utils_test.go | 80 - x/erc20/types/interfaces.go | 2 +- x/erc20/v2/ibc_middleware.go | 4 +- x/feemarket/keeper/integration_test.go | 688 ---- x/feemarket/keeper/setup_test.go | 47 - x/precisebank/keeper/keeper_test.go | 15 +- x/precisebank/keeper/setup_test.go | 45 - x/vm/ante/suite_test.go | 15 - x/vm/genesis_test.go | 250 -- x/vm/keeper/abci_test.go | 25 - x/vm/keeper/grpc_query.go | 2 +- x/vm/keeper/integration_test.go | 673 ---- x/vm/keeper/state_transition.go | 6 +- x/vm/statedb/integration_test.go | 325 -- x/vm/types/errors.go | 2 +- x/vm/types/evm.pb.go | 2 +- x/vm/types/msg_test.go | 4 +- x/vm/types/permissions_test.go | 2 +- 320 files changed, 25588 insertions(+), 22606 deletions(-) delete mode 100644 ante/cosmos/authz_test.go delete mode 100644 ante/cosmos/setup_test.go delete mode 100644 ante/evm/setup_test.go delete mode 100644 ante/evm/signverify_test.go delete mode 100644 ante/evm/sigs_test.go delete mode 100644 ante/evm/suite_test.go delete mode 100644 ante/evm/utils_test.go delete mode 100644 ante/testutils/testutil.go delete mode 100644 evmd/ante/integration_test.go delete mode 100644 evmd/eips/eips_test.go create mode 100644 evmd/go.mod create mode 100644 evmd/go.sum create mode 100644 evmd/tests/ante/authz_test.go rename {tests => evmd/tests}/ibc/helper.go (98%) rename {tests => evmd/tests}/ibc/ibc_middleware_test.go (99%) rename {tests => evmd/tests}/ibc/ics20_precompile_transfer_test.go (99%) rename {tests => evmd/tests}/ibc/transfer_test.go (99%) rename {tests => evmd/tests}/ibc/v2_ibc_middleware_test.go (99%) rename {tests => evmd/tests}/ibc/v2_ics20_precompile_transfer_test.go (99%) rename {tests => evmd/tests}/ibc/v2_transfer_test.go (99%) create mode 100644 evmd/tests/integration/ante_test.go create mode 100644 evmd/tests/integration/backend_test.go create mode 100644 evmd/tests/integration/create_app.go create mode 100644 evmd/tests/integration/eip712_test.go create mode 100644 evmd/tests/integration/eips_test.go create mode 100644 evmd/tests/integration/evm_ante_bench_test.go create mode 100644 evmd/tests/integration/evm_ante_test.go create mode 100644 evmd/tests/integration/ibc_test.go create mode 100644 evmd/tests/integration/indexer_test.go create mode 100644 evmd/tests/integration/precompile_bank_test.go create mode 100644 evmd/tests/integration/precompile_bech32_test.go create mode 100644 evmd/tests/integration/precompile_distribution_test.go create mode 100644 evmd/tests/integration/precompile_erc20_test.go create mode 100644 evmd/tests/integration/precompile_evidence_test.go create mode 100644 evmd/tests/integration/precompile_gov_test.go create mode 100644 evmd/tests/integration/precompile_p256_test.go create mode 100644 evmd/tests/integration/precompile_slashing_test.go create mode 100644 evmd/tests/integration/precompile_staking_test.go create mode 100644 evmd/tests/integration/precompile_werc20_test.go create mode 100644 evmd/tests/integration/testutil_test.go create mode 100644 evmd/tests/integration/wallets_test.go create mode 100644 evmd/tests/integration/x_erc20_test.go create mode 100644 evmd/tests/integration/x_feemarket_test.go create mode 100644 evmd/tests/integration/x_precisebank_test.go create mode 100644 evmd/tests/integration/x_vm_test.go delete mode 100644 evmd/testutil/app.go delete mode 100644 evmd/testutil/fund.go create mode 100644 interfaces.go delete mode 100644 precompiles/bank/integration_test.go delete mode 100644 precompiles/distribution/integration_test.go delete mode 100644 precompiles/erc20/integration_test.go delete mode 100644 precompiles/gov/integration_test.go delete mode 100644 precompiles/p256/integration_test.go delete mode 100644 precompiles/staking/integration_test.go delete mode 100644 precompiles/werc20/integration_test.go create mode 100644 tests/integration/README.md create mode 100644 tests/integration/ante/ante_test_suite.go rename evmd/ante/evm_benchmark_test.go => tests/integration/ante/benchmark_evm_antehandler.go (76%) create mode 100644 tests/integration/ante/evm_ante_test_suite.go create mode 100644 tests/integration/ante/evm_unit_ante_test_suite.go rename ante/evm/eth_benchmark_test.go => tests/integration/ante/test_bench_evm_ante.go (77%) rename ante/evm/01_setup_ctx_test.go => tests/integration/ante/test_evm_01_setup_ctx.go (64%) rename ante/evm/ante_test.go => tests/integration/ante/test_evm_ante.go (61%) rename ante/evm/fee_market_test.go => tests/integration/ante/test_evm_fee_market.go (84%) rename ante/evm/02_mempool_fee_test.go => tests/integration/ante/test_evm_unit_02_mempool_fee.go (95%) rename ante/evm/03_global_fee_test.go => tests/integration/ante/test_evm_unit_03_global_fee.go (95%) rename ante/evm/04_validate_test.go => tests/integration/ante/test_evm_unit_04_validate.go (97%) rename ante/evm/06_account_verification_test.go => tests/integration/ante/test_evm_unit_06_account_verification.go (88%) rename ante/evm/07_can_transfer_test.go => tests/integration/ante/test_evm_unit_07_can_transfer.go (86%) rename ante/evm/08_gas_consume_test.go => tests/integration/ante/test_evm_unit_08_gas_consume.go (89%) rename ante/evm/09_increment_sequence_test.go => tests/integration/ante/test_evm_unit_09_increment_sequence.go (82%) rename ante/evm/10_gas_wanted_test.go => tests/integration/ante/test_evm_unit_10_gas_wanted.go (83%) create mode 100644 tests/integration/ante/test_integration.go rename ante/cosmos/min_gas_price_test.go => tests/integration/ante/test_min_gas_price.go (59%) rename evmd/ante/handler_options_test.go => tests/integration/ante/test_validate_handler_options.go (56%) rename ethereum/eip712/eip712_test.go => tests/integration/eip712/test_eip712.go (97%) create mode 100644 tests/integration/eip712/test_eip712_fuzzer.go create mode 100644 tests/integration/eips/test_eips.go rename indexer/kv_indexer_test.go => tests/integration/indexer/test_kv_indexer.go (96%) create mode 100644 tests/integration/precompiles/bank/test_integration.go rename precompiles/bank/query_test.go => tests/integration/precompiles/bank/test_query.go (98%) rename precompiles/bank/setup_test.go => tests/integration/precompiles/bank/test_setup.go (61%) rename precompiles/bank/utils_test.go => tests/integration/precompiles/bank/test_utils.go (81%) rename precompiles/bech32/bech32_test.go => tests/integration/precompiles/bech32/test_bech32.go (97%) rename precompiles/bech32/methods_test.go => tests/integration/precompiles/bech32/test_methods.go (99%) rename precompiles/bech32/setup_test.go => tests/integration/precompiles/bech32/test_setup.go (57%) rename precompiles/distribution/distribution_test.go => tests/integration/precompiles/distribution/test_distribution.go (89%) rename precompiles/distribution/events_test.go => tests/integration/precompiles/distribution/test_event.go (98%) create mode 100644 tests/integration/precompiles/distribution/test_integration.go rename precompiles/distribution/query_test.go => tests/integration/precompiles/distribution/test_query.go (96%) rename precompiles/distribution/setup_test.go => tests/integration/precompiles/distribution/test_setup.go (78%) rename precompiles/distribution/tx_test.go => tests/integration/precompiles/distribution/test_tx.go (89%) rename precompiles/distribution/utils_test.go => tests/integration/precompiles/distribution/test_utils.go (83%) rename precompiles/erc20/approve_test.go => tests/integration/precompiles/erc20/test_approve.go (99%) rename precompiles/erc20/erc20_test.go => tests/integration/precompiles/erc20/test_erc20.go (99%) rename precompiles/erc20/errors_test.go => tests/integration/precompiles/erc20/test_errors.go (89%) rename precompiles/erc20/events_test.go => tests/integration/precompiles/erc20/test_events.go (85%) create mode 100644 tests/integration/precompiles/erc20/test_integration.go rename precompiles/erc20/query_test.go => tests/integration/precompiles/erc20/test_query.go (76%) rename precompiles/erc20/setup_test.go => tests/integration/precompiles/erc20/test_setup.go (65%) rename precompiles/erc20/tx_test.go => tests/integration/precompiles/erc20/test_tx.go (79%) rename precompiles/erc20/types_test.go => tests/integration/precompiles/erc20/test_types.go (99%) rename precompiles/erc20/utils_test.go => tests/integration/precompiles/erc20/test_utils.go (90%) rename precompiles/evidence/query_test.go => tests/integration/precompiles/evidence/test_query.go (92%) rename precompiles/evidence/setup_test.go => tests/integration/precompiles/evidence/test_setup.go (62%) rename precompiles/evidence/tx_test.go => tests/integration/precompiles/evidence/test_tx.go (93%) rename precompiles/gov/events_test.go => tests/integration/precompiles/gov/test_events.go (99%) rename precompiles/gov/gov_test.go => tests/integration/precompiles/gov/test_gov.go (88%) create mode 100644 tests/integration/precompiles/gov/test_integration.go rename precompiles/gov/query_test.go => tests/integration/precompiles/gov/test_query.go (94%) rename precompiles/gov/setup_test.go => tests/integration/precompiles/gov/test_setup.go (84%) rename precompiles/gov/tx_test.go => tests/integration/precompiles/gov/test_tx.go (94%) rename precompiles/gov/utils_test.go => tests/integration/precompiles/gov/test_utils.go (89%) create mode 100644 tests/integration/precompiles/p256/test_integration.go rename precompiles/p256/p256_test.go => tests/integration/precompiles/p256/test_p256.go (99%) rename precompiles/p256/setup_test.go => tests/integration/precompiles/p256/test_setup.go (73%) rename precompiles/slashing/events_test.go => tests/integration/precompiles/slashing/test_events.go (93%) rename precompiles/slashing/query_test.go => tests/integration/precompiles/slashing/test_query.go (96%) rename precompiles/slashing/setup_test.go => tests/integration/precompiles/slashing/test_setup.go (57%) rename precompiles/slashing/tx_test.go => tests/integration/precompiles/slashing/test_tx.go (84%) rename precompiles/staking/events_test.go => tests/integration/precompiles/staking/test_events.go (99%) create mode 100644 tests/integration/precompiles/staking/test_integration.go rename precompiles/staking/query_test.go => tests/integration/precompiles/staking/test_query.go (99%) rename precompiles/staking/setup_test.go => tests/integration/precompiles/staking/test_setup.go (72%) rename precompiles/staking/staking_test.go => tests/integration/precompiles/staking/test_staking.go (85%) rename precompiles/staking/tx_test.go => tests/integration/precompiles/staking/test_tx.go (97%) rename precompiles/staking/utils_test.go => tests/integration/precompiles/staking/test_utils.go (98%) rename precompiles/werc20/events_test.go => tests/integration/precompiles/werc20/test_events.go (83%) create mode 100644 tests/integration/precompiles/werc20/test_integration.go rename precompiles/werc20/utils_test.go => tests/integration/precompiles/werc20/test_utils.go (88%) rename rpc/backend/account_info_test.go => tests/integration/rpc/backend/test_account_info.go (67%) rename rpc/backend/backend_suite_test.go => tests/integration/rpc/backend/test_backend_suite.go (64%) rename rpc/backend/blocks_test.go => tests/integration/rpc/backend/test_blocks.go (67%) rename rpc/backend/call_tx_test.go => tests/integration/rpc/backend/test_call_tx.go (57%) rename rpc/backend/chain_info_test.go => tests/integration/rpc/backend/test_chain_info.go (58%) rename rpc/backend/client_test.go => tests/integration/rpc/backend/test_client.go (100%) rename rpc/backend/evm_query_client_test.go => tests/integration/rpc/backend/test_evm_query_client.go (100%) rename rpc/backend/feemarket_query_client_test.go => tests/integration/rpc/backend/test_feemarket_query_client.go (100%) rename rpc/backend/filters_test.go => tests/integration/rpc/backend/test_filters.go (70%) rename rpc/backend/node_info_test.go => tests/integration/rpc/backend/test_node_info.go (61%) rename rpc/backend/sign_tx_test.go => tests/integration/rpc/backend/test_sign_tx.go (60%) rename rpc/backend/tracing_test.go => tests/integration/rpc/backend/test_tracing.go (72%) rename rpc/backend/tx_info_test.go => tests/integration/rpc/backend/test_tx_info.go (58%) rename rpc/backend/utils_test.go => tests/integration/rpc/backend/test_utils.go (81%) create mode 100644 tests/integration/testutil/test_bank.go create mode 100644 tests/integration/testutil/test_config.go create mode 100644 tests/integration/testutil/test_evm.go create mode 100644 tests/integration/testutil/test_suite.go rename wallets/ledger/ledger_suite_test.go => tests/integration/wallets/test_ledger_suite.go (77%) rename wallets/ledger/ledger_test.go => tests/integration/wallets/test_legder.go (99%) rename wallets/ledger/wallet_test.go => tests/integration/wallets/test_wallet.go (98%) rename x/erc20/keeper/allowance_test.go => tests/integration/x/erc20/test_allowance.go (70%) rename x/erc20/keeper/dynamic_precompiles_test.go => tests/integration/x/erc20/test_dynamic_precompiles.go (50%) rename x/erc20/keeper/erc20_utils_test.go => tests/integration/x/erc20/test_erc20_utils.go (53%) rename x/erc20/keeper/evm_test.go => tests/integration/x/erc20/test_evm.go (80%) rename x/erc20/genesis_test.go => tests/integration/x/erc20/test_genesis.go (58%) rename x/erc20/keeper/grpc_query_test.go => tests/integration/x/erc20/test_grpc_query.go (68%) rename x/erc20/keeper/ibc_callbacks_test.go => tests/integration/x/erc20/test_ibc_callback.go (70%) create mode 100644 tests/integration/x/erc20/test_integration.go create mode 100644 tests/integration/x/erc20/test_mint.go rename x/erc20/keeper/msg_server_test.go => tests/integration/x/erc20/test_msg_server.go (62%) rename x/erc20/keeper/params_test.go => tests/integration/x/erc20/test_params.go (68%) rename x/erc20/keeper/precompiles_test.go => tests/integration/x/erc20/test_precompiles.go (66%) rename x/erc20/keeper/proposals_test.go => tests/integration/x/erc20/test_proposals.go (50%) rename x/erc20/keeper/setup_test.go => tests/integration/x/erc20/test_setup.go (60%) rename x/erc20/keeper/token_pairs_test.go => tests/integration/x/erc20/test_token_pairs.go (55%) create mode 100644 tests/integration/x/erc20/test_util.go rename x/feemarket/keeper/abci_test.go => tests/integration/x/feemarket/test_abci.go (50%) rename x/feemarket/keeper/eip1559_test.go => tests/integration/x/feemarket/test_eip1559.go (75%) rename x/feemarket/keeper/grpc_query_test.go => tests/integration/x/feemarket/test_grpc_query.go (64%) create mode 100644 tests/integration/x/feemarket/test_integration.go rename x/feemarket/keeper/keeper_test.go => tests/integration/x/feemarket/test_keeper.go (52%) rename x/feemarket/keeper/msg_server_test.go => tests/integration/x/feemarket/test_msg_server.go (70%) rename x/feemarket/keeper/params_test.go => tests/integration/x/feemarket/test_params.go (53%) create mode 100644 tests/integration/x/feemarket/test_setup.go rename x/ibc/transfer/keeper/keeper_test.go => tests/integration/x/ibc/test_keeper.go (65%) rename x/ibc/transfer/keeper/msg_server_test.go => tests/integration/x/ibc/test_msg_server.go (85%) rename x/precisebank/keeper/burn_integration_test.go => tests/integration/x/precisebank/test_burn_integration.go (65%) rename x/precisebank/genesis_test.go => tests/integration/x/precisebank/test_genesis.go (66%) rename x/precisebank/keeper/grpc_query_test.go => tests/integration/x/precisebank/test_grpc_query.go (66%) rename x/precisebank/keeper/integration_test.go => tests/integration/x/precisebank/test_integration.go (55%) rename x/precisebank/keeper/mint_integration_test.go => tests/integration/x/precisebank/test_mint_integration.go (76%) rename x/precisebank/keeper/send_integration_test.go => tests/integration/x/precisebank/test_send_integration.go (71%) create mode 100644 tests/integration/x/precisebank/test_setup.go rename x/precisebank/keeper/util_test.go => tests/integration/x/precisebank/test_utils.go (53%) rename x/precisebank/keeper/view_integration_test.go => tests/integration/x/precisebank/test_view_integration.go (74%) create mode 100644 tests/integration/x/vm/ante_test_suite.go rename x/vm/keeper/params_benchmark_test.go => tests/integration/x/vm/benchmark_params.go (70%) rename x/vm/keeper/statedb_benchmark_test.go => tests/integration/x/vm/benchmark_statedb.go (89%) create mode 100644 tests/integration/x/vm/genesis_test_suite.go rename x/vm/keeper/setup_test.go => tests/integration/x/vm/keeper_test_suite.go (67%) create mode 100644 tests/integration/x/vm/nested_evm_extension_test_suite.go rename x/vm/keeper/state_transition_benchmark_test.go => tests/integration/x/vm/state_transition_benchmark.go (76%) create mode 100644 tests/integration/x/vm/test_abci.go rename x/vm/keeper/benchmark_test.go => tests/integration/x/vm/test_benchmark.go (72%) rename x/vm/keeper/call_evm_test.go => tests/integration/x/vm/test_call_evm.go (70%) rename x/vm/ante/ctx_test.go => tests/integration/x/vm/test_ctx.go (75%) rename x/vm/keeper/fees_test.go => tests/integration/x/vm/test_fees.go (76%) create mode 100644 tests/integration/x/vm/test_flash_loan_exploit.go create mode 100644 tests/integration/x/vm/test_genesis.go rename x/vm/keeper/grpc_query_test.go => tests/integration/x/vm/test_grpc_query.go (68%) rename x/vm/keeper/hooks_test.go => tests/integration/x/vm/test_hooks.go (77%) rename x/vm/keeper/keeper_test.go => tests/integration/x/vm/test_keeper.go (64%) rename x/vm/keeper/msg_server_test.go => tests/integration/x/vm/test_msg_server.go (51%) rename x/vm/keeper/params_test.go => tests/integration/x/vm/test_params.go (65%) rename x/vm/keeper/state_transition_test.go => tests/integration/x/vm/test_state_transition.go (61%) rename x/vm/keeper/statedb_test.go => tests/integration/x/vm/test_statedb.go (56%) rename x/vm/keeper/utils_test.go => tests/integration/x/vm/utils.go (66%) rename {evmd/testutil => testutil}/gas.go (100%) rename testutil/integration/{common => base}/factory/base.go (97%) rename testutil/integration/{common => base}/factory/distribution.go (100%) rename testutil/integration/{common => base}/factory/factory.go (89%) rename testutil/integration/{common => base}/factory/fund.go (95%) rename testutil/integration/{common => base}/factory/helper.go (100%) rename testutil/integration/{common => base}/factory/sign.go (100%) rename testutil/integration/{common => base}/factory/staking.go (100%) rename testutil/integration/{common => base}/factory/types.go (100%) rename testutil/integration/{common => base}/grpc/account.go (100%) rename testutil/integration/{common => base}/grpc/authz.go (100%) rename testutil/integration/{common => base}/grpc/bank.go (100%) rename testutil/integration/{common => base}/grpc/distribution.go (100%) rename testutil/integration/{common => base}/grpc/grpc.go (98%) rename testutil/integration/{common => base}/grpc/staking.go (100%) rename testutil/integration/{common => base}/network/network.go (100%) rename {evmd/testutil => testutil/integration}/contract.go (94%) rename testutil/integration/{os => evm}/factory/broadcast.go (93%) rename testutil/integration/{os => evm}/factory/build.go (97%) rename testutil/integration/{os => evm}/factory/factory.go (91%) rename testutil/integration/{os => evm}/factory/helpers.go (100%) rename testutil/integration/{os => evm}/factory/sign.go (100%) rename testutil/integration/{os => evm}/grpc/evm.go (100%) rename testutil/integration/{os => evm}/grpc/feemarket.go (100%) rename testutil/integration/{os => evm}/grpc/gov.go (100%) rename testutil/integration/{os => evm}/grpc/grpc.go (87%) rename testutil/integration/{os => evm}/network/abci.go (98%) rename testutil/integration/{os => evm}/network/amounts.go (100%) rename testutil/integration/{os => evm}/network/chain_id_modifiers.go (100%) rename testutil/integration/{os => evm}/network/clients.go (87%) rename testutil/integration/{os => evm}/network/coins.go (100%) rename testutil/integration/{os => evm}/network/config.go (98%) rename testutil/integration/{os => evm}/network/example_contracts.go (100%) rename testutil/integration/{os => evm}/network/ibc.go (100%) rename testutil/integration/{os => evm}/network/network.go (84%) rename testutil/integration/{os => evm}/network/setup.go (84%) rename testutil/integration/{os => evm}/network/unit_network.go (77%) rename testutil/integration/{os => evm}/utils/bank.go (85%) rename testutil/integration/{os => evm}/utils/contracts.go (88%) rename testutil/integration/{os => evm}/utils/erc20.go (96%) rename testutil/integration/{os => evm}/utils/events.go (100%) rename testutil/integration/{os => evm}/utils/evm.go (95%) rename testutil/integration/{os => evm}/utils/genesis.go (79%) rename testutil/integration/{os => evm}/utils/gov.go (96%) rename testutil/integration/{os => evm}/utils/params.go (96%) rename testutil/integration/{os => evm}/utils/staking.go (96%) rename testutil/integration/{os => evm}/utils/types.go (100%) rename testutil/integration/{os => evm}/utils/unit.go (73%) delete mode 100644 testutil/integration/os/network/config_test.go delete mode 100644 testutil/integration/os/utils/bank_test.go delete mode 100644 testutil/integration/os/utils/evm_test.go create mode 100644 testutil/integration/params.go create mode 100644 testutil/integration/utils.go rename testutil/{integration/os => }/keyring/keyring.go (100%) delete mode 100644 testutil/staking_rewards.go rename testutil/{integration/os/factory => types}/types.go (98%) rename ante/cosmos/utils_test.go => testutil/util.go (65%) delete mode 100644 x/erc20/keeper/integration_test.go delete mode 100644 x/erc20/keeper/mint_test.go delete mode 100644 x/erc20/keeper/utils_test.go delete mode 100644 x/feemarket/keeper/integration_test.go delete mode 100644 x/feemarket/keeper/setup_test.go delete mode 100644 x/precisebank/keeper/setup_test.go delete mode 100644 x/vm/ante/suite_test.go delete mode 100644 x/vm/genesis_test.go delete mode 100644 x/vm/keeper/abci_test.go delete mode 100644 x/vm/keeper/integration_test.go delete mode 100644 x/vm/statedb/integration_test.go diff --git a/ante/cosmos/authz_test.go b/ante/cosmos/authz_test.go deleted file mode 100644 index 3e616dc1f..000000000 --- a/ante/cosmos/authz_test.go +++ /dev/null @@ -1,496 +0,0 @@ -package cosmos_test - -import ( - "fmt" - "math/big" - "testing" - "time" - - ethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/stretchr/testify/require" - - abci "github.com/cometbft/cometbft/abci/types" - - cosmosante "github.com/cosmos/evm/ante/cosmos" - "github.com/cosmos/evm/testutil" - "github.com/cosmos/evm/testutil/integration/common/factory" - "github.com/cosmos/evm/testutil/integration/os/network" - utiltx "github.com/cosmos/evm/testutil/tx" - evmtypes "github.com/cosmos/evm/x/vm/types" - - "cosmossdk.io/math" - - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - sdkvesting "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" - "github.com/cosmos/cosmos-sdk/x/authz" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" -) - -func TestAuthzLimiterDecorator(t *testing.T) { - nw := network.New() - txCfg := nw.GetEncodingConfig().TxConfig - testPrivKeys, testAddresses, err := generatePrivKeyAddressPairs(5) - require.NoError(t, err) - - evmDenom := evmtypes.GetEVMCoinDenom() - distantFuture := time.Date(9000, 1, 1, 0, 0, 0, 0, time.UTC) - - validator := sdk.ValAddress(testAddresses[4]) - stakingAuthDelegate, err := stakingtypes.NewStakeAuthorization([]sdk.ValAddress{validator}, nil, stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, nil) - require.NoError(t, err) - - stakingAuthUndelegate, err := stakingtypes.NewStakeAuthorization([]sdk.ValAddress{validator}, nil, stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_UNDELEGATE, nil) - require.NoError(t, err) - - decorator := cosmosante.NewAuthzLimiterDecorator( - sdk.MsgTypeURL(&evmtypes.MsgEthereumTx{}), - sdk.MsgTypeURL(&stakingtypes.MsgUndelegate{}), - ) - - testCases := []struct { - name string - msgs []sdk.Msg - checkTx bool - expectedErr error - }{ - { - "enabled msg - non blocked msg", - []sdk.Msg{ - banktypes.NewMsgSend( - testAddresses[0], - testAddresses[1], - sdk.NewCoins(sdk.NewInt64Coin(evmDenom, 100e6)), - ), - }, - false, - nil, - }, - { - "enabled msg MsgEthereumTx - blocked msg not wrapped in MsgExec", - []sdk.Msg{ - &evmtypes.MsgEthereumTx{}, - }, - false, - nil, - }, - { - "enabled msg - blocked msg not wrapped in MsgExec", - []sdk.Msg{ - &stakingtypes.MsgCancelUnbondingDelegation{}, - }, - false, - nil, - }, - { - "enabled msg - MsgGrant contains a non blocked msg", - []sdk.Msg{ - newMsgGrant( - testAddresses[0], - testAddresses[1], - authz.NewGenericAuthorization(sdk.MsgTypeURL(&banktypes.MsgSend{})), - &distantFuture, - ), - }, - false, - nil, - }, - { - "enabled msg - MsgGrant contains a non blocked msg", - []sdk.Msg{ - newMsgGrant( - testAddresses[0], - testAddresses[1], - stakingAuthDelegate, - &distantFuture, - ), - }, - false, - nil, - }, - { - "disabled msg - MsgGrant contains a blocked msg", - []sdk.Msg{ - newMsgGrant( - testAddresses[0], - testAddresses[1], - authz.NewGenericAuthorization(sdk.MsgTypeURL(&evmtypes.MsgEthereumTx{})), - &distantFuture, - ), - }, - false, - sdkerrors.ErrUnauthorized, - }, - { - "disabled msg - MsgGrant contains a blocked msg", - []sdk.Msg{ - newMsgGrant( - testAddresses[0], - testAddresses[1], - stakingAuthUndelegate, - &distantFuture, - ), - }, - false, - sdkerrors.ErrUnauthorized, - }, - { - "allowed msg - when a MsgExec contains a non blocked msg", - []sdk.Msg{ - newMsgExec( - testAddresses[1], - []sdk.Msg{banktypes.NewMsgSend( - testAddresses[0], - testAddresses[3], - sdk.NewCoins(sdk.NewInt64Coin(evmDenom, 100e6)), - )}), - }, - false, - nil, - }, - { - "disabled msg - MsgExec contains a blocked msg", - []sdk.Msg{ - newMsgExec( - testAddresses[1], - []sdk.Msg{ - &evmtypes.MsgEthereumTx{}, - }, - ), - }, - false, - sdkerrors.ErrUnauthorized, - }, - { - "disabled msg - surrounded by valid msgs", - []sdk.Msg{ - newMsgGrant( - testAddresses[0], - testAddresses[1], - stakingAuthDelegate, - &distantFuture, - ), - newMsgExec( - testAddresses[1], - []sdk.Msg{ - banktypes.NewMsgSend( - testAddresses[0], - testAddresses[3], - sdk.NewCoins(sdk.NewInt64Coin(evmDenom, 100e6)), - ), - &evmtypes.MsgEthereumTx{}, - }, - ), - }, - false, - sdkerrors.ErrUnauthorized, - }, - { - "disabled msg - nested MsgExec containing a blocked msg", - []sdk.Msg{ - createNestedMsgExec( - testAddresses[1], - 2, - []sdk.Msg{ - &evmtypes.MsgEthereumTx{}, - }, - ), - }, - false, - sdkerrors.ErrUnauthorized, - }, - { - "disabled msg - nested MsgGrant containing a blocked msg", - []sdk.Msg{ - newMsgExec( - testAddresses[1], - []sdk.Msg{ - newMsgGrant( - testAddresses[0], - testAddresses[1], - authz.NewGenericAuthorization(sdk.MsgTypeURL(&evmtypes.MsgEthereumTx{})), - &distantFuture, - ), - }, - ), - }, - false, - sdkerrors.ErrUnauthorized, - }, - { - "disabled msg - nested MsgExec NOT containing a blocked msg but has more nesting levels than the allowed", - []sdk.Msg{ - createNestedMsgExec( - testAddresses[1], - 6, - []sdk.Msg{ - banktypes.NewMsgSend( - testAddresses[0], - testAddresses[3], - sdk.NewCoins(sdk.NewInt64Coin(evmDenom, 100e6)), - ), - }, - ), - }, - false, - sdkerrors.ErrUnauthorized, - }, - { - "disabled msg - multiple two nested MsgExec messages NOT containing a blocked msg over the limit", - []sdk.Msg{ - createNestedMsgExec( - testAddresses[1], - 5, - []sdk.Msg{ - banktypes.NewMsgSend( - testAddresses[0], - testAddresses[3], - sdk.NewCoins(sdk.NewInt64Coin(evmDenom, 100e6)), - ), - }, - ), - createNestedMsgExec( - testAddresses[1], - 5, - []sdk.Msg{ - banktypes.NewMsgSend( - testAddresses[0], - testAddresses[3], - sdk.NewCoins(sdk.NewInt64Coin(evmDenom, 100e6)), - ), - }, - ), - }, - false, - sdkerrors.ErrUnauthorized, - }, - } - - for _, tc := range testCases { - t.Run(fmt.Sprintf("Case %s", tc.name), func(t *testing.T) { - ctx := sdk.Context{}.WithIsCheckTx(tc.checkTx) - tx, err := createTx(ctx, txCfg, testPrivKeys[0], tc.msgs...) - require.NoError(t, err) - - _, err = decorator.AnteHandle(ctx, tx, false, testutil.NoOpNextFn) - if tc.expectedErr != nil { - require.Error(t, err) - require.ErrorIs(t, err, tc.expectedErr) - } else { - require.NoError(t, err) - } - }) - } -} - -func (suite *AnteTestSuite) TestRejectMsgsInAuthz() { - _, testAddresses, err := generatePrivKeyAddressPairs(10) - suite.Require().NoError(err) - - var gasLimit uint64 = 1000000 - distantFuture := time.Date(9000, 1, 1, 0, 0, 0, 0, time.UTC) - - nw := suite.GetNetwork() - evmDenom := evmtypes.GetEVMCoinDenom() - - baseFeeRes, err := nw.GetEvmClient().BaseFee(nw.GetContext(), &evmtypes.QueryBaseFeeRequest{}) - suite.Require().NoError(err, "failed to get base fee") - - // create a dummy MsgEthereumTx for the test - // otherwise throws error that cannot unpack tx data - msgEthereumTx := evmtypes.NewTx(&evmtypes.EvmTxArgs{ - ChainID: nw.GetEIP155ChainID(), - Nonce: 0, - GasLimit: gasLimit, - GasFeeCap: baseFeeRes.BaseFee.BigInt(), - GasTipCap: big.NewInt(1), - Input: nil, - Accesses: ðtypes.AccessList{}, - }) - - newMsgGrant := func(msgTypeUrl string) *authz.MsgGrant { - msg, err := authz.NewMsgGrant( - testAddresses[0], - testAddresses[1], - authz.NewGenericAuthorization(msgTypeUrl), - &distantFuture, - ) - if err != nil { - panic(err) - } - return msg - } - - testcases := []struct { - name string - msgs []sdk.Msg - expectedCode uint32 - isEIP712 bool - }{ - { - name: "a MsgGrant with MsgEthereumTx typeURL on the authorization field is blocked", - msgs: []sdk.Msg{newMsgGrant(sdk.MsgTypeURL(&evmtypes.MsgEthereumTx{}))}, - expectedCode: sdkerrors.ErrUnauthorized.ABCICode(), - }, - { - name: "a MsgGrant with MsgCreateVestingAccount typeURL on the authorization field is blocked", - msgs: []sdk.Msg{newMsgGrant(sdk.MsgTypeURL(&sdkvesting.MsgCreateVestingAccount{}))}, - expectedCode: sdkerrors.ErrUnauthorized.ABCICode(), - }, - { - name: "a MsgGrant with MsgEthereumTx typeURL on the authorization field included on EIP712 tx is blocked", - msgs: []sdk.Msg{newMsgGrant(sdk.MsgTypeURL(&evmtypes.MsgEthereumTx{}))}, - expectedCode: sdkerrors.ErrUnauthorized.ABCICode(), - isEIP712: true, - }, - { - name: "a MsgExec with nested messages (valid: MsgSend and invalid: MsgEthereumTx) is blocked", - msgs: []sdk.Msg{ - newMsgExec( - testAddresses[1], - []sdk.Msg{ - banktypes.NewMsgSend( - testAddresses[0], - testAddresses[3], - sdk.NewCoins(sdk.NewInt64Coin(evmDenom, 100e6)), - ), - msgEthereumTx, - }, - ), - }, - expectedCode: sdkerrors.ErrUnauthorized.ABCICode(), - }, - { - name: "a MsgExec with nested MsgExec messages that has invalid messages is blocked", - msgs: []sdk.Msg{ - createNestedMsgExec( - testAddresses[1], - 2, - []sdk.Msg{ - msgEthereumTx, - }, - ), - }, - expectedCode: sdkerrors.ErrUnauthorized.ABCICode(), - }, - { - name: "a MsgExec with more nested MsgExec messages than allowed and with valid messages is blocked", - msgs: []sdk.Msg{ - createNestedMsgExec( - testAddresses[1], - 6, - []sdk.Msg{ - banktypes.NewMsgSend( - testAddresses[0], - testAddresses[3], - sdk.NewCoins(sdk.NewInt64Coin(evmDenom, 100e6)), - ), - }, - ), - }, - expectedCode: sdkerrors.ErrUnauthorized.ABCICode(), - }, - { - name: "two MsgExec messages NOT containing a blocked msg but between the two have more nesting than the allowed. Then, is blocked", - msgs: []sdk.Msg{ - createNestedMsgExec( - testAddresses[1], - 5, - []sdk.Msg{ - banktypes.NewMsgSend( - testAddresses[0], - testAddresses[3], - sdk.NewCoins(sdk.NewInt64Coin(evmDenom, 100e6)), - ), - }, - ), - createNestedMsgExec( - testAddresses[1], - 5, - []sdk.Msg{ - banktypes.NewMsgSend( - testAddresses[0], - testAddresses[3], - sdk.NewCoins(sdk.NewInt64Coin(evmDenom, 100e6)), - ), - }, - ), - }, - expectedCode: sdkerrors.ErrUnauthorized.ABCICode(), - }, - } - - for _, tc := range testcases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() - nw = suite.GetNetwork() - var ( - tx sdk.Tx - err error - ) - ctx := nw.GetContext() - priv := suite.GetKeyring().GetPrivKey(0) - - if tc.isEIP712 { - coinAmount := sdk.NewCoin(evmDenom, math.NewInt(20)) - fees := sdk.NewCoins(coinAmount) - cosmosTxArgs := utiltx.CosmosTxArgs{ - TxCfg: suite.GetClientCtx().TxConfig, - Priv: priv, - ChainID: ctx.ChainID(), - Gas: 200000, - Fees: fees, - Msgs: tc.msgs, - } - - tx, err = utiltx.CreateEIP712CosmosTx( - ctx, - nw.App, - utiltx.EIP712TxArgs{ - CosmosTxArgs: cosmosTxArgs, - UseLegacyTypedData: true, - }, - ) - } else { - tx, err = suite.GetTxFactory().BuildCosmosTx( - priv, - factory.CosmosTxArgs{ - Gas: &gasLimit, - Msgs: tc.msgs, - }, - ) - } - suite.Require().NoError(err) - - txEncoder := suite.GetClientCtx().TxConfig.TxEncoder() - bz, err := txEncoder(tx) - suite.Require().NoError(err) - - resCheckTx, err := nw.App.CheckTx( - &abci.RequestCheckTx{ - Tx: bz, - Type: abci.CheckTxType_New, - }, - ) - suite.Require().NoError(err) - suite.Require().Equal(resCheckTx.Code, tc.expectedCode, resCheckTx.Log) - - header := ctx.BlockHeader() - blockRes, err := nw.App.FinalizeBlock( - &abci.RequestFinalizeBlock{ - Height: ctx.BlockHeight() + 1, - Txs: [][]byte{bz}, - Hash: header.AppHash, - NextValidatorsHash: header.NextValidatorsHash, - ProposerAddress: header.ProposerAddress, - Time: header.Time.Add(time.Second), - }, - ) - suite.Require().NoError(err) - suite.Require().Len(blockRes.TxResults, 1) - txRes := blockRes.TxResults[0] - suite.Require().Equal(txRes.Code, tc.expectedCode, txRes.Log) - }) - } -} diff --git a/ante/cosmos/setup_test.go b/ante/cosmos/setup_test.go deleted file mode 100644 index 617e75a22..000000000 --- a/ante/cosmos/setup_test.go +++ /dev/null @@ -1,21 +0,0 @@ -package cosmos_test - -import ( - "testing" - - "github.com/stretchr/testify/suite" - - "github.com/cosmos/evm/ante/testutils" -) - -type AnteTestSuite struct { - *testutils.AnteTestSuite -} - -func TestAnteTestSuite(t *testing.T) { - baseSuite := new(testutils.AnteTestSuite) - baseSuite.WithLondonHardForkEnabled(true) - baseSuite.WithFeemarketEnabled(true) - - suite.Run(t, &AnteTestSuite{baseSuite}) -} diff --git a/ante/evm/fee_checker_test.go b/ante/evm/fee_checker_test.go index a9bfdcd14..e47db6ab5 100644 --- a/ante/evm/fee_checker_test.go +++ b/ante/evm/fee_checker_test.go @@ -4,14 +4,16 @@ import ( "math/big" "testing" + "cosmosevm.io/evmd" "github.com/stretchr/testify/require" tmproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cosmos/evm/ante/evm" anteinterfaces "github.com/cosmos/evm/ante/interfaces" + evmdconfig "github.com/cosmos/evm/cmd/evmd/config" + "github.com/cosmos/evm/encoding" testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/os/network" "github.com/cosmos/evm/types" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -56,8 +58,11 @@ func TestSDKTxFeeChecker(t *testing.T) { // with extension option // without extension option // london hardfork enableness - nw := network.New() - encodingConfig := nw.GetEncodingConfig() + chainId := uint64(evmdconfig.EighteenDecimalsChainID) + encodingConfig := encoding.MakeConfig(chainId) + err := evmd.EvmAppOptions(chainId) + require.NoError(t, err) + evmDenom := evmtypes.GetEVMCoinDenom() minGasPrices := sdk.NewDecCoins(sdk.NewDecCoin(evmDenom, math.NewInt(10))) diff --git a/ante/evm/setup_test.go b/ante/evm/setup_test.go deleted file mode 100644 index 21508c885..000000000 --- a/ante/evm/setup_test.go +++ /dev/null @@ -1,30 +0,0 @@ -package evm_test - -import ( - "testing" - - "github.com/stretchr/testify/suite" - - "github.com/cosmos/evm/ante/testutils" -) - -type AnteTestSuite struct { - *testutils.AnteTestSuite - useLegacyEIP712TypedData bool -} - -func TestAnteTestSuite(t *testing.T) { - baseSuite := new(testutils.AnteTestSuite) - baseSuite.WithLondonHardForkEnabled(true) - - suite.Run(t, &AnteTestSuite{ - AnteTestSuite: baseSuite, - }) - - // Re-run the tests with EIP-712 Legacy encodings to ensure backwards compatibility. - // LegacyEIP712Extension should not be run with current TypedData encodings, since they are not compatible. - suite.Run(t, &AnteTestSuite{ - AnteTestSuite: baseSuite, - useLegacyEIP712TypedData: true, - }) -} diff --git a/ante/evm/signverify_test.go b/ante/evm/signverify_test.go deleted file mode 100644 index 9f67d83c1..000000000 --- a/ante/evm/signverify_test.go +++ /dev/null @@ -1,88 +0,0 @@ -package evm_test - -import ( - "math/big" - - ethtypes "github.com/ethereum/go-ethereum/core/types" - - ethante "github.com/cosmos/evm/ante/evm" - "github.com/cosmos/evm/testutil" - testutiltx "github.com/cosmos/evm/testutil/tx" - evmtypes "github.com/cosmos/evm/x/vm/types" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -func (suite *AnteTestSuite) TestEthSigVerificationDecorator() { - addr, privKey := testutiltx.NewAddrKey() - ethCfg := evmtypes.GetEthChainConfig() - ethSigner := ethtypes.LatestSignerForChainID(ethCfg.ChainID) - - ethContractCreationTxParams := &evmtypes.EvmTxArgs{ - ChainID: ethCfg.ChainID, - Nonce: 1, - Amount: big.NewInt(10), - GasLimit: 1000, - GasPrice: big.NewInt(1), - } - signedTx := evmtypes.NewTx(ethContractCreationTxParams) - signedTx.From = addr.Hex() - err := signedTx.Sign(ethSigner, testutiltx.NewSigner(privKey)) - suite.Require().NoError(err) - - unprotectedEthTxParams := &evmtypes.EvmTxArgs{ - Nonce: 1, - Amount: big.NewInt(10), - GasLimit: 1000, - GasPrice: big.NewInt(1), - } - unprotectedTx := evmtypes.NewTx(unprotectedEthTxParams) - unprotectedTx.From = addr.Hex() - err = unprotectedTx.Sign(ethtypes.HomesteadSigner{}, testutiltx.NewSigner(privKey)) - suite.Require().NoError(err) - - testCases := []struct { - name string - tx sdk.Tx - allowUnprotectedTxs bool - reCheckTx bool - expPass bool - }{ - {"ReCheckTx", &testutiltx.InvalidTx{}, false, true, false}, - {"invalid transaction type", &testutiltx.InvalidTx{}, false, false, false}, - { - "invalid sender", - evmtypes.NewTx(&evmtypes.EvmTxArgs{ - To: &addr, - Nonce: 1, - Amount: big.NewInt(10), - GasLimit: 1000, - GasPrice: big.NewInt(1), - }), - true, - false, - false, - }, - {"successful signature verification", signedTx, false, false, true}, - {"invalid, reject unprotected txs", unprotectedTx, false, false, false}, - {"successful, allow unprotected txs", unprotectedTx, true, false, true}, - } - - for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.WithEvmParamsOptions(func(params *evmtypes.Params) { - params.AllowUnprotectedTxs = tc.allowUnprotectedTxs - }) - suite.SetupTest() - dec := ethante.NewEthSigVerificationDecorator(suite.GetNetwork().App.EVMKeeper) - _, err := dec.AnteHandle(suite.GetNetwork().GetContext().WithIsReCheckTx(tc.reCheckTx), tc.tx, false, testutil.NoOpNextFn) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } - suite.WithEvmParamsOptions(nil) -} diff --git a/ante/evm/sigs_test.go b/ante/evm/sigs_test.go deleted file mode 100644 index f192ac98d..000000000 --- a/ante/evm/sigs_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package evm_test - -import ( - "math/big" - - utiltx "github.com/cosmos/evm/testutil/tx" - evmtypes "github.com/cosmos/evm/x/vm/types" -) - -func (suite *AnteTestSuite) TestSignatures() { - suite.WithFeemarketEnabled(false) - suite.SetupTest() // reset - - privKey := suite.GetKeyring().GetPrivKey(0) - to := utiltx.GenerateAddress() - - txArgs := evmtypes.EvmTxArgs{ - ChainID: evmtypes.GetEthChainConfig().ChainID, - Nonce: 0, - To: &to, - Amount: big.NewInt(10), - GasLimit: 100000, - GasPrice: big.NewInt(1), - } - - // CreateTestTx will sign the msgEthereumTx but not sign the cosmos tx since we have signCosmosTx as false - tx := suite.CreateTxBuilder(privKey, txArgs).GetTx() - sigs, err := tx.GetSignaturesV2() - suite.Require().NoError(err) - - // signatures of cosmos tx should be empty - suite.Require().Equal(len(sigs), 0) - - msg := tx.GetMsgs()[0] - msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx) - suite.Require().True(ok) - txData, err := evmtypes.UnpackTxData(msgEthTx.Data) - suite.Require().NoError(err) - - msgV, msgR, msgS := txData.GetRawSignatureValues() - - ethTx := msgEthTx.AsTransaction() - ethV, ethR, ethS := ethTx.RawSignatureValues() - - // The signatures of MsgEthereumTx should be the same with the corresponding eth tx - suite.Require().Equal(msgV, ethV) - suite.Require().Equal(msgR, ethR) - suite.Require().Equal(msgS, ethS) -} diff --git a/ante/evm/suite_test.go b/ante/evm/suite_test.go deleted file mode 100644 index 3a19c5069..000000000 --- a/ante/evm/suite_test.go +++ /dev/null @@ -1,36 +0,0 @@ -package evm_test - -import ( - "testing" - - gethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/stretchr/testify/suite" - - testconstants "github.com/cosmos/evm/testutil/constants" -) - -// EvmAnteTestSuite aims to test all EVM ante handler unit functions. -// NOTE: the suite only holds properties related to global execution parameters -// (what type of tx to run the tests with) not independent tests values. -type EvmAnteTestSuite struct { - suite.Suite - - // To make sure that every tests is run with all the tx types - ethTxType int - chainID string - evmChainID uint64 -} - -func TestEvmAnteTestSuite(t *testing.T) { - txTypes := []int{gethtypes.DynamicFeeTxType, gethtypes.LegacyTxType, gethtypes.AccessListTxType} - chainIDs := []testconstants.ChainID{testconstants.ExampleChainID, testconstants.SixDecimalsChainID} - for _, txType := range txTypes { - for _, chainID := range chainIDs { - suite.Run(t, &EvmAnteTestSuite{ - ethTxType: txType, - chainID: chainID.ChainID, - evmChainID: chainID.EVMChainID, - }) - } - } -} diff --git a/ante/evm/utils_test.go b/ante/evm/utils_test.go deleted file mode 100644 index b134f8119..000000000 --- a/ante/evm/utils_test.go +++ /dev/null @@ -1,580 +0,0 @@ -package evm_test - -import ( - "encoding/json" - "fmt" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/holiman/uint256" - - "github.com/cosmos/evm/ante/testutils" - "github.com/cosmos/evm/crypto/ethsecp256k1" - "github.com/cosmos/evm/ethereum/eip712" - "github.com/cosmos/evm/testutil" - utiltx "github.com/cosmos/evm/testutil/tx" - evmtypes "github.com/cosmos/evm/x/vm/types" - ibctypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - ibcclienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" - - sdkmath "cosmossdk.io/math" - storetypes "cosmossdk.io/store/types" - evtypes "cosmossdk.io/x/evidence/types" - "cosmossdk.io/x/feegrant" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" - kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - "github.com/cosmos/cosmos-sdk/crypto/types/multisig" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/tx/signing" - sdkante "github.com/cosmos/cosmos-sdk/x/auth/ante" - "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" - authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" - authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" - authz "github.com/cosmos/cosmos-sdk/x/authz" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - govtypesv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" -) - -func (suite *AnteTestSuite) CreateTxBuilder(privKey cryptotypes.PrivKey, txArgs evmtypes.EvmTxArgs, unsetExtensionOptions ...bool) client.TxBuilder { - var option *codectypes.Any - var err error - if len(unsetExtensionOptions) == 0 { - option, err = codectypes.NewAnyWithValue(&evmtypes.ExtensionOptionsEthereumTx{}) - suite.Require().NoError(err) - } - msgEthTx, err := suite.GetTxFactory().GenerateMsgEthereumTx(privKey, txArgs) - suite.Require().NoError(err) - - signedMsg, err := suite.GetTxFactory().SignMsgEthereumTx(privKey, msgEthTx) - suite.Require().NoError(err) - suite.Require().NoError(signedMsg.ValidateBasic()) - - tb := suite.GetClientCtx().TxConfig.NewTxBuilder() - builder, ok := tb.(authtx.ExtensionOptionsTxBuilder) - suite.Require().True(ok) - - if len(unsetExtensionOptions) == 0 { - builder.SetExtensionOptions(option) - } - - err = builder.SetMsgs(&signedMsg) - suite.Require().NoError(err) - - txData, err := evmtypes.UnpackTxData(signedMsg.Data) - suite.Require().NoError(err) - - fees := sdk.NewCoins(sdk.NewCoin(suite.GetNetwork().GetBaseDenom(), sdkmath.NewIntFromBigInt(txData.Fee()))) - builder.SetFeeAmount(fees) - builder.SetGasLimit(signedMsg.GetGas()) - return builder -} - -func (suite *AnteTestSuite) RequireErrorForLegacyTypedData(err error) { - if suite.useLegacyEIP712TypedData { - suite.Require().Error(err) - } else { - suite.Require().NoError(err) - } -} - -func (suite *AnteTestSuite) TxForLegacyTypedData(txBuilder client.TxBuilder) sdk.Tx { - if suite.useLegacyEIP712TypedData { - // Since the TxBuilder will be nil on failure, - // we return an empty Tx to avoid panics. - emptyTxBuilder := suite.GetClientCtx().TxConfig.NewTxBuilder() - return emptyTxBuilder.GetTx() - } - - return txBuilder.GetTx() -} - -func (suite *AnteTestSuite) CreateTestCosmosTxBuilder(gasPrice sdkmath.Int, denom string, msgs ...sdk.Msg) client.TxBuilder { - txBuilder := suite.GetClientCtx().TxConfig.NewTxBuilder() - - txBuilder.SetGasLimit(testutils.TestGasLimit) - fees := &sdk.Coins{{Denom: denom, Amount: gasPrice.MulRaw(int64(testutils.TestGasLimit))}} - txBuilder.SetFeeAmount(*fees) - err := txBuilder.SetMsgs(msgs...) - suite.Require().NoError(err) - return txBuilder -} - -func (suite *AnteTestSuite) CreateTestEIP712TxBuilderMsgSend(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { - // Build MsgSend - recipient := sdk.AccAddress(common.Address{}.Bytes()) - msgSend := banktypes.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(suite.GetNetwork().GetBaseDenom(), sdkmath.NewInt(1)))) - return suite.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, msgSend) -} - -func (suite *AnteTestSuite) CreateTestEIP712TxBuilderMsgDelegate(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { - // Build MsgDelegate - val := suite.GetNetwork().GetValidators()[0] - msgDelegate := stakingtypes.NewMsgDelegate(from.String(), val.OperatorAddress, sdk.NewCoin(suite.GetNetwork().GetBaseDenom(), sdkmath.NewInt(20))) - return suite.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, msgDelegate) -} - -func (suite *AnteTestSuite) CreateTestEIP712MsgCreateValidator(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { - // Build MsgCreateValidator - valAddr := sdk.ValAddress(from.Bytes()) - privEd := ed25519.GenPrivKey() - evmDenom := evmtypes.GetEVMCoinDenom() - msgCreate, err := stakingtypes.NewMsgCreateValidator( - valAddr.String(), - privEd.PubKey(), - sdk.NewCoin(evmDenom, sdkmath.NewInt(20)), - stakingtypes.NewDescription("moniker", "identity", "website", "security_contract", "details"), - stakingtypes.NewCommissionRates(sdkmath.LegacyOneDec(), sdkmath.LegacyOneDec(), sdkmath.LegacyOneDec()), - sdkmath.OneInt(), - ) - suite.Require().NoError(err) - return suite.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, msgCreate) -} - -func (suite *AnteTestSuite) CreateTestEIP712MsgCreateValidator2(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { - // Build MsgCreateValidator - valAddr := sdk.ValAddress(from.Bytes()) - privEd := ed25519.GenPrivKey() - msgCreate, err := stakingtypes.NewMsgCreateValidator( - valAddr.String(), - privEd.PubKey(), - sdk.NewCoin(suite.GetNetwork().GetBaseDenom(), sdkmath.NewInt(20)), - // Ensure optional fields can be left blank - stakingtypes.NewDescription("moniker", "identity", "", "", ""), - stakingtypes.NewCommissionRates(sdkmath.LegacyOneDec(), sdkmath.LegacyOneDec(), sdkmath.LegacyOneDec()), - sdkmath.OneInt(), - ) - suite.Require().NoError(err) - return suite.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, msgCreate) -} - -func (suite *AnteTestSuite) CreateTestEIP712SubmitProposal(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins, deposit sdk.Coins) (client.TxBuilder, error) { - proposal, ok := govtypes.ContentFromProposalType("My proposal", "My description", govtypes.ProposalTypeText) - suite.Require().True(ok) - msgSubmit, err := govtypes.NewMsgSubmitProposal(proposal, deposit, from) - suite.Require().NoError(err) - return suite.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, msgSubmit) -} - -func (suite *AnteTestSuite) CreateTestEIP712GrantAllowance(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { - spendLimit := sdk.NewCoins(sdk.NewInt64Coin(suite.GetNetwork().GetBaseDenom(), 10)) - threeHours := time.Now().Add(3 * time.Hour) - basic := &feegrant.BasicAllowance{ - SpendLimit: spendLimit, - Expiration: &threeHours, - } - granted := utiltx.GenerateAddress() - grantedAddr := suite.GetNetwork().App.AccountKeeper.NewAccountWithAddress(suite.GetNetwork().GetContext(), granted.Bytes()) - msgGrant, err := feegrant.NewMsgGrantAllowance(basic, from, grantedAddr.GetAddress()) - suite.Require().NoError(err) - return suite.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, msgGrant) -} - -func (suite *AnteTestSuite) CreateTestEIP712MsgEditValidator(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { - valAddr := sdk.ValAddress(from.Bytes()) - msgEdit := stakingtypes.NewMsgEditValidator( - valAddr.String(), - stakingtypes.NewDescription("moniker", "identity", "website", "security_contract", "details"), - nil, - nil, - ) - return suite.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, msgEdit) -} - -func (suite *AnteTestSuite) CreateTestEIP712MsgSubmitEvidence(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { - pk := ed25519.GenPrivKey() - msgEvidence, err := evtypes.NewMsgSubmitEvidence(from, &evtypes.Equivocation{ - Height: 11, - Time: time.Now().UTC(), - Power: 100, - ConsensusAddress: pk.PubKey().Address().String(), - }) - suite.Require().NoError(err) - - return suite.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, msgEvidence) -} - -func (suite *AnteTestSuite) CreateTestEIP712MsgVoteV1(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { - msgVote := govtypesv1.NewMsgVote(from, 1, govtypesv1.VoteOption_VOTE_OPTION_YES, "") - return suite.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, msgVote) -} - -func (suite *AnteTestSuite) CreateTestEIP712SubmitProposalV1(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { - // Build V1 proposal messages. Must all be same-type, since EIP-712 - // does not support arrays of variable type. - authAcc := suite.GetNetwork().App.GovKeeper.GetGovernanceAccount(suite.GetNetwork().GetContext()) - - proposal1, ok := govtypes.ContentFromProposalType("My proposal 1", "My description 1", govtypes.ProposalTypeText) - suite.Require().True(ok) - content1, err := govtypesv1.NewLegacyContent( - proposal1, - sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), authAcc.GetAddress().Bytes()), - ) - suite.Require().NoError(err) - - proposal2, ok := govtypes.ContentFromProposalType("My proposal 2", "My description 2", govtypes.ProposalTypeText) - suite.Require().True(ok) - content2, err := govtypesv1.NewLegacyContent( - proposal2, - sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), authAcc.GetAddress().Bytes()), - ) - suite.Require().NoError(err) - - proposalMsgs := []sdk.Msg{ - content1, - content2, - } - - // Build V1 proposal - msgProposal, err := govtypesv1.NewMsgSubmitProposal( - proposalMsgs, - sdk.NewCoins(sdk.NewCoin(suite.GetNetwork().GetBaseDenom(), sdkmath.NewInt(100))), - sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), from.Bytes()), - "Metadata", "title", "summary", - false, - ) - - suite.Require().NoError(err) - - return suite.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, msgProposal) -} - -func (suite *AnteTestSuite) CreateTestEIP712MsgExec(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { - recipient := sdk.AccAddress(common.Address{}.Bytes()) - msgSend := banktypes.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(suite.GetNetwork().GetBaseDenom(), sdkmath.NewInt(1)))) - msgExec := authz.NewMsgExec(from, []sdk.Msg{msgSend}) - return suite.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, &msgExec) -} - -func (suite *AnteTestSuite) CreateTestEIP712MultipleMsgSend(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { - recipient := sdk.AccAddress(common.Address{}.Bytes()) - msgSend := banktypes.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(suite.GetNetwork().GetBaseDenom(), sdkmath.NewInt(1)))) - return suite.CreateTestEIP712CosmosTxBuilder(priv, chainID, evmChainID, gas, gasAmount, []sdk.Msg{msgSend, msgSend, msgSend}) -} - -func (suite *AnteTestSuite) CreateTestEIP712MultipleDifferentMsgs(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { - recipient := sdk.AccAddress(common.Address{}.Bytes()) - msgSend := banktypes.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(suite.GetNetwork().GetBaseDenom(), sdkmath.NewInt(1)))) - - msgVote := govtypesv1.NewMsgVote(from, 1, govtypesv1.VoteOption_VOTE_OPTION_YES, "") - - valEthAddr := utiltx.GenerateAddress() - valAddr := sdk.ValAddress(valEthAddr.Bytes()) - msgDelegate := stakingtypes.NewMsgDelegate(from.String(), valAddr.String(), sdk.NewCoin(suite.GetNetwork().GetBaseDenom(), sdkmath.NewInt(20))) - - return suite.CreateTestEIP712CosmosTxBuilder(priv, chainID, evmChainID, gas, gasAmount, []sdk.Msg{msgSend, msgVote, msgDelegate}) -} - -func (suite *AnteTestSuite) CreateTestEIP712SameMsgDifferentSchemas(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { - msgVote1 := govtypesv1.NewMsgVote(from, 1, govtypesv1.VoteOption_VOTE_OPTION_YES, "") - msgVote2 := govtypesv1.NewMsgVote(from, 5, govtypesv1.VoteOption_VOTE_OPTION_ABSTAIN, "With Metadata") - - return suite.CreateTestEIP712CosmosTxBuilder(priv, chainID, evmChainID, gas, gasAmount, []sdk.Msg{msgVote1, msgVote2}) -} - -func (suite *AnteTestSuite) CreateTestEIP712ZeroValueArray(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { - recipient := sdk.AccAddress(common.Address{}.Bytes()) - msgSend := banktypes.NewMsgSend(from, recipient, sdk.NewCoins()) - return suite.CreateTestEIP712CosmosTxBuilder(priv, chainID, evmChainID, gas, gasAmount, []sdk.Msg{msgSend}) -} - -func (suite *AnteTestSuite) CreateTestEIP712ZeroValueNumber(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { - msgVote := govtypesv1.NewMsgVote(from, 0, govtypesv1.VoteOption_VOTE_OPTION_NO, "") - - return suite.CreateTestEIP712CosmosTxBuilder(priv, chainID, evmChainID, gas, gasAmount, []sdk.Msg{msgVote}) -} - -func (suite *AnteTestSuite) CreateTestEIP712MsgTransfer(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { - msgTransfer := suite.createMsgTransfer(from, "With Memo") - return suite.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, msgTransfer) -} - -func (suite *AnteTestSuite) CreateTestEIP712MsgTransferWithoutMemo(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { - msgTransfer := suite.createMsgTransfer(from, "") - return suite.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, msgTransfer) -} - -func (suite *AnteTestSuite) createMsgTransfer(from sdk.AccAddress, memo string) *ibctypes.MsgTransfer { - recipient := sdk.AccAddress(common.Address{}.Bytes()) - msgTransfer := ibctypes.NewMsgTransfer("transfer", "channel-25", sdk.NewCoin(suite.GetNetwork().GetBaseDenom(), sdkmath.NewInt(100000)), from.String(), recipient.String(), ibcclienttypes.NewHeight(1000, 1000), 1000, memo) - return msgTransfer -} - -func (suite *AnteTestSuite) CreateTestEIP712MultipleSignerMsgs(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { - recipient := sdk.AccAddress(common.Address{}.Bytes()) - msgSend1 := banktypes.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(suite.GetNetwork().GetBaseDenom(), sdkmath.NewInt(1)))) - msgSend2 := banktypes.NewMsgSend(recipient, from, sdk.NewCoins(sdk.NewCoin(suite.GetNetwork().GetBaseDenom(), sdkmath.NewInt(1)))) - return suite.CreateTestEIP712CosmosTxBuilder(priv, chainID, evmChainID, gas, gasAmount, []sdk.Msg{msgSend1, msgSend2}) -} - -// StdSignBytes returns the bytes to sign for a transaction. -func StdSignBytes(cdc *codec.LegacyAmino, chainID string, accnum uint64, sequence uint64, timeout uint64, fee legacytx.StdFee, msgs []sdk.Msg, memo string) []byte { - msgsBytes := make([]json.RawMessage, 0, len(msgs)) - for _, msg := range msgs { - legacyMsg, ok := msg.(legacytx.LegacyMsg) - if !ok { - panic(fmt.Errorf("expected %T when using amino JSON", (*legacytx.LegacyMsg)(nil))) - } - - msgsBytes = append(msgsBytes, json.RawMessage(legacyMsg.GetSignBytes())) - } - - bz, err := cdc.MarshalJSON(legacytx.StdSignDoc{ - AccountNumber: accnum, - ChainID: chainID, - Fee: json.RawMessage(fee.Bytes()), - Memo: memo, - Msgs: msgsBytes, - Sequence: sequence, - TimeoutHeight: timeout, - }) - if err != nil { - panic(err) - } - - return sdk.MustSortJSON(bz) -} - -func (suite *AnteTestSuite) CreateTestEIP712SingleMessageTxBuilder( - priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins, msg sdk.Msg, -) (client.TxBuilder, error) { - msgs := []sdk.Msg{msg} - return suite.CreateTestEIP712CosmosTxBuilder( - priv, - chainID, - evmChainID, - gas, - gasAmount, - msgs, - ) -} - -func (suite *AnteTestSuite) CreateTestEIP712CosmosTxBuilder( - priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins, msgs []sdk.Msg, -) (client.TxBuilder, error) { - txConf := suite.GetClientCtx().TxConfig - cosmosTxArgs := utiltx.CosmosTxArgs{ - TxCfg: txConf, - Priv: priv, - ChainID: chainID, - Gas: gas, - Fees: gasAmount, - Msgs: msgs, - } - - return utiltx.PrepareEIP712CosmosTx( - suite.GetNetwork().GetContext(), - suite.GetNetwork().App, - utiltx.EIP712TxArgs{ - CosmosTxArgs: cosmosTxArgs, - UseLegacyTypedData: suite.useLegacyEIP712TypedData, - EVMChainID: evmChainID, - }, - ) -} - -// Generate a set of pub/priv keys to be used in creating multi-keys -func (suite *AnteTestSuite) GenerateMultipleKeys(n int) ([]cryptotypes.PrivKey, []cryptotypes.PubKey) { - privKeys := make([]cryptotypes.PrivKey, n) - pubKeys := make([]cryptotypes.PubKey, n) - for i := 0; i < n; i++ { - privKey, err := ethsecp256k1.GenerateKey() - suite.Require().NoError(err) - privKeys[i] = privKey - pubKeys[i] = privKey.PubKey() - } - return privKeys, pubKeys -} - -// generateSingleSignature signs the given sign doc bytes using the given signType (EIP-712 or Standard) -func (suite *AnteTestSuite) generateSingleSignature(signMode signing.SignMode, privKey cryptotypes.PrivKey, signDocBytes []byte, signType string) (signature signing.SignatureV2) { - var ( - msg []byte - err error - ) - - msg = signDocBytes - - if signType == "EIP-712" { - msg, err = eip712.GetEIP712BytesForMsg(signDocBytes) - suite.Require().NoError(err) - } - - sigBytes, _ := privKey.Sign(msg) - sigData := &signing.SingleSignatureData{ - SignMode: signMode, - Signature: sigBytes, - } - - return signing.SignatureV2{ - PubKey: privKey.PubKey(), - Data: sigData, - } -} - -// generateMultikeySignatures signs a set of messages using each private key within a given multi-key -func (suite *AnteTestSuite) generateMultikeySignatures(signMode signing.SignMode, privKeys []cryptotypes.PrivKey, signDocBytes []byte, signType string) (signatures []signing.SignatureV2) { - n := len(privKeys) - signatures = make([]signing.SignatureV2, n) - - for i := 0; i < n; i++ { - privKey := privKeys[i] - currentType := signType - - // If mixed type, alternate signing type on each iteration - if signType == "mixed" { - if i%2 == 0 { - currentType = "EIP-712" - } else { - currentType = "Standard" - } - } - - signatures[i] = suite.generateSingleSignature( - signMode, - privKey, - signDocBytes, - currentType, - ) - } - - return signatures -} - -// RegisterAccount creates an account with the keeper and populates the initial balance -func (suite *AnteTestSuite) RegisterAccount(pubKey cryptotypes.PubKey, balance *uint256.Int) { - ctx := suite.GetNetwork().GetContext() - - acc := suite.GetNetwork().App.AccountKeeper.NewAccountWithAddress(ctx, sdk.AccAddress(pubKey.Address())) - suite.GetNetwork().App.AccountKeeper.SetAccount(ctx, acc) - - err := suite.GetNetwork().App.EVMKeeper.SetBalance(ctx, common.BytesToAddress(pubKey.Address()), balance) - suite.Require().NoError(err) -} - -// createSignerBytes generates sign doc bytes using the given parameters -func (suite *AnteTestSuite) createSignerBytes(chainID string, signMode signing.SignMode, pubKey cryptotypes.PubKey, txBuilder client.TxBuilder) []byte { - ctx := suite.GetNetwork().GetContext() - acc, err := sdkante.GetSignerAcc(ctx, suite.GetNetwork().App.AccountKeeper, sdk.AccAddress(pubKey.Address())) - suite.Require().NoError(err) - signerInfo := authsigning.SignerData{ - Address: sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), acc.GetAddress().Bytes()), - ChainID: chainID, - AccountNumber: acc.GetAccountNumber(), - Sequence: acc.GetSequence(), - PubKey: pubKey, - } - - signerBytes, err := authsigning.GetSignBytesAdapter( - ctx, - suite.GetClientCtx().TxConfig.SignModeHandler(), - signMode, - signerInfo, - txBuilder.GetTx(), - ) - - suite.Require().NoError(err) - - return signerBytes -} - -// createBaseTxBuilder creates a TxBuilder to be used for Single- or Multi-signing -func (suite *AnteTestSuite) createBaseTxBuilder(msg sdk.Msg, gas uint64) client.TxBuilder { - txBuilder := suite.GetClientCtx().TxConfig.NewTxBuilder() - - txBuilder.SetGasLimit(gas) - txBuilder.SetFeeAmount(sdk.NewCoins( - sdk.NewCoin(suite.GetNetwork().GetBaseDenom(), sdkmath.NewInt(10000)), - )) - - err := txBuilder.SetMsgs(msg) - suite.Require().NoError(err) - - txBuilder.SetMemo("") - - return txBuilder -} - -// CreateTestSignedMultisigTx creates and sign a multi-signed tx for the given message. `signType` indicates whether to use standard signing ("Standard"), -// EIP-712 signing ("EIP-712"), or a mix of the two ("mixed"). -func (suite *AnteTestSuite) CreateTestSignedMultisigTx(privKeys []cryptotypes.PrivKey, signMode signing.SignMode, msg sdk.Msg, chainID string, gas uint64, signType string) client.TxBuilder { - pubKeys := make([]cryptotypes.PubKey, len(privKeys)) - for i, privKey := range privKeys { - pubKeys[i] = privKey.PubKey() - } - - // Re-derive multikey - numKeys := len(privKeys) - multiKey := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys) - - suite.RegisterAccount(multiKey, uint256.NewInt(10000000000)) - - txBuilder := suite.createBaseTxBuilder(msg, gas) - - // Prepare signature field - sig := multisig.NewMultisig(len(pubKeys)) - err := txBuilder.SetSignatures(signing.SignatureV2{ - PubKey: multiKey, - Data: sig, - }) - suite.Require().NoError(err) - - signerBytes := suite.createSignerBytes(chainID, signMode, multiKey, txBuilder) - - // Sign for each key and update signature field - sigs := suite.generateMultikeySignatures(signMode, privKeys, signerBytes, signType) - for _, pkSig := range sigs { - err := multisig.AddSignatureV2(sig, pkSig, pubKeys) - suite.Require().NoError(err) - } - - err = txBuilder.SetSignatures(signing.SignatureV2{ - PubKey: multiKey, - Data: sig, - }) - suite.Require().NoError(err) - - return txBuilder -} - -func (suite *AnteTestSuite) CreateTestSingleSignedTx(privKey cryptotypes.PrivKey, signMode signing.SignMode, msg sdk.Msg, chainID string, gas uint64, signType string) client.TxBuilder { - pubKey := privKey.PubKey() - - suite.RegisterAccount(pubKey, uint256.NewInt(10_000_000_000)) - - txBuilder := suite.createBaseTxBuilder(msg, gas) - - // Prepare signature field - sig := signing.SingleSignatureData{} - err := txBuilder.SetSignatures(signing.SignatureV2{ - PubKey: pubKey, - Data: &sig, - }) - suite.Require().NoError(err) - - signerBytes := suite.createSignerBytes(chainID, signMode, pubKey, txBuilder) - - sigData := suite.generateSingleSignature(signMode, privKey, signerBytes, signType) - err = txBuilder.SetSignatures(sigData) - suite.Require().NoError(err) - - return txBuilder -} - -// prepareAccount is a helper function that assigns the corresponding -// balance and rewards to the provided account -func (suite *AnteTestSuite) prepareAccount(ctx sdk.Context, addr sdk.AccAddress, balance, rewards sdkmath.Int) sdk.Context { - ctx, err := testutil.PrepareAccountsForDelegationRewards( - suite.T(), ctx, suite.GetNetwork().App, addr, balance, rewards, - ) - suite.Require().NoError(err, "error while preparing accounts for delegation rewards") - return ctx. - WithBlockGasMeter(storetypes.NewGasMeter(1e19)). - WithBlockHeight(ctx.BlockHeight() + 1) -} diff --git a/ante/testutils/testutil.go b/ante/testutils/testutil.go deleted file mode 100644 index d26a50ade..000000000 --- a/ante/testutils/testutil.go +++ /dev/null @@ -1,178 +0,0 @@ -package testutils - -import ( - "math" - - "github.com/stretchr/testify/suite" - - "github.com/cosmos/evm/ante" - evmante "github.com/cosmos/evm/ante/evm" - chainante "github.com/cosmos/evm/evmd/ante" - chainutil "github.com/cosmos/evm/evmd/testutil" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" - "github.com/cosmos/evm/types" - feemarkettypes "github.com/cosmos/evm/x/feemarket/types" - evmtypes "github.com/cosmos/evm/x/vm/types" - - sdkmath "cosmossdk.io/math" - - "github.com/cosmos/cosmos-sdk/client" - sdk "github.com/cosmos/cosmos-sdk/types" - consensustypes "github.com/cosmos/cosmos-sdk/x/consensus/types" -) - -type AnteTestSuite struct { - suite.Suite - - network *network.UnitTestNetwork - handler grpc.Handler - keyring keyring.Keyring - factory factory.TxFactory - clientCtx client.Context - - anteHandler sdk.AnteHandler - enableFeemarket bool - baseFee *sdkmath.LegacyDec - enableLondonHF bool - evmParamsOption func(*evmtypes.Params) -} - -const TestGasLimit uint64 = 100000 - -func (suite *AnteTestSuite) SetupTest() { - keys := keyring.New(2) - - customGenesis := network.CustomGenesisState{} - feemarketGenesis := feemarkettypes.DefaultGenesisState() - if suite.enableFeemarket { - feemarketGenesis.Params.EnableHeight = 1 - feemarketGenesis.Params.NoBaseFee = false - } else { - feemarketGenesis.Params.NoBaseFee = true - } - if suite.baseFee != nil { - feemarketGenesis.Params.BaseFee = *suite.baseFee - } - customGenesis[feemarkettypes.ModuleName] = feemarketGenesis - - evmGenesis := evmtypes.DefaultGenesisState() - - if suite.evmParamsOption != nil { - suite.evmParamsOption(&evmGenesis.Params) - } - customGenesis[evmtypes.ModuleName] = evmGenesis - - // set block max gas to be less than maxUint64 - cp := chainutil.DefaultConsensusParams - cp.Block.MaxGas = 1000000000000000000 - customGenesis[consensustypes.ModuleName] = cp - - nw := network.NewUnitTestNetwork( - network.WithPreFundedAccounts(keys.GetAllAccAddrs()...), - network.WithCustomGenesis(customGenesis), - ) - - gh := grpc.NewIntegrationHandler(nw) - tf := factory.New(nw, gh) - - suite.network = nw - suite.factory = tf - suite.handler = gh - suite.keyring = keys - - encodingConfig := nw.GetEncodingConfig() - - suite.clientCtx = client.Context{}.WithTxConfig(encodingConfig.TxConfig) - - suite.Require().NotNil(suite.network.App.AppCodec()) - - chainConfig := evmtypes.DefaultChainConfig(suite.network.GetEIP155ChainID().Uint64()) - if !suite.enableLondonHF { - maxInt := sdkmath.NewInt(math.MaxInt64) - chainConfig.LondonBlock = &maxInt - chainConfig.ArrowGlacierBlock = &maxInt - chainConfig.GrayGlacierBlock = &maxInt - chainConfig.MergeNetsplitBlock = &maxInt - chainConfig.ShanghaiTime = &maxInt - chainConfig.CancunTime = &maxInt - chainConfig.PragueTime = &maxInt - } - - // get the denom and decimals set when initialized the chain - // to set them again - // when resetting the chain config - denom := evmtypes.GetEVMCoinDenom() //nolint:staticcheck - extendedDenom := evmtypes.GetEVMCoinExtendedDenom() //nolint:staticcheck - decimals := evmtypes.GetEVMCoinDecimals() //nolint:staticcheck - - configurator := evmtypes.NewEVMConfigurator() - configurator.ResetTestConfig() - err := configurator. - WithChainConfig(chainConfig). - WithEVMCoinInfo(evmtypes.EvmCoinInfo{ - Denom: denom, - ExtendedDenom: extendedDenom, - Decimals: decimals, - }). - Configure() - suite.Require().NoError(err) - - anteHandler := chainante.NewAnteHandler(chainante.HandlerOptions{ - Cdc: suite.network.App.AppCodec(), - AccountKeeper: suite.network.App.AccountKeeper, - BankKeeper: suite.network.App.BankKeeper, - EvmKeeper: suite.network.App.EVMKeeper, - FeegrantKeeper: suite.network.App.FeeGrantKeeper, - IBCKeeper: suite.network.App.IBCKeeper, - FeeMarketKeeper: suite.network.App.FeeMarketKeeper, - SignModeHandler: encodingConfig.TxConfig.SignModeHandler(), - SigGasConsumer: ante.SigVerificationGasConsumer, - ExtensionOptionChecker: types.HasDynamicFeeExtensionOption, - TxFeeChecker: evmante.NewDynamicFeeChecker(suite.network.App.FeeMarketKeeper), - }) - - suite.anteHandler = anteHandler -} - -func (suite *AnteTestSuite) WithFeemarketEnabled(enabled bool) { - suite.enableFeemarket = enabled -} - -func (suite *AnteTestSuite) WithLondonHardForkEnabled(enabled bool) { - suite.enableLondonHF = enabled -} - -func (suite *AnteTestSuite) WithBaseFee(baseFee *sdkmath.LegacyDec) { - suite.baseFee = baseFee -} - -func (suite *AnteTestSuite) WithEvmParamsOptions(evmParamsOpts func(*evmtypes.Params)) { - suite.evmParamsOption = evmParamsOpts -} - -func (suite *AnteTestSuite) ResetEvmParamsOptions() { - suite.evmParamsOption = nil -} - -func (suite *AnteTestSuite) GetKeyring() keyring.Keyring { - return suite.keyring -} - -func (suite *AnteTestSuite) GetTxFactory() factory.TxFactory { - return suite.factory -} - -func (suite *AnteTestSuite) GetNetwork() *network.UnitTestNetwork { - return suite.network -} - -func (suite *AnteTestSuite) GetClientCtx() client.Context { - return suite.clientCtx -} - -func (suite *AnteTestSuite) GetAnteHandler() sdk.AnteHandler { - return suite.anteHandler -} diff --git a/cmd/evmd/cmd/root.go b/cmd/evmd/cmd/root.go index 48783d05c..4c42b58f7 100644 --- a/cmd/evmd/cmd/root.go +++ b/cmd/evmd/cmd/root.go @@ -5,6 +5,7 @@ import ( "io" "os" + "cosmosevm.io/evmd" "github.com/spf13/cast" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -16,8 +17,6 @@ import ( cosmosevmcmd "github.com/cosmos/evm/client" evmdconfig "github.com/cosmos/evm/cmd/evmd/config" cosmosevmkeyring "github.com/cosmos/evm/crypto/keyring" - "github.com/cosmos/evm/evmd" - "github.com/cosmos/evm/evmd/testutil" cosmosevmserver "github.com/cosmos/evm/server" cosmosevmserverconfig "github.com/cosmos/evm/server/config" srvflags "github.com/cosmos/evm/server/flags" @@ -57,6 +56,9 @@ func NewRootCmd() *cobra.Command { // we "pre"-instantiate the application for getting the injected/configured encoding configuration // and the CLI options for the modules // add keyring to autocli opts + noOpEvmAppOptions := func(_ uint64) error { + return nil + } tempApp := evmd.NewExampleApp( log.NewNopLogger(), dbm.NewMemDB(), @@ -64,7 +66,7 @@ func NewRootCmd() *cobra.Command { true, simtestutil.EmptyAppOptions{}, cosmosevmserverconfig.DefaultEVMChainID, - testutil.NoOpEvmAppOptions, + noOpEvmAppOptions, ) encodingConfig := sdktestutil.TestEncodingConfig{ diff --git a/cmd/evmd/main.go b/cmd/evmd/main.go index a38b867ff..c65e5cb62 100644 --- a/cmd/evmd/main.go +++ b/cmd/evmd/main.go @@ -4,9 +4,10 @@ import ( "fmt" "os" + "cosmosevm.io/evmd" + "github.com/cosmos/evm/cmd/evmd/cmd" evmdconfig "github.com/cosmos/evm/cmd/evmd/config" - examplechain "github.com/cosmos/evm/evmd" svrcmd "github.com/cosmos/cosmos-sdk/server/cmd" sdk "github.com/cosmos/cosmos-sdk/types" @@ -16,7 +17,7 @@ func main() { setupSDKConfig() rootCmd := cmd.NewRootCmd() - if err := svrcmd.Execute(rootCmd, "evmd", examplechain.DefaultNodeHome); err != nil { + if err := svrcmd.Execute(rootCmd, "evmd", evmd.DefaultNodeHome); err != nil { fmt.Fprintln(rootCmd.OutOrStderr(), err) os.Exit(1) } diff --git a/evmd/activators.go b/evmd/activators.go index 05bccbef6..1416dc6ad 100644 --- a/evmd/activators.go +++ b/evmd/activators.go @@ -1,9 +1,8 @@ package evmd import ( + "cosmosevm.io/evmd/eips" "github.com/ethereum/go-ethereum/core/vm" - - "github.com/cosmos/evm/evmd/eips" ) // cosmosEVMActivators defines a map of opcode modifiers associated diff --git a/evmd/ante/integration_test.go b/evmd/ante/integration_test.go deleted file mode 100644 index 1397bf278..000000000 --- a/evmd/ante/integration_test.go +++ /dev/null @@ -1,175 +0,0 @@ -package ante_test - -import ( - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" - - commonfactory "github.com/cosmos/evm/testutil/integration/common/factory" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" - integrationutils "github.com/cosmos/evm/testutil/integration/os/utils" - testutiltx "github.com/cosmos/evm/testutil/tx" - - "cosmossdk.io/math" - - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - sdk "github.com/cosmos/cosmos-sdk/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" -) - -type IntegrationTestSuite struct { - network network.Network - factory factory.TxFactory - grpcHandler grpc.Handler - keyring testkeyring.Keyring -} - -var _ = Describe("when sending a Cosmos transaction", Label("AnteHandler"), Ordered, func() { - var ( - s *IntegrationTestSuite - addr sdk.AccAddress - priv cryptotypes.PrivKey - msg sdk.Msg - ) - - BeforeAll(func() { - keyring := testkeyring.New(3) - - integrationNetwork := network.New( - network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), - ) - grpcHandler := grpc.NewIntegrationHandler(integrationNetwork) - txFactory := factory.New(integrationNetwork, grpcHandler) - s = &IntegrationTestSuite{ - network: integrationNetwork, - factory: txFactory, - grpcHandler: grpcHandler, - keyring: keyring, - } - }) - - Context("and the sender account has enough balance to pay for the transaction cost", Ordered, func() { - var ( - // rewards are the real accrued rewards - rewards sdk.DecCoins - // minExpRewards are the minimun rewards that should be accrued - // for the test case - minExpRewards = sdk.DecCoins{sdk.DecCoin{Amount: math.LegacyNewDec(1e5), Denom: s.network.GetBaseDenom()}} - delegationCoin = sdk.Coin{Amount: math.NewInt(1e15), Denom: s.network.GetBaseDenom()} - transferAmt = math.NewInt(1e14) - ) - - BeforeEach(func() { - key := s.keyring.GetKey(0) - addr = key.AccAddr - priv = key.Priv - - msg = &banktypes.MsgSend{ - FromAddress: addr.String(), - ToAddress: "cosmos1dx67l23hz9l0k9hcher8xz04uj7wf3yu26l2yn", - Amount: sdk.Coins{sdk.Coin{Amount: transferAmt, Denom: s.network.GetBaseDenom()}}, - } - - valAddr := s.network.GetValidators()[0].OperatorAddress - err := s.factory.Delegate(priv, valAddr, delegationCoin) - Expect(err).To(BeNil()) - - rewards, err = integrationutils.WaitToAccrueRewards(s.network, s.grpcHandler, addr.String(), minExpRewards) - Expect(err).To(BeNil()) - }) - - It("should succeed & not withdraw any staking rewards", func() { - prevBalanceRes, err := s.grpcHandler.GetBalanceFromBank(addr, s.network.GetBaseDenom()) - Expect(err).To(BeNil()) - - baseFeeRes, err := s.grpcHandler.GetEvmBaseFee() - Expect(err).To(BeNil()) - Expect(baseFeeRes).ToNot(BeNil(), "baseFeeRes is nil") - - gasPrice := baseFeeRes.BaseFee - - res, err := s.factory.ExecuteCosmosTx( - priv, - commonfactory.CosmosTxArgs{ - Msgs: []sdk.Msg{msg}, - GasPrice: gasPrice, - }, - ) - Expect(err).To(BeNil()) - Expect(res.IsOK()).To(BeTrue()) - - // include the tx in a block to update state - err = s.network.NextBlock() - Expect(err).To(BeNil()) - - // fees should be deducted from balance - Expect(baseFeeRes.BaseFee).ToNot(BeNil(), "baseFeeRes.BaseFee is nil") - - feesAmt := math.NewInt(res.GasWanted).Mul(*baseFeeRes.BaseFee) - balanceRes, err := s.grpcHandler.GetBalanceFromBank(addr, s.network.GetBaseDenom()) - Expect(err).To(BeNil()) - Expect(balanceRes.Balance.Amount).To(Equal(prevBalanceRes.Balance.Amount.Sub(transferAmt).Sub(feesAmt))) - - rewardsRes, err := s.grpcHandler.GetDelegationTotalRewards(addr.String()) - Expect(err).To(BeNil()) - - // rewards should not be used. Should be more - // than the previous value queried - Expect(rewardsRes.Total.Sub(rewards).IsAllPositive()).To(BeTrue()) - }) - }) - - Context("and the sender account neither has enough balance nor sufficient staking rewards to pay for the transaction cost", func() { - BeforeEach(func() { - addr, priv = testutiltx.NewAccAddressAndKey() - - // this is a new address that does not exist on chain. - // Transfer 1 aatom to this account so it is - // added on chain - err := s.factory.FundAccount( - s.keyring.GetKey(0), - addr, - sdk.Coins{ - sdk.Coin{ - Amount: math.NewInt(1), - Denom: s.network.GetBaseDenom(), - }, - }, - ) - Expect(err).To(BeNil()) - // persist the state changes - Expect(s.network.NextBlock()).To(BeNil()) - - msg = &banktypes.MsgSend{ - FromAddress: addr.String(), - ToAddress: "cosmos1dx67l23hz9l0k9hcher8xz04uj7wf3yu26l2yn", - Amount: sdk.Coins{sdk.Coin{Amount: math.NewInt(1e14), Denom: s.network.GetBaseDenom()}}, - } - }) - - It("should fail", func() { - var gas uint64 = 200_000 // specify gas to avoid failing on simulation tx (internal call in the ExecuteCosmosTx if gas not specified) - res, err := s.factory.ExecuteCosmosTx( - priv, - commonfactory.CosmosTxArgs{ - Msgs: []sdk.Msg{msg}, - Gas: &gas, - }, - ) - Expect(res.IsErr()).To(BeTrue()) - Expect(res.GetLog()).To(ContainSubstring("insufficient funds")) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - }) - - It("should not withdraw any staking rewards", func() { - rewardsRes, err := s.grpcHandler.GetDelegationTotalRewards(addr.String()) - Expect(err).To(BeNil()) - Expect(rewardsRes.Total.Empty()).To(BeTrue()) - }) - }) -}) diff --git a/evmd/app.go b/evmd/app.go index ba72b9728..6c1d8446c 100644 --- a/evmd/app.go +++ b/evmd/app.go @@ -8,6 +8,7 @@ import ( "os" "sort" + chainante "cosmosevm.io/evmd/ante" corevm "github.com/ethereum/go-ethereum/core/vm" "github.com/spf13/cast" @@ -18,10 +19,10 @@ import ( abci "github.com/cometbft/cometbft/abci/types" dbm "github.com/cosmos/cosmos-db" + "github.com/cosmos/evm" evmante "github.com/cosmos/evm/ante" cosmosevmante "github.com/cosmos/evm/ante/evm" evmosencoding "github.com/cosmos/evm/encoding" - chainante "github.com/cosmos/evm/evmd/ante" srvflags "github.com/cosmos/evm/server/flags" cosmosevmtypes "github.com/cosmos/evm/types" cosmosevmutils "github.com/cosmos/evm/utils" @@ -1034,6 +1035,78 @@ func (app *EVMD) GetIBCKeeper() *ibckeeper.Keeper { return app.IBCKeeper } +func (app *EVMD) GetEVMKeeper() *evmkeeper.Keeper { + return app.EVMKeeper +} + +func (app *EVMD) GetErc20Keeper() evm.Erc20Keeper { + return &app.Erc20Keeper +} + +func (app *EVMD) SetErc20Keeper(erc20Keeper evm.Erc20Keeper) { + app.Erc20Keeper = *erc20Keeper.(*erc20keeper.Keeper) +} + +func (app *EVMD) GetGovKeeper() govkeeper.Keeper { + return app.GovKeeper +} + +func (app *EVMD) GetEvidenceKeeper() *evidencekeeper.Keeper { + return &app.EvidenceKeeper +} + +func (app *EVMD) GetSlashingKeeper() slashingkeeper.Keeper { + return app.SlashingKeeper +} + +func (app *EVMD) GetBankKeeper() bankkeeper.Keeper { + return app.BankKeeper +} + +func (app *EVMD) GetFeeMarketKeeper() *feemarketkeeper.Keeper { + return &app.FeeMarketKeeper +} + +func (app *EVMD) GetFeeGrantKeeper() feegrantkeeper.Keeper { + return app.FeeGrantKeeper +} + +func (app *EVMD) GetAccountKeeper() authkeeper.AccountKeeper { + return app.AccountKeeper +} + +func (app *EVMD) GetAuthzKeeper() authzkeeper.Keeper { + return app.AuthzKeeper +} + +func (app *EVMD) GetDistrKeeper() distrkeeper.Keeper { + return app.DistrKeeper +} + +func (app *EVMD) GetStakingKeeper() *stakingkeeper.Keeper { + return app.StakingKeeper +} + +func (app *EVMD) GetMintKeeper() mintkeeper.Keeper { + return app.MintKeeper +} + +func (app *EVMD) GetPreciseBankKeeper() *precisebankkeeper.Keeper { + return &app.PreciseBankKeeper +} + +func (app *EVMD) GetTransferKeeper() transferkeeper.Keeper { + return app.TransferKeeper +} + +func (app *EVMD) SetTransferKeeper(transferKeeper transferkeeper.Keeper) { + app.TransferKeeper = transferKeeper +} + +func (app *EVMD) GetAnteHandler() sdk.AnteHandler { + return app.BaseApp.AnteHandler() +} + // GetTxConfig implements the TestingApp interface. func (app *EVMD) GetTxConfig() client.TxConfig { return app.txConfig diff --git a/evmd/eips/eips_test.go b/evmd/eips/eips_test.go deleted file mode 100644 index ab71335f3..000000000 --- a/evmd/eips/eips_test.go +++ /dev/null @@ -1,438 +0,0 @@ -package eips_test - -import ( - "fmt" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/params" - - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" - - "github.com/cosmos/evm/evmd/eips" - "github.com/cosmos/evm/evmd/eips/testdata" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" - integrationutils "github.com/cosmos/evm/testutil/integration/os/utils" - evmtypes "github.com/cosmos/evm/x/vm/types" - - "github.com/cosmos/cosmos-sdk/crypto/types" -) - -// Below tests are divided in 3 steps: -// 1. Deploy and interact with contracts to compute the gas used BEFORE enabling -// the EIP. -// 2. Activate the EIP under test. -// 3. Deploy and interact with contracts to compute the gas used AFTER enabling -// the EIP. - -func TestEIPs(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "EIPs Suite") -} - -var _ = Describe("EIP-0000 - ", Ordered, func() { - var ( - in network.Network - tf factory.TxFactory - gh grpc.Handler - k keyring.Keyring - - senderPriv types.PrivKey - senderPriv2 types.PrivKey - senderAddr2 common.Address - - // Gas used before enabling the EIP. - gasUsedPre int64 - ) - - // Multiplier used to modify the opcodes associated with EIP-0. - eipMultiplier := uint64(5) - - // The factory counter is used because it will create a new instance of - // the counter contract, allowing to test the CREATE opcode. - counterFactoryContract, err := testdata.LoadCounterFactoryContract() - Expect(err).ToNot(HaveOccurred(), "failed to load Counter Factory contract") - - deploymentData := factory.ContractDeploymentData{ - Contract: counterFactoryContract, - ConstructorArgs: []interface{}{}, - } - - BeforeAll(func() { - k = keyring.New(2) - in = network.New( - network.WithPreFundedAccounts(k.GetAllAccAddrs()...), - ) - gh = grpc.NewIntegrationHandler(in) - tf = factory.New(in, gh) - - // Account used to deploy the contract before enabling the EIP. - senderPriv = k.GetPrivKey(0) - // Account used to deploy the contract after enabling the EIP. A second - // account is used to avoid possible additional gas costs due to the change - // in the Nonce. - senderPriv2 = k.GetPrivKey(1) - senderAddr2 = k.GetAddr(1) - - // Set extra EIPs to empty to allow testing a single modifier. - defaultParams := evmtypes.DefaultParams() - defaultParams.ExtraEIPs = []int64{} - - err := integrationutils.UpdateEvmParams( - integrationutils.UpdateParamsInput{ - Tf: tf, - Network: in, - Pk: senderPriv, - Params: defaultParams, - }, - ) - Expect(err).To(BeNil(), "failed during update of evm params") - Expect(in.NextBlock()).To(BeNil()) - }) - - It("should deploy the contract before enabling the EIP", func() { - deploymentTxArgs, err := tf.GenerateDeployContractArgs(senderAddr2, evmtypes.EvmTxArgs{}, deploymentData) - Expect(err).To(BeNil(), "failed to create deployment tx args") - - res, err := tf.ExecuteEthTx(senderPriv2, deploymentTxArgs) - Expect(err).To(BeNil(), "failed during contract deployment") - gasUsedPre = res.GasUsed - }) - - It("should enable the new EIP", func() { - eips.Multiplier = eipMultiplier - newEIP := 0o000 - - qRes, err := gh.GetEvmParams() - Expect(err).To(BeNil(), "failed during query to evm params") - qRes.Params.ExtraEIPs = append(qRes.Params.ExtraEIPs, int64(newEIP)) - err = integrationutils.UpdateEvmParams( - integrationutils.UpdateParamsInput{ - Tf: tf, - Network: in, - Pk: senderPriv, - Params: qRes.Params, - }, - ) - Expect(err).To(BeNil(), "failed during update of evm params") - - Expect(in.NextBlock()).To(BeNil()) - - qRes, err = gh.GetEvmParams() - Expect(err).To(BeNil(), "failed during query to evm params") - Expect(qRes.Params.ExtraEIPs).To(ContainElement(int64(newEIP)), "expected to have EIP 0000 in evm params") - }) - - It("should change CREATE opcode constant gas after enabling EIP", func() { - gasCostPre := params.CreateGas - - deploymentTxArgs, err := tf.GenerateDeployContractArgs(senderAddr2, evmtypes.EvmTxArgs{}, deploymentData) - Expect(err).To(BeNil(), "failed to create deployment tx args") - - res, err := tf.ExecuteEthTx(senderPriv2, deploymentTxArgs) - Expect(err).To(BeNil(), "failed during contract deployment") - // commit block to update sender nonce - Expect(in.NextBlock()).To(BeNil()) - - gasUsedPost := res.GasUsed - - // The difference in gas is the new cost of the opcode, minus the cost of the - // opcode before enabling the new eip. - gasUsedDiff := eipMultiplier*gasCostPre - gasCostPre - expectedGas := gasUsedPre + int64(gasUsedDiff) - Expect(gasUsedPost).To(Equal(expectedGas)) - }) -}) - -var _ = Describe("EIP0001 - ", Ordered, func() { - var ( - in network.Network - tf factory.TxFactory - gh grpc.Handler - k keyring.Keyring - - senderPriv types.PrivKey - - // Gas used before enabling the EIP. - gasUsedPre int64 - - // The address of the factory counter. - counterFactoryAddr common.Address - ) - - // Multiplier used to modify the opcodes associated with EIP_0001. - eipMultiplier := uint64(5) - initialCounterValue := 1 - - // The counter factory contract is used to deploy a counter contract and - // perform state transition using the CALL opcode. - counterFactoryContract, err := testdata.LoadCounterFactoryContract() - Expect(err).ToNot(HaveOccurred(), "failed to load Counter Factory contract") - - BeforeAll(func() { - k = keyring.New(1) - in = network.New( - network.WithPreFundedAccounts(k.GetAllAccAddrs()...), - ) - gh = grpc.NewIntegrationHandler(in) - tf = factory.New(in, gh) - - senderPriv = k.GetPrivKey(0) - - // Set extra EIPs to empty to allow testing a single modifier. - defaultParams := evmtypes.DefaultParams() - defaultParams.ExtraEIPs = []int64{} - err = integrationutils.UpdateEvmParams( - integrationutils.UpdateParamsInput{ - Tf: tf, - Network: in, - Pk: senderPriv, - Params: defaultParams, - }, - ) - Expect(err).To(BeNil(), "failed during update of evm params") - - Expect(in.NextBlock()).To(BeNil()) - }) - - It("should deploy the contract before enabling the EIP", func() { - counterFactoryAddr, err = tf.DeployContract( - senderPriv, - evmtypes.EvmTxArgs{}, - factory.ContractDeploymentData{ - Contract: counterFactoryContract, - ConstructorArgs: []interface{}{}, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to deploy counter factory contract") - Expect(in.NextBlock()).To(BeNil()) - - res, err := tf.ExecuteContractCall( - senderPriv, - evmtypes.EvmTxArgs{To: &counterFactoryAddr}, - factory.CallArgs{ - ContractABI: counterFactoryContract.ABI, - MethodName: "incrementCounter", - Args: []interface{}{}, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to increment counter value") - gasUsedPre = res.GasUsed - - Expect(in.NextBlock()).To(BeNil()) - - // Query the counter value to check proper state transition later. - res, err = tf.ExecuteContractCall( - senderPriv, - evmtypes.EvmTxArgs{To: &counterFactoryAddr}, - factory.CallArgs{ - ContractABI: counterFactoryContract.ABI, - MethodName: "getCounterValue", - Args: []interface{}{}, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to get counter value") - Expect(in.NextBlock()).To(BeNil()) - - ethRes, err := evmtypes.DecodeTxResponse(res.Data) - Expect(err).ToNot(HaveOccurred(), "failed to decode tx response") - - unpacked, err := counterFactoryContract.ABI.Unpack( - "getCounterValue", - ethRes.Ret, - ) - Expect(err).ToNot(HaveOccurred(), "failed to unpack counter value") - - counter, ok := unpacked[0].(*big.Int) - Expect(ok).To(BeTrue(), "failed to convert counter to big.Int") - Expect(counter.String()).To(Equal(fmt.Sprintf("%d", initialCounterValue+1)), "counter is not correct") - }) - It("should enable the new EIP", func() { - eips.Multiplier = eipMultiplier - newEIP := 0o001 - - qRes, err := gh.GetEvmParams() - Expect(err).To(BeNil(), "failed during query to evm params") - qRes.Params.ExtraEIPs = append(qRes.Params.ExtraEIPs, int64(newEIP)) - - err = integrationutils.UpdateEvmParams( - integrationutils.UpdateParamsInput{ - Tf: tf, - Network: in, - Pk: senderPriv, - Params: qRes.Params, - }, - ) - Expect(err).To(BeNil(), "failed during update of evm params") - - Expect(in.NextBlock()).To(BeNil()) - - qRes, err = gh.GetEvmParams() - Expect(err).To(BeNil(), "failed during query to evm params") - Expect(qRes.Params.ExtraEIPs).To(ContainElement(int64(newEIP)), "expected to have eip 0001 in evm params") - }) - It("should change CALL opcode constant gas after enabling EIP", func() { - // Constant gas cost used before enabling the new EIP. - gasCostPre := params.WarmStorageReadCostEIP2929 - - res, err := tf.ExecuteContractCall( - senderPriv, - evmtypes.EvmTxArgs{To: &counterFactoryAddr}, - factory.CallArgs{ - ContractABI: counterFactoryContract.ABI, - MethodName: "incrementCounter", - Args: []interface{}{}, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to increment counter value") - gasUsedPost := res.GasUsed - Expect(in.NextBlock()).To(BeNil()) - - res, err = tf.ExecuteContractCall( - senderPriv, - evmtypes.EvmTxArgs{To: &counterFactoryAddr}, - factory.CallArgs{ - ContractABI: counterFactoryContract.ABI, - MethodName: "getCounterValue", - Args: []interface{}{}, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to get counter value") - Expect(in.NextBlock()).To(BeNil()) - - ethRes, err := evmtypes.DecodeTxResponse(res.Data) - Expect(err).ToNot(HaveOccurred(), "failed to decode tx response") - - unpacked, err := counterFactoryContract.ABI.Unpack( - "getCounterValue", - ethRes.Ret, - ) - Expect(err).ToNot(HaveOccurred(), "failed to unpack counter value") - - counter, ok := unpacked[0].(*big.Int) - Expect(ok).To(BeTrue(), "failed to convert counter to big.Int") - Expect(counter.String()).To(Equal(fmt.Sprintf("%d", initialCounterValue+2)), "counter is not updated correctly") - - // The difference in gas is the new cost of the opcode, minus the cost of the - // opcode before enabling the new eip. - gasUsedDiff := eipMultiplier*gasCostPre - gasCostPre - expectedGas := gasUsedPre + int64(gasUsedDiff) - Expect(gasUsedPost).To(Equal(expectedGas)) - }) -}) - -var _ = Describe("EIP0002 - ", Ordered, func() { - var ( - in network.Network - tf factory.TxFactory - gh grpc.Handler - k keyring.Keyring - - senderPriv types.PrivKey - senderAddr common.Address - senderPriv2 types.PrivKey - senderAddr2 common.Address - gasUsedPre int64 - ) - // Constant gas used to modify the opcodes associated with EIP_0002. - constantGas := uint64(500) - - counterContract, err := testdata.LoadCounterContract() - Expect(err).ToNot(HaveOccurred(), "failed to load Counter contract") - - deploymentData := factory.ContractDeploymentData{ - Contract: counterContract, - ConstructorArgs: []interface{}{}, - } - BeforeAll(func() { - k = keyring.New(2) - in = network.New( - network.WithPreFundedAccounts(k.GetAllAccAddrs()...), - ) - gh = grpc.NewIntegrationHandler(in) - tf = factory.New(in, gh) - - // Account used to deploy the contract before enabling the EIP. - senderPriv = k.GetPrivKey(0) - senderAddr = k.GetAddr(0) - // Account used to deploy the contract after enabling the EIP. A second - // account is used to avoid possible additional gas costs due to the change - // in the Nonce. - senderPriv2 = k.GetPrivKey(0) - senderAddr2 = k.GetAddr(0) - - // Set extra EIPs to empty to allow testing a single modifier. - defaultParams := evmtypes.DefaultParams() - defaultParams.ExtraEIPs = []int64{} - - err = integrationutils.UpdateEvmParams( - integrationutils.UpdateParamsInput{ - Tf: tf, - Network: in, - Pk: senderPriv, - Params: defaultParams, - }, - ) - Expect(err).To(BeNil(), "failed during update of evm params") - - Expect(in.NextBlock()).To(BeNil()) - }) - - It("should deploy the contract before enabling the EIP", func() { - deploymentTxArgs, err := tf.GenerateDeployContractArgs(senderAddr, evmtypes.EvmTxArgs{}, deploymentData) - Expect(err).To(BeNil(), "failed to create deployment tx args") - - res, err := tf.ExecuteEthTx(senderPriv, deploymentTxArgs) - Expect(err).To(BeNil(), "failed during contract deployment") - Expect(in.NextBlock()).To(BeNil()) - - gasUsedPre = res.GasUsed - }) - - It("should enable the new EIP", func() { - eips.SstoreConstantGas = constantGas - newEIP := 0o002 - - qRes, err := gh.GetEvmParams() - Expect(err).To(BeNil(), "failed during query to evm params") - qRes.Params.ExtraEIPs = append(qRes.Params.ExtraEIPs, int64(newEIP)) - err = integrationutils.UpdateEvmParams( - integrationutils.UpdateParamsInput{ - Tf: tf, - Network: in, - Pk: senderPriv, - Params: qRes.Params, - }, - ) - Expect(err).To(BeNil(), "failed during update of evm params") - - Expect(in.NextBlock()).To(BeNil()) - - qRes, err = gh.GetEvmParams() - Expect(err).To(BeNil(), "failed during query to evm params") - Expect(qRes.Params.ExtraEIPs).To(ContainElement(int64(newEIP)), "expected to have eip 0002 in evm params") - }) - - It("should change SSTORE opcode constant gas after enabling EIP", func() { - deploymentTxArgs, err := tf.GenerateDeployContractArgs(senderAddr2, evmtypes.EvmTxArgs{}, deploymentData) - Expect(err).To(BeNil(), "failed to create deployment tx args") - - res, err := tf.ExecuteEthTx(senderPriv2, deploymentTxArgs) - Expect(err).To(BeNil(), "failed during contract deployment") - Expect(in.NextBlock()).To(BeNil()) - - gasUsedPost := res.GasUsed - - // The expected gas is previous gas plus the constant gas because - // previous this eip, SSTORE was using only the dynamic gas. - expectedGas := gasUsedPre + int64(constantGas) - Expect(gasUsedPost).To(Equal(expectedGas)) - }) -}) diff --git a/evmd/go.mod b/evmd/go.mod new file mode 100644 index 000000000..4d872a18a --- /dev/null +++ b/evmd/go.mod @@ -0,0 +1,280 @@ +module cosmosevm.io/evmd + +go 1.23.8 + +require ( + cosmossdk.io/api v0.9.2 + cosmossdk.io/client/v2 v2.0.0-beta.7 + cosmossdk.io/core v0.11.3 + cosmossdk.io/errors v1.0.2 + cosmossdk.io/log v1.5.1 + cosmossdk.io/math v1.5.3 + cosmossdk.io/store v1.1.2 + cosmossdk.io/x/evidence v0.1.1 + cosmossdk.io/x/feegrant v0.1.1 + cosmossdk.io/x/tx v0.14.0 + cosmossdk.io/x/upgrade v0.2.0 + github.com/cometbft/cometbft v0.38.17 + github.com/cosmos/cosmos-db v1.1.1 + github.com/cosmos/cosmos-sdk v0.53.0 + github.com/cosmos/evm v0.2.0 + github.com/cosmos/gogoproto v1.7.0 + github.com/cosmos/ibc-go/v10 v10.2.0 + github.com/ethereum/go-ethereum v1.15.10 + github.com/spf13/cast v1.8.0 + github.com/stretchr/testify v1.10.0 +) + +require ( + cel.dev/expr v0.20.0 // indirect + cloud.google.com/go v0.116.0 // indirect + cloud.google.com/go/auth v0.14.1 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.7 // indirect + cloud.google.com/go/compute/metadata v0.6.0 // indirect + cloud.google.com/go/iam v1.2.2 // indirect + cloud.google.com/go/monitoring v1.21.2 // indirect + cloud.google.com/go/storage v1.49.0 // indirect + cosmossdk.io/collections v1.2.0 // indirect + cosmossdk.io/depinject v1.2.0 // indirect + cosmossdk.io/schema v1.1.0 // indirect + filippo.io/edwards25519 v1.1.0 // indirect + github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect + github.com/99designs/keyring v1.2.2 // indirect + github.com/DataDog/datadog-go v4.8.3+incompatible // indirect + github.com/DataDog/zstd v1.5.7 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.26.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/StackExchange/wmi v1.2.1 // indirect + github.com/VictoriaMetrics/fastcache v1.12.2 // indirect + github.com/aws/aws-sdk-go v1.44.224 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect + github.com/bgentry/speakeasy v0.2.0 // indirect + github.com/bits-and-blooms/bitset v1.22.0 // indirect + github.com/btcsuite/btcd v0.24.2 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/btcsuite/btcd/btcutil v1.1.6 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect + github.com/bytedance/sonic v1.13.2 // indirect + github.com/bytedance/sonic/loader v0.2.4 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/chzyer/readline v1.5.1 // indirect + github.com/cloudwego/base64x v0.1.5 // indirect + github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42 // indirect + github.com/cockroachdb/apd/v2 v2.0.2 // indirect + github.com/cockroachdb/errors v1.11.3 // indirect + github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect + github.com/cockroachdb/pebble v1.1.5 // indirect + github.com/cockroachdb/redact v1.1.6 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect + github.com/cometbft/cometbft-db v0.14.1 // indirect + github.com/consensys/bavard v0.1.27 // indirect + github.com/consensys/gnark-crypto v0.16.0 // indirect + github.com/cosmos/btcutil v1.0.5 // indirect + github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect + github.com/cosmos/go-bip39 v1.0.0 // indirect + github.com/cosmos/gogogateway v1.2.0 // indirect + github.com/cosmos/iavl v1.2.2 // indirect + github.com/cosmos/ibc-go/modules/capability v1.0.1 // indirect + github.com/cosmos/ics23/go v0.11.0 // indirect + github.com/cosmos/ledger-cosmos-go v0.14.0 // indirect + github.com/crate-crypto/go-eth-kzg v1.3.0 // indirect + github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect + github.com/danieljoos/wincred v1.2.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/deckarep/golang-set/v2 v2.6.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect + github.com/desertbit/timer v1.0.1 // indirect + github.com/dgraph-io/badger/v4 v4.2.0 // indirect + github.com/dgraph-io/ristretto v0.1.1 // indirect + github.com/dlclark/regexp2 v1.7.0 // indirect + github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/dvsekhvalnov/jose2go v1.7.0 // indirect + github.com/emicklei/dot v1.6.2 // indirect + github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect + github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect + github.com/ethereum/c-kzg-4844/v2 v2.1.0 // indirect + github.com/ethereum/go-verkle v0.2.2 // indirect + github.com/fatih/color v1.17.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/getsentry/sentry-go v0.28.1 // indirect + github.com/go-jose/go-jose/v4 v4.0.5 // indirect + github.com/go-kit/kit v0.13.0 // indirect + github.com/go-kit/log v0.2.1 // indirect + github.com/go-logfmt/logfmt v0.6.0 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect + github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect + github.com/go-task/slim-sprig/v3 v3.0.0 // indirect + github.com/go-viper/mapstructure/v2 v2.2.1 // indirect + github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect + github.com/gofrs/flock v0.8.1 // indirect + github.com/gogo/googleapis v1.4.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/glog v1.2.4 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect + github.com/google/btree v1.1.3 // indirect + github.com/google/flatbuffers v24.3.25+incompatible // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/google/orderedcode v0.0.1 // indirect + github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect + github.com/google/s2a-go v0.1.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect + github.com/googleapis/gax-go/v2 v2.14.1 // indirect + github.com/gorilla/handlers v1.5.2 // indirect + github.com/gorilla/mux v1.8.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect + github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect + github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-getter v1.7.8 // indirect + github.com/hashicorp/go-hclog v1.6.3 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-metrics v0.5.4 // indirect + github.com/hashicorp/go-plugin v1.6.3 // indirect + github.com/hashicorp/go-safetemp v1.0.0 // indirect + github.com/hashicorp/go-version v1.7.0 // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/hashicorp/yamux v0.1.2 // indirect + github.com/hdevalence/ed25519consensus v0.2.0 // indirect + github.com/holiman/bloomfilter/v2 v2.0.3 // indirect + github.com/holiman/uint256 v1.3.2 // indirect + github.com/huandu/skiplist v1.2.1 // indirect + github.com/huin/goupnp v1.3.0 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect + github.com/improbable-eng/grpc-web v0.15.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jackpal/go-nat-pmp v1.0.2 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/jmhodges/levigo v1.0.0 // indirect + github.com/klauspost/compress v1.18.0 // indirect + github.com/klauspost/cpuid/v2 v2.2.10 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/lib/pq v1.10.9 // indirect + github.com/linxGnu/grocksdb v1.9.8 // indirect + github.com/manifoldco/promptui v0.9.0 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/minio/highwayhash v1.0.3 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/mtibben/percent v0.2.1 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect + github.com/oklog/run v1.1.0 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/onsi/ginkgo/v2 v2.22.2 // indirect + github.com/onsi/gomega v1.36.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect + github.com/pion/dtls/v2 v2.2.7 // indirect + github.com/pion/logging v0.2.2 // indirect + github.com/pion/stun/v2 v2.0.0 // indirect + github.com/pion/transport/v2 v2.2.1 // indirect + github.com/pion/transport/v3 v3.0.1 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_golang v1.22.0 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.63.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/rogpeppe/go-internal v1.14.1 // indirect + github.com/rs/cors v1.11.1 // indirect + github.com/rs/zerolog v1.34.0 // indirect + github.com/sagikazarmark/locafero v0.7.0 // indirect + github.com/sasha-s/go-deadlock v0.3.5 // indirect + github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.12.0 // indirect + github.com/spf13/cobra v1.9.1 // indirect + github.com/spf13/pflag v1.0.6 // indirect + github.com/spf13/viper v1.20.1 // indirect + github.com/spiffe/go-spiffe/v2 v2.5.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/supranational/blst v0.3.14 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect + github.com/tendermint/go-amino v0.16.0 // indirect + github.com/tidwall/btree v1.7.0 // indirect + github.com/tidwall/gjson v1.18.0 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.0 // indirect + github.com/tidwall/sjson v1.2.5 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/ulikunitz/xz v0.5.11 // indirect + github.com/zeebo/errs v1.4.0 // indirect + github.com/zondax/hid v0.9.2 // indirect + github.com/zondax/ledger-go v0.14.3 // indirect + go.etcd.io/bbolt v1.4.0-alpha.1 // indirect + go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/contrib/detectors/gcp v1.34.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect + go.opentelemetry.io/otel v1.34.0 // indirect + go.opentelemetry.io/otel/metric v1.34.0 // indirect + go.opentelemetry.io/otel/sdk v1.34.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect + go.opentelemetry.io/otel/trace v1.34.0 // indirect + go.uber.org/mock v0.5.2 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/arch v0.15.0 // indirect + golang.org/x/crypto v0.38.0 // indirect + golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect + golang.org/x/net v0.39.0 // indirect + golang.org/x/oauth2 v0.27.0 // indirect + golang.org/x/sync v0.14.0 // indirect + golang.org/x/sys v0.33.0 // indirect + golang.org/x/term v0.32.0 // indirect + golang.org/x/text v0.25.0 // indirect + golang.org/x/time v0.10.0 // indirect + golang.org/x/tools v0.31.0 // indirect + google.golang.org/api v0.222.0 // indirect + google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250422160041-2d3770c4ea7f // indirect + google.golang.org/grpc v1.72.0 // indirect + google.golang.org/protobuf v1.36.6 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + gotest.tools/v3 v3.5.2 // indirect + nhooyr.io/websocket v1.8.11 // indirect + pgregory.net/rapid v1.2.0 // indirect + rsc.io/tmplfunc v0.0.3 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect +) + +replace ( + cosmosevm.io/evmd => ./evmd + // use cosmos fork of keyring + github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 + // Pin this pebble version to avoid breaking compilation of geth + github.com/cockroachdb/pebble => github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 + github.com/cosmos/evm => ../ + // use Cosmos geth fork + github.com/ethereum/go-ethereum => github.com/cosmos/go-ethereum v1.15.11-cosmos-0 + // Security Advisory https://github.com/advisories/GHSA-h395-qcrw-5vmq + github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.9.1 + // replace broken goleveldb + github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 +) diff --git a/evmd/go.sum b/evmd/go.sum new file mode 100644 index 000000000..ffd48c9d9 --- /dev/null +++ b/evmd/go.sum @@ -0,0 +1,2605 @@ +cel.dev/expr v0.20.0 h1:OunBvVCfvpWlt4dN7zg3FM6TDkzOePe1+foGJ9AXeeI= +cel.dev/expr v0.20.0/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U= +cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= +cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= +cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= +cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= +cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= +cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= +cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= +cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= +cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= +cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= +cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= +cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= +cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= +cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= +cloud.google.com/go/accesscontextmanager v1.6.0/go.mod h1:8XCvZWfYw3K/ji0iVnp+6pu7huxoQTLmxAbVjbloTtM= +cloud.google.com/go/accesscontextmanager v1.7.0/go.mod h1:CEGLewx8dwa33aDAZQujl7Dx+uYhS0eay198wB/VumQ= +cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= +cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= +cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg= +cloud.google.com/go/aiplatform v1.35.0/go.mod h1:7MFT/vCaOyZT/4IIFfxH4ErVg/4ku6lKv3w0+tFTgXQ= +cloud.google.com/go/aiplatform v1.36.1/go.mod h1:WTm12vJRPARNvJ+v6P52RDHCNe4AhvjcIZ/9/RRHy/k= +cloud.google.com/go/aiplatform v1.37.0/go.mod h1:IU2Cv29Lv9oCn/9LkFiiuKfwrRTq+QQMbW+hPCxJGZw= +cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= +cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= +cloud.google.com/go/analytics v0.17.0/go.mod h1:WXFa3WSym4IZ+JiKmavYdJwGG/CvpqiqczmL59bTD9M= +cloud.google.com/go/analytics v0.18.0/go.mod h1:ZkeHGQlcIPkw0R/GW+boWHhCOR43xz9RN/jn7WcqfIE= +cloud.google.com/go/analytics v0.19.0/go.mod h1:k8liqf5/HCnOUkbawNtrWWc+UAzyDlW89doe8TtoDsE= +cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= +cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc= +cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8= +cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc= +cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04= +cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8= +cloud.google.com/go/apigeeregistry v0.4.0/go.mod h1:EUG4PGcsZvxOXAdyEghIdXwAEi/4MEaoqLMLDMIwKXY= +cloud.google.com/go/apigeeregistry v0.5.0/go.mod h1:YR5+s0BVNZfVOUkMa5pAR2xGd0A473vA5M7j247o1wM= +cloud.google.com/go/apigeeregistry v0.6.0/go.mod h1:BFNzW7yQVLZ3yj0TKcwzb8n25CFBri51GVGOEUcgQsc= +cloud.google.com/go/apikeys v0.4.0/go.mod h1:XATS/yqZbaBK0HOssf+ALHp8jAlNHUgyfprvNcBIszU= +cloud.google.com/go/apikeys v0.5.0/go.mod h1:5aQfwY4D+ewMMWScd3hm2en3hCj+BROlyrt3ytS7KLI= +cloud.google.com/go/apikeys v0.6.0/go.mod h1:kbpXu5upyiAlGkKrJgQl8A0rKNNJ7dQ377pdroRSSi8= +cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno= +cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak= +cloud.google.com/go/appengine v1.6.0/go.mod h1:hg6i0J/BD2cKmDJbaFSYHFyZkgBEfQrDg/X0V5fJn84= +cloud.google.com/go/appengine v1.7.0/go.mod h1:eZqpbHFCqRGa2aCdope7eC0SWLV1j0neb/QnMJVWx6A= +cloud.google.com/go/appengine v1.7.1/go.mod h1:IHLToyb/3fKutRysUlFO0BPt5j7RiQ45nrzEJmKTo6E= +cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= +cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= +cloud.google.com/go/area120 v0.7.0/go.mod h1:a3+8EUD1SX5RUcCs3MY5YasiO1z6yLiNLRiFrykbynY= +cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k= +cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= +cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= +cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0= +cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc= +cloud.google.com/go/artifactregistry v1.11.1/go.mod h1:lLYghw+Itq9SONbCa1YWBoWs1nOucMH0pwXN1rOBZFI= +cloud.google.com/go/artifactregistry v1.11.2/go.mod h1:nLZns771ZGAwVLzTX/7Al6R9ehma4WUEhZGWV6CeQNQ= +cloud.google.com/go/artifactregistry v1.12.0/go.mod h1:o6P3MIvtzTOnmvGagO9v/rOjjA0HmhJ+/6KAXrmYDCI= +cloud.google.com/go/artifactregistry v1.13.0/go.mod h1:uy/LNfoOIivepGhooAUpL1i30Hgee3Cu0l4VTWHUC08= +cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= +cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= +cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= +cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ= +cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY= +cloud.google.com/go/asset v1.11.1/go.mod h1:fSwLhbRvC9p9CXQHJ3BgFeQNM4c9x10lqlrdEUYXlJo= +cloud.google.com/go/asset v1.12.0/go.mod h1:h9/sFOa4eDIyKmH6QMpm4eUK3pDojWnUhTgJlk762Hg= +cloud.google.com/go/asset v1.13.0/go.mod h1:WQAMyYek/b7NBpYq/K4KJWcRqzoalEsxz/t/dTk4THw= +cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= +cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= +cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= +cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo= +cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= +cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= +cloud.google.com/go/auth v0.14.1 h1:AwoJbzUdxA/whv1qj3TLKwh3XX5sikny2fc40wUl+h0= +cloud.google.com/go/auth v0.14.1/go.mod h1:4JHUxlGXisL0AW8kXPtUF6ztuOksyfUQNFjfsOCXkPM= +cloud.google.com/go/auth/oauth2adapt v0.2.7 h1:/Lc7xODdqcEw8IrZ9SvwnlLX6j9FHQM74z6cBk9Rw6M= +cloud.google.com/go/auth/oauth2adapt v0.2.7/go.mod h1:NTbTTzfvPl1Y3V1nPpOgl2w6d/FjO7NNUQaWSox6ZMc= +cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= +cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= +cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= +cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM= +cloud.google.com/go/automl v1.12.0/go.mod h1:tWDcHDp86aMIuHmyvjuKeeHEGq76lD7ZqfGLN6B0NuU= +cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc= +cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI= +cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss= +cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE= +cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE= +cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oevL159g= +cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4= +cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8= +cloud.google.com/go/beyondcorp v0.4.0/go.mod h1:3ApA0mbhHx6YImmuubf5pyW8srKnCEPON32/5hj+RmM= +cloud.google.com/go/beyondcorp v0.5.0/go.mod h1:uFqj9X+dSfrheVp7ssLTaRHd2EHqSL4QZmH4e8WXGGU= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= +cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw= +cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc= +cloud.google.com/go/bigquery v1.47.0/go.mod h1:sA9XOgy0A8vQK9+MWhEQTY6Tix87M/ZurWFIxmF9I/E= +cloud.google.com/go/bigquery v1.48.0/go.mod h1:QAwSz+ipNgfL5jxiaK7weyOhzdoAy1zFm0Nf1fysJac= +cloud.google.com/go/bigquery v1.49.0/go.mod h1:Sv8hMmTFFYBlt/ftw2uN6dFdQPzBlREY9yBh7Oy7/4Q= +cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU= +cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= +cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= +cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= +cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y= +cloud.google.com/go/billing v1.12.0/go.mod h1:yKrZio/eu+okO/2McZEbch17O5CB5NpZhhXG6Z766ss= +cloud.google.com/go/billing v1.13.0/go.mod h1:7kB2W9Xf98hP9Sr12KfECgfGclsH3CQR0R08tnRlRbc= +cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= +cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= +cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0= +cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk= +cloud.google.com/go/binaryauthorization v1.5.0/go.mod h1:OSe4OU1nN/VswXKRBmciKpo9LulY41gch5c68htf3/Q= +cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg= +cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590= +cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5vQ/fE1sh8o+Mdd6KPgY8= +cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk= +cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk= +cloud.google.com/go/channel v1.11.0/go.mod h1:IdtI0uWGqhEeatSB62VOoJ8FSUhJ9/+iGkJVqp74CGE= +cloud.google.com/go/channel v1.12.0/go.mod h1:VkxCGKASi4Cq7TbXxlaBezonAYpp1GCnKMY6tnMQnLU= +cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U= +cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA= +cloud.google.com/go/cloudbuild v1.6.0/go.mod h1:UIbc/w9QCbH12xX+ezUsgblrWv+Cv4Tw83GiSMHOn9M= +cloud.google.com/go/cloudbuild v1.7.0/go.mod h1:zb5tWh2XI6lR9zQmsm1VRA+7OCuve5d8S+zJUul8KTg= +cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb4wQGAbIgL1s= +cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM= +cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk= +cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA= +cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= +cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= +cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4= +cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI= +cloud.google.com/go/cloudtasks v1.9.0/go.mod h1:w+EyLsVkLWHcOaqNEyvcKAsWp9p29dL6uL9Nst1cI7Y= +cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs= +cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= +cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= +cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= +cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= +cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= +cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= +cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= +cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= +cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= +cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= +cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= +cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= +cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= +cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= +cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= +cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= +cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= +cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= +cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= +cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= +cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo= +cloud.google.com/go/container v1.13.1/go.mod h1:6wgbMPeQRw9rSnKBCAJXnds3Pzj03C4JHamr8asWKy4= +cloud.google.com/go/container v1.14.0/go.mod h1:3AoJMPhHfLDxLvrlVWaK57IXzaPnLaZq63WX59aQBfM= +cloud.google.com/go/container v1.15.0/go.mod h1:ft+9S0WGjAyjDggg5S06DXj+fHJICWg8L7isCQe9pQA= +cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= +cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= +cloud.google.com/go/containeranalysis v0.7.0/go.mod h1:9aUL+/vZ55P2CXfuZjS4UjQ9AgXoSw8Ts6lemfmxBxI= +cloud.google.com/go/containeranalysis v0.9.0/go.mod h1:orbOANbwk5Ejoom+s+DUCTTJ7IBdBQJDcSylAx/on9s= +cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= +cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= +cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= +cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H0/tc8f8ZbZIE= +cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM= +cloud.google.com/go/datacatalog v1.8.1/go.mod h1:RJ58z4rMp3gvETA465Vg+ag8BGgBdnRPEMMSTr5Uv+M= +cloud.google.com/go/datacatalog v1.12.0/go.mod h1:CWae8rFkfp6LzLumKOnmVh4+Zle4A3NXLzVJ1d1mRm0= +cloud.google.com/go/datacatalog v1.13.0/go.mod h1:E4Rj9a5ZtAxcQJlEBTLgMTphfP11/lNaAshpoBgemX8= +cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= +cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= +cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE= +cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= +cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= +cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0= +cloud.google.com/go/dataform v0.6.0/go.mod h1:QPflImQy33e29VuapFdf19oPbE4aYTJxr31OAPV+ulA= +cloud.google.com/go/dataform v0.7.0/go.mod h1:7NulqnVozfHvWUBpMDfKMUESr+85aJsC/2O0o3jWPDE= +cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38= +cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w= +cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8= +cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= +cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= +cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxByuW2E+FU+wXcM= +cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA= +cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A= +cloud.google.com/go/dataplex v1.5.2/go.mod h1:cVMgQHsmfRoI5KFYq4JtIBEUbYwc3c7tXmIDhRmNNVQ= +cloud.google.com/go/dataplex v1.6.0/go.mod h1:bMsomC/aEJOSpHXdFKFGQ1b0TDPIeL28nJObeO1ppRs= +cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s= +cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI= +cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= +cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= +cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= +cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZWwP12Qq3c= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM= +cloud.google.com/go/datastore v1.11.0/go.mod h1:TvGxBIHCS50u8jzG+AW/ppf87v1of8nwzFNgEZU1D3c= +cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= +cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= +cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= +cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4= +cloud.google.com/go/datastream v1.6.0/go.mod h1:6LQSuswqLa7S4rPAOZFVjHIG3wJIjZcZrw8JDEDJuIs= +cloud.google.com/go/datastream v1.7.0/go.mod h1:uxVRMm2elUSPuh65IbZpzJNMbuzkcvu5CjMqVIUHrww= +cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c= +cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s= +cloud.google.com/go/deploy v1.6.0/go.mod h1:f9PTHehG/DjCom3QH0cntOVRm93uGBDt2vKzAPwpXQI= +cloud.google.com/go/deploy v1.8.0/go.mod h1:z3myEJnA/2wnB4sgjqdMfgxCA0EqC3RBTNcVPs93mtQ= +cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= +cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= +cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= +cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz0njv7sMx/iek= +cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0= +cloud.google.com/go/dialogflow v1.29.0/go.mod h1:b+2bzMe+k1s9V+F2jbJwpHPzrnIyHihAdRFMtn2WXuM= +cloud.google.com/go/dialogflow v1.31.0/go.mod h1:cuoUccuL1Z+HADhyIA7dci3N5zUssgpBJmCzI6fNRB4= +cloud.google.com/go/dialogflow v1.32.0/go.mod h1:jG9TRJl8CKrDhMEcvfcfFkkpp8ZhgPz3sBGmAUYJ2qE= +cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM= +cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q= +cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4= +cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= +cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= +cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k= +cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4= +cloud.google.com/go/documentai v1.16.0/go.mod h1:o0o0DLTEZ+YnJZ+J4wNfTxmDVyrkzFvttBXXtYRMHkM= +cloud.google.com/go/documentai v1.18.0/go.mod h1:F6CK6iUH8J81FehpskRmhLq/3VlwQvb7TvwOceQ2tbs= +cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= +cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= +cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE= +cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= +cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= +cloud.google.com/go/edgecontainer v0.3.0/go.mod h1:FLDpP4nykgwwIfcLt6zInhprzw0lEi2P1fjO6Ie0qbc= +cloud.google.com/go/edgecontainer v1.0.0/go.mod h1:cttArqZpBB2q58W/upSG++ooo6EsblxDIolxa3jSjbY= +cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= +cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= +cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= +cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aUF2CTzdNtvv42niCX0M= +cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= +cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw= +cloud.google.com/go/eventarc v1.10.0/go.mod h1:u3R35tmZ9HvswGRBnF48IlYgYeBcPUCjkr4BTdem2Kw= +cloud.google.com/go/eventarc v1.11.0/go.mod h1:PyUjsUKPWoRBCHeOxZd/lbOOjahV41icXyUY5kSTvVY= +cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= +cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= +cloud.google.com/go/filestore v1.5.0/go.mod h1:FqBXDWBp4YLHqRnVGveOkHDf8svj9r5+mUDLupOWEDs= +cloud.google.com/go/filestore v1.6.0/go.mod h1:di5unNuss/qfZTw2U9nhFqo8/ZDSc466dre85Kydllg= +cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= +cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= +cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= +cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= +cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08= +cloud.google.com/go/functions v1.10.0/go.mod h1:0D3hEOe3DbEvCXtYOZHQZmD+SzYsi1YbI7dGvHfldXw= +cloud.google.com/go/functions v1.12.0/go.mod h1:AXWGrF3e2C/5ehvwYo/GH6O5s09tOPksiKhz+hH8WkA= +cloud.google.com/go/functions v1.13.0/go.mod h1:EU4O007sQm6Ef/PwRsI8N2umygGqPBS/IZQKBQBcJ3c= +cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= +cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= +cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w= +cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM= +cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0= +cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60= +cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo= +cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg= +cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= +cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= +cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+obZ+QTky2Myw= +cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= +cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= +cloud.google.com/go/gkehub v0.11.0/go.mod h1:JOWHlmN+GHyIbuWQPl47/C2RFhnFKH38jH9Ascu3n0E= +cloud.google.com/go/gkehub v0.12.0/go.mod h1:djiIwwzTTBrF5NaXCGv3mf7klpEMcST17VBTVVDcuaw= +cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA= +cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI= +cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y= +cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= +cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM= +cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o= +cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo= +cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= +cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= +cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= +cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc= +cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= +cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= +cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY= +cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= +cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= +cloud.google.com/go/iam v1.2.2 h1:ozUSofHUGf/F4tCNy/mu9tHLTaxZFLOUiKzjcgWHGIA= +cloud.google.com/go/iam v1.2.2/go.mod h1:0Ys8ccaZHdI1dEUilwzqng/6ps2YB6vRsjIe00/+6JY= +cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= +cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= +cloud.google.com/go/iap v1.6.0/go.mod h1:NSuvI9C/j7UdjGjIde7t7HBz+QTwBcapPE07+sSRcLk= +cloud.google.com/go/iap v1.7.0/go.mod h1:beqQx56T9O1G1yNPph+spKpNibDlYIiIixiqsQXxLIo= +cloud.google.com/go/iap v1.7.1/go.mod h1:WapEwPc7ZxGt2jFGB/C/bm+hP0Y6NXzOYGjpPnmMS74= +cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= +cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= +cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4= +cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= +cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= +cloud.google.com/go/iot v1.5.0/go.mod h1:mpz5259PDl3XJthEmh9+ap0affn/MqNSP4My77Qql9o= +cloud.google.com/go/iot v1.6.0/go.mod h1:IqdAsmE2cTYYNO1Fvjfzo9po179rAtJeVGUvkLN3rLE= +cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= +cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= +cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= +cloud.google.com/go/kms v1.8.0/go.mod h1:4xFEhYFqvW+4VMELtZyxomGSYtSQKzM178ylFW4jMAg= +cloud.google.com/go/kms v1.9.0/go.mod h1:qb1tPTgfF9RQP8e1wq4cLFErVuTJv7UsSC915J8dh3w= +cloud.google.com/go/kms v1.10.0/go.mod h1:ng3KTUtQQU9bPX3+QGLsflZIHlkbn8amFAMY63m8d24= +cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI= +cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= +cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= +cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= +cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8= +cloud.google.com/go/language v1.9.0/go.mod h1:Ns15WooPM5Ad/5no/0n81yUetis74g3zrbeJBE+ptUY= +cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= +cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= +cloud.google.com/go/lifesciences v0.8.0/go.mod h1:lFxiEOMqII6XggGbOnKiyZ7IBwoIqA84ClvoezaA/bo= +cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw= +cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= +cloud.google.com/go/logging v1.12.0 h1:ex1igYcGFd4S/RZWOCU51StlIEuey5bjqwH9ZYjHibk= +cloud.google.com/go/logging v1.12.0/go.mod h1:wwYBt5HlYP1InnrtYI0wtwttpVU1rifnMT7RejksUAM= +cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= +cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= +cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= +cloud.google.com/go/longrunning v0.6.2 h1:xjDfh1pQcWPEvnfjZmwjKQEcHnpz6lHjfy7Fo0MK+hc= +cloud.google.com/go/longrunning v0.6.2/go.mod h1:k/vIs83RN4bE3YCswdXC5PFfWVILjm3hpEUlSko4PiI= +cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= +cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= +cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA= +cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= +cloud.google.com/go/maps v0.6.0/go.mod h1:o6DAMMfb+aINHz/p/jbcY+mYeXBoZoxTfdSQ8VAJaCw= +cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY= +cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= +cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= +cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I= +cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= +cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= +cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA= +cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY= +cloud.google.com/go/memcache v1.9.0/go.mod h1:8oEyzXCu+zo9RzlEaEjHl4KkgjlNDaXbCQeQWlzNFJM= +cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= +cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= +cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8= +cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI= +cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJPWOodSaf45Eo= +cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk= +cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= +cloud.google.com/go/monitoring v1.12.0/go.mod h1:yx8Jj2fZNEkL/GYZyTLS4ZtZEZN8WtDEiEqG4kLK50w= +cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw= +cloud.google.com/go/monitoring v1.21.2 h1:FChwVtClH19E7pJ+e0xUhJPGksctZNVOk2UhMmblmdU= +cloud.google.com/go/monitoring v1.21.2/go.mod h1:hS3pXvaG8KgWTSz+dAdyzPrGUYmi2Q+WFX8g2hqVEZU= +cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= +cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= +cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= +cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8= +cloud.google.com/go/networkconnectivity v1.10.0/go.mod h1:UP4O4sWXJG13AqrTdQCD9TnLGEbtNRqjuaaA7bNjF5E= +cloud.google.com/go/networkconnectivity v1.11.0/go.mod h1:iWmDD4QF16VCDLXUqvyspJjIEtBR/4zq5hwnY2X3scM= +cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8= +cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4= +cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY= +cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= +cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= +cloud.google.com/go/networksecurity v0.7.0/go.mod h1:mAnzoxx/8TBSyXEeESMy9OOYwo1v+gZ5eMRnsT5bC8k= +cloud.google.com/go/networksecurity v0.8.0/go.mod h1:B78DkqsxFG5zRSVuwYFRZ9Xz8IcQ5iECsNrPn74hKHU= +cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= +cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= +cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA= +cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0= +cloud.google.com/go/notebooks v1.7.0/go.mod h1:PVlaDGfJgj1fl1S3dUwhFMXFgfYGhYQt2164xOMONmE= +cloud.google.com/go/notebooks v1.8.0/go.mod h1:Lq6dYKOYOWUCTvw5t2q1gp1lAp0zxAxRycayS0iJcqQ= +cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4= +cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs= +cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI= +cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA= +cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk= +cloud.google.com/go/orchestration v1.6.0/go.mod h1:M62Bevp7pkxStDfFfTuCOaXgaaqRAga1yKyoMtEoWPQ= +cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE= +cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc= +cloud.google.com/go/orgpolicy v1.10.0/go.mod h1:w1fo8b7rRqlXlIJbVhOMPrwVljyuW5mqssvBtU18ONc= +cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= +cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= +cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo= +cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw= +cloud.google.com/go/osconfig v1.11.0/go.mod h1:aDICxrur2ogRd9zY5ytBLV89KEgT2MKB2L/n6x1ooPw= +cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= +cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= +cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70= +cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo= +cloud.google.com/go/oslogin v1.9.0/go.mod h1:HNavntnH8nzrn8JCTT5fj18FuJLFJc4NaZJtBnQtKFs= +cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= +cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= +cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2omRLSLYSu9bU0EKCNI+Lk= +cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg= +cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE= +cloud.google.com/go/policytroubleshooter v1.5.0/go.mod h1:Rz1WfV+1oIpPdN2VvvuboLVRsB1Hclg3CKQ53j9l8vw= +cloud.google.com/go/policytroubleshooter v1.6.0/go.mod h1:zYqaPTsmfvpjm5ULxAyD/lINQxJ0DDsnWOP/GZ7xzBc= +cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= +cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= +cloud.google.com/go/privatecatalog v0.7.0/go.mod h1:2s5ssIFO69F5csTXcwBP7NPFTZvps26xGzvQ2PQaBYg= +cloud.google.com/go/privatecatalog v0.8.0/go.mod h1:nQ6pfaegeDAq/Q5lrfCQzQLhubPiZhSaNhIgfJlnIXs= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI= +cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0= +cloud.google.com/go/pubsub v1.28.0/go.mod h1:vuXFpwaVoIPQMGXqRyUQigu/AX1S3IWugR9xznmcXX8= +cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4= +cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg= +cloud.google.com/go/pubsublite v1.6.0/go.mod h1:1eFCS0U11xlOuMFV/0iBqw3zP12kddMeCbj/F3FSj9k= +cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM= +cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= +cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= +cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= +cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= +cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE= +cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U= +cloud.google.com/go/recaptchaenterprise/v2 v2.6.0/go.mod h1:RPauz9jeLtB3JVzg6nCbe12qNoaa8pXc4d/YukAmcnA= +cloud.google.com/go/recaptchaenterprise/v2 v2.7.0/go.mod h1:19wVj/fs5RtYtynAPJdDTb69oW0vNHYDBTbB4NvMD9c= +cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= +cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= +cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac= +cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= +cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= +cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs= +cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70= +cloud.google.com/go/recommender v1.9.0/go.mod h1:PnSsnZY7q+VL1uax2JWkt/UegHssxjUVVCrX52CuEmQ= +cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= +cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= +cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA= +cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM= +cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0fWAJ7uQ= +cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA= +cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0= +cloud.google.com/go/resourcemanager v1.5.0/go.mod h1:eQoXNAiAvCf5PXxWxXjhKQoTMaUSNrEfg+6qdf/wots= +cloud.google.com/go/resourcemanager v1.6.0/go.mod h1:YcpXGRs8fDzcUl1Xw8uOVmI8JEadvhRIkoXXUNVYcVo= +cloud.google.com/go/resourcemanager v1.7.0/go.mod h1:HlD3m6+bwhzj9XCouqmeiGuni95NTrExfhoSrkC/3EI= +cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU= +cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg= +cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA= +cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= +cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= +cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc= +cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y= +cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQkVPU5kF14= +cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do= +cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo= +cloud.google.com/go/run v0.8.0/go.mod h1:VniEnuBwqjigv0A7ONfQUaEItaiCRVujlMqerPPiktM= +cloud.google.com/go/run v0.9.0/go.mod h1:Wwu+/vvg8Y+JUApMwEDfVfhetv30hCG4ZwDR/IXl2Qg= +cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= +cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= +cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk= +cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44= +cloud.google.com/go/scheduler v1.8.0/go.mod h1:TCET+Y5Gp1YgHT8py4nlg2Sew8nUHMqcpousDgXJVQc= +cloud.google.com/go/scheduler v1.9.0/go.mod h1:yexg5t+KSmqu+njTIh3b7oYPheFtBWGcbVUYF1GGMIc= +cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= +cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= +cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4= +cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU= +cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= +cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= +cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= +cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q= +cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA= +cloud.google.com/go/security v1.12.0/go.mod h1:rV6EhrpbNHrrxqlvW0BWAIawFWq3X90SduMJdFwtLB8= +cloud.google.com/go/security v1.13.0/go.mod h1:Q1Nvxl1PAgmeW0y3HTt54JYIvUdtcpYKVfIB8AOMZ+0= +cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= +cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= +cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk= +cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk= +cloud.google.com/go/securitycenter v1.18.1/go.mod h1:0/25gAzCM/9OL9vVx4ChPeM/+DlfGQJDwBy/UC8AKK0= +cloud.google.com/go/securitycenter v1.19.0/go.mod h1:LVLmSg8ZkkyaNy4u7HCIshAngSQ8EcIRREP3xBnyfag= +cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU= +cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s= +cloud.google.com/go/servicecontrol v1.10.0/go.mod h1:pQvyvSRh7YzUF2efw7H87V92mxU8FnFDawMClGCNuAA= +cloud.google.com/go/servicecontrol v1.11.0/go.mod h1:kFmTzYzTUIuZs0ycVqRHNaNhgR+UMUpw9n02l/pY+mc= +cloud.google.com/go/servicecontrol v1.11.1/go.mod h1:aSnNNlwEFBY+PWGQ2DoM0JJ/QUXqV5/ZD9DOLB7SnUk= +cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= +cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= +cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4= +cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U= +cloud.google.com/go/servicedirectory v1.8.0/go.mod h1:srXodfhY1GFIPvltunswqXpVxFPpZjf8nkKQT7XcXaY= +cloud.google.com/go/servicedirectory v1.9.0/go.mod h1:29je5JjiygNYlmsGz8k6o+OZ8vd4f//bQLtvzkPPT/s= +cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco= +cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo= +cloud.google.com/go/servicemanagement v1.6.0/go.mod h1:aWns7EeeCOtGEX4OvZUWCCJONRZeFKiptqKf1D0l/Jc= +cloud.google.com/go/servicemanagement v1.8.0/go.mod h1:MSS2TDlIEQD/fzsSGfCdJItQveu9NXnUniTrq/L8LK4= +cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E= +cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU= +cloud.google.com/go/serviceusage v1.5.0/go.mod h1:w8U1JvqUqwJNPEOTQjrMHkw3IaIFLoLsPLvsE3xueec= +cloud.google.com/go/serviceusage v1.6.0/go.mod h1:R5wwQcbOWsyuOfbP9tGdAnCAc6B9DRwPG1xtWMDeuPA= +cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= +cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= +cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A= +cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= +cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= +cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= +cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= +cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= +cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= +cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco= +cloud.google.com/go/speech v1.14.1/go.mod h1:gEosVRPJ9waG7zqqnsHpYTOoAS4KouMRLDFMekpJ0J0= +cloud.google.com/go/speech v1.15.0/go.mod h1:y6oH7GhqCaZANH7+Oe0BhgIogsNInLlz542tg3VqeYI= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= +cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= +cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= +cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= +cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= +cloud.google.com/go/storage v1.49.0 h1:zenOPBOWHCnojRd9aJZAyQXBYqkJkdQS42dxL55CIMw= +cloud.google.com/go/storage v1.49.0/go.mod h1:k1eHhhpLvrPjVGfo0mOUPEJ4Y2+a/Hv5PiwehZI9qGU= +cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= +cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= +cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4= +cloud.google.com/go/storagetransfer v1.8.0/go.mod h1:JpegsHHU1eXg7lMHkvf+KE5XDJ7EQu0GwNJbbVGanEw= +cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= +cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= +cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM= +cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA= +cloud.google.com/go/talent v1.5.0/go.mod h1:G+ODMj9bsasAEJkQSzO2uHQWXHHXUomArjWQQYkqK6c= +cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8= +cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4= +cloud.google.com/go/texttospeech v1.6.0/go.mod h1:YmwmFT8pj1aBblQOI3TfKmwibnsfvhIBzPXcW4EBovc= +cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ= +cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg= +cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV61fPM= +cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28= +cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= +cloud.google.com/go/trace v1.8.0/go.mod h1:zH7vcsbAhklH8hWFig58HvxcxyQbaIqMarMg9hn5ECA= +cloud.google.com/go/trace v1.9.0/go.mod h1:lOQqpE5IaWY0Ixg7/r2SjixMuc6lfTFeO4QGM4dQWOk= +cloud.google.com/go/trace v1.11.2 h1:4ZmaBdL8Ng/ajrgKqY5jfvzqMXbrDcBsUGXOT9aqTtI= +cloud.google.com/go/trace v1.11.2/go.mod h1:bn7OwXd4pd5rFuAnTrzBuoZ4ax2XQeG3qNgYmfCy0Io= +cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs= +cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg= +cloud.google.com/go/translate v1.5.0/go.mod h1:29YDSYveqqpA1CQFD7NQuP49xymq17RXNaUDdc0mNu0= +cloud.google.com/go/translate v1.6.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= +cloud.google.com/go/translate v1.7.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= +cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk= +cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw= +cloud.google.com/go/video v1.12.0/go.mod h1:MLQew95eTuaNDEGriQdcYn0dTwf9oWiA4uYebxM5kdg= +cloud.google.com/go/video v1.13.0/go.mod h1:ulzkYlYgCp15N2AokzKjy7MQ9ejuynOJdf1tR5lGthk= +cloud.google.com/go/video v1.14.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= +cloud.google.com/go/video v1.15.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= +cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= +cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= +cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M= +cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU= +cloud.google.com/go/videointelligence v1.10.0/go.mod h1:LHZngX1liVtUhZvi2uNS0VQuOzNi2TkY1OakiuoUOjU= +cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= +cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= +cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= +cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY= +cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= +cloud.google.com/go/vision/v2 v2.6.0/go.mod h1:158Hes0MvOS9Z/bDMSFpjwsUrZ5fPrdwuyyvKSGAGMY= +cloud.google.com/go/vision/v2 v2.7.0/go.mod h1:H89VysHy21avemp6xcf9b9JvZHVehWbET0uT/bcuY/0= +cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= +cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= +cloud.google.com/go/vmmigration v1.5.0/go.mod h1:E4YQ8q7/4W9gobHjQg4JJSgXXSgY21nA5r8swQV+Xxc= +cloud.google.com/go/vmmigration v1.6.0/go.mod h1:bopQ/g4z+8qXzichC7GW1w2MjbErL54rk3/C843CjfY= +cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208= +cloud.google.com/go/vmwareengine v0.2.2/go.mod h1:sKdctNJxb3KLZkE/6Oui94iw/xs9PRNC2wnNLXsHvH8= +cloud.google.com/go/vmwareengine v0.3.0/go.mod h1:wvoyMvNWdIzxMYSpH/R7y2h5h3WFkx6d+1TIsP39WGY= +cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= +cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= +cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes= +cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= +cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= +cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc= +cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A= +cloud.google.com/go/webrisk v1.8.0/go.mod h1:oJPDuamzHXgUc+b8SiHRcVInZQuybnvEW72PqTc7sSg= +cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo= +cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ= +cloud.google.com/go/websecurityscanner v1.5.0/go.mod h1:Y6xdCPy81yi0SQnDY1xdNTNpfY1oAgXUlcfN3B3eSng= +cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= +cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= +cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= +cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= +cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw= +cosmossdk.io/api v0.9.2 h1:9i9ptOBdmoIEVEVWLtYYHjxZonlF/aOVODLFaxpmNtg= +cosmossdk.io/api v0.9.2/go.mod h1:CWt31nVohvoPMTlPv+mMNCtC0a7BqRdESjCsstHcTkU= +cosmossdk.io/client/v2 v2.0.0-beta.7 h1:O0PfZL5kC3Sp54wZASLNihQ612Gd6duMp11aM9wawNg= +cosmossdk.io/client/v2 v2.0.0-beta.7/go.mod h1:TzwwrzeK+AfSVSESVEIOYO/9xuCh1fPv0HgeocmfVnM= +cosmossdk.io/collections v1.2.0 h1:IesfVG8G/+FYCMVMP01frS/Cw99Omk5vBh3cHbO01Gg= +cosmossdk.io/collections v1.2.0/go.mod h1:4NkMoYw6qRA8fnSH/yn1D/MOutr8qyQnwsO50Mz9ItU= +cosmossdk.io/core v0.11.3 h1:mei+MVDJOwIjIniaKelE3jPDqShCc/F4LkNNHh+4yfo= +cosmossdk.io/core v0.11.3/go.mod h1:9rL4RE1uDt5AJ4Tg55sYyHWXA16VmpHgbe0PbJc6N2Y= +cosmossdk.io/depinject v1.2.0 h1:6NW/FSK1IkWTrX7XxUpBmX1QMBozpEI9SsWkKTBc5zw= +cosmossdk.io/depinject v1.2.0/go.mod h1:pvitjtUxZZZTQESKNS9KhGjWVslJZxtO9VooRJYyPjk= +cosmossdk.io/errors v1.0.2 h1:wcYiJz08HThbWxd/L4jObeLaLySopyyuUFB5w4AGpCo= +cosmossdk.io/errors v1.0.2/go.mod h1:0rjgiHkftRYPj//3DrD6y8hcm40HcPv/dR4R/4efr0k= +cosmossdk.io/log v1.5.1 h1:wLwiYXmfrort/O+j6EkjF+HvbdrRQd+4cYCPKFSm+zM= +cosmossdk.io/log v1.5.1/go.mod h1:5cXXBvfBkR2/BcXmosdCSLXllvgSjphrrDVdfVRmBGM= +cosmossdk.io/math v1.5.3 h1:WH6tu6Z3AUCeHbeOSHg2mt9rnoiUWVWaQ2t6Gkll96U= +cosmossdk.io/math v1.5.3/go.mod h1:uqcZv7vexnhMFJF+6zh9EWdm/+Ylyln34IvPnBauPCQ= +cosmossdk.io/schema v1.1.0 h1:mmpuz3dzouCoyjjcMcA/xHBEmMChN+EHh8EHxHRHhzE= +cosmossdk.io/schema v1.1.0/go.mod h1:Gb7pqO+tpR+jLW5qDcNOSv0KtppYs7881kfzakguhhI= +cosmossdk.io/store v1.1.2 h1:3HOZG8+CuThREKv6cn3WSohAc6yccxO3hLzwK6rBC7o= +cosmossdk.io/store v1.1.2/go.mod h1:60rAGzTHevGm592kFhiUVkNC9w7gooSEn5iUBPzHQ6A= +cosmossdk.io/x/evidence v0.1.1 h1:Ks+BLTa3uftFpElLTDp9L76t2b58htjVbSZ86aoK/E4= +cosmossdk.io/x/evidence v0.1.1/go.mod h1:OoDsWlbtuyqS70LY51aX8FBTvguQqvFrt78qL7UzeNc= +cosmossdk.io/x/feegrant v0.1.1 h1:EKFWOeo/pup0yF0svDisWWKAA9Zags6Zd0P3nRvVvw8= +cosmossdk.io/x/feegrant v0.1.1/go.mod h1:2GjVVxX6G2fta8LWj7pC/ytHjryA6MHAJroBWHFNiEQ= +cosmossdk.io/x/tx v0.14.0 h1:hB3O25kIcyDW/7kMTLMaO8Ripj3yqs5imceVd6c/heA= +cosmossdk.io/x/tx v0.14.0/go.mod h1:Tn30rSRA1PRfdGB3Yz55W4Sn6EIutr9xtMKSHij+9PM= +cosmossdk.io/x/upgrade v0.2.0 h1:ZHy0xny3wBCSLomyhE06+UmQHWO8cYlVYjfFAJxjz5g= +cosmossdk.io/x/upgrade v0.2.0/go.mod h1:DXDtkvi//TrFyHWSOaeCZGBoiGAE6Rs8/0ABt2pcDD0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= +git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= +github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= +github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/datadog-go v4.8.3+incompatible h1:fNGaYSuObuQb5nzeTQqowRAd9bpDIRRV4/gUtIBjh8Q= +github.com/DataDog/datadog-go v4.8.3+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/zstd v1.5.7 h1:ybO8RBeh29qrxIhCA9E8gKY6xfONU9T6G6aP9DTKfLE= +github.com/DataDog/zstd v1.5.7/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.26.0 h1:f2Qw/Ehhimh5uO1fayV0QIW7DShEQqhtUfhYc+cBPlw= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.26.0/go.mod h1:2bIszWvQRlJVmJLiuLhukLImRjKPcYdzzsx6darK02A= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 h1:UQ0AhxogsIRZDkElkblfnwjc3IaltCm2HUMvezQaL7s= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1/go.mod h1:jyqM3eLpJ3IbIFDTKVz2rF9T/xWGW0rIriGwnz8l9Tk= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.48.1 h1:oTX4vsorBZo/Zdum6OKPA4o7544hm6smoRv1QjpTwGo= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.48.1/go.mod h1:0wEl7vrAD8mehJyohS9HZy+WyEOaQO2mJx86Cvh93kM= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 h1:8nn+rsCvTq9axyEh382S0PFLBeaFwNsT43IrPWzctRU= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1/go.mod h1:viRWSEhtMZqz1rhwmOVKkWl6SwmVowfL9O2YR5gI2PE= +github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= +github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= +github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= +github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/adlio/schema v1.3.6 h1:k1/zc2jNfeiZBA5aFTRy37jlBIuCkXCm0XmvpzCKI9I= +github.com/adlio/schema v1.3.6/go.mod h1:qkxwLgPBd1FgLRHYVCmQT/rrBr3JH38J9LjmVzWNudg= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= +github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= +github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= +github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= +github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= +github.com/aws/aws-sdk-go v1.44.224 h1:09CiaaF35nRmxrzWZ2uRq5v6Ghg/d2RiPjZnSgtt+RQ= +github.com/aws/aws-sdk-go v1.44.224/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= +github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bgentry/speakeasy v0.2.0 h1:tgObeVOf8WAvtuAX6DhJ4xks4CFNwPDZiqzGqIHE51E= +github.com/bgentry/speakeasy v0.2.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bits-and-blooms/bitset v1.22.0 h1:Tquv9S8+SGaS3EhyA+up3FXzmkhxPGjQQCkcs2uw7w4= +github.com/bits-and-blooms/bitset v1.22.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= +github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= +github.com/btcsuite/btcd v0.24.2 h1:aLmxPguqxza+4ag8R1I2nnJjSu2iFn/kqtHTIImswcY= +github.com/btcsuite/btcd v0.24.2/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg= +github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= +github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= +github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c= +github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/FBatYVw= +github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c= +github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= +github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= +github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ= +github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4= +github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY= +github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= +github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= +github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= +github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= +github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= +github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= +github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= +github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4= +github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= +github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42 h1:Om6kYQYDUk5wWbT0t0q6pvyM49i9XZAv9dDrkDA7gjk= +github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E= +github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= +github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= +github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= +github.com/cockroachdb/redact v1.1.6 h1:zXJBwDZ84xJNlHl1rMyCojqyIxv+7YUpQiJLQ7n4314= +github.com/cockroachdb/redact v1.1.6/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/cometbft/cometbft v0.38.17 h1:FkrQNbAjiFqXydeAO81FUzriL4Bz0abYxN/eOHrQGOk= +github.com/cometbft/cometbft v0.38.17/go.mod h1:5l0SkgeLRXi6bBfQuevXjKqML1jjfJJlvI1Ulp02/o4= +github.com/cometbft/cometbft-db v0.14.1 h1:SxoamPghqICBAIcGpleHbmoPqy+crij/++eZz3DlerQ= +github.com/cometbft/cometbft-db v0.14.1/go.mod h1:KHP1YghilyGV/xjD5DP3+2hyigWx0WTp9X+0Gnx0RxQ= +github.com/consensys/bavard v0.1.27 h1:j6hKUrGAy/H+gpNrpLU3I26n1yc+VMGmd6ID5+gAhOs= +github.com/consensys/bavard v0.1.27/go.mod h1:k/zVjHHC4B+PQy1Pg7fgvG3ALicQw540Crag8qx+dZs= +github.com/consensys/gnark-crypto v0.16.0 h1:8Dl4eYmUWK9WmlP1Bj6je688gBRJCJbT8Mw4KoTAawo= +github.com/consensys/gnark-crypto v0.16.0/go.mod h1:Ke3j06ndtPTVvo++PhGNgvm+lgpLvzbcE2MqljY7diU= +github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= +github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= +github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= +github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= +github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= +github.com/cosmos/cosmos-sdk v0.53.0 h1:ZsB2tnBVudumV059oPuElcr0K1lLOutaI6WJ+osNTbI= +github.com/cosmos/cosmos-sdk v0.53.0/go.mod h1:UPcRyFwOUy2PfSFBWxBceO/HTjZOuBVqY583WyazIGs= +github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= +github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= +github.com/cosmos/go-ethereum v1.15.11-cosmos-0 h1:a8C6CAL2ta06CYpI08a3jM1OdjRquYe4ur6JMjL35lQ= +github.com/cosmos/go-ethereum v1.15.11-cosmos-0/go.mod h1:mf8YiHIb0GR4x4TipcvBUPxJLw1mFdmxzoDi11sDRoI= +github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE= +github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ4GUkT+tbFI= +github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= +github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fro= +github.com/cosmos/gogoproto v1.7.0/go.mod h1:yWChEv5IUEYURQasfyBW5ffkMHR/90hiHgbNgrtp4j0= +github.com/cosmos/iavl v1.2.2 h1:qHhKW3I70w+04g5KdsdVSHRbFLgt3yY3qTMd4Xa4rC8= +github.com/cosmos/iavl v1.2.2/go.mod h1:GiM43q0pB+uG53mLxLDzimxM9l/5N9UuSY3/D0huuVw= +github.com/cosmos/ibc-go/modules/capability v1.0.1 h1:ibwhrpJ3SftEEZRxCRkH0fQZ9svjthrX2+oXdZvzgGI= +github.com/cosmos/ibc-go/modules/capability v1.0.1/go.mod h1:rquyOV262nGJplkumH+/LeYs04P3eV8oB7ZM4Ygqk4E= +github.com/cosmos/ibc-go/v10 v10.2.0 h1:wlk/zqz2O0WRyE6UConoR1ci2HSW02P9ywamZCh5/N4= +github.com/cosmos/ibc-go/v10 v10.2.0/go.mod h1:ijeyJ1FDvXoc5w+rlhpMntjhZ558EF02SBFjroW1hPo= +github.com/cosmos/ics23/go v0.11.0 h1:jk5skjT0TqX5e5QJbEnwXIS2yI2vnmLOgpQPeM5RtnU= +github.com/cosmos/ics23/go v0.11.0/go.mod h1:A8OjxPE67hHST4Icw94hOxxFEJMBG031xIGF/JHNIY0= +github.com/cosmos/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo= +github.com/cosmos/keyring v1.2.0/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= +github.com/cosmos/ledger-cosmos-go v0.14.0 h1:WfCHricT3rPbkPSVKRH+L4fQGKYHuGOK9Edpel8TYpE= +github.com/cosmos/ledger-cosmos-go v0.14.0/go.mod h1:E07xCWSBl3mTGofZ2QnL4cIUzMbbGVyik84QYKbX3RA= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/crate-crypto/go-eth-kzg v1.3.0 h1:05GrhASN9kDAidaFJOda6A4BEvgvuXbazXg/0E3OOdI= +github.com/crate-crypto/go-eth-kzg v1.3.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI= +github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg= +github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM= +github.com/crate-crypto/go-kzg-4844 v1.1.0 h1:EN/u9k2TF6OWSHrCCDBBU6GLNMq88OspHHlMnHfoyU4= +github.com/crate-crypto/go-kzg-4844 v1.1.0/go.mod h1:JolLjpSff1tCCJKaJx4psrlEdlXuJEC996PL3tTAFks= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/danieljoos/wincred v1.2.1 h1:dl9cBrupW8+r5250DYkYxocLeZ1Y4vB1kxgtjxw8GQs= +github.com/danieljoos/wincred v1.2.1/go.mod h1:uGaFL9fDn3OLTvzCGulzE+SzjEe5NGlh5FdCcyfPwps= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= +github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8= +github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= +github.com/desertbit/timer v1.0.1 h1:yRpYNn5Vaaj6QXecdLMPMJsW81JLiI1eokUft5nBmeo= +github.com/desertbit/timer v1.0.1/go.mod h1:htRrYeY5V/t4iu1xCJ5XsQvp4xve8QulXXctAzxqcwE= +github.com/dgraph-io/badger/v4 v4.2.0 h1:kJrlajbXXL9DFTNuhhu9yCx7JJa4qpYWxtE8BzuWsEs= +github.com/dgraph-io/badger/v4 v4.2.0/go.mod h1:qfCqhPoWDFJRx1gp5QwwyGo8xk1lbHUxvK9nK0OGAak= +github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= +github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= +github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= +github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 h1:qwcF+vdFrvPSEUDSX5RVoRccG8a5DhOdWdQ4zN62zzo= +github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= +github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= +github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/dvsekhvalnov/jose2go v1.7.0 h1:bnQc8+GMnidJZA8zc6lLEAb4xNrIqHwO+9TzqvtQZPo= +github.com/dvsekhvalnov/jose2go v1.7.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/emicklei/dot v1.6.2 h1:08GN+DD79cy/tzN6uLCT84+2Wk9u+wvqP+Hkx/dIR8A= +github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= +github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= +github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= +github.com/envoyproxy/go-control-plane v0.13.4 h1:zEqyPVyku6IvWCFwux4x9RxkLOMUL+1vC9xUFv5l2/M= +github.com/envoyproxy/go-control-plane v0.13.4/go.mod h1:kDfuBlDVsSj2MjrLEtRWtHlsWIFcGyB2RMO44Dc5GZA= +github.com/envoyproxy/go-control-plane/envoy v1.32.4 h1:jb83lalDRZSpPWW2Z7Mck/8kXZ5CQAFYVjQcdVIr83A= +github.com/envoyproxy/go-control-plane/envoy v1.32.4/go.mod h1:Gzjc5k8JcJswLjAx1Zm+wSYE20UrLtt7JZMWiWQXQEw= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= +github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= +github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= +github.com/envoyproxy/protoc-gen-validate v1.2.1 h1:DEo3O99U8j4hBFwbJfrz9VtgcDfUKS7KJ7spH3d86P8= +github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU= +github.com/ethereum/c-kzg-4844/v2 v2.1.0 h1:gQropX9YFBhl3g4HYhwE70zq3IHFRgbbNPw0Shwzf5w= +github.com/ethereum/c-kzg-4844/v2 v2.1.0/go.mod h1:TC48kOKjJKPbN7C++qIgt0TJzZ70QznYR7Ob+WXl57E= +github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8= +github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= +github.com/getsentry/sentry-go v0.28.1 h1:zzaSm/vHmGllRM6Tpx1492r0YDzauArdBfkJRtY6P5k= +github.com/getsentry/sentry-go v0.28.1/go.mod h1:1fQZ+7l7eeJ3wYi82q5Hg8GqAPgefRq+FP/QhafYVgg= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= +github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= +github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/liberation v0.2.0/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE= +github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +github.com/go-kit/kit v0.13.0 h1:OoneCcHKHQ03LfBpoQCUfCluwd2Vt3ohz+kvbJneZAU= +github.com/go-kit/kit v0.13.0/go.mod h1:phqEHMMUbyrCFCTgH48JueqrM3md2HcAZ8N3XE4FKDg= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= +github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= +github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= +github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= +github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= +github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= +github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/googleapis v1.4.1-0.20201022092350-68b0159b7869/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= +github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= +github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= +github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= +github.com/golang/glog v1.2.4 h1:CNNw5U8lSiiBk7druxtSHHTsRWcxKoac6kZKm2peBBc= +github.com/golang/glog v1.2.4/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/flatbuffers v24.3.25+incompatible h1:CX395cjN9Kke9mmalRoL3d81AtFUxJM+yDthflgJGkI= +github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= +github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= +github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= +github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= +github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg= +github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= +github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= +github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= +github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= +github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= +github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= +github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= +github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= +github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= +github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= +github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q= +github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= +github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= +github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-getter v1.7.8 h1:mshVHx1Fto0/MydBekWan5zUipGq7jO0novchgMmSiY= +github.com/hashicorp/go-getter v1.7.8/go.mod h1:2c6CboOEb9jG6YvmC9xdD+tyAFsrUaJPedwXDGr0TM4= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-metrics v0.5.4 h1:8mmPiIJkTPPEbAiV97IxdAGNdRdaWwVap1BU6elejKY= +github.com/hashicorp/go-metrics v0.5.4/go.mod h1:CG5yz4NZ/AI/aQt9Ucm/vdBnbh7fvmv4lxZ350i+QQI= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-plugin v1.6.3 h1:xgHB+ZUSYeuJi96WtxEjzi23uh7YQpznjGh0U0UUrwg= +github.com/hashicorp/go-plugin v1.6.3/go.mod h1:MRobyh+Wc/nYy1V4KAXUiYfzxoYhs7V1mlH1Z7iY2h0= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= +github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= +github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= +github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= +github.com/hdevalence/ed25519consensus v0.2.0 h1:37ICyZqdyj0lAZ8P4D1d1id3HqbbG1N3iBb1Tb4rdcU= +github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= +github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= +github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= +github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA= +github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= +github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= +github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= +github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= +github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94= +github.com/jhump/protoreflect v1.17.0/go.mod h1:h9+vUUL38jiBzck8ck+6G/aeMX8Z4QUY/NiJPwPNi+8= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= +github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= +github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= +github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= +github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= +github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/linxGnu/grocksdb v1.9.8 h1:vOIKv9/+HKiqJAElJIEYv3ZLcihRxyP7Suu/Mu8Dxjs= +github.com/linxGnu/grocksdb v1.9.8/go.mod h1:C3CNe9UYc9hlEM2pC82AqiGS3LRW537u9LFV4wIZuHk= +github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= +github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= +github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= +github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= +github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= +github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= +github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q= +github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= +github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= +github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/grpc-proxy v0.0.0-20181017164139-0f1106ef9c76/go.mod h1:x5OoJHDHqxHS801UIuhqGl6QdSAEJvtausosHSdazIo= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= +github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= +github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a h1:dlRvE5fWabOchtH7znfiFCcOvmIYgOeAS5ifBXBlh9Q= +github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= +github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU= +github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= +github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= +github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= +github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss= +github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= +github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= +github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8= +github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= +github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= +github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= +github.com/pion/stun/v2 v2.0.0 h1:A5+wXKLAypxQri59+tmQKVs7+l6mMM+3d+eER9ifRU0= +github.com/pion/stun/v2 v2.0.0/go.mod h1:22qRSh08fSEttYUmJZGlriq9+03jtVmXNODgLccj8GQ= +github.com/pion/transport/v2 v2.2.1 h1:7qYnCBlpgSJNYMbLCKuSY9KbQdBFoETvPNETv0y4N7c= +github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= +github.com/pion/transport/v3 v3.0.1 h1:gDTlPJwROfSfz6QfSi0ZmeCSkFcnWWiiR9ES0ouANiM= +github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= +github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= +github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= +github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= +github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= +github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= +github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU= +github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= +github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= +github.com/spf13/cast v1.8.0 h1:gEN9K4b8Xws4EX0+a0reLmhq8moKn7ntRlQYgjPeCDk= +github.com/spf13/cast v1.8.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= +github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= +github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= +github.com/spiffe/go-spiffe/v2 v2.5.0 h1:N2I01KCUkv1FAjZXJMwh95KK1ZIQLYbPfhaxw8WS0hE= +github.com/spiffe/go-spiffe/v2 v2.5.0/go.mod h1:P+NxobPc6wXhVtINNtFjNWGBTreew1GBUCwT2wPmb7g= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/supranational/blst v0.3.14 h1:xNMoHRJOTwMn63ip6qoWJ2Ymgvj7E2b9jY2FAwY+qRo= +github.com/supranational/blst v0.3.14/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= +github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= +github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= +github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= +github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= +github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= +github.com/zeebo/errs v1.4.0 h1:XNdoD/RRMKP7HD0UhJnIzUy74ISdGGxURlYG8HSWSfM= +github.com/zeebo/errs v1.4.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4= +github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= +github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= +github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= +github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.4.0-alpha.1 h1:3yrqQzbRRPFPdOMWS/QQIVxVnzSkAZQYeWlZFv1kbj4= +go.etcd.io/bbolt v1.4.0-alpha.1/go.mod h1:S/Z/Nm3iuOnyO1W4XuFfPci51Gj6F1Hv0z8hisyYYOw= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/contrib/detectors/gcp v1.34.0 h1:JRxssobiPg23otYU5SbWtQC//snGVIM3Tx6QRzlQBao= +go.opentelemetry.io/contrib/detectors/gcp v1.34.0/go.mod h1:cV4BMFcscUR/ckqLkbfQmF0PRsq8w/lMGzdbCSveBHo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 h1:PS8wXpbyaDJQ2VDHHncMe9Vct0Zn1fEjpsjrLxGJoSc= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0/go.mod h1:HDBUsEjOuRC0EzKZ1bSaRGZWUBAzo+MhAcUUORSr4D0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q= +go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= +go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0 h1:WDdP9acbMYjbKIyJUhTvtzj601sVJOqgWdUxSdR/Ysc= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0/go.mod h1:BLbf7zbNIONBLPwvFnwNHGj4zge8uTCM/UPIVW1Mq2I= +go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= +go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= +go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= +go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= +go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= +go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= +go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= +go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= +go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko= +go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.15.0 h1:QtOrQd0bTUnhNVNndMpLHNWrDmYzZ2KDqSrEymqInZw= +golang.org/x/arch v0.15.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= +golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= +golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= +golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw= +golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= +golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= +golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= +golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= +golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= +golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= +golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= +golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= +golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= +golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= +golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4= +golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU= +golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= +gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= +gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= +gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= +gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= +google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= +google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= +google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= +google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= +google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= +google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= +google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= +google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g= +google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= +google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= +google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI= +google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08= +google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= +google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= +google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= +google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= +google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= +google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= +google.golang.org/api v0.222.0 h1:Aiewy7BKLCuq6cUCeOUrsAlzjXPqBkEeQ/iwGHVQa/4= +google.golang.org/api v0.222.0/go.mod h1:efZia3nXpWELrwMlN5vyQrD4GmJN1Vw0x68Et3r+a9c= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE= +google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= +google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw= +google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= +google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= +google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= +google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= +google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= +google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= +google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= +google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo= +google.golang.org/genproto v0.0.0-20221109142239-94d6d90a7d66/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221117204609-8f9c96812029/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221201204527-e3fa12d562f3/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= +google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230112194545-e10362b5ecf9/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230123190316-2c411cf9d197/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230125152338-dcaf20b6aeaa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230127162408-596548ed4efa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA= +google.golang.org/genproto v0.0.0-20230222225845-10f96fb3dbec/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= +google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= +google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= +google.golang.org/genproto v0.0.0-20230320184635-7606e756e683/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= +google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= +google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk= +google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc= +google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e h1:UdXH7Kzbj+Vzastr5nVfccbmFsmYNygVLSPk1pEfDoY= +google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e/go.mod h1:085qFyf2+XaZlRdCgKNCIZ3afY2p4HHZdoIRpId8F4A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250422160041-2d3770c4ea7f h1:N/PrbTw4kdkqNRzVfWPrBekzLuarFREcbFOiOLkXon4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250422160041-2d3770c4ea7f/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= +google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= +google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= +google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= +google.golang.org/grpc v1.72.0 h1:S7UkcVa60b5AAQTaO6ZKamFp1zMZSU0fGDK2WZLbBnM= +google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= +gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= +lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= +modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= +modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= +modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= +modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws= +modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo= +modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= +modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= +modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= +modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= +modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU= +modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= +modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= +modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0= +modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s= +modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= +modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= +modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4= +modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= +modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= +modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= +modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= +nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= +nhooyr.io/websocket v1.8.11 h1:f/qXNc2/3DpoSZkHt1DQu6rj4zGC8JmkkLkWss0MgN0= +nhooyr.io/websocket v1.8.11/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= +nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= +pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk= +pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/evmd/precompiles.go b/evmd/precompiles.go index 49fcdab1a..01aa23418 100644 --- a/evmd/precompiles.go +++ b/evmd/precompiles.go @@ -84,7 +84,7 @@ func NewAvailableStaticPrecompiles( panic(fmt.Errorf("failed to instantiate ICS20 precompile: %w", err)) } - bankPrecompile, err := bankprecompile.NewPrecompile(bankKeeper, erc20Keeper) + bankPrecompile, err := bankprecompile.NewPrecompile(bankKeeper, &erc20Keeper) if err != nil { panic(fmt.Errorf("failed to instantiate bank precompile: %w", err)) } diff --git a/evmd/tests/ante/authz_test.go b/evmd/tests/ante/authz_test.go new file mode 100644 index 000000000..f52ce2584 --- /dev/null +++ b/evmd/tests/ante/authz_test.go @@ -0,0 +1,277 @@ +package ante_test + +import ( + "fmt" + "testing" + "time" + + "cosmosevm.io/evmd/tests/integration" + "github.com/stretchr/testify/require" + + cosmosante "github.com/cosmos/evm/ante/cosmos" + "github.com/cosmos/evm/testutil" + "github.com/cosmos/evm/testutil/integration/evm/network" + evmtypes "github.com/cosmos/evm/x/vm/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/x/authz" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +func TestAuthzLimiterDecorator(t *testing.T) { + nw := network.New(integration.CreateEvmd) + txCfg := nw.GetEncodingConfig().TxConfig + testPrivKeys, testAddresses, err := testutil.GeneratePrivKeyAddressPairs(5) + require.NoError(t, err) + + evmDenom := evmtypes.GetEVMCoinDenom() + distantFuture := time.Date(9000, 1, 1, 0, 0, 0, 0, time.UTC) + + validator := sdk.ValAddress(testAddresses[4]) + stakingAuthDelegate, err := stakingtypes.NewStakeAuthorization([]sdk.ValAddress{validator}, nil, stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, nil) + require.NoError(t, err) + + stakingAuthUndelegate, err := stakingtypes.NewStakeAuthorization([]sdk.ValAddress{validator}, nil, stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_UNDELEGATE, nil) + require.NoError(t, err) + + decorator := cosmosante.NewAuthzLimiterDecorator( + sdk.MsgTypeURL(&evmtypes.MsgEthereumTx{}), + sdk.MsgTypeURL(&stakingtypes.MsgUndelegate{}), + ) + + testCases := []struct { + name string + msgs []sdk.Msg + checkTx bool + expectedErr error + }{ + { + "enabled msg - non blocked msg", + []sdk.Msg{ + banktypes.NewMsgSend( + testAddresses[0], + testAddresses[1], + sdk.NewCoins(sdk.NewInt64Coin(evmDenom, 100e6)), + ), + }, + false, + nil, + }, + { + "enabled msg MsgEthereumTx - blocked msg not wrapped in MsgExec", + []sdk.Msg{ + &evmtypes.MsgEthereumTx{}, + }, + false, + nil, + }, + { + "enabled msg - blocked msg not wrapped in MsgExec", + []sdk.Msg{ + &stakingtypes.MsgCancelUnbondingDelegation{}, + }, + false, + nil, + }, + { + "enabled msg - MsgGrant contains a non blocked msg", + []sdk.Msg{ + testutil.NewMsgGrant( + testAddresses[0], + testAddresses[1], + authz.NewGenericAuthorization(sdk.MsgTypeURL(&banktypes.MsgSend{})), + &distantFuture, + ), + }, + false, + nil, + }, + { + "enabled msg - MsgGrant contains a non blocked msg", + []sdk.Msg{ + testutil.NewMsgGrant( + testAddresses[0], + testAddresses[1], + stakingAuthDelegate, + &distantFuture, + ), + }, + false, + nil, + }, + { + "disabled msg - MsgGrant contains a blocked msg", + []sdk.Msg{ + testutil.NewMsgGrant( + testAddresses[0], + testAddresses[1], + authz.NewGenericAuthorization(sdk.MsgTypeURL(&evmtypes.MsgEthereumTx{})), + &distantFuture, + ), + }, + false, + sdkerrors.ErrUnauthorized, + }, + { + "disabled msg - MsgGrant contains a blocked msg", + []sdk.Msg{ + testutil.NewMsgGrant( + testAddresses[0], + testAddresses[1], + stakingAuthUndelegate, + &distantFuture, + ), + }, + false, + sdkerrors.ErrUnauthorized, + }, + { + "allowed msg - when a MsgExec contains a non blocked msg", + []sdk.Msg{ + testutil.NewMsgExec( + testAddresses[1], + []sdk.Msg{banktypes.NewMsgSend( + testAddresses[0], + testAddresses[3], + sdk.NewCoins(sdk.NewInt64Coin(evmDenom, 100e6)), + )}), + }, + false, + nil, + }, + { + "disabled msg - MsgExec contains a blocked msg", + []sdk.Msg{ + testutil.NewMsgExec( + testAddresses[1], + []sdk.Msg{ + &evmtypes.MsgEthereumTx{}, + }, + ), + }, + false, + sdkerrors.ErrUnauthorized, + }, + { + "disabled msg - surrounded by valid msgs", + []sdk.Msg{ + testutil.NewMsgGrant( + testAddresses[0], + testAddresses[1], + stakingAuthDelegate, + &distantFuture, + ), + testutil.NewMsgExec( + testAddresses[1], + []sdk.Msg{ + banktypes.NewMsgSend( + testAddresses[0], + testAddresses[3], + sdk.NewCoins(sdk.NewInt64Coin(evmDenom, 100e6)), + ), + &evmtypes.MsgEthereumTx{}, + }, + ), + }, + false, + sdkerrors.ErrUnauthorized, + }, + { + "disabled msg - nested MsgExec containing a blocked msg", + []sdk.Msg{ + testutil.CreateNestedMsgExec( + testAddresses[1], + 2, + []sdk.Msg{ + &evmtypes.MsgEthereumTx{}, + }, + ), + }, + false, + sdkerrors.ErrUnauthorized, + }, + { + "disabled msg - nested MsgGrant containing a blocked msg", + []sdk.Msg{ + testutil.NewMsgExec( + testAddresses[1], + []sdk.Msg{ + testutil.NewMsgGrant( + testAddresses[0], + testAddresses[1], + authz.NewGenericAuthorization(sdk.MsgTypeURL(&evmtypes.MsgEthereumTx{})), + &distantFuture, + ), + }, + ), + }, + false, + sdkerrors.ErrUnauthorized, + }, + { + "disabled msg - nested MsgExec NOT containing a blocked msg but has more nesting levels than the allowed", + []sdk.Msg{ + testutil.CreateNestedMsgExec( + testAddresses[1], + 6, + []sdk.Msg{ + banktypes.NewMsgSend( + testAddresses[0], + testAddresses[3], + sdk.NewCoins(sdk.NewInt64Coin(evmDenom, 100e6)), + ), + }, + ), + }, + false, + sdkerrors.ErrUnauthorized, + }, + { + "disabled msg - multiple two nested MsgExec messages NOT containing a blocked msg over the limit", + []sdk.Msg{ + testutil.CreateNestedMsgExec( + testAddresses[1], + 5, + []sdk.Msg{ + banktypes.NewMsgSend( + testAddresses[0], + testAddresses[3], + sdk.NewCoins(sdk.NewInt64Coin(evmDenom, 100e6)), + ), + }, + ), + testutil.CreateNestedMsgExec( + testAddresses[1], + 5, + []sdk.Msg{ + banktypes.NewMsgSend( + testAddresses[0], + testAddresses[3], + sdk.NewCoins(sdk.NewInt64Coin(evmDenom, 100e6)), + ), + }, + ), + }, + false, + sdkerrors.ErrUnauthorized, + }, + } + + for _, tc := range testCases { + t.Run(fmt.Sprintf("Case %s", tc.name), func(t *testing.T) { + ctx := sdk.Context{}.WithIsCheckTx(tc.checkTx) + tx, err := testutil.CreateTx(ctx, txCfg, testPrivKeys[0], tc.msgs...) + require.NoError(t, err) + + _, err = decorator.AnteHandle(ctx, tx, false, testutil.NoOpNextFn) + if tc.expectedErr != nil { + require.Error(t, err) + require.ErrorIs(t, err, tc.expectedErr) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/tests/ibc/helper.go b/evmd/tests/ibc/helper.go similarity index 98% rename from tests/ibc/helper.go rename to evmd/tests/ibc/helper.go index 3af6ae4e3..fd56cf5e9 100644 --- a/tests/ibc/helper.go +++ b/evmd/tests/ibc/helper.go @@ -4,11 +4,11 @@ import ( "math/big" "testing" + "cosmosevm.io/evmd" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/cosmos/evm/contracts" - "github.com/cosmos/evm/evmd" evmibctesting "github.com/cosmos/evm/ibc/testing" erc20types "github.com/cosmos/evm/x/erc20/types" ibctesting "github.com/cosmos/ibc-go/v10/testing" diff --git a/tests/ibc/ibc_middleware_test.go b/evmd/tests/ibc/ibc_middleware_test.go similarity index 99% rename from tests/ibc/ibc_middleware_test.go rename to evmd/tests/ibc/ibc_middleware_test.go index 00418a47b..478e29e03 100644 --- a/tests/ibc/ibc_middleware_test.go +++ b/evmd/tests/ibc/ibc_middleware_test.go @@ -5,9 +5,9 @@ import ( "math/big" "testing" + "cosmosevm.io/evmd" testifysuite "github.com/stretchr/testify/suite" - "github.com/cosmos/evm/evmd" "github.com/cosmos/evm/ibc" evmibctesting "github.com/cosmos/evm/ibc/testing" "github.com/cosmos/evm/testutil" diff --git a/tests/ibc/ics20_precompile_transfer_test.go b/evmd/tests/ibc/ics20_precompile_transfer_test.go similarity index 99% rename from tests/ibc/ics20_precompile_transfer_test.go rename to evmd/tests/ibc/ics20_precompile_transfer_test.go index 50316e670..bf3f92d95 100644 --- a/tests/ibc/ics20_precompile_transfer_test.go +++ b/evmd/tests/ibc/ics20_precompile_transfer_test.go @@ -9,10 +9,10 @@ import ( "math/big" "testing" + "cosmosevm.io/evmd" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/suite" - "github.com/cosmos/evm/evmd" evmibctesting "github.com/cosmos/evm/ibc/testing" "github.com/cosmos/evm/precompiles/ics20" evmante "github.com/cosmos/evm/x/vm/ante" diff --git a/tests/ibc/transfer_test.go b/evmd/tests/ibc/transfer_test.go similarity index 99% rename from tests/ibc/transfer_test.go rename to evmd/tests/ibc/transfer_test.go index a678959a0..4f740c9f1 100644 --- a/tests/ibc/transfer_test.go +++ b/evmd/tests/ibc/transfer_test.go @@ -8,9 +8,9 @@ package ibc import ( "testing" + "cosmosevm.io/evmd" "github.com/stretchr/testify/suite" - "github.com/cosmos/evm/evmd" evmibctesting "github.com/cosmos/evm/ibc/testing" "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" diff --git a/tests/ibc/v2_ibc_middleware_test.go b/evmd/tests/ibc/v2_ibc_middleware_test.go similarity index 99% rename from tests/ibc/v2_ibc_middleware_test.go rename to evmd/tests/ibc/v2_ibc_middleware_test.go index 60dd25f7b..d10249ce6 100644 --- a/tests/ibc/v2_ibc_middleware_test.go +++ b/evmd/tests/ibc/v2_ibc_middleware_test.go @@ -7,9 +7,9 @@ import ( "testing" "time" + "cosmosevm.io/evmd" testifysuite "github.com/stretchr/testify/suite" - "github.com/cosmos/evm/evmd" evmibctesting "github.com/cosmos/evm/ibc/testing" "github.com/cosmos/evm/testutil" erc20Keeper "github.com/cosmos/evm/x/erc20/keeper" diff --git a/tests/ibc/v2_ics20_precompile_transfer_test.go b/evmd/tests/ibc/v2_ics20_precompile_transfer_test.go similarity index 99% rename from tests/ibc/v2_ics20_precompile_transfer_test.go rename to evmd/tests/ibc/v2_ics20_precompile_transfer_test.go index 1a96d9b5f..08a23fcda 100644 --- a/tests/ibc/v2_ics20_precompile_transfer_test.go +++ b/evmd/tests/ibc/v2_ics20_precompile_transfer_test.go @@ -10,10 +10,10 @@ import ( "testing" "time" + "cosmosevm.io/evmd" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/suite" - "github.com/cosmos/evm/evmd" evmibctesting "github.com/cosmos/evm/ibc/testing" "github.com/cosmos/evm/precompiles/ics20" evmante "github.com/cosmos/evm/x/vm/ante" diff --git a/tests/ibc/v2_transfer_test.go b/evmd/tests/ibc/v2_transfer_test.go similarity index 99% rename from tests/ibc/v2_transfer_test.go rename to evmd/tests/ibc/v2_transfer_test.go index 02210c5ad..570627580 100644 --- a/tests/ibc/v2_transfer_test.go +++ b/evmd/tests/ibc/v2_transfer_test.go @@ -17,9 +17,9 @@ import ( "testing" "time" + "cosmosevm.io/evmd" testifysuite "github.com/stretchr/testify/suite" - "github.com/cosmos/evm/evmd" evmibctesting "github.com/cosmos/evm/ibc/testing" "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" diff --git a/evmd/tests/integration/ante_test.go b/evmd/tests/integration/ante_test.go new file mode 100644 index 000000000..03294b1f4 --- /dev/null +++ b/evmd/tests/integration/ante_test.go @@ -0,0 +1,11 @@ +package integration + +import ( + "testing" + + "github.com/cosmos/evm/tests/integration/ante" +) + +func TestAnte_Integration(t *testing.T) { + ante.TestIntegrationAnteHandler(t, CreateEvmd) +} diff --git a/evmd/tests/integration/backend_test.go b/evmd/tests/integration/backend_test.go new file mode 100644 index 000000000..303f0e7c6 --- /dev/null +++ b/evmd/tests/integration/backend_test.go @@ -0,0 +1,14 @@ +package integration + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/tests/integration/rpc/backend" +) + +func TestBackend(t *testing.T) { + s := backend.NewBackendTestSuite(CreateEvmd) + suite.Run(t, s) +} diff --git a/evmd/tests/integration/create_app.go b/evmd/tests/integration/create_app.go new file mode 100644 index 000000000..7f6c0d151 --- /dev/null +++ b/evmd/tests/integration/create_app.go @@ -0,0 +1,34 @@ +package integration + +import ( + "cosmosevm.io/evmd" + + dbm "github.com/cosmos/cosmos-db" + "github.com/cosmos/evm" + + "cosmossdk.io/log" + + "github.com/cosmos/cosmos-sdk/baseapp" + simutils "github.com/cosmos/cosmos-sdk/testutil/sims" +) + +// CreateEvmd creates an evmos app +func CreateEvmd(chainID string, evmChainID uint64, customBaseAppOptions ...func(*baseapp.BaseApp)) evm.EvmApp { + // create evmos app + db := dbm.NewMemDB() + logger := log.NewNopLogger() + loadLatest := true + appOptions := simutils.NewAppOptionsWithFlagHome(evmd.DefaultNodeHome) + baseAppOptions := append(customBaseAppOptions, baseapp.SetChainID(chainID)) //nolint:gocritic + + return evmd.NewExampleApp( + logger, + db, + nil, + loadLatest, + appOptions, + evmChainID, + evmd.EvmAppOptions, + baseAppOptions..., + ) +} diff --git a/evmd/tests/integration/eip712_test.go b/evmd/tests/integration/eip712_test.go new file mode 100644 index 000000000..2df778a52 --- /dev/null +++ b/evmd/tests/integration/eip712_test.go @@ -0,0 +1,19 @@ +package integration + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/tests/integration/eip712" +) + +func TestEIP712TestSuite(t *testing.T) { + s := eip712.NewEIP712TestSuite(CreateEvmd, false) + suite.Run(t, s) + + // Note that we don't test the Legacy EIP-712 Extension, since that case + // is sufficiently covered by the AnteHandler tests. + s = eip712.NewEIP712TestSuite(CreateEvmd, true) + suite.Run(t, s) +} diff --git a/evmd/tests/integration/eips_test.go b/evmd/tests/integration/eips_test.go new file mode 100644 index 000000000..fffbefc79 --- /dev/null +++ b/evmd/tests/integration/eips_test.go @@ -0,0 +1,11 @@ +package integration + +import ( + "testing" + + "github.com/cosmos/evm/tests/integration/eips" +) + +func Test_EIPs(t *testing.T) { + eips.TestEIPs(t, CreateEvmd) +} diff --git a/evmd/tests/integration/evm_ante_bench_test.go b/evmd/tests/integration/evm_ante_bench_test.go new file mode 100644 index 000000000..5b4f99e24 --- /dev/null +++ b/evmd/tests/integration/evm_ante_bench_test.go @@ -0,0 +1,15 @@ +package integration + +import ( + "testing" + + "github.com/cosmos/evm/tests/integration/ante" +) + +func BenchmarkEvmAnteTestSuite(b *testing.B) { + ante.RunBenchmarkEthGasConsumeDecorator(b, CreateEvmd) +} + +func BenchmarkEvmAnteHnadler(b *testing.B) { + ante.RunBenchmarkAnteHandler(b, CreateEvmd) +} diff --git a/evmd/tests/integration/evm_ante_test.go b/evmd/tests/integration/evm_ante_test.go new file mode 100644 index 000000000..b9de94dc1 --- /dev/null +++ b/evmd/tests/integration/evm_ante_test.go @@ -0,0 +1,45 @@ +package integration + +import ( + "testing" + + gethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/tests/integration/ante" + testconstants "github.com/cosmos/evm/testutil/constants" +) + +func TestEvmAnteTestSuite(t *testing.T) { + s := ante.NewEvmAnteTestSuite(CreateEvmd) + s.WithLondonHardForkEnabled(true) + + suite.Run(t, s) + + s = ante.NewEvmAnteTestSuite(CreateEvmd) + s.WithLondonHardForkEnabled(true) + // Re-run the tests with EIP-712 Legacy encodings to ensure backwards compatibility. + // LegacyEIP712Extension should not be run with current TypedData encodings, since they are not compatible. + s.UseLegacyEIP712TypedData = true + suite.Run(t, s) +} + +func TestEvmUnitAnteTestSuite(t *testing.T) { + txTypes := []int{gethtypes.DynamicFeeTxType, gethtypes.LegacyTxType, gethtypes.AccessListTxType} + chainIDs := []testconstants.ChainID{testconstants.ExampleChainID, testconstants.SixDecimalsChainID} + + evmTestSuite := ante.NewEvmUnitAnteTestSuite(CreateEvmd) + + for _, txType := range txTypes { + for _, chainID := range chainIDs { + evmTestSuite.EthTxType = txType + evmTestSuite.ChainID = chainID.ChainID + evmTestSuite.EvmChainID = chainID.EVMChainID + suite.Run(t, evmTestSuite) + } + } +} + +func TestValidateHandlerOptionsTest(t *testing.T) { + ante.RunValidateHandlerOptionsTest(t, CreateEvmd) +} diff --git a/evmd/tests/integration/ibc_test.go b/evmd/tests/integration/ibc_test.go new file mode 100644 index 000000000..75048733a --- /dev/null +++ b/evmd/tests/integration/ibc_test.go @@ -0,0 +1,14 @@ +package integration + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/tests/integration/x/ibc" +) + +func TestIBCKeeperTestSuite(t *testing.T) { + s := ibc.NewKeeperTestSuite(CreateEvmd) + suite.Run(t, s) +} diff --git a/evmd/tests/integration/indexer_test.go b/evmd/tests/integration/indexer_test.go new file mode 100644 index 000000000..926d07866 --- /dev/null +++ b/evmd/tests/integration/indexer_test.go @@ -0,0 +1,11 @@ +package integration + +import ( + "testing" + + "github.com/cosmos/evm/tests/integration/indexer" +) + +func TestKVIndexer(t *testing.T) { + indexer.TestKVIndexer(t, CreateEvmd) +} diff --git a/evmd/tests/integration/precompile_bank_test.go b/evmd/tests/integration/precompile_bank_test.go new file mode 100644 index 000000000..1009201c1 --- /dev/null +++ b/evmd/tests/integration/precompile_bank_test.go @@ -0,0 +1,18 @@ +package integration + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/tests/integration/precompiles/bank" +) + +func TestBankPrecompileTestSuite(t *testing.T) { + s := bank.NewPrecompileTestSuite(CreateEvmd) + suite.Run(t, s) +} + +func TestBankPrecompileIntegrationTestSuite(t *testing.T) { + bank.TestIntegrationSuite(t, CreateEvmd) +} diff --git a/evmd/tests/integration/precompile_bech32_test.go b/evmd/tests/integration/precompile_bech32_test.go new file mode 100644 index 000000000..52052b86c --- /dev/null +++ b/evmd/tests/integration/precompile_bech32_test.go @@ -0,0 +1,14 @@ +package integration + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/tests/integration/precompiles/bech32" +) + +func TestBech32PrecompileTestSuite(t *testing.T) { + s := bech32.NewPrecompileTestSuite(CreateEvmd) + suite.Run(t, s) +} diff --git a/evmd/tests/integration/precompile_distribution_test.go b/evmd/tests/integration/precompile_distribution_test.go new file mode 100644 index 000000000..3d0c7d60d --- /dev/null +++ b/evmd/tests/integration/precompile_distribution_test.go @@ -0,0 +1,18 @@ +package integration + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/tests/integration/precompiles/distribution" +) + +func TestDistributionPrecompileTestSuite(t *testing.T) { + s := distribution.NewPrecompileTestSuite(CreateEvmd) + suite.Run(t, s) +} + +func TestDistributionPrecompileIntegrationTestSuite(t *testing.T) { + distribution.TestPrecompileIntegrationTestSuite(t, CreateEvmd) +} diff --git a/evmd/tests/integration/precompile_erc20_test.go b/evmd/tests/integration/precompile_erc20_test.go new file mode 100644 index 000000000..81313367e --- /dev/null +++ b/evmd/tests/integration/precompile_erc20_test.go @@ -0,0 +1,18 @@ +package integration + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + erc21 "github.com/cosmos/evm/tests/integration/precompiles/erc20" +) + +func TestErc20PrecompileTestSuite(t *testing.T) { + s := erc21.NewPrecompileTestSuite(CreateEvmd) + suite.Run(t, s) +} + +func TestErc20IntegrationTestSuite(t *testing.T) { + erc21.TestIntegrationTestSuite(t, CreateEvmd) +} diff --git a/evmd/tests/integration/precompile_evidence_test.go b/evmd/tests/integration/precompile_evidence_test.go new file mode 100644 index 000000000..649d48c76 --- /dev/null +++ b/evmd/tests/integration/precompile_evidence_test.go @@ -0,0 +1,14 @@ +package integration + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/tests/integration/precompiles/evidence" +) + +func TestEvidencePrecompileTestSuite(t *testing.T) { + s := evidence.NewPrecompileTestSuite(CreateEvmd) + suite.Run(t, s) +} diff --git a/evmd/tests/integration/precompile_gov_test.go b/evmd/tests/integration/precompile_gov_test.go new file mode 100644 index 000000000..3b474b89a --- /dev/null +++ b/evmd/tests/integration/precompile_gov_test.go @@ -0,0 +1,18 @@ +package integration + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/tests/integration/precompiles/gov" +) + +func TestGovPrecompileTestSuite(t *testing.T) { + s := gov.NewPrecompileTestSuite(CreateEvmd) + suite.Run(t, s) +} + +func TestGovPrecompileIntegrationTestSuite(t *testing.T) { + gov.TestPrecompileIntegrationTestSuite(t, CreateEvmd) +} diff --git a/evmd/tests/integration/precompile_p256_test.go b/evmd/tests/integration/precompile_p256_test.go new file mode 100644 index 000000000..75600909c --- /dev/null +++ b/evmd/tests/integration/precompile_p256_test.go @@ -0,0 +1,18 @@ +package integration + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/tests/integration/precompiles/p256" +) + +func TestP256PrecompileTestSuite(t *testing.T) { + s := p256.NewPrecompileTestSuite(CreateEvmd) + suite.Run(t, s) +} + +func TestP256PrecompileIntegrationTestSuite(t *testing.T) { + p256.TestPrecompileIntegrationTestSuite(t, CreateEvmd) +} diff --git a/evmd/tests/integration/precompile_slashing_test.go b/evmd/tests/integration/precompile_slashing_test.go new file mode 100644 index 000000000..ad0990a80 --- /dev/null +++ b/evmd/tests/integration/precompile_slashing_test.go @@ -0,0 +1,14 @@ +package integration + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/tests/integration/precompiles/slashing" +) + +func TestSlashingPrecompileTestSuite(t *testing.T) { + s := slashing.NewPrecompileTestSuite(CreateEvmd) + suite.Run(t, s) +} diff --git a/evmd/tests/integration/precompile_staking_test.go b/evmd/tests/integration/precompile_staking_test.go new file mode 100644 index 000000000..0c906bf6c --- /dev/null +++ b/evmd/tests/integration/precompile_staking_test.go @@ -0,0 +1,18 @@ +package integration + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/tests/integration/precompiles/staking" +) + +func TestStakingPrecompileTestSuite(t *testing.T) { + s := staking.NewPrecompileTestSuite(CreateEvmd) + suite.Run(t, s) +} + +func TestStakingPrecompileIntegrationTestSuite(t *testing.T) { + staking.TestPrecompileIntegrationTestSuite(t, CreateEvmd) +} diff --git a/evmd/tests/integration/precompile_werc20_test.go b/evmd/tests/integration/precompile_werc20_test.go new file mode 100644 index 000000000..3a63d5c04 --- /dev/null +++ b/evmd/tests/integration/precompile_werc20_test.go @@ -0,0 +1,18 @@ +package integration + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/tests/integration/precompiles/werc20" +) + +func TestWERC20PrecompileUnitTestSuite(t *testing.T) { + s := werc20.NewPrecompileUnitTestSuite(CreateEvmd) + suite.Run(t, s) +} + +func TestWERC20PrecompileIntegrationTestSuite(t *testing.T) { + werc20.TestPrecompileIntegrationTestSuite(t, CreateEvmd) +} diff --git a/evmd/tests/integration/testutil_test.go b/evmd/tests/integration/testutil_test.go new file mode 100644 index 000000000..a8e33354c --- /dev/null +++ b/evmd/tests/integration/testutil_test.go @@ -0,0 +1,14 @@ +package integration + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/tests/integration/testutil" +) + +func TestTestUtilTestSuite(t *testing.T) { + s := testutil.NewTestSuite(CreateEvmd) + suite.Run(t, s) +} diff --git a/evmd/tests/integration/wallets_test.go b/evmd/tests/integration/wallets_test.go new file mode 100644 index 000000000..c30584d56 --- /dev/null +++ b/evmd/tests/integration/wallets_test.go @@ -0,0 +1,14 @@ +package integration + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/tests/integration/wallets" +) + +func TestLedgerTestSuite(t *testing.T) { + s := wallets.NewLedgerTestSuite(CreateEvmd) + suite.Run(t, s) +} diff --git a/evmd/tests/integration/x_erc20_test.go b/evmd/tests/integration/x_erc20_test.go new file mode 100644 index 000000000..1a1e46b01 --- /dev/null +++ b/evmd/tests/integration/x_erc20_test.go @@ -0,0 +1,22 @@ +package integration + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/tests/integration/x/erc20" +) + +func TestERC20GenesisTestSuite(t *testing.T) { + suite.Run(t, erc20.NewGenesisTestSuite(CreateEvmd)) +} + +func TestERC20KeeperTestSuite(t *testing.T) { + s := erc20.NewKeeperTestSuite(CreateEvmd) + suite.Run(t, s) +} + +func TestERC20PrecompileIntegrationTestSuite(t *testing.T) { + erc20.TestPrecompileIntegrationTestSuite(t, CreateEvmd) +} diff --git a/evmd/tests/integration/x_feemarket_test.go b/evmd/tests/integration/x_feemarket_test.go new file mode 100644 index 000000000..34cbcbd17 --- /dev/null +++ b/evmd/tests/integration/x_feemarket_test.go @@ -0,0 +1,14 @@ +package integration + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/tests/integration/x/feemarket" +) + +func TestFeeMarketKeeperTestSuite(t *testing.T) { + s := feemarket.NewTestKeeperTestSuite(CreateEvmd) + suite.Run(t, s) +} diff --git a/evmd/tests/integration/x_precisebank_test.go b/evmd/tests/integration/x_precisebank_test.go new file mode 100644 index 000000000..950b473f4 --- /dev/null +++ b/evmd/tests/integration/x_precisebank_test.go @@ -0,0 +1,19 @@ +package integration + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/tests/integration/x/precisebank" +) + +func TestPreciseBankGenesis(t *testing.T) { + s := precisebank.NewGenesisTestSuite(CreateEvmd) + suite.Run(t, s) +} + +func TestPreciseBankKeeper(t *testing.T) { + s := precisebank.NewKeeperIntegrationTestSuite(CreateEvmd) + suite.Run(t, s) +} diff --git a/evmd/tests/integration/x_vm_test.go b/evmd/tests/integration/x_vm_test.go new file mode 100644 index 000000000..92ddbe214 --- /dev/null +++ b/evmd/tests/integration/x_vm_test.go @@ -0,0 +1,31 @@ +package integration + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/tests/integration/x/vm" +) + +func TestKeeperTestSuite(t *testing.T) { + s := vm.NewKeeperTestSuite(CreateEvmd) + s.EnableFeemarket = false + s.EnableLondonHF = true + suite.Run(t, s) +} + +func TestNestedEVMExtensionCallSuite(t *testing.T) { + s := vm.NewNestedEVMExtensionCallSuite(CreateEvmd) + suite.Run(t, s) +} + +func TestGenesisTestSuite(t *testing.T) { + s := vm.NewGenesisTestSuite(CreateEvmd) + suite.Run(t, s) +} + +func TestVmAnteTestSuite(t *testing.T) { + s := vm.NewEvmAnteTestSuite(CreateEvmd) + suite.Run(t, s) +} diff --git a/evmd/testutil/abci.go b/evmd/testutil/abci.go index 66e1ced6a..9f0aa4143 100644 --- a/evmd/testutil/abci.go +++ b/evmd/testutil/abci.go @@ -8,7 +8,8 @@ import ( tmproto "github.com/cometbft/cometbft/proto/tendermint/types" cmttypes "github.com/cometbft/cometbft/types" - app "github.com/cosmos/evm/evmd" + "github.com/cosmos/evm" + "github.com/cosmos/evm/testutil/integration" "github.com/cosmos/evm/testutil/tx" errorsmod "cosmossdk.io/errors" @@ -25,7 +26,7 @@ import ( // 2. DeliverTx // 3. EndBlock // 4. Commit -func Commit(ctx sdk.Context, app *app.EVMD, t time.Duration, vs *cmttypes.ValidatorSet) (sdk.Context, error) { +func Commit(ctx sdk.Context, app evm.EvmApp, t time.Duration, vs *cmttypes.ValidatorSet) (sdk.Context, error) { header, err := commit(ctx, app, t, vs) if err != nil { return ctx, err @@ -37,7 +38,7 @@ func Commit(ctx sdk.Context, app *app.EVMD, t time.Duration, vs *cmttypes.Valida // CommitAndCreateNewCtx commits a block at a given time creating a ctx with the current settings // This is useful to keep test settings that could be affected by EndBlockers, e.g. // setting a baseFee == 0 and expecting this condition to continue after commit -func CommitAndCreateNewCtx(ctx sdk.Context, app *app.EVMD, t time.Duration, vs *cmttypes.ValidatorSet) (sdk.Context, error) { +func CommitAndCreateNewCtx(ctx sdk.Context, app evm.EvmApp, t time.Duration, vs *cmttypes.ValidatorSet) (sdk.Context, error) { header, err := commit(ctx, app, t, vs) if err != nil { return ctx, err @@ -46,7 +47,7 @@ func CommitAndCreateNewCtx(ctx sdk.Context, app *app.EVMD, t time.Duration, vs * // NewContext function keeps the multistore // but resets other context fields // GasMeter is set as InfiniteGasMeter - newCtx := app.BaseApp.NewContextLegacy(false, header) + newCtx := app.GetBaseApp().NewContextLegacy(false, header) // set the reseted fields to keep the current ctx settings newCtx = newCtx.WithMinGasPrices(ctx.MinGasPrices()) newCtx = newCtx.WithEventManager(ctx.EventManager()) @@ -59,7 +60,7 @@ func CommitAndCreateNewCtx(ctx sdk.Context, app *app.EVMD, t time.Duration, vs * // DeliverTx delivers a cosmos tx for a given set of msgs func DeliverTx( ctx sdk.Context, - exampleApp *app.EVMD, + exampleApp evm.EvmApp, priv cryptotypes.PrivKey, gasPrice *sdkmath.Int, msgs ...sdk.Msg, @@ -87,7 +88,7 @@ func DeliverTx( // If a private key is provided, it will attempt to sign all messages with the given private key, // otherwise, it will assume the messages have already been signed. func DeliverEthTx( - exampleApp *app.EVMD, + exampleApp evm.EvmApp, priv cryptotypes.PrivKey, msgs ...sdk.Msg, ) (abci.ExecTxResult, error) { @@ -103,7 +104,7 @@ func DeliverEthTx( } codec := exampleApp.AppCodec() - if _, err := CheckEthTxResponse(res, codec); err != nil { + if _, err := integration.CheckEthTxResponse(res, codec); err != nil { return res, err } return res, nil @@ -114,7 +115,7 @@ func DeliverEthTx( // otherwise, it will assume the messages have already been signed. It does not check if the Eth tx is // successful or not. func DeliverEthTxWithoutCheck( - exampleApp *app.EVMD, + exampleApp evm.EvmApp, priv cryptotypes.PrivKey, msgs ...sdk.Msg, ) (abci.ExecTxResult, error) { @@ -136,7 +137,7 @@ func DeliverEthTxWithoutCheck( // CheckTx checks a cosmos tx for a given set of msgs func CheckTx( ctx sdk.Context, - exampleApp *app.EVMD, + exampleApp evm.EvmApp, priv cryptotypes.PrivKey, gasPrice *sdkmath.Int, msgs ...sdk.Msg, @@ -163,7 +164,7 @@ func CheckTx( // CheckEthTx checks a Ethereum tx for a given set of msgs func CheckEthTx( - exampleApp *app.EVMD, + exampleApp evm.EvmApp, priv cryptotypes.PrivKey, msgs ...sdk.Msg, ) (abci.ResponseCheckTx, error) { @@ -177,7 +178,7 @@ func CheckEthTx( } // BroadcastTxBytes encodes a transaction and calls DeliverTx on the app. -func BroadcastTxBytes(app *app.EVMD, txEncoder sdk.TxEncoder, tx sdk.Tx) (abci.ExecTxResult, error) { +func BroadcastTxBytes(app evm.EvmApp, txEncoder sdk.TxEncoder, tx sdk.Tx) (abci.ExecTxResult, error) { // bz are bytes to be broadcasted over the network bz, err := txEncoder(tx) if err != nil { @@ -186,7 +187,7 @@ func BroadcastTxBytes(app *app.EVMD, txEncoder sdk.TxEncoder, tx sdk.Tx) (abci.E req := abci.RequestFinalizeBlock{Txs: [][]byte{bz}} - res, err := app.BaseApp.FinalizeBlock(&req) + res, err := app.GetBaseApp().FinalizeBlock(&req) if err != nil { return abci.ExecTxResult{}, err } @@ -203,7 +204,7 @@ func BroadcastTxBytes(app *app.EVMD, txEncoder sdk.TxEncoder, tx sdk.Tx) (abci.E // commit is a private helper function that runs the EndBlocker logic, commits the changes, // updates the header, runs the BeginBlocker function and returns the updated header -func commit(ctx sdk.Context, app *app.EVMD, t time.Duration, vs *cmttypes.ValidatorSet) (tmproto.Header, error) { +func commit(ctx sdk.Context, app evm.EvmApp, t time.Duration, vs *cmttypes.ValidatorSet) (tmproto.Header, error) { header := ctx.BlockHeader() req := abci.RequestFinalizeBlock{Height: header.Height} @@ -241,14 +242,14 @@ func commit(ctx sdk.Context, app *app.EVMD, t time.Duration, vs *cmttypes.Valida } // checkTxBytes encodes a transaction and calls checkTx on the app. -func checkTxBytes(app *app.EVMD, txEncoder sdk.TxEncoder, tx sdk.Tx) (abci.ResponseCheckTx, error) { +func checkTxBytes(app evm.EvmApp, txEncoder sdk.TxEncoder, tx sdk.Tx) (abci.ResponseCheckTx, error) { bz, err := txEncoder(tx) if err != nil { return abci.ResponseCheckTx{}, err } req := abci.RequestCheckTx{Tx: bz} - res, err := app.BaseApp.CheckTx(&req) + res, err := app.GetBaseApp().CheckTx(&req) if err != nil { return abci.ResponseCheckTx{}, err } diff --git a/evmd/testutil/app.go b/evmd/testutil/app.go deleted file mode 100644 index 54c73f3c5..000000000 --- a/evmd/testutil/app.go +++ /dev/null @@ -1,5 +0,0 @@ -package testutil - -func NoOpEvmAppOptions(_ uint64) error { - return nil -} diff --git a/evmd/testutil/eth_setup.go b/evmd/testutil/eth_setup.go index 7da040f88..ed5be0fe4 100644 --- a/evmd/testutil/eth_setup.go +++ b/evmd/testutil/eth_setup.go @@ -1,52 +1,26 @@ package testutil import ( - "encoding/json" "time" - abci "github.com/cometbft/cometbft/abci/types" - tmproto "github.com/cometbft/cometbft/proto/tendermint/types" cmtypes "github.com/cometbft/cometbft/types" - dbm "github.com/cosmos/cosmos-db" - exampleapp "github.com/cosmos/evm/evmd" + "github.com/cosmos/evm" cosmosevmtypes "github.com/cosmos/evm/types" - "cosmossdk.io/log" "cosmossdk.io/math" - "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/cosmos/cosmos-sdk/testutil/mock" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" 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" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) -// DefaultConsensusParams defines the default Tendermint consensus params used in -// Cosmos EVM testing. -var DefaultConsensusParams = &tmproto.ConsensusParams{ - Block: &tmproto.BlockParams{ - MaxBytes: 200000, - MaxGas: -1, // no limit - }, - Evidence: &tmproto.EvidenceParams{ - MaxAgeNumBlocks: 302400, - MaxAgeDuration: 504 * time.Hour, // 3 weeks is the max duration - MaxBytes: 10000, - }, - Validator: &tmproto.ValidatorParams{ - PubKeyTypes: []string{ - cmtypes.ABCIPubKeyTypeEd25519, - }, - }, -} - // EthDefaultConsensusParams defines the default Tendermint consensus params used in // Cosmos EVM app testing. // @@ -68,58 +42,13 @@ var EthDefaultConsensusParams = &cmtypes.ConsensusParams{ }, } -// EthSetup initializes a new Cosmos EVM application. A Nop logger is set in EVMD. -func EthSetup(isCheckTx bool, chainID string, evmChainID uint64, patchGenesis func(*exampleapp.EVMD, cosmosevmtypes.GenesisState) cosmosevmtypes.GenesisState) *exampleapp.EVMD { - return EthSetupWithDB(isCheckTx, chainID, evmChainID, patchGenesis, dbm.NewMemDB()) -} - -// EthSetupWithDB initializes a new EVMD. A Nop logger is set in EVMD. -func EthSetupWithDB(isCheckTx bool, chainID string, evmChainID uint64, patchGenesis func(*exampleapp.EVMD, cosmosevmtypes.GenesisState) cosmosevmtypes.GenesisState, db dbm.DB) *exampleapp.EVMD { - app := exampleapp.NewExampleApp(log.NewNopLogger(), - db, - nil, - true, - simtestutil.NewAppOptionsWithFlagHome(exampleapp.DefaultNodeHome), - evmChainID, - exampleapp.EvmAppOptions, - baseapp.SetChainID(chainID), - ) - if !isCheckTx { - // init chain must be called to stop deliverState from being nil - genesisState := NewTestGenesisState(app) - if patchGenesis != nil { - genesisState = patchGenesis(app, genesisState) - } - - stateBytes, err := json.MarshalIndent(genesisState, "", " ") - if err != nil { - panic(err) - } - - // Initialize the chain - _, err = app.InitChain( - &abci.RequestInitChain{ - ChainId: chainID, - Validators: []abci.ValidatorUpdate{}, - ConsensusParams: DefaultConsensusParams, - AppStateBytes: stateBytes, - }, - ) - if err != nil { - panic(err) - } - } - - return app -} - // NewTestGenesisState generate genesis state with single validator // // It is also setting up the EVM parameters to use sensible defaults. // // TODO: are these different genesis functions necessary or can they all be refactored into one? // there's also other genesis state functions; some like app.DefaultGenesis() or others in test helpers only. -func NewTestGenesisState(app *exampleapp.EVMD) cosmosevmtypes.GenesisState { +func NewTestGenesisState(app evm.EvmApp) cosmosevmtypes.GenesisState { privVal := mock.NewPV() pubKey, err := privVal.GetPubKey() if err != nil { diff --git a/evmd/testutil/fund.go b/evmd/testutil/fund.go deleted file mode 100644 index 6a227c793..000000000 --- a/evmd/testutil/fund.go +++ /dev/null @@ -1,42 +0,0 @@ -package testutil - -import ( - "github.com/cosmos/evm/testutil/constants" - - "cosmossdk.io/math" - - sdk "github.com/cosmos/cosmos-sdk/types" - bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" - minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" -) - -// FundAccount is a utility function that funds an account by minting and -// sending the coins to the address. -func FundAccount(ctx sdk.Context, bankKeeper bankkeeper.Keeper, addr sdk.AccAddress, amounts sdk.Coins) error { - if err := bankKeeper.MintCoins(ctx, minttypes.ModuleName, amounts); err != nil { - return err - } - - return bankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, amounts) -} - -// FundAccountWithBaseDenom is a utility function that uses the FundAccount function -// to fund an account with the default denomination. -// -// TODO: as per Freddy these methods should be replaced with a bank transfer from a main account, not by minting in the process -func FundAccountWithBaseDenom(ctx sdk.Context, bankKeeper bankkeeper.Keeper, addr sdk.AccAddress, amount int64) error { - coins := sdk.NewCoins( - sdk.NewCoin(constants.ExampleAttoDenom, math.NewInt(amount)), - ) - return FundAccount(ctx, bankKeeper, addr, coins) -} - -// FundModuleAccount is a utility function that funds a module account by -// minting and sending the coins to the address. -func FundModuleAccount(ctx sdk.Context, bankKeeper bankkeeper.Keeper, recipientMod string, amounts sdk.Coins) error { - if err := bankKeeper.MintCoins(ctx, minttypes.ModuleName, amounts); err != nil { - return err - } - - return bankKeeper.SendCoinsFromModuleToModule(ctx, minttypes.ModuleName, recipientMod, amounts) -} diff --git a/evmd/testutil/integration.go b/evmd/testutil/integration.go index f23d5cd6f..630546fff 100644 --- a/evmd/testutil/integration.go +++ b/evmd/testutil/integration.go @@ -5,8 +5,8 @@ import ( abci "github.com/cometbft/cometbft/abci/types" + "github.com/cosmos/evm" "github.com/cosmos/evm/crypto/ethsecp256k1" - exampleapp "github.com/cosmos/evm/evmd" errorsmod "cosmossdk.io/errors" "cosmossdk.io/math" @@ -21,7 +21,7 @@ import ( // event. func SubmitProposal( ctx sdk.Context, - appEvmos *exampleapp.EVMD, + evmApp evm.EvmApp, pk *ethsecp256k1.PrivKey, content govv1beta1.Content, eventNum int, @@ -34,7 +34,7 @@ func SubmitProposal( if err != nil { return id, err } - res, err := DeliverTx(ctx, appEvmos, pk, nil, msg) + res, err := DeliverTx(ctx, evmApp, pk, nil, msg) if err != nil { return id, err } @@ -50,7 +50,7 @@ func SubmitProposal( // Delegate delivers a delegate tx func Delegate( ctx sdk.Context, - appEvmos *exampleapp.EVMD, + evmApp evm.EvmApp, priv *ethsecp256k1.PrivKey, delegateAmount sdk.Coin, validator stakingtypes.Validator, @@ -63,13 +63,13 @@ func Delegate( } delegateMsg := stakingtypes.NewMsgDelegate(accountAddress.String(), val.String(), delegateAmount) - return DeliverTx(ctx, appEvmos, priv, nil, delegateMsg) + return DeliverTx(ctx, evmApp, priv, nil, delegateMsg) } // Vote delivers a vote tx with the VoteOption "yes" func Vote( ctx sdk.Context, - appEvmos *exampleapp.EVMD, + evmApp evm.EvmApp, priv *ethsecp256k1.PrivKey, proposalID uint64, voteOption govv1beta1.VoteOption, @@ -77,5 +77,5 @@ func Vote( accountAddress := sdk.AccAddress(priv.PubKey().Address().Bytes()) voteMsg := govv1beta1.NewMsgVote(accountAddress, proposalID, voteOption) - return DeliverTx(ctx, appEvmos, priv, nil, voteMsg) + return DeliverTx(ctx, evmApp, priv, nil, voteMsg) } diff --git a/go.mod b/go.mod index d28413728..e8b1a23da 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/cosmos/evm go 1.23.8 require ( + cosmosevm.io/evmd v0.0.0 cosmossdk.io/api v0.9.2 - cosmossdk.io/client/v2 v2.0.0-beta.7 cosmossdk.io/core v0.11.3 cosmossdk.io/errors v1.0.2 cosmossdk.io/log v1.5.1 @@ -14,7 +14,6 @@ require ( cosmossdk.io/x/evidence v0.1.1 cosmossdk.io/x/feegrant v0.1.1 cosmossdk.io/x/tx v0.14.0 - cosmossdk.io/x/upgrade v0.2.0 github.com/btcsuite/btcd v0.24.2 github.com/btcsuite/btcd/btcutil v1.1.6 github.com/cometbft/cometbft v0.38.17 @@ -68,9 +67,11 @@ require ( cloud.google.com/go/iam v1.2.2 // indirect cloud.google.com/go/monitoring v1.21.2 // indirect cloud.google.com/go/storage v1.49.0 // indirect + cosmossdk.io/client/v2 v2.0.0-beta.7 // indirect cosmossdk.io/collections v1.2.0 // indirect cosmossdk.io/depinject v1.2.0 // indirect cosmossdk.io/schema v1.1.0 // indirect + cosmossdk.io/x/upgrade v0.2.0 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.2 // indirect @@ -270,6 +271,7 @@ require ( ) replace ( + cosmosevm.io/evmd => ./evmd // use cosmos fork of keyring github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 // Pin this pebble version to avoid breaking compilation of geth diff --git a/ibc/testing/chain.go b/ibc/testing/chain.go index a62695770..fd9f0a300 100644 --- a/ibc/testing/chain.go +++ b/ibc/testing/chain.go @@ -7,6 +7,7 @@ import ( "testing" "time" + "cosmosevm.io/evmd" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" @@ -19,7 +20,6 @@ import ( "github.com/cosmos/evm/cmd/evmd/config" "github.com/cosmos/evm/crypto/ethsecp256k1" - "github.com/cosmos/evm/evmd" "github.com/cosmos/evm/testutil/tx" clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" diff --git a/ibc/testing/coordinator.go b/ibc/testing/coordinator.go index 0b5908002..33cf655cb 100644 --- a/ibc/testing/coordinator.go +++ b/ibc/testing/coordinator.go @@ -6,9 +6,9 @@ import ( "testing" "time" + "cosmosevm.io/evmd" "github.com/stretchr/testify/require" - "github.com/cosmos/evm/evmd" ibctesting "github.com/cosmos/ibc-go/v10/testing" ) diff --git a/ibc/testing/testing_app.go b/ibc/testing/testing_app.go index f22679e33..b5813bb17 100644 --- a/ibc/testing/testing_app.go +++ b/ibc/testing/testing_app.go @@ -3,8 +3,9 @@ package ibctesting import ( "encoding/json" + "cosmosevm.io/evmd" + dbm "github.com/cosmos/cosmos-db" - "github.com/cosmos/evm/evmd" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" ibctesting "github.com/cosmos/ibc-go/v10/testing" diff --git a/interfaces.go b/interfaces.go new file mode 100644 index 000000000..ce233fc80 --- /dev/null +++ b/interfaces.go @@ -0,0 +1,145 @@ +package evm + +import ( + "context" + "encoding/json" + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" + + erc20types "github.com/cosmos/evm/x/erc20/types" + feemarketkeeper "github.com/cosmos/evm/x/feemarket/keeper" + transferkeeper "github.com/cosmos/evm/x/ibc/transfer/keeper" + precisebankkeeper "github.com/cosmos/evm/x/precisebank/keeper" + evmkeeper "github.com/cosmos/evm/x/vm/keeper" + transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" + channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" + "github.com/cosmos/ibc-go/v10/modules/core/exported" + ibctesting "github.com/cosmos/ibc-go/v10/testing" + + storetypes "cosmossdk.io/store/types" + evidencekeeper "cosmossdk.io/x/evidence/keeper" + feegrantkeeper "cosmossdk.io/x/feegrant/keeper" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/runtime" + sdk "github.com/cosmos/cosmos-sdk/types" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" + govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" + mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper" + paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" + slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" +) + +// EvmApp defines the interface for an EVM application. +type EvmApp interface { + ibctesting.TestingApp + runtime.AppI + InterfaceRegistry() types.InterfaceRegistry + ChainID() string + GetEVMKeeper() *evmkeeper.Keeper + GetErc20Keeper() Erc20Keeper + SetErc20Keeper(Erc20Keeper) + GetGovKeeper() govkeeper.Keeper + GetSlashingKeeper() slashingkeeper.Keeper + GetEvidenceKeeper() *evidencekeeper.Keeper + GetBankKeeper() bankkeeper.Keeper + GetFeeMarketKeeper() *feemarketkeeper.Keeper + GetAccountKeeper() authkeeper.AccountKeeper + GetAuthzKeeper() authzkeeper.Keeper + GetDistrKeeper() distrkeeper.Keeper + GetStakingKeeper() *stakingkeeper.Keeper + GetMintKeeper() mintkeeper.Keeper + GetPreciseBankKeeper() *precisebankkeeper.Keeper + GetFeeGrantKeeper() feegrantkeeper.Keeper + GetTransferKeeper() transferkeeper.Keeper + SetTransferKeeper(transferKeeper transferkeeper.Keeper) + DefaultGenesis() map[string]json.RawMessage + GetKey(storeKey string) *storetypes.KVStoreKey + GetAnteHandler() sdk.AnteHandler + GetSubspace(moduleName string) paramstypes.Subspace + MsgServiceRouter() *baseapp.MsgServiceRouter +} + +type Erc20Keeper interface { + SetToken(ctx sdk.Context, pair erc20types.TokenPair) + GetTokenPairID(ctx sdk.Context, token string) []byte + GetTokenPair(ctx sdk.Context, id []byte) (erc20types.TokenPair, bool) + GetParams(ctx sdk.Context) erc20types.Params + SetAllowance(ctx sdk.Context, erc20 common.Address, owner common.Address, spender common.Address, value *big.Int) error + GetAllowance(ctx sdk.Context, erc20 common.Address, owner common.Address, spender common.Address) (*big.Int, error) + DeleteAllowance(ctx sdk.Context, erc20 common.Address, owner common.Address, spender common.Address) error + EnableDynamicPrecompiles(ctx sdk.Context, addresses ...common.Address) error + TokenPairs(context.Context, *erc20types.QueryTokenPairsRequest) (*erc20types.QueryTokenPairsResponse, error) + TokenPair(context.Context, *erc20types.QueryTokenPairRequest) (*erc20types.QueryTokenPairResponse, error) + Params(context.Context, *erc20types.QueryParamsRequest) (*erc20types.QueryParamsResponse, error) + RegisterERC20Extension(ctx sdk.Context, denom string) (*erc20types.TokenPair, error) + GetDenomMap(ctx sdk.Context, denom string) []byte + GetERC20Map(ctx sdk.Context, erc20 common.Address) []byte + BalanceOf(ctx sdk.Context, abi abi.ABI, contract, account common.Address) *big.Int + GetCoinAddress(ctx sdk.Context, denom string) (common.Address, error) + GetTokenDenom(ctx sdk.Context, tokenAddress common.Address) (string, error) + ConvertERC20(ctx context.Context, msg *erc20types.MsgConvertERC20) (*erc20types.MsgConvertERC20Response, error) + IsERC20Enabled(ctx sdk.Context) bool + GetTokenPairs(ctx sdk.Context) []erc20types.TokenPair + GetAllowances(ctx sdk.Context) []erc20types.Allowance + SetERC20Map(ctx sdk.Context, erc20 common.Address, id []byte) + SetDenomMap(ctx sdk.Context, denom string, id []byte) + CreateCoinMetadata(ctx sdk.Context, contract common.Address) (*banktypes.Metadata, error) + SetPermissionlessRegistration(ctx sdk.Context, permissionlessRegistration bool) + RegisterERC20(goCtx context.Context, req *erc20types.MsgRegisterERC20) (*erc20types.MsgRegisterERC20Response, error) + ToggleConversion(goCtx context.Context, req *erc20types.MsgToggleConversion) (*erc20types.MsgToggleConversionResponse, error) + UnsafeSetAllowance( + ctx sdk.Context, + erc20 common.Address, + owner common.Address, + spender common.Address, + value *big.Int, + ) error + DeleteTokenPair(ctx sdk.Context, tokenPair erc20types.TokenPair) + RegisterERC20CodeHash(ctx sdk.Context, erc20Addr common.Address) error + UnRegisterERC20CodeHash(ctx sdk.Context, erc20Addr common.Address) error + QueryERC20( + ctx sdk.Context, + contract common.Address, + ) (erc20types.ERC20Data, error) + SetTokenPair(ctx sdk.Context, tokenPair erc20types.TokenPair) + SetParams(ctx sdk.Context, newParams erc20types.Params) error + ConvertCoinToERC20FromPacket(ctx sdk.Context, data transfertypes.FungibleTokenPacketData) error + OnRecvPacket( + ctx sdk.Context, + packet channeltypes.Packet, + ack exported.Acknowledgement, + ) exported.Acknowledgement + OnAcknowledgementPacket( + ctx sdk.Context, _ channeltypes.Packet, + data transfertypes.FungibleTokenPacketData, + ack channeltypes.Acknowledgement, + ) error + OnTimeoutPacket(ctx sdk.Context, _ channeltypes.Packet, data transfertypes.FungibleTokenPacketData) error + MintingEnabled( + ctx sdk.Context, + sender, receiver sdk.AccAddress, + token string, + ) (erc20types.TokenPair, error) + ConvertCoin( + goCtx context.Context, + msg *erc20types.MsgConvertCoin, + ) (*erc20types.MsgConvertCoinResponse, error) + UpdateParams(goCtx context.Context, req *erc20types.MsgUpdateParams) (*erc20types.MsgUpdateParamsResponse, error) + GetERC20PrecompileInstance( + ctx sdk.Context, + address common.Address, + ) (contract vm.PrecompiledContract, found bool, err error) + IsTokenPairRegistered(ctx sdk.Context, id []byte) bool + IsERC20Registered(ctx sdk.Context, erc20 common.Address) bool + IsDenomRegistered(ctx sdk.Context, denom string) bool +} diff --git a/precompiles/bank/bank.go b/precompiles/bank/bank.go index f81b725e6..6cb201b90 100644 --- a/precompiles/bank/bank.go +++ b/precompiles/bank/bank.go @@ -14,8 +14,8 @@ import ( "github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/vm" + "github.com/cosmos/evm" cmn "github.com/cosmos/evm/precompiles/common" - erc20keeper "github.com/cosmos/evm/x/erc20/keeper" evmtypes "github.com/cosmos/evm/x/vm/types" storetypes "cosmossdk.io/store/types" @@ -43,14 +43,14 @@ var f embed.FS type Precompile struct { cmn.Precompile bankKeeper cmn.BankKeeper - erc20Keeper erc20keeper.Keeper + erc20Keeper evm.Erc20Keeper } // NewPrecompile creates a new bank Precompile instance implementing the // PrecompiledContract interface. func NewPrecompile( bankKeeper cmn.BankKeeper, - erc20Keeper erc20keeper.Keeper, + erc20Keeper evm.Erc20Keeper, ) (*Precompile, error) { newABI, err := cmn.LoadABI(f, "abi.json") if err != nil { diff --git a/precompiles/bank/integration_test.go b/precompiles/bank/integration_test.go deleted file mode 100644 index 9e9511a41..000000000 --- a/precompiles/bank/integration_test.go +++ /dev/null @@ -1,431 +0,0 @@ -package bank_test - -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" - - "github.com/cosmos/evm/precompiles/bank" - "github.com/cosmos/evm/precompiles/bank/testdata" - "github.com/cosmos/evm/precompiles/testutil" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" - testutils "github.com/cosmos/evm/testutil/integration/os/utils" - utiltx "github.com/cosmos/evm/testutil/tx" - evmtypes "github.com/cosmos/evm/x/vm/types" - - "cosmossdk.io/math" - - sdk "github.com/cosmos/cosmos-sdk/types" - minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" -) - -var is *IntegrationTestSuite - -// IntegrationTestSuite is the implementation of the TestSuite interface for Bank precompile -// unit testis. -type IntegrationTestSuite struct { - bondDenom, tokenDenom string - cosmosEVMAddr, xmplAddr common.Address - - network *network.UnitTestNetwork - factory factory.TxFactory - grpcHandler grpc.Handler - keyring keyring.Keyring - - precompile *bank.Precompile -} - -func (is *IntegrationTestSuite) SetupTest() { - // Mint and register a second coin for testing purposes - // FIXME the RegisterCoin logic will need to be refactored - // once logic is integrated - // with the protocol via genesis and/or a transaction - is.tokenDenom = xmplDenom - keyring := keyring.New(2) - genesis := testutils.CreateGenesisWithTokenPairs(keyring) - - integrationNetwork := network.NewUnitTestNetwork( - network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), - network.WithOtherDenoms([]string{is.tokenDenom}), // set some funds of other denom to the prefunded accounts - network.WithCustomGenesis(genesis), - ) - grpcHandler := grpc.NewIntegrationHandler(integrationNetwork) - txFactory := factory.New(integrationNetwork, grpcHandler) - - ctx := integrationNetwork.GetContext() - sk := integrationNetwork.App.StakingKeeper - bondDenom, err := sk.BondDenom(ctx) - Expect(err).ToNot(HaveOccurred()) - Expect(bondDenom).ToNot(BeEmpty(), "bond denom cannot be empty") - - is.bondDenom = bondDenom - is.factory = txFactory - is.grpcHandler = grpcHandler - is.keyring = keyring - is.network = integrationNetwork - - tokenPairID := is.network.App.Erc20Keeper.GetTokenPairID(is.network.GetContext(), is.bondDenom) - tokenPair, found := is.network.App.Erc20Keeper.GetTokenPair(is.network.GetContext(), tokenPairID) - Expect(found).To(BeTrue(), "failed to register token erc20 extension") - is.cosmosEVMAddr = common.HexToAddress(tokenPair.Erc20Address) - - // Mint and register a second coin for testing purposes - err = is.network.App.BankKeeper.MintCoins(is.network.GetContext(), minttypes.ModuleName, sdk.Coins{{Denom: is.tokenDenom, Amount: math.NewInt(1e18)}}) - Expect(err).ToNot(HaveOccurred(), "failed to mint coin") - - tokenPairID = is.network.App.Erc20Keeper.GetTokenPairID(is.network.GetContext(), is.tokenDenom) - tokenPair, found = is.network.App.Erc20Keeper.GetTokenPair(is.network.GetContext(), tokenPairID) - Expect(found).To(BeTrue(), "failed to register token erc20 extension") - is.xmplAddr = common.HexToAddress(tokenPair.Erc20Address) - is.precompile = is.setupBankPrecompile() -} - -func TestIntegrationSuite(t *testing.T) { - is = new(IntegrationTestSuite) - - // Run Ginkgo integration tests - RegisterFailHandler(Fail) - RunSpecs(t, "Bank Extension Suite") -} - -var _ = Describe("Bank Extension -", func() { - var ( - bankCallerContractAddr common.Address - bankCallerContract evmtypes.CompiledContract - - err error - sender keyring.Key - amount *big.Int - - // contractData is a helper struct to hold the addresses and ABIs for the - // different contract instances that are subject to testing here. - contractData ContractData - passCheck testutil.LogCheckArgs - - cosmosEVMTotalSupply, _ = new(big.Int).SetString("200003000000000000000000", 10) - xmplTotalSupply, _ = new(big.Int).SetString("200000000000000000000000", 10) - ) - - BeforeEach(func() { - is.SetupTest() - - // Default sender, amount - sender = is.keyring.GetKey(0) - amount = big.NewInt(1e18) - - bankCallerContract, err = testdata.LoadBankCallerContract() - Expect(err).ToNot(HaveOccurred(), "failed to load BankCaller contract") - - bankCallerContractAddr, err = is.factory.DeployContract( - sender.Priv, - evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values - factory.ContractDeploymentData{ - Contract: bankCallerContract, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to deploy ERC20 minter burner contract") - - contractData = ContractData{ - ownerPriv: sender.Priv, - precompileAddr: is.precompile.Address(), - precompileABI: is.precompile.ABI, - contractAddr: bankCallerContractAddr, - contractABI: bankCallerContract.ABI, - } - - passCheck = testutil.LogCheckArgs{}.WithExpPass(true) - - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "failed to advance block") - }) - - Context("Direct precompile queries", func() { - Context("balances query", func() { - It("should return the correct balance", func() { - // New account with 0 balances (does not exist on the chain yet) - receiver := utiltx.GenerateAddress() - - err := is.factory.FundAccount(sender, receiver.Bytes(), sdk.NewCoins(sdk.NewCoin(is.tokenDenom, math.NewIntFromBigInt(amount)))) - Expect(err).ToNot(HaveOccurred(), "error while funding account") - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - queryArgs, balancesArgs := getTxAndCallArgs(directCall, contractData, bank.BalancesMethod, receiver) - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, balancesArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - var balances []bank.Balance - err = is.precompile.UnpackIntoInterface(&balances, bank.BalancesMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") - - balanceAfter, err := is.grpcHandler.GetBalanceFromBank(receiver.Bytes(), is.tokenDenom) - Expect(err).ToNot(HaveOccurred(), "failed to get balance") - - Expect(math.NewInt(balances[0].Amount.Int64())).To(Equal(balanceAfter.Balance.Amount)) - Expect(*balances[0].Amount).To(Equal(*amount)) - }) - - It("should return a single token balance", func() { - // New account with 0 balances (does not exist on the chain yet) - receiver := utiltx.GenerateAddress() - - err := testutils.FundAccountWithBaseDenom(is.factory, is.network, sender, receiver.Bytes(), math.NewIntFromBigInt(amount)) - Expect(err).ToNot(HaveOccurred(), "error while funding account") - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - queryArgs, balancesArgs := getTxAndCallArgs(directCall, contractData, bank.BalancesMethod, receiver) - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, balancesArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - var balances []bank.Balance - err = is.precompile.UnpackIntoInterface(&balances, bank.BalancesMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") - - balanceAfter, err := is.grpcHandler.GetBalanceFromBank(receiver.Bytes(), is.network.GetBaseDenom()) - Expect(err).ToNot(HaveOccurred(), "failed to get balance") - - Expect(math.NewInt(balances[0].Amount.Int64())).To(Equal(balanceAfter.Balance.Amount)) - Expect(*balances[0].Amount).To(Equal(*amount)) - }) - - It("should return no balance for new account", func() { - queryArgs, balancesArgs := getTxAndCallArgs(directCall, contractData, bank.BalancesMethod, utiltx.GenerateAddress()) - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, balancesArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - var balances []bank.Balance - err = is.precompile.UnpackIntoInterface(&balances, bank.BalancesMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") - - Expect(balances).To(BeEmpty()) - }) - - It("should consume the correct amount of gas", func() { - queryArgs, balancesArgs := getTxAndCallArgs(directCall, contractData, bank.BalancesMethod, sender.Addr) - res, err := is.factory.ExecuteContractCall(sender.Priv, queryArgs, balancesArgs) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - ethRes, err := evmtypes.DecodeTxResponse(res.Data) - Expect(err).ToNot(HaveOccurred(), "failed to decode tx response") - - var balances []bank.Balance - err = is.precompile.UnpackIntoInterface(&balances, bank.BalancesMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") - - gasUsed := Max(bank.GasBalances, len(balances)*bank.GasBalances) - // Here increasing the GasBalanceOf will increase the use of gas so they will never be equal - Expect(gasUsed).To(BeNumerically("<=", ethRes.GasUsed)) - }) - }) - - Context("totalSupply query", func() { - It("should return the correct total supply", func() { - queryArgs, supplyArgs := getTxAndCallArgs(directCall, contractData, bank.TotalSupplyMethod) - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - var balances []bank.Balance - err = is.precompile.UnpackIntoInterface(&balances, bank.TotalSupplyMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") - - Expect(balances[0].Amount.String()).To(Equal(cosmosEVMTotalSupply.String())) - Expect(balances[1].Amount.String()).To(Equal(xmplTotalSupply.String())) - }) - }) - - Context("supplyOf query", func() { - It("should return the supply of Cosmos EVM", func() { - queryArgs, supplyArgs := getTxAndCallArgs(directCall, contractData, bank.SupplyOfMethod, is.cosmosEVMAddr) - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - out, err := is.precompile.Unpack(bank.SupplyOfMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") - - Expect(out[0].(*big.Int).String()).To(Equal(cosmosEVMTotalSupply.String())) - }) - - It("should return the supply of XMPL", func() { - queryArgs, supplyArgs := getTxAndCallArgs(directCall, contractData, bank.SupplyOfMethod, is.xmplAddr) - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - out, err := is.precompile.Unpack(bank.SupplyOfMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") - - Expect(out[0].(*big.Int).String()).To(Equal(xmplTotalSupply.String())) - }) - - It("should return a supply of 0 for a non existing token", func() { - queryArgs, supplyArgs := getTxAndCallArgs(directCall, contractData, bank.SupplyOfMethod, utiltx.GenerateAddress()) - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - out, err := is.precompile.Unpack(bank.SupplyOfMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") - - Expect(out[0].(*big.Int).Int64()).To(Equal(big.NewInt(0).Int64())) - }) - - It("should consume the correct amount of gas", func() { - queryArgs, supplyArgs := getTxAndCallArgs(directCall, contractData, bank.SupplyOfMethod, is.xmplAddr) - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // Here increasing the GasSupplyOf will increase the use of gas so they will never be equal - Expect(bank.GasSupplyOf).To(BeNumerically("<=", ethRes.GasUsed)) - }) - }) - }) - - Context("Calls from a contract", func() { - const ( - BalancesFunction = "callBalances" - TotalSupplyOf = "callTotalSupply" - SupplyOfFunction = "callSupplyOf" - ) - - Context("balances query", func() { - It("should return the correct balance", func() { - receiver := utiltx.GenerateAddress() - - err := is.factory.FundAccount(sender, receiver.Bytes(), sdk.NewCoins(sdk.NewCoin(is.tokenDenom, math.NewIntFromBigInt(amount)))) - Expect(err).ToNot(HaveOccurred(), "error while funding account") - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - queryArgs, balancesArgs := getTxAndCallArgs(contractCall, contractData, BalancesFunction, receiver) - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, balancesArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - var balances []bank.Balance - err = is.precompile.UnpackIntoInterface(&balances, bank.BalancesMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") - - balanceAfter, err := is.grpcHandler.GetBalanceFromBank(receiver.Bytes(), is.tokenDenom) - Expect(err).ToNot(HaveOccurred(), "failed to get balance") - - Expect(math.NewInt(balances[0].Amount.Int64())).To(Equal(balanceAfter.Balance.Amount)) - Expect(*balances[0].Amount).To(Equal(*amount)) - }) - - It("should return a single token balance", func() { - // New account with 0 balances (does not exist on the chain yet) - receiver := utiltx.GenerateAddress() - - err := testutils.FundAccountWithBaseDenom(is.factory, is.network, sender, receiver.Bytes(), math.NewIntFromBigInt(amount)) - Expect(err).ToNot(HaveOccurred(), "error while funding account") - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - queryArgs, balancesArgs := getTxAndCallArgs(contractCall, contractData, BalancesFunction, receiver) - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, balancesArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - var balances []bank.Balance - err = is.precompile.UnpackIntoInterface(&balances, bank.BalancesMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") - - balanceAfter, err := is.grpcHandler.GetBalanceFromBank(receiver.Bytes(), is.network.GetBaseDenom()) - Expect(err).ToNot(HaveOccurred(), "failed to get balance") - - Expect(math.NewInt(balances[0].Amount.Int64())).To(Equal(balanceAfter.Balance.Amount)) - Expect(*balances[0].Amount).To(Equal(*amount)) - }) - - It("should return no balance for new account", func() { - queryArgs, balancesArgs := getTxAndCallArgs(contractCall, contractData, BalancesFunction, utiltx.GenerateAddress()) - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, balancesArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - var balances []bank.Balance - err = is.precompile.UnpackIntoInterface(&balances, bank.BalancesMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") - - Expect(balances).To(BeEmpty()) - }) - - It("should consume the correct amount of gas", func() { - queryArgs, balancesArgs := getTxAndCallArgs(contractCall, contractData, BalancesFunction, sender.Addr) - res, err := is.factory.ExecuteContractCall(sender.Priv, queryArgs, balancesArgs) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - ethRes, err := evmtypes.DecodeTxResponse(res.Data) - Expect(err).ToNot(HaveOccurred(), "failed to decode tx response") - - var balances []bank.Balance - err = is.precompile.UnpackIntoInterface(&balances, bank.BalancesMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") - - gasUsed := Max(bank.GasBalances, len(balances)*bank.GasBalances) - // Here increasing the GasBalanceOf will increase the use of gas so they will never be equal - Expect(gasUsed).To(BeNumerically("<=", ethRes.GasUsed)) - }) - }) - - Context("totalSupply query", func() { - It("should return the correct total supply", func() { - queryArgs, supplyArgs := getTxAndCallArgs(contractCall, contractData, TotalSupplyOf) - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - var balances []bank.Balance - err = is.precompile.UnpackIntoInterface(&balances, bank.TotalSupplyMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") - - Expect(balances[0].Amount.String()).To(Equal(cosmosEVMTotalSupply.String())) - Expect(balances[1].Amount.String()).To(Equal(xmplTotalSupply.String())) - }) - }) - - Context("supplyOf query", func() { - It("should return the supply of Cosmos EVM", func() { - queryArgs, supplyArgs := getTxAndCallArgs(contractCall, contractData, SupplyOfFunction, is.cosmosEVMAddr) - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - out, err := is.precompile.Unpack(bank.SupplyOfMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") - - Expect(out[0].(*big.Int).String()).To(Equal(cosmosEVMTotalSupply.String())) - }) - - It("should return the supply of XMPL", func() { - queryArgs, supplyArgs := getTxAndCallArgs(contractCall, contractData, SupplyOfFunction, is.xmplAddr) - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - out, err := is.precompile.Unpack(bank.SupplyOfMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") - - Expect(out[0].(*big.Int).String()).To(Equal(xmplTotalSupply.String())) - }) - - It("should return a supply of 0 for a non existing token", func() { - queryArgs, supplyArgs := getTxAndCallArgs(contractCall, contractData, SupplyOfFunction, utiltx.GenerateAddress()) - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - out, err := is.precompile.Unpack(bank.SupplyOfMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") - - Expect(out[0].(*big.Int).Int64()).To(Equal(big.NewInt(0).Int64())) - }) - - It("should consume the correct amount of gas", func() { - queryArgs, supplyArgs := getTxAndCallArgs(contractCall, contractData, SupplyOfFunction, is.xmplAddr) - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // Here increasing the GasSupplyOf will increase the use of gas so they will never be equal - Expect(bank.GasSupplyOf).To(BeNumerically("<=", ethRes.GasUsed)) - }) - }) - }) -}) diff --git a/precompiles/distribution/integration_test.go b/precompiles/distribution/integration_test.go deleted file mode 100644 index db04415d2..000000000 --- a/precompiles/distribution/integration_test.go +++ /dev/null @@ -1,3205 +0,0 @@ -package distribution_test - -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/vm" - - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" - - cmn "github.com/cosmos/evm/precompiles/common" - "github.com/cosmos/evm/precompiles/distribution" - "github.com/cosmos/evm/precompiles/staking" - "github.com/cosmos/evm/precompiles/testutil" - "github.com/cosmos/evm/precompiles/testutil/contracts" - testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/os/factory" - testutils "github.com/cosmos/evm/testutil/integration/os/utils" - testutiltx "github.com/cosmos/evm/testutil/tx" - evmtypes "github.com/cosmos/evm/x/vm/types" - - "cosmossdk.io/math" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/query" -) - -// General variables used for integration tests -var ( - // differentAddr is an address generated for testing purposes that e.g. raises the different requester error (msg.sender != requester) - differentAddr, diffKey = testutiltx.NewAddrKey() - // gasPrice is the gas price used for the transactions - gasPrice = math.NewInt(1e9) - // callArgs are the default arguments for calling the smart contract - // - // NOTE: this has to be populated in a BeforeEach block because the contractAddr would otherwise be a nil address. - callArgs factory.CallArgs - - // defaultLogCheck instantiates a log check arguments struct with the precompile ABI events populated. - defaultLogCheck testutil.LogCheckArgs - // passCheck defines the arguments to check if the precompile returns no error - passCheck testutil.LogCheckArgs - // outOfGasCheck defines the arguments to check if the precompile returns out of gas error - outOfGasCheck testutil.LogCheckArgs - // txArgs are the EVM transaction arguments to use in the transactions - txArgs evmtypes.EvmTxArgs - // minExpRewardOrCommission is the minimun coins expected for validator's rewards or commission - // required for the tests - minExpRewardOrCommission = sdk.NewDecCoins(sdk.NewDecCoin(testconstants.ExampleAttoDenom, testRewardsAmt)) -) - -func TestPrecompileIntegrationTestSuite(t *testing.T) { - // Run Ginkgo integration tests - RegisterFailHandler(Fail) - RunSpecs(t, "Distribution Precompile Suite") -} - -var _ = Describe("Calling distribution precompile from EOA", func() { - s := new(PrecompileTestSuite) - - BeforeEach(func() { - s.SetupTest() - - // set the default call arguments - callArgs = factory.CallArgs{ - ContractABI: s.precompile.ABI, - } - - defaultLogCheck = testutil.LogCheckArgs{ - ABIEvents: s.precompile.Events, - } - passCheck = defaultLogCheck.WithExpPass(true) - outOfGasCheck = defaultLogCheck.WithErrContains(vm.ErrOutOfGas.Error()) - - // reset tx args each test to avoid keeping custom - // values of previous tests (e.g. gasLimit) - precompileAddr := s.precompile.Address() - txArgs = evmtypes.EvmTxArgs{ - To: &precompileAddr, - } - }) - - // ===================================== - // TRANSACTIONS - // ===================================== - Describe("Execute SetWithdrawAddress transaction", func() { - const method = distribution.SetWithdrawAddressMethod - - BeforeEach(func() { - // set the default call arguments - callArgs.MethodName = method - }) - - It("should return error if the provided gasLimit is too low", func() { - txArgs.GasLimit = 30000 - - callArgs.Args = []interface{}{ - s.keyring.GetAddr(0), - differentAddr.String(), - } - _, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - outOfGasCheck, - ) - Expect(err).To(BeNil(), "error while calling the precompile") - Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock") - - // withdraw address should remain unchanged - delAddr := s.keyring.GetAccAddr(0).String() - res, err := s.grpcHandler.GetDelegatorWithdrawAddr(delAddr) - Expect(err).To(BeNil(), "error while calling the precompile") - Expect(res.WithdrawAddress).To(Equal(delAddr), "expected withdraw address to remain unchanged") - }) - - It("should return error if the msg.sender is different than the delegator", func() { - callArgs.Args = []interface{}{ - differentAddr, - s.keyring.GetAddr(0).String(), - } - - withdrawAddrSetCheck := defaultLogCheck.WithErrContains(cmn.ErrRequesterIsNotMsgSender, s.keyring.GetAddr(0).String(), differentAddr.String()) - - _, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - withdrawAddrSetCheck, - ) - Expect(err).To(BeNil(), "error while calling the precompile") - }) - - It("should set withdraw address", func() { - // initially, withdraw address should be same as address - res, err := s.grpcHandler.GetDelegatorWithdrawAddr(s.keyring.GetAccAddr(0).String()) - Expect(err).To(BeNil(), "error while querying withdraw address") - Expect(res.WithdrawAddress).To(Equal(s.keyring.GetAccAddr(0).String())) - - callArgs.Args = []interface{}{ - s.keyring.GetAddr(0), - differentAddr.String(), - } - - withdrawAddrSetCheck := passCheck. - WithExpEvents(distribution.EventTypeSetWithdrawAddress) - - _, _, err = s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - withdrawAddrSetCheck, - ) - Expect(err).To(BeNil(), "error while calling the precompile") - - // persist state changes - Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock") - - // withdraw should be updated - res, err = s.grpcHandler.GetDelegatorWithdrawAddr(s.keyring.GetAccAddr(0).String()) - Expect(err).To(BeNil(), "error while querying withdraw address") - Expect(res.WithdrawAddress).To(Equal(sdk.AccAddress(differentAddr.Bytes()).String()), "expected different withdraw address") - }) - }) - - Describe("Execute WithdrawDelegatorReward transaction", func() { - var accruedRewards sdk.DecCoins - - BeforeEach(func() { - var err error - // set the default call arguments - callArgs.MethodName = distribution.WithdrawDelegatorRewardMethod - - accruedRewards, err = testutils.WaitToAccrueRewards(s.network, s.grpcHandler, s.keyring.GetAccAddr(0).String(), minExpRewardOrCommission) - Expect(err).To(BeNil()) - }) - - It("should return error if the msg.sender is different than the delegator", func() { - callArgs.Args = []interface{}{ - differentAddr, - s.network.GetValidators()[0].OperatorAddress, - } - - withdrawalCheck := defaultLogCheck.WithErrContains( - cmn.ErrRequesterIsNotMsgSender, - s.keyring.GetAddr(0).String(), - differentAddr.String(), - ) - - _, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - withdrawalCheck, - ) - Expect(err).To(BeNil(), "error while calling the precompile") - }) - - It("should withdraw delegation rewards", func() { - // get initial balance - queryRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil(), "error while calling GetBalance") - initialBalance := queryRes.Balance - - txArgs.GasPrice = gasPrice.BigInt() - txArgs.GasLimit = 100_000 - - callArgs.Args = []interface{}{ - s.keyring.GetAddr(0), - s.network.GetValidators()[0].OperatorAddress, - } - - withdrawalCheck := passCheck. - WithExpEvents(distribution.EventTypeWithdrawDelegatorReward) - - res, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - withdrawalCheck, - ) - Expect(err).To(BeNil(), "error while calling the precompile") - Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock") - - var rewards []cmn.Coin - err = s.precompile.UnpackIntoInterface(&rewards, distribution.WithdrawDelegatorRewardMethod, ethRes.Ret) - Expect(err).To(BeNil()) - Expect(len(rewards)).To(Equal(1)) - - // The accrued rewards are based on 3 equal delegations to the existing 3 validators - // The query is from only 1 validator, thus, the expected reward - // for this delegation is totalAccruedRewards / validatorsCount (3) - valCount := len(s.network.GetValidators()) - accruedRewardsAmt := accruedRewards.AmountOf(s.bondDenom) - expRewardPerValidator := accruedRewardsAmt.Quo(math.LegacyNewDec(int64(valCount))) - - Expect(rewards[0].Denom).To(Equal(s.bondDenom)) - Expect(rewards[0].Amount).To(Equal(expRewardPerValidator.TruncateInt().BigInt())) - - // check that the rewards were added to the balance - queryRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil(), "error while calling GetBalance") - fees := gasPrice.Mul(math.NewInt(res.GasUsed)) - expFinal := initialBalance.Amount.Add(expRewardPerValidator.TruncateInt()).Sub(fees) - Expect(queryRes.Balance.Amount).To(Equal(expFinal), "expected final balance to be equal to initial balance + rewards - fees") - }) - - It("should withdraw rewards successfully to the new withdrawer address", func() { - balRes, err := s.grpcHandler.GetBalanceFromBank(differentAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - withdrawerInitialBalance := balRes.Balance - // Set new withdrawer address - err = s.factory.SetWithdrawAddress(s.keyring.GetPrivKey(0), differentAddr.Bytes()) - Expect(err).To(BeNil()) - // persist state change - Expect(s.network.NextBlock()).To(BeNil()) - - // get initial balance - queryRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil(), "error while calling GetBalance") - initialBalance := queryRes.Balance - - // get rewards - rwRes, err := s.grpcHandler.GetDelegationRewards(s.keyring.GetAccAddr(0).String(), s.network.GetValidators()[0].OperatorAddress) - Expect(err).To(BeNil()) - expRewardsAmt := rwRes.Rewards.AmountOf(s.bondDenom).TruncateInt() - - txArgs.GasPrice = gasPrice.BigInt() - callArgs.Args = []interface{}{ - s.keyring.GetAddr(0), - s.network.GetValidators()[0].OperatorAddress, - } - - withdrawalCheck := passCheck. - WithExpEvents(distribution.EventTypeWithdrawDelegatorReward) - - txArgs.GasLimit = 300_000 - res, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - withdrawalCheck, - ) - Expect(err).To(BeNil(), "error while calling the precompile") - Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock") - - var rewards []cmn.Coin - err = s.precompile.UnpackIntoInterface(&rewards, distribution.WithdrawDelegatorRewardMethod, ethRes.Ret) - Expect(err).To(BeNil()) - Expect(len(rewards)).To(Equal(1)) - - Expect(rewards[0].Denom).To(Equal(s.bondDenom)) - Expect(rewards[0].Amount).To(Equal(expRewardsAmt.BigInt())) - - // check that the delegator final balance is initialBalance - fee - queryRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil(), "error while calling GetBalance") - fees := gasPrice.Mul(math.NewInt(res.GasUsed)) - expDelgatorFinal := initialBalance.Amount.Sub(fees) - Expect(queryRes.Balance.Amount).To(Equal(expDelgatorFinal), "expected delegator final balance to be equal to initial balance - fees") - - // check that the rewards were added to the withdrawer balance - queryRes, err = s.grpcHandler.GetBalanceFromBank(differentAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil(), "error while calling GetBalance") - expWithdrawerFinal := withdrawerInitialBalance.Amount.Add(expRewardsAmt) - - Expect(queryRes.Balance.Amount).To(Equal(expWithdrawerFinal), "expected withdrawer final balance to be equal to initial balance + rewards") - }) - - It("should withdraw delegation rewards to a smart contract", func() { - // deploy a smart contract to use as withdrawer - distributionCallerContract, err := contracts.LoadDistributionCallerContract() - Expect(err).To(BeNil(), "error while loading the smart contract: %v", err) - - contractAddr, err := s.factory.DeployContract( - s.keyring.GetPrivKey(0), - evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values - factory.ContractDeploymentData{ - Contract: distributionCallerContract, - }, - ) - Expect(err).To(BeNil(), "error while deploying the smart contract: %v", err) - // persist state change - Expect(s.network.NextBlock()).To(BeNil()) - - balRes, err := s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - initialWithdrawerBalance := balRes.Balance - Expect(initialWithdrawerBalance.Amount).To(Equal(math.ZeroInt())) - - // set contract address as withdrawer address - err = s.factory.SetWithdrawAddress(s.keyring.GetPrivKey(0), contractAddr.Bytes()) - Expect(err).To(BeNil()) - // persist state change - Expect(s.network.NextBlock()).To(BeNil()) - - // get tx sender initial balance - balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil(), "error while calling GetBalance") - initialBalance := balRes.Balance - - // get rewards - rwRes, err := s.grpcHandler.GetDelegationRewards(s.keyring.GetAccAddr(0).String(), s.network.GetValidators()[0].OperatorAddress) - Expect(err).To(BeNil()) - expRewardsAmt := rwRes.Rewards.AmountOf(s.bondDenom).TruncateInt() - - txArgs.GasPrice = gasPrice.BigInt() - callArgs.Args = []interface{}{ - s.keyring.GetAddr(0), - s.network.GetValidators()[0].OperatorAddress, - } - - withdrawalCheck := passCheck. - WithExpEvents(distribution.EventTypeWithdrawDelegatorReward) - - txArgs.GasLimit = 300_000 - res, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - withdrawalCheck, - ) - Expect(err).To(BeNil(), "error while calling the precompile") - Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock") - - var rewards []cmn.Coin - err = s.precompile.UnpackIntoInterface(&rewards, distribution.WithdrawDelegatorRewardMethod, ethRes.Ret) - Expect(err).To(BeNil()) - Expect(len(rewards)).To(Equal(1)) - Expect(rewards[0].Denom).To(Equal(s.bondDenom)) - Expect(rewards[0].Amount).To(Equal(expRewardsAmt.BigInt())) - - // check tx sender balance is reduced by fees paid - balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - finalBalance := balRes.Balance - fees := gasPrice.MulRaw(res.GasUsed) - expFinal := initialBalance.Amount.Sub(fees) - Expect(finalBalance.Amount).To(Equal(expFinal), "expected final balance to be equal to initial balance - fees") - - // check that the rewards were added to the withdrawer balance - balRes, err = s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - finalWithdrawerBalance := balRes.Balance - Expect(finalWithdrawerBalance.Amount).To(Equal(expRewardsAmt)) - }) - }) - - Describe("Validator Commission: Execute WithdrawValidatorCommission tx", func() { - // expCommAmt is the expected commission amount - expCommAmt := math.NewInt(1) - - BeforeEach(func() { - // set the default call arguments - callArgs.MethodName = distribution.WithdrawValidatorCommissionMethod - valAddr := sdk.ValAddress(s.validatorsKeys[0].AccAddr) - - _, err := testutils.WaitToAccrueCommission( - s.network, s.grpcHandler, - valAddr.String(), - sdk.NewDecCoins(sdk.NewDecCoin(s.bondDenom, expCommAmt)), - ) - Expect(err).To(BeNil()) - - // Send some funds to the validator to pay for fees - err = testutils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), s.validatorsKeys[0].AccAddr, math.NewInt(1e17)) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - }) - - It("should return error if the provided gasLimit is too low", func() { - txArgs.GasLimit = 50000 - callArgs.Args = []interface{}{ - s.network.GetValidators()[0].OperatorAddress, - } - - _, _, err := s.factory.CallContractAndCheckLogs( - s.validatorsKeys[0].Priv, - txArgs, - callArgs, - outOfGasCheck, - ) - Expect(err).To(BeNil(), "error while calling the precompile") - }) - - It("should return error if the msg.sender is different than the validator", func() { - callArgs.Args = []interface{}{ - s.network.GetValidators()[0].OperatorAddress, - } - - validatorHexAddr := common.BytesToAddress(s.validatorsKeys[0].AccAddr) - - withdrawalCheck := defaultLogCheck.WithErrContains(cmn.ErrRequesterIsNotMsgSender, s.keyring.GetAddr(0).String(), validatorHexAddr.String()) - - _, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - withdrawalCheck, - ) - Expect(err).To(BeNil(), "error while calling the precompile") - }) - - It("should withdraw validator commission", func() { - // initial balance should be the initial amount minus the staked amount used to create the validator - queryRes, err := s.grpcHandler.GetBalanceFromBank(s.validatorsKeys[0].AccAddr, s.bondDenom) - Expect(err).To(BeNil(), "error while calling GetBalance") - - initialBalance := queryRes.Balance - - // get the accrued commission amount - commRes, err := s.grpcHandler.GetValidatorCommission(s.network.GetValidators()[0].OperatorAddress) - Expect(err).To(BeNil()) - expCommAmt := commRes.Commission.Commission.AmountOf(s.bondDenom).TruncateInt() - - callArgs.Args = []interface{}{s.network.GetValidators()[0].OperatorAddress} - txArgs.GasPrice = gasPrice.BigInt() - - withdrawalCheck := passCheck. - WithExpEvents(distribution.EventTypeWithdrawValidatorCommission) - - txArgs.GasLimit = 300_000 - res, ethRes, err := s.factory.CallContractAndCheckLogs( - s.validatorsKeys[0].Priv, - txArgs, - callArgs, - withdrawalCheck, - ) - Expect(err).To(BeNil(), "error while calling the precompile") - - var comm []cmn.Coin - err = s.precompile.UnpackIntoInterface(&comm, distribution.WithdrawValidatorCommissionMethod, ethRes.Ret) - Expect(err).To(BeNil()) - Expect(len(comm)).To(Equal(1)) - Expect(comm[0].Denom).To(Equal(s.bondDenom)) - Expect(comm[0].Amount).To(Equal(expCommAmt.BigInt())) - - Expect(s.network.NextBlock()).To(BeNil()) - - queryRes, err = s.grpcHandler.GetBalanceFromBank(s.validatorsKeys[0].AccAddr, s.bondDenom) - Expect(err).To(BeNil(), "error while calling GetBalance") - finalBalance := queryRes.Balance - - fees := gasPrice.Mul(math.NewInt(res.GasUsed)) - expFinal := initialBalance.Amount.Add(expCommAmt).Sub(fees) - - Expect(finalBalance.Amount).To(Equal(expFinal), "expected final balance to be equal to the final balance after withdrawing commission") - }) - - It("should withdraw validator commission to a smart contract", func() { - // deploy a smart contract to use as withdrawer - distributionCallerContract, err := contracts.LoadDistributionCallerContract() - Expect(err).To(BeNil(), "error while loading the smart contract: %v", err) - - contractAddr, err := s.factory.DeployContract( - s.keyring.GetPrivKey(0), - evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values - factory.ContractDeploymentData{ - Contract: distributionCallerContract, - }, - ) - Expect(err).To(BeNil(), "error while deploying the smart contract: %v", err) - // persist state change - Expect(s.network.NextBlock()).To(BeNil()) - - balRes, err := s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - initialWithdrawerBalance := balRes.Balance - Expect(initialWithdrawerBalance.Amount).To(Equal(math.ZeroInt())) - - // set contract address as withdrawer address - err = s.factory.SetWithdrawAddress(s.validatorsKeys[0].Priv, contractAddr.Bytes()) - Expect(err).To(BeNil()) - // persist state change - Expect(s.network.NextBlock()).To(BeNil()) - - // get validator initial balance - balRes, err = s.grpcHandler.GetBalanceFromBank(s.validatorsKeys[0].AccAddr, s.bondDenom) - Expect(err).To(BeNil(), "error while calling GetBalance") - initialBalance := balRes.Balance - - // get the accrued commission amount - commRes, err := s.grpcHandler.GetValidatorCommission(s.network.GetValidators()[0].OperatorAddress) - Expect(err).To(BeNil()) - expCommAmt := commRes.Commission.Commission.AmountOf(s.bondDenom).TruncateInt() - - callArgs.Args = []interface{}{s.network.GetValidators()[0].OperatorAddress} - txArgs.GasPrice = gasPrice.BigInt() - - withdrawalCheck := passCheck. - WithExpEvents(distribution.EventTypeWithdrawValidatorCommission) - - txArgs.GasLimit = 300_000 - res, ethRes, err := s.factory.CallContractAndCheckLogs( - s.validatorsKeys[0].Priv, - txArgs, - callArgs, - withdrawalCheck, - ) - Expect(err).To(BeNil(), "error while calling the precompile") - // persist state change - Expect(s.network.NextBlock()).To(BeNil()) - - var comm []cmn.Coin - err = s.precompile.UnpackIntoInterface(&comm, distribution.WithdrawValidatorCommissionMethod, ethRes.Ret) - Expect(err).To(BeNil()) - Expect(len(comm)).To(Equal(1)) - Expect(comm[0].Denom).To(Equal(s.bondDenom)) - Expect(comm[0].Amount).To(Equal(expCommAmt.BigInt())) - - balRes, err = s.grpcHandler.GetBalanceFromBank(s.validatorsKeys[0].AccAddr, s.bondDenom) - Expect(err).To(BeNil(), "error while calling GetBalance") - finalBalance := balRes.Balance - - fees := gasPrice.MulRaw(res.GasUsed) - expFinal := initialBalance.Amount.Sub(fees) - Expect(finalBalance.Amount).To(Equal(expFinal), "expected final balance to be equal to the final balance after withdrawing commission") - - // check that the commission was added to the withdrawer balance - balRes, err = s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - finalWithdrawerBalance := balRes.Balance - Expect(finalWithdrawerBalance.Amount).To(Equal(expCommAmt)) - }) - }) - - Describe("Execute ClaimRewards transaction", func() { - // defaultWithdrawRewardsArgs are the default arguments to withdraw rewards - // - // NOTE: this has to be populated in the BeforeEach block because the private key otherwise is not yet initialized. - var accruedRewards sdk.DecCoins - - BeforeEach(func() { - var err error - // set the default call arguments - callArgs.MethodName = distribution.ClaimRewardsMethod - accruedRewards, err = testutils.WaitToAccrueRewards( - s.network, - s.grpcHandler, - s.keyring.GetAccAddr(0).String(), - minExpRewardOrCommission) - Expect(err).To(BeNil(), "error waiting to accrue rewards") - }) - - It("should return err if the msg.sender is different than the delegator", func() { - callArgs.Args = []interface{}{ - differentAddr, uint32(1), - } - - claimRewardsCheck := defaultLogCheck.WithErrContains(cmn.ErrRequesterIsNotMsgSender, s.keyring.GetAddr(0).String(), differentAddr.String()) - - _, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - claimRewardsCheck, - ) - Expect(err).To(BeNil(), "error while calling the precompile") - }) - - It("should claim all rewards from all validators", func() { - queryRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil(), "error while calling GetBalance") - initialBalance := queryRes.Balance - - valCount := len(s.network.GetValidators()) - callArgs.Args = []interface{}{ - s.keyring.GetAddr(0), uint32(valCount), - } - txArgs.GasLimit = 250_000 - - // get base fee to use in tx to then calculate fee paid - bfQuery, err := s.grpcHandler.GetEvmBaseFee() - Expect(err).To(BeNil(), "error while calling BaseFee") - gasPrice := bfQuery.BaseFee.BigInt() - txArgs.GasPrice = gasPrice - - claimRewardsCheck := passCheck.WithExpEvents(distribution.EventTypeClaimRewards) - - txRes, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - claimRewardsCheck, - ) - Expect(err).To(BeNil(), "error while calling the precompile") - - // persist state change - Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock") - - // check that the rewards were added to the balance - queryRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil(), "error while calling GetBalance") - - // get the fee paid and calculate the expFinalBalance - fee := gasPrice.Mul(math.NewInt(txRes.GasUsed).BigInt(), gasPrice) - accruedRewardsAmt := accruedRewards.AmountOf(s.bondDenom).TruncateInt() - // expected balance is initial + rewards - fee - expBalanceAmt := initialBalance.Amount.Add(accruedRewardsAmt).Sub(math.NewIntFromBigInt(fee)) - - finalBalance := queryRes.Balance - Expect(finalBalance.Amount).To(Equal(expBalanceAmt), "expected final balance to be equal to initial balance + rewards - fees") - }) - }) - - Describe("Execute DepositValidatorRewardsPool transaction", func() { - const method = distribution.DepositValidatorRewardsPoolMethod - - BeforeEach(func() { - txArgs.GasLimit = 300_000 - txArgs.GasPrice = gasPrice.BigInt() - callArgs.MethodName = method - }) - - It("should revert if the msg.sender is different from the depositor", func() { - callArgs.Args = []interface{}{ - differentAddr, // depositor - s.network.GetValidators()[0].OperatorAddress, - []cmn.Coin{ - {Denom: s.bondDenom, Amount: big.NewInt(1_000_000)}, - }, - } - - failureCheck := defaultLogCheck.WithErrContains( - cmn.ErrRequesterIsNotMsgSender, - s.keyring.GetAddr(0).String(), - differentAddr, - ) - - _, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), // tx from Addr0 - txArgs, - callArgs, - failureCheck, - ) - Expect(err).To(BeNil()) - }) - - It("should revert if the depositor has insufficient funds", func() { - balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - excessAmount := balRes.Balance.Amount.Add(math.NewInt(1)) - - callArgs.Args = []interface{}{ - s.keyring.GetAddr(0), - s.network.GetValidators()[0].OperatorAddress, - []cmn.Coin{{Denom: s.bondDenom, Amount: excessAmount.BigInt()}}, - } - - failureCheck := defaultLogCheck.WithErrContains("insufficient funds") - - _, _, err = s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - failureCheck, - ) - Expect(err).To(BeNil()) - }) - - It("should deposit rewards to the validator rewards pool", func() { - // check initial balance - balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - initialBalance := balRes.Balance - - callArgs.Args = []interface{}{ - s.keyring.GetAddr(0), // depositor - s.network.GetValidators()[0].OperatorAddress, - []cmn.Coin{ - {Denom: s.bondDenom, Amount: big.NewInt(1_000_000)}, - }, - } - - passCheckWithEvent := passCheck.WithExpEvents(distribution.EventTypeDepositValidatorRewardsPool) - - _, txRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), // tx from Addr0 - txArgs, - callArgs, - passCheckWithEvent, - ) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - // check that the balance is reduced by the amount deposited - expBalance := initialBalance.Amount.Sub(math.NewInt(1_000_000)) - fees := math.NewIntFromUint64(txRes.GasUsed).Mul(math.NewIntFromBigInt(txArgs.GasPrice)) - expBalance = expBalance.Sub(fees) - - balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - Expect(balRes.Balance.Amount).To(Equal(expBalance), "expected final balance to be equal to initial balance - deposit amount") - }) - - It("should deposit rewards to the validator rewards pool with multiple coins", func() { - // get initial balances - balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - initialBalance := balRes.Balance - - balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.otherDenoms[0]) - Expect(err).To(BeNil()) - initialBalance1 := balRes.Balance - - balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.otherDenoms[1]) - Expect(err).To(BeNil()) - initialBalance2 := balRes.Balance - - callArgs.Args = []interface{}{ - s.keyring.GetAddr(0), // depositor - s.network.GetValidators()[0].OperatorAddress, - []cmn.Coin{ - {Denom: s.bondDenom, Amount: big.NewInt(1_000_000)}, - {Denom: s.otherDenoms[0], Amount: big.NewInt(1_000_001)}, - {Denom: s.otherDenoms[1], Amount: big.NewInt(1_000_002)}, - }, - } - - passCheckWithEvent := passCheck.WithExpEvents( - distribution.EventTypeDepositValidatorRewardsPool, - distribution.EventTypeDepositValidatorRewardsPool, - distribution.EventTypeDepositValidatorRewardsPool, - ) - - _, txRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), // tx from Addr0 - txArgs, - callArgs, - passCheckWithEvent, - ) - Expect(err).To(BeNil()) - Expect(txRes).NotTo(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - fees := math.NewIntFromUint64(txRes.GasUsed).Mul(math.NewIntFromBigInt(txArgs.GasPrice)) - - // check that the balance is reduced by the amount deposited - balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - expBalance := initialBalance.Amount.Sub(math.NewInt(1_000_000)).Sub(fees) - Expect(balRes.Balance.Amount).To(Equal(expBalance), "expected final balance to be equal to initial balance - deposit amount") - - balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.otherDenoms[0]) - Expect(err).To(BeNil()) - expBalance1 := initialBalance1.Amount.Sub(math.NewInt(1_000_001)) - Expect(balRes.Balance.Amount).To(Equal(expBalance1), "expected final balance to be equal to initial balance - deposit amount") - - balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.otherDenoms[1]) - Expect(err).To(BeNil()) - expBalance2 := initialBalance2.Amount.Sub(math.NewInt(1_000_002)) - Expect(balRes.Balance.Amount).To(Equal(expBalance2), "expected final balance to be equal to initial balance - deposit amount") - }) - }) - - Describe("Execute FundCommunityPool transaction", func() { - const method = distribution.FundCommunityPoolMethod - - BeforeEach(func() { - callArgs.MethodName = method - }) - - It("should fail if the depositor has insufficient balance", func() { - // Here, we attempt to deposit an amount that the EOA does not have. - - // 1) Query the current balance - balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - initialBalance := balRes.Balance - - // 2) Attempt to deposit more than current balance - deposit := initialBalance.Amount.Add(math.NewInt(9999999999)) - - callArgs.Args = []interface{}{ - s.keyring.GetAddr(0), - []cmn.Coin{ - {Denom: s.bondDenom, Amount: deposit.BigInt()}, - }, - } - - // We expect the tx to fail ("execution reverted") because of insufficient funds - insufficientFundsCheck := defaultLogCheck.WithErrContains("insufficient funds") - - _, _, err = s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - insufficientFundsCheck, - ) - Expect(err).To(BeNil()) - }) - - It("should fund the community pool successfully from EOA", func() { - // 1) Fund the EOA to ensure it has enough tokens - err := testutils.FundAccountWithBaseDenom( - s.factory, s.network, - s.keyring.GetKey(0), - s.keyring.GetAccAddr(0), - math.NewInt(1_000_000), - ) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - initialEOABal := balRes.Balance - - // 2) Prepare and execute the FundCommunityPool call - fundAmt := math.NewInt(10) - callArgs.Args = []interface{}{ - s.keyring.GetAddr(0), - []cmn.Coin{ - {Denom: s.bondDenom, Amount: fundAmt.BigInt()}, - }, - } - - txArgs.GasPrice = gasPrice.BigInt() - txArgs.GasLimit = 500_000 - - logCheckArgs := passCheck.WithExpEvents(distribution.EventTypeFundCommunityPool) - - res, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil()) - - // Persist state changes - Expect(s.network.NextBlock()).To(BeNil()) - - // 3) Ensure the EOA's final balance is decreased by (fundAmt + fees) - balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - finalEOABal := balRes.Balance - - fees := gasPrice.Mul(math.NewInt(res.GasUsed)) - // The final balance must be: initialBalance - fundAmt - fees - // We only check if it's consistent ( >= ), because we funded the EOA in step 1 - expLowerBound := fundAmt.Add(fees) - - diff := initialEOABal.Amount.Sub(finalEOABal.Amount) - Expect(diff.GTE(expLowerBound)).To(BeTrue(), - "final EOA balance must be decreased at least by funded amt + fees") - }) - - It("should fund multiple coins to the community pool successfully from EOA", func() { - // 1) Fund the EOA to ensure it has enough tokens - err := testutils.FundAccountWithBaseDenom( - s.factory, s.network, - s.keyring.GetKey(0), - s.keyring.GetAccAddr(0), - math.NewInt(1_000_000), - ) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - balRes, err := s.grpcHandler.GetAllBalances(s.keyring.GetAccAddr(0)) - Expect(err).To(BeNil()) - initialEOABals := balRes.Balances - - // 2) Prepare and execute the FundCommunityPool call - fundAmt := math.NewInt(10) - sendAmt := []cmn.Coin{ - {Denom: s.bondDenom, Amount: fundAmt.BigInt()}, - {Denom: testconstants.OtherCoinDenoms[0], Amount: fundAmt.BigInt()}, - {Denom: testconstants.OtherCoinDenoms[1], Amount: fundAmt.BigInt()}, - } - sendSdkCoins, err := cmn.NewSdkCoinsFromCoins(sendAmt) - Expect(err).To(BeNil()) - - callArgs.Args = []interface{}{s.keyring.GetAddr(0), sendAmt} - - txArgs.GasPrice = gasPrice.BigInt() - txArgs.GasLimit = 500_000 - - logCheckArgs := passCheck.WithExpEvents( - distribution.EventTypeFundCommunityPool, - distribution.EventTypeFundCommunityPool, - distribution.EventTypeFundCommunityPool, - ) - - _, _, err = s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil()) - - // Persist state changes - Expect(s.network.NextBlock()).To(BeNil()) - - // 3) Ensure the EOA's final balance is decreased by (fundAmt + fees) - balRes, err = s.grpcHandler.GetAllBalances(s.keyring.GetAccAddr(0)) - Expect(err).To(BeNil()) - finalEOABals := balRes.Balances - - diffs := initialEOABals.Sub(finalEOABals...) - Expect(diffs.IsAllGTE(sendSdkCoins)).To(BeTrue(), - "final EOA balance must be decreased at least by funded amt + fees") - }) - }) - - // ===================================== - // QUERIES - // ===================================== - Describe("Execute queries", func() { - It("should get validator distribution info - validatorDistributionInfo query", func() { - // fund validator account to make self-delegation - err := testutils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), s.validatorsKeys[0].AccAddr, math.NewInt(1e17)) - Expect(err).To(BeNil()) - // persist changes - Expect(s.network.NextBlock()).To(BeNil()) - - opAddr := s.network.GetValidators()[0].OperatorAddress - // use the validator priv key - // make a self delegation - err = s.factory.Delegate(s.validatorsKeys[0].Priv, opAddr, sdk.NewCoin(s.bondDenom, math.NewInt(1))) - Expect(err).To(BeNil()) - // persist changes - Expect(s.network.NextBlock()).To(BeNil()) - - callArgs.MethodName = distribution.ValidatorDistributionInfoMethod - callArgs.Args = []interface{}{opAddr} - txArgs.GasLimit = 200_000 - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.validatorsKeys[0].Priv, - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the precompile") - - var out distribution.ValidatorDistributionInfoOutput - err = s.precompile.UnpackIntoInterface(&out, distribution.ValidatorDistributionInfoMethod, ethRes.Ret) - Expect(err).To(BeNil()) - - expAddr := s.validatorsKeys[0].AccAddr.String() - Expect(expAddr).To(Equal(out.DistributionInfo.OperatorAddress)) - Expect(1).To(Equal(len(out.DistributionInfo.Commission))) - Expect(1).To(Equal(len(out.DistributionInfo.SelfBondRewards))) - }) - - It("should get validator outstanding rewards - validatorOutstandingRewards query", func() { - accruedRewards, err := testutils.WaitToAccrueRewards( - s.network, - s.grpcHandler, - s.keyring.GetAccAddr(0).String(), - minExpRewardOrCommission) - Expect(err).To(BeNil(), "error waiting to accrue rewards") - - callArgs.MethodName = distribution.ValidatorOutstandingRewardsMethod - callArgs.Args = []interface{}{s.network.GetValidators()[0].OperatorAddress} - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the precompile") - - var rewards []cmn.DecCoin - err = s.precompile.UnpackIntoInterface(&rewards, distribution.ValidatorOutstandingRewardsMethod, ethRes.Ret) - Expect(err).To(BeNil()) - Expect(len(rewards)).To(Equal(1)) - - Expect(uint8(18)).To(Equal(rewards[0].Precision)) - Expect(s.bondDenom).To(Equal(rewards[0].Denom)) - - // the expected rewards should be the accruedRewards per validator - // plus the 5% commission - expRewardAmt := accruedRewards.AmountOf(s.bondDenom). - Quo(math.LegacyNewDec(3)). - Quo(math.LegacyNewDecWithPrec(95, 2)). // add 5% commission - TruncateInt() - - Expect(rewards[0].Amount.String()).To(Equal(expRewardAmt.BigInt().String())) - }) - - It("should get validator commission - validatorCommission query", func() { - opAddr := s.network.GetValidators()[0].OperatorAddress - accruedCommission, err := testutils.WaitToAccrueCommission( - s.network, - s.grpcHandler, - opAddr, - minExpRewardOrCommission) - Expect(err).To(BeNil(), "error waiting to accrue rewards") - - callArgs.MethodName = distribution.ValidatorCommissionMethod - callArgs.Args = []interface{}{opAddr} - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the precompile") - - var commission []cmn.DecCoin - err = s.precompile.UnpackIntoInterface(&commission, distribution.ValidatorCommissionMethod, ethRes.Ret) - Expect(err).To(BeNil()) - Expect(len(commission)).To(Equal(1)) - Expect(uint8(18)).To(Equal(commission[0].Precision)) - Expect(s.bondDenom).To(Equal(commission[0].Denom)) - - expCommissionAmt := accruedCommission.AmountOf(s.bondDenom).TruncateInt() - Expect(commission[0].Amount).To(Equal(expCommissionAmt.BigInt())) - }) - - Context("validatorSlashes query query", Ordered, func() { - BeforeAll(func() { - s.withValidatorSlashes = true - s.SetupTest() - }) - AfterAll(func() { - s.withValidatorSlashes = false - }) - - It("should get validator slashing events (default pagination)", func() { - callArgs.MethodName = distribution.ValidatorSlashesMethod - callArgs.Args = []interface{}{ - s.network.GetValidators()[0].OperatorAddress, - uint64(1), uint64(5), - query.PageRequest{}, - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil()) - - var out distribution.ValidatorSlashesOutput - err = s.precompile.UnpackIntoInterface(&out, distribution.ValidatorSlashesMethod, ethRes.Ret) - Expect(err).To(BeNil()) - Expect(len(out.Slashes)).To(Equal(2)) - // expected values according to the values used on test setup (custom genesis) - for _, s := range out.Slashes { - Expect(s.Fraction.Value).To(Equal(math.LegacyNewDecWithPrec(5, 2).BigInt())) - Expect(s.ValidatorPeriod).To(Equal(uint64(1))) - } - Expect(uint64(2)).To(Equal(out.PageResponse.Total)) - Expect(out.PageResponse.NextKey).To(BeEmpty()) - }) - - It("should get validator slashing events - query w/pagination limit = 1)", func() { - callArgs.MethodName = distribution.ValidatorSlashesMethod - callArgs.Args = []interface{}{ - s.network.GetValidators()[0].OperatorAddress, - uint64(1), uint64(5), - query.PageRequest{ - Limit: 1, - CountTotal: true, - }, - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil()) - - var out distribution.ValidatorSlashesOutput - err = s.precompile.UnpackIntoInterface(&out, distribution.ValidatorSlashesMethod, ethRes.Ret) - Expect(err).To(BeNil()) - Expect(len(out.Slashes)).To(Equal(1)) - Expect(out.Slashes[0].Fraction.Value).To(Equal(math.LegacyNewDecWithPrec(5, 2).BigInt())) - Expect(out.Slashes[0].ValidatorPeriod).To(Equal(uint64(1))) - // total slashes count is 2 - Expect(uint64(2)).To(Equal(out.PageResponse.Total)) - Expect(out.PageResponse.NextKey).NotTo(BeEmpty()) - }) - }) - - It("should get empty delegation rewards - delegationRewards query", func() { - callArgs.MethodName = distribution.DelegationRewardsMethod - callArgs.Args = []interface{}{ - s.keyring.GetAddr(0), - s.network.GetValidators()[0].OperatorAddress, - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the precompile") - - var rewards []cmn.DecCoin - err = s.precompile.UnpackIntoInterface(&rewards, distribution.DelegationRewardsMethod, ethRes.Ret) - Expect(err).To(BeNil()) - Expect(len(rewards)).To(Equal(0)) - }) - - It("should get delegation rewards - delegationRewards query", func() { - accruedRewards, err := testutils.WaitToAccrueRewards(s.network, s.grpcHandler, s.keyring.GetAccAddr(0).String(), minExpRewardOrCommission) - Expect(err).To(BeNil()) - - callArgs.MethodName = distribution.DelegationRewardsMethod - callArgs.Args = []interface{}{ - s.keyring.GetAddr(0), - s.network.GetValidators()[0].OperatorAddress, - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the precompile") - - var rewards []cmn.DecCoin - err = s.precompile.UnpackIntoInterface(&rewards, distribution.DelegationRewardsMethod, ethRes.Ret) - Expect(err).To(BeNil()) - Expect(len(rewards)).To(Equal(1)) - - // The accrued rewards are based on 3 equal delegations to the existing 3 validators - // The query is from only 1 validator, thus, the expected reward - // for this delegation is totalAccruedRewards / validatorsCount (3) - expRewardAmt := accruedRewards.AmountOf(s.bondDenom).Quo(math.LegacyNewDec(3)) - - Expect(rewards[0].Denom).To(Equal(s.bondDenom)) - Expect(rewards[0].Amount).To(Equal(expRewardAmt.TruncateInt().BigInt())) - }) - - It("should get delegators's total rewards - delegationTotalRewards query", func() { - // wait for rewards to accrue - accruedRewards, err := testutils.WaitToAccrueRewards(s.network, s.grpcHandler, s.keyring.GetAccAddr(0).String(), minExpRewardOrCommission) - Expect(err).To(BeNil()) - - callArgs.MethodName = distribution.DelegationTotalRewardsMethod - callArgs.Args = []interface{}{s.keyring.GetAddr(0)} - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the precompile") - - var out distribution.DelegationTotalRewardsOutput - - err = s.precompile.UnpackIntoInterface(&out, distribution.DelegationTotalRewardsMethod, ethRes.Ret) - Expect(err).To(BeNil()) - Expect(3).To(Equal(len(out.Rewards))) - - // The accrued rewards are based on 3 equal delegations to the existing 3 validators - // The query is from only 1 validator, thus, the expected reward - // for this delegation is totalAccruedRewards / validatorsCount (3) - accruedRewardsAmt := accruedRewards.AmountOf(s.bondDenom) - expRewardPerValidator := accruedRewardsAmt.Quo(math.LegacyNewDec(3)) - - // the response order may change - for _, or := range out.Rewards { - Expect(1).To(Equal(len(or.Reward))) - Expect(or.Reward[0].Denom).To(Equal(s.bondDenom)) - Expect(or.Reward[0].Amount).To(Equal(expRewardPerValidator.TruncateInt().BigInt())) - } - - Expect(1).To(Equal(len(out.Total))) - Expect(out.Total[0].Amount).To(Equal(accruedRewardsAmt.TruncateInt().BigInt())) - }) - - It("should get all validators a delegators has delegated to - delegatorValidators query", func() { - callArgs.MethodName = distribution.DelegatorValidatorsMethod - callArgs.Args = []interface{}{s.keyring.GetAddr(0)} - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the precompile") - - var validators []string - err = s.precompile.UnpackIntoInterface(&validators, distribution.DelegatorValidatorsMethod, ethRes.Ret) - Expect(err).To(BeNil()) - Expect(3).To(Equal(len(validators))) - }) - - It("should get withdraw address - delegatorWithdrawAddress query", func() { - callArgs.MethodName = distribution.DelegatorWithdrawAddressMethod - callArgs.Args = []interface{}{s.keyring.GetAddr(0)} - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the precompile") - - withdrawAddr, err := s.precompile.Unpack(distribution.DelegatorWithdrawAddressMethod, ethRes.Ret) - Expect(err).To(BeNil()) - // get the bech32 encoding - expAddr := s.keyring.GetAccAddr(0) - Expect(withdrawAddr[0]).To(Equal(expAddr.String())) - }) - - It("should get community pool coins - communityPool query", func() { - fundAmount := big.NewInt(1_000_000) - callArgs.MethodName = distribution.FundCommunityPoolMethod - callArgs.Args = []interface{}{ - s.keyring.GetAddr(0), - []cmn.Coin{ - {Denom: s.bondDenom, Amount: fundAmount}, - }, - } - - txArgs.GasLimit = 200_000 - - fundCheck := passCheck.WithExpEvents(distribution.EventTypeFundCommunityPool) - - _, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - fundCheck, - ) - Expect(err).To(BeNil(), "error while calling the precompile") - Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock") - - callArgs.MethodName = distribution.CommunityPoolMethod - callArgs.Args = []interface{}{} - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the precompile") - - var coins []cmn.DecCoin - err = s.precompile.UnpackIntoInterface(&coins, distribution.CommunityPoolMethod, ethRes.Ret) - Expect(err).To(BeNil()) - Expect(len(coins)).To(Equal(1)) - Expect(coins[0].Denom).To(Equal(s.bondDenom)) - Expect(coins[0].Amount.Cmp(fundAmount)).To(Equal(1)) - }) - }) -}) - -var _ = Describe("Calling distribution precompile from contract", Ordered, func() { - s := new(PrecompileTestSuite) - // testCase is a struct used for cases of contracts calls that have some operation - // performed before and/or after the precompile call - type testCase struct { - withdrawer *common.Address - before bool - after bool - } - - var ( - distrCallerContract evmtypes.CompiledContract - // contractAddr is the address of the smart contract that will be deployed - contractAddr common.Address - contractAccAddr sdk.AccAddress - err error - - // execRevertedCheck defines the default log checking arguments which includes the - // standard revert message. - execRevertedCheck testutil.LogCheckArgs - ) - - BeforeAll(func() { - distrCallerContract, err = contracts.LoadDistributionCallerContract() - Expect(err).To(BeNil(), "error while loading the smart contract: %v", err) - }) - - BeforeEach(func() { - s.SetupTest() - - // send funds to the contract - err := testutils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), contractAddr.Bytes(), math.NewInt(2e18)) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - contractAddr, err = s.factory.DeployContract( - s.keyring.GetPrivKey(0), - evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values - factory.ContractDeploymentData{ - Contract: distrCallerContract, - }, - ) - Expect(err).To(BeNil(), "error while deploying the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil(), "error calling NextBlock: %v", err) - contractAccAddr = sdk.AccAddress(contractAddr.Bytes()) - - // check contract was correctly deployed - cAcc := s.network.App.EVMKeeper.GetAccount(s.network.GetContext(), contractAddr) - Expect(cAcc).ToNot(BeNil(), "contract account should exist") - Expect(cAcc.IsContract()).To(BeTrue(), "account should be a contract") - - // Contract delegate - stkPrecompile, err := s.getStakingPrecompile() - Expect(err).To(BeNil(), "error while getting staking precompile: %v", err) - // make a delegation with contract as delegator - logCheck := testutil.LogCheckArgs{ - ExpPass: true, - ABIEvents: stkPrecompile.ABI.Events, - ExpEvents: []string{staking.EventTypeDelegate}, - } - delegateAmt := big.NewInt(1e18) - _, _, err = s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - evmtypes.EvmTxArgs{ - To: &contractAddr, - GasLimit: 500_000, - Amount: delegateAmt, - }, - factory.CallArgs{ - ContractABI: distrCallerContract.ABI, - MethodName: "testDelegateFromContract", - Args: []interface{}{ - s.network.GetValidators()[0].OperatorAddress, - delegateAmt, - }, - }, - logCheck, - ) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - // wait to accrue some rewards for contract address - _, err = testutils.WaitToAccrueRewards(s.network, s.grpcHandler, contractAccAddr.String(), minExpRewardOrCommission) - Expect(err).To(BeNil()) - - // populate default call args - callArgs = factory.CallArgs{ - ContractABI: distrCallerContract.ABI, - } - - // reset tx args each test to avoid keeping custom - // values of previous tests (e.g. gasLimit) - txArgs = evmtypes.EvmTxArgs{ - To: &contractAddr, - } - - // default log check arguments - defaultLogCheck = testutil.LogCheckArgs{ABIEvents: s.precompile.Events} - execRevertedCheck = defaultLogCheck.WithErrContains("execution reverted") - passCheck = defaultLogCheck.WithExpPass(true) - }) - - // ===================================== - // TRANSACTIONS - // ===================================== - Context("setWithdrawAddress", func() { - // newWithdrawer is the address to set the withdraw address to - newWithdrawer := differentAddr - - BeforeEach(func() { - // withdraw address should be same as address - res, err := s.grpcHandler.GetDelegatorWithdrawAddr(s.keyring.GetAccAddr(0).String()) - Expect(err).To(BeNil(), "error while calling the precompile") - Expect(res.WithdrawAddress).To(Equal(s.keyring.GetAccAddr(0).String())) - - // populate default arguments - callArgs.MethodName = "testSetWithdrawAddress" - }) - - It("should set withdraw address successfully", func() { - txArgs = evmtypes.EvmTxArgs{ - To: &contractAddr, - } - callArgs.Args = []interface{}{ - contractAddr, newWithdrawer.String(), - } - - setWithdrawCheck := passCheck.WithExpEvents(distribution.EventTypeSetWithdrawAddress) - - _, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - setWithdrawCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) - - queryRes, err := s.grpcHandler.GetDelegatorWithdrawAddr(contractAccAddr.String()) - Expect(err).To(BeNil(), "error while calling the precompile") - Expect(queryRes.WithdrawAddress).To(Equal(sdk.AccAddress(newWithdrawer.Bytes()).String())) - }) - }) - - Context("setWithdrawerAddress with contract as delegator", func() { - // newWithdrawer is the address to set the withdraw address to - newWithdrawer := differentAddr - - BeforeEach(func() { - // withdraw address should be same as address - res, err := s.grpcHandler.GetDelegatorWithdrawAddr(s.keyring.GetAccAddr(0).String()) - Expect(err).To(BeNil(), "error while calling the precompile") - Expect(res.WithdrawAddress).To(Equal(s.keyring.GetAccAddr(0).String())) - - // populate default arguments - callArgs.MethodName = "testSetWithdrawAddressFromContract" - }) - - It("should set withdraw address successfully", func() { - callArgs.Args = []interface{}{newWithdrawer.String()} - setWithdrawCheck := passCheck.WithExpEvents(distribution.EventTypeSetWithdrawAddress) - - _, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - setWithdrawCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) - - res, err := s.grpcHandler.GetDelegatorWithdrawAddr(sdk.AccAddress(contractAddr.Bytes()).String()) - Expect(err).To(BeNil(), "error while calling GetDelegatorWithdrawAddr: %v", err) - Expect(res.WithdrawAddress).To(Equal(sdk.AccAddress(newWithdrawer.Bytes()).String())) - }) - }) - - Context("withdrawDelegatorRewards", func() { - // initialBalance is the initial balance of the delegator - var initialBalance *sdk.Coin - - BeforeEach(func() { - // fund the diffAddr - err := testutils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), differentAddr.Bytes(), math.NewInt(2e18)) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - // make a delegation - err = s.factory.Delegate(diffKey, s.network.GetValidators()[0].OperatorAddress, sdk.NewCoin(s.bondDenom, math.NewInt(1e18))) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - // wait to accrue some rewards for s.keyring.GetAddr(0) & another address - _, err = testutils.WaitToAccrueRewards(s.network, s.grpcHandler, sdk.AccAddress(differentAddr.Bytes()).String(), minExpRewardOrCommission) - Expect(err).To(BeNil()) - - // check if s.keyring.GetAddr(0) accrued rewards too - _, err = testutils.WaitToAccrueRewards(s.network, s.grpcHandler, s.keyring.GetAccAddr(0).String(), minExpRewardOrCommission) - Expect(err).To(BeNil()) - - balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - initialBalance = balRes.Balance - - callArgs.MethodName = "testWithdrawDelegatorReward" - - // set gas price to calculate fees paid - txArgs.GasPrice = gasPrice.BigInt() - }) - - It("should not withdraw rewards when sending from a different address", func() { - balRes, err := s.grpcHandler.GetBalanceFromBank(differentAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - differentAddrInitialBalance := balRes.Balance - - callArgs.Args = []interface{}{ - differentAddr, s.network.GetValidators()[0].OperatorAddress, - } - - res, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - execRevertedCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) - - // balance should be equal as initial balance or less (because of fees) - balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - finalBalance := balRes.Balance - fees := gasPrice.Mul(math.NewInt(res.GasUsed)) - Expect(finalBalance.Amount).To(Equal(initialBalance.Amount.Sub(fees))) - - // differentAddr balance should remain unchanged - balRes, err = s.grpcHandler.GetBalanceFromBank(differentAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - differentAddrFinalBalance := balRes.Balance - Expect(differentAddrFinalBalance.Amount).To(Equal(differentAddrInitialBalance.Amount)) - }) - - It("should withdraw rewards successfully", func() { - balRes, err := s.grpcHandler.GetBalanceFromBank(contractAccAddr, s.bondDenom) - Expect(err).To(BeNil()) - initBalanceAmt := balRes.Balance.Amount - - callArgs.Args = []interface{}{ - contractAddr, s.network.GetValidators()[0].OperatorAddress, - } - - rwRes, err := s.grpcHandler.GetDelegationRewards(contractAccAddr.String(), s.network.GetValidators()[0].OperatorAddress) - Expect(err).To(BeNil()) - expRewardsAmt := rwRes.Rewards.AmountOf(s.bondDenom).TruncateInt() - - logCheckArgs := passCheck. - WithExpEvents(distribution.EventTypeWithdrawDelegatorReward) - - _, _, err = s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) - - // balance should increase - balRes, err = s.grpcHandler.GetBalanceFromBank(contractAccAddr, s.bondDenom) - Expect(err).To(BeNil()) - - Expect(balRes.Balance.Amount).To(Equal(initBalanceAmt.Add(expRewardsAmt)), "expected final balance to be greater than initial balance after withdrawing rewards") - }) - - DescribeTable("should withdraw rewards successfully to the new withdrawer address", func(tc testCase) { - balRes, err := s.grpcHandler.GetBalanceFromBank(tc.withdrawer.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - withdrawerInitialBalance := balRes.Balance - - callArgs = factory.CallArgs{ - ContractABI: distrCallerContract.ABI, - MethodName: "testSetWithdrawAddressFromContract", - Args: []interface{}{sdk.AccAddress(tc.withdrawer.Bytes()).String()}, - } - logCheckArgs := passCheck.WithExpEvents(distribution.EventTypeSetWithdrawAddress) - _, _, err = s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) - - // get delegator initial balance - balRes, err = s.grpcHandler.GetBalanceFromBank(contractAccAddr, s.bondDenom) - Expect(err).To(BeNil()) - delegatorInitialBalance := balRes.Balance - - // get the expected rewards for the delegation - rwRes, err := s.grpcHandler.GetDelegationRewards(contractAccAddr.String(), s.network.GetValidators()[0].OperatorAddress) - Expect(err).To(BeNil()) - expRewardsAmt := rwRes.Rewards.AmountOf(s.bondDenom).TruncateInt() - - callArgs.MethodName = "testWithdrawDelegatorReward" - callArgs.Args = []interface{}{ - contractAddr, s.network.GetValidators()[0].OperatorAddress, - } - - logCheckArgs = passCheck. - WithExpEvents(distribution.EventTypeWithdrawDelegatorReward) - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) - - var rewards []cmn.Coin - err = s.precompile.UnpackIntoInterface(&rewards, distribution.WithdrawDelegatorRewardMethod, ethRes.Ret) - Expect(err).To(BeNil()) - Expect(len(rewards)).To(Equal(1)) - - Expect(rewards[0].Denom).To(Equal(s.bondDenom)) - Expect(rewards[0].Amount).To(Equal(expRewardsAmt.BigInt())) - - // should increase withdrawer balance by rewards - balRes, err = s.grpcHandler.GetBalanceFromBank(tc.withdrawer.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - Expect(balRes.Balance.Amount).To(Equal(withdrawerInitialBalance.Amount.Add(expRewardsAmt)), "expected final balance to be greater than initial balance after withdrawing rewards") - - // check that the delegator final balance is initialBalance - fee - balRes, err = s.grpcHandler.GetBalanceFromBank(contractAccAddr, s.bondDenom) - Expect(err).To(BeNil(), "error while calling GetBalance") - Expect(balRes.Balance.Amount).To(Equal(delegatorInitialBalance.Amount), "expected delegator final balance to be equal to initial balance") - }, - Entry("withdrawer addr is existing acc", testCase{ - withdrawer: &differentAddr, - }), - Entry("withdrawer addr is non-existing acc", testCase{ - withdrawer: func() *common.Address { - addr := testutiltx.GenerateAddress() - return &addr - }(), - }), - ) - - // Specific BeforeEach for table-driven tests - Context("Table-driven tests for Withdraw Delegator Rewards", func() { - contractInitialBalance := math.NewInt(100) - - BeforeEach(func() { - callArgs.MethodName = "testWithdrawDelegatorRewardWithTransfer" - - // send some funds to the contract - err := testutils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), contractAddr.Bytes(), contractInitialBalance) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - }) - - DescribeTable("withdraw delegation rewards with internal transfers to delegator - should withdraw rewards successfully to the withdrawer address", - func(tc testCase) { - txSender := s.keyring.GetAccAddr(0) - txSenderKey := s.keyring.GetPrivKey(0) - balRes, err := s.grpcHandler.GetBalanceFromBank(contractAccAddr, s.bondDenom) - Expect(err).To(BeNil()) - if tc.withdrawer != nil { - callArgs = factory.CallArgs{ - ContractABI: distrCallerContract.ABI, - MethodName: "testSetWithdrawAddressFromContract", - Args: []interface{}{sdk.AccAddress(tc.withdrawer.Bytes()).String()}, - } - logCheckArgs := passCheck.WithExpEvents(distribution.EventTypeSetWithdrawAddress) - _, _, err = s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, logCheckArgs) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) - - balRes, err = s.grpcHandler.GetBalanceFromBank(tc.withdrawer.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - } - withdrawerInitialBalance := balRes.Balance - - balRes, err = s.grpcHandler.GetBalanceFromBank(txSender, s.bondDenom) - Expect(err).To(BeNil()) - txSenderInitialBalance := balRes.Balance - - // get the pending rewards to claim - qRes, err := s.grpcHandler.GetDelegationRewards(contractAccAddr.String(), s.network.GetValidators()[0].OperatorAddress) - Expect(err).To(BeNil()) - expRewards := qRes.Rewards.AmountOf(s.bondDenom).TruncateInt() - - callArgs.MethodName = "testWithdrawDelegatorRewardWithTransfer" - callArgs.Args = []interface{}{ - s.network.GetValidators()[0].OperatorAddress, tc.before, tc.after, - } - - logCheckArgs := passCheck. - WithExpEvents(distribution.EventTypeWithdrawDelegatorReward) - - res, _, err := s.factory.CallContractAndCheckLogs( - txSenderKey, - txArgs, - callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) - - fees := gasPrice.MulRaw(res.GasUsed) - - // check balances - contractTransferredAmt := math.ZeroInt() - for _, transferred := range []bool{tc.before, tc.after} { - if transferred { - contractTransferredAmt = contractTransferredAmt.AddRaw(15) - } - } - - if tc.withdrawer != nil { - expWithdrawerFinalBalance := withdrawerInitialBalance.Amount.Add(expRewards) - // withdrawer balance should have the rewards - balRes, err = s.grpcHandler.GetBalanceFromBank(tc.withdrawer.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - withdrawerFinalBalance := balRes.Balance - Expect(withdrawerFinalBalance.Amount).To(Equal(expWithdrawerFinalBalance), "expected final balance to be greater than initial balance after withdrawing rewards") - } else { // contract is the withdrawer - // contract balance be updated according to the transferred amount and rewards - balRes, err = s.grpcHandler.GetBalanceFromBank(contractAccAddr, s.bondDenom) - Expect(err).To(BeNil()) - contractFinalBalance := balRes.Balance - Expect(contractFinalBalance.Amount).To(Equal( - contractInitialBalance. - Add(expRewards). - Sub(contractTransferredAmt))) - } - - // delegator balance should have the transferred amt - fees + rewards (when is the withdrawer) - balRes, err = s.grpcHandler.GetBalanceFromBank(txSender, s.bondDenom) - Expect(err).To(BeNil()) - txSenderFinalBalance := balRes.Balance - Expect(txSenderFinalBalance.Amount).To(Equal( - txSenderInitialBalance.Amount. - Sub(fees). - Add(contractTransferredAmt))) - }, - - Entry("delegator == withdrawer - with internal transfers before and after precompile call", testCase{ - before: true, - after: true, - }), - - Entry("delegator == withdrawer - with internal transfers before precompile call", testCase{ - before: true, - after: false, - }), - - Entry("delegator == withdrawer - with internal transfers after precompile call", testCase{ - before: false, - after: true, - }), - Entry("delegator != withdrawer - with internal transfers before and after precompile call", testCase{ - withdrawer: &differentAddr, - before: true, - after: true, - }), - - Entry("delegator != withdrawer - with internal transfers before precompile call", testCase{ - withdrawer: &differentAddr, - before: true, - after: false, - }), - - Entry("delegator != withdrawer - with internal transfers after precompile call", testCase{ - withdrawer: &differentAddr, - before: false, - after: true, - }), - ) - - DescribeTable("should revert withdraw rewards successfully and update correspondingly the withdrawer and contract's balances", func(tc testCase) { - // Set new withdrawer address - err = s.factory.SetWithdrawAddress(s.keyring.GetPrivKey(0), tc.withdrawer.Bytes()) - Expect(err).To(BeNil()) - // persist state change - Expect(s.network.NextBlock()).To(BeNil()) - - // get the pending rewards to claim - qRes, err := s.grpcHandler.GetDelegationRewards(s.keyring.GetAccAddr(0).String(), s.network.GetValidators()[0].OperatorAddress) - Expect(err).To(BeNil()) - initRewards := qRes.Rewards.AmountOf(s.bondDenom).TruncateInt() - - balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - delInitBalance := balRes.Balance - balRes, err = s.grpcHandler.GetBalanceFromBank(tc.withdrawer.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - withdrawerInitBalance := balRes.Balance - - // update args to call the corresponding contract method - callArgs.MethodName = "revertWithdrawRewardsAndTransfer" - callArgs.Args = []interface{}{ - s.keyring.GetAddr(0), *tc.withdrawer, s.network.GetValidators()[0].OperatorAddress, true, - } - - res, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) - fees := gasPrice.MulRaw(res.GasUsed) - - // check balances - contractTransferredAmt := math.NewInt(15) - // contract balance be updated according to the transferred amount - balRes, err = s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - contractFinalBalance := balRes.Balance - Expect(contractFinalBalance.Amount).To(Equal(contractInitialBalance.Sub(contractTransferredAmt))) - - // delegator balance should be initial_balance - fees - balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - delFinalBalance := balRes.Balance - Expect(delFinalBalance.Amount).To(Equal(delInitBalance.Amount.Sub(fees))) - - // withdrawer balance should increase by the transferred amount only - // the rewards withdrawal should revert - balRes, err = s.grpcHandler.GetBalanceFromBank(tc.withdrawer.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - withdrawerFinalBalance := balRes.Balance - Expect(withdrawerFinalBalance.Amount).To(Equal(withdrawerInitBalance.Amount.Add(contractTransferredAmt)), "expected final balance to be greater than initial balance after withdrawing rewards") - - // rewards to claim should be the same or more than before - qRes, err = s.grpcHandler.GetDelegationRewards(s.keyring.GetAccAddr(0).String(), s.network.GetValidators()[0].OperatorAddress) - Expect(err).To(BeNil()) - finalRewards := qRes.Rewards.AmountOf(s.bondDenom).TruncateInt() - Expect(finalRewards.GTE(initRewards)).To(BeTrue()) - }, - Entry("withdrawer addr is existing acc", testCase{ - withdrawer: &differentAddr, - }), - Entry("withdrawer addr is non-existing acc", testCase{ - withdrawer: func() *common.Address { - addr := testutiltx.GenerateAddress() - return &addr - }(), - }), - ) - }) - }) - - Context("withdrawDelegatorRewards with contract as delegator", func() { - var ( - // initialBalance is the initial balance of the delegator - initialBalance *sdk.Coin - accruedRewardsAmt math.Int - ) - - BeforeEach(func() { //nolint:dupl - // send funds to the contract - err := testutils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), contractAddr.Bytes(), math.NewInt(2e18)) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - stkPrecompile, err := s.getStakingPrecompile() - Expect(err).To(BeNil()) - // make a delegation with contract as delegator - logCheck := testutil.LogCheckArgs{ - ExpPass: true, - ABIEvents: stkPrecompile.ABI.Events, - ExpEvents: []string{staking.EventTypeDelegate}, - } - _, _, err = s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - factory.CallArgs{ - ContractABI: distrCallerContract.ABI, - MethodName: "testDelegateFromContract", - Args: []interface{}{ - s.network.GetValidators()[0].OperatorAddress, - big.NewInt(1e18), - }, - }, - logCheck, - ) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - // wait to accrue some rewards for contract address - rwRes, err := testutils.WaitToAccrueRewards(s.network, s.grpcHandler, sdk.AccAddress(contractAddr.Bytes()).String(), minExpRewardOrCommission) - Expect(err).To(BeNil()) - - // contract's accrued rewards amt - accruedRewardsAmt = rwRes.AmountOf(s.bondDenom).TruncateInt() - - balRes, err := s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - initialBalance = balRes.Balance - - // populate default arguments - callArgs.MethodName = "testWithdrawDelegatorRewardFromContract" - }) - - It("should withdraw rewards successfully", func() { - callArgs.Args = []interface{}{s.network.GetValidators()[0].OperatorAddress} - - logCheckArgs := passCheck.WithExpEvents(distribution.EventTypeWithdrawDelegatorReward) - - _, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) - - // balance should increase - balRes, err := s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - finalBalance := balRes.Balance - Expect(finalBalance.Amount).To(Equal(initialBalance.Amount.Add(accruedRewardsAmt)), "expected final balance to be greater than initial balance after withdrawing rewards") - }) - - It("should withdraw rewards successfully", func() { - withdrawerAddr, _ := testutiltx.NewAccAddressAndKey() - - balRes, err := s.grpcHandler.GetBalanceFromBank(withdrawerAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - initialWithdrawerBalance := balRes.Balance - Expect(initialWithdrawerBalance.Amount).To(Equal(math.ZeroInt())) - - // call the smart contract to update the withdrawer - // Set new withdrawer address for the contract - setWithdrawCheck := passCheck.WithExpEvents(distribution.EventTypeSetWithdrawAddress) - res1, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - factory.CallArgs{ - ContractABI: distrCallerContract.ABI, - MethodName: "testSetWithdrawAddressFromContract", - Args: []interface{}{withdrawerAddr.String()}, - }, - setWithdrawCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(res1.IsOK()).To(BeTrue(), "error while calling the smart contract") - Expect(s.network.NextBlock()).To(BeNil()) - - // get accrued rewards prev to tx - rwRes, err := s.grpcHandler.GetDelegationRewards(sdk.AccAddress(contractAddr.Bytes()).String(), s.network.GetValidators()[0].OperatorAddress) - Expect(err).To(BeNil()) - accruedRewardsAmt = rwRes.Rewards.AmountOf(s.bondDenom).TruncateInt() - - callArgs.Args = []interface{}{s.network.GetValidators()[0].OperatorAddress} - logCheckArgs := passCheck.WithExpEvents(distribution.EventTypeWithdrawDelegatorReward) - - txArgs.GasLimit = 300_000 - _, _, err = s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) - - // withdrawer balance should increase with the rewards amt - balRes, err = s.grpcHandler.GetBalanceFromBank(withdrawerAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - finalWithdrawerBalance := balRes.Balance - Expect(finalWithdrawerBalance.Amount).To(Equal(accruedRewardsAmt), "expected final balance to be greater than initial balance after withdrawing rewards") - - // delegator balance (contract) should remain unchanged - balRes, err = s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - finalDelegatorBalance := balRes.Balance - Expect(finalDelegatorBalance.Amount.Equal(initialBalance.Amount)).To(BeTrue(), "expected delegator final balance remain unchanged after withdrawing rewards to withdrawer") - }) - - It("should withdraw rewards successfully", func() { - withdrawerAddr, _ := testutiltx.NewAccAddressAndKey() - - balRes, err := s.grpcHandler.GetBalanceFromBank(withdrawerAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - initialWithdrawerBalance := balRes.Balance - Expect(initialWithdrawerBalance.Amount).To(Equal(math.ZeroInt())) - - // Set new withdrawer address for the contract - setWithdrawCheck := passCheck.WithExpEvents(distribution.EventTypeSetWithdrawAddress) - res1, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - factory.CallArgs{ - ContractABI: distrCallerContract.ABI, - MethodName: "testSetWithdrawAddressFromContract", - Args: []interface{}{withdrawerAddr.String()}, - }, - setWithdrawCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(res1.IsOK()).To(BeTrue(), "error while calling the smart contract") - Expect(s.network.NextBlock()).To(BeNil()) - - // get the pending rewards to claim - rwRes, err := s.grpcHandler.GetDelegationRewards(sdk.AccAddress(contractAddr.Bytes()).String(), s.network.GetValidators()[0].OperatorAddress) - Expect(err).To(BeNil()) - expRewards := rwRes.Rewards.AmountOf(s.bondDenom).TruncateInt() - - logCheckArgs := passCheck.WithExpEvents(distribution.EventTypeWithdrawDelegatorReward) - - callArgs.Args = []interface{}{s.network.GetValidators()[0].OperatorAddress} - - txArgs.GasLimit = 500_000 - _, _, err = s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) - - // withdrawer balance should increase with the rewards amt - balRes, err = s.grpcHandler.GetBalanceFromBank(withdrawerAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - finalWithdrawerBalance := balRes.Balance - Expect(finalWithdrawerBalance.Amount.Equal(expRewards)).To(BeTrue(), "expected final balance to be greater than initial balance after withdrawing rewards") - - // delegator balance (contract) should remain unchanged - balRes, err = s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - finalDelegatorBalance := balRes.Balance - Expect(finalDelegatorBalance.Amount.Equal(initialBalance.Amount)).To(BeTrue(), "expected delegator final balance remain unchanged after withdrawing rewards to withdrawer") - }) - }) - - Context("claimRewards", func() { - var ( - // initialBalance is the initial balance of the delegator - initialBalance *sdk.Coin - // diffAddrInitialBalance is the initial balance of the different address - diffAddrInitialBalance *sdk.Coin - ) - - BeforeEach(func() { - // fund the diffAddr - err := testutils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), contractAccAddr, math.NewInt(2e18)) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - stkPrecompile, err := s.getStakingPrecompile() - Expect(err).To(BeNil()) - // make a delegation with contract as delegator - logCheck := testutil.LogCheckArgs{ - ExpPass: true, - ABIEvents: stkPrecompile.ABI.Events, - ExpEvents: []string{staking.EventTypeDelegate}, - } - _, _, err = s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - factory.CallArgs{ - ContractABI: distrCallerContract.ABI, - MethodName: "testDelegateFromContract", - Args: []interface{}{ - s.network.GetValidators()[0].OperatorAddress, - big.NewInt(1e18), - }, - }, - logCheck, - ) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - // wait to accrue some rewards for contract address - _, err = testutils.WaitToAccrueRewards(s.network, s.grpcHandler, contractAccAddr.String(), minExpRewardOrCommission) - Expect(err).To(BeNil()) - - balRes, err := s.grpcHandler.GetBalanceFromBank(contractAccAddr, s.bondDenom) - Expect(err).To(BeNil()) - initialBalance = balRes.Balance - - balRes, err = s.grpcHandler.GetBalanceFromBank(differentAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - diffAddrInitialBalance = balRes.Balance - - // populate default arguments - callArgs.MethodName = "testClaimRewards" - txArgs.GasPrice = gasPrice.BigInt() - }) - - It("should not claim rewards when sending from a different address", func() { - callArgs.Args = []interface{}{differentAddr, uint32(1)} - - _, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - execRevertedCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - // balance should be equal as initial balance or less (because of fees) - balRes, err := s.grpcHandler.GetBalanceFromBank(contractAccAddr, s.bondDenom) - Expect(err).To(BeNil()) - finalBalance := balRes.Balance - Expect(finalBalance.Amount).To(Equal(initialBalance.Amount)) - - // differentAddr balance should remain unchanged - balRes, err = s.grpcHandler.GetBalanceFromBank(differentAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - differentAddrFinalBalance := balRes.Balance - Expect(differentAddrFinalBalance.Amount).To(Equal(diffAddrInitialBalance.Amount)) - }) - - It("should claim rewards successfully", func() { - callArgs.Args = []interface{}{contractAddr, uint32(2)} - - logCheckArgs := passCheck. - WithExpEvents(distribution.EventTypeClaimRewards) - - _, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - // balance should remain unchanged - balRes, err := s.grpcHandler.GetBalanceFromBank(contractAccAddr, s.bondDenom) - Expect(err).To(BeNil()) - finalBalance := balRes.Balance - Expect(finalBalance.Amount.GT(initialBalance.Amount)).To(BeTrue(), "expected final balance to be greater than initial balance after claiming rewards") - }) - - Context("Table driven tests", func() { - BeforeEach(func() { - callArgs.MethodName = "testClaimRewardsWithTransfer" - - // send some funds to the contract - err = testutils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), contractAddr.Bytes(), math.NewInt(1e18)) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - // make a delegation with key 1 - err = s.factory.Delegate(s.keyring.GetKey(1).Priv, s.network.GetValidators()[0].OperatorAddress, sdk.NewCoin(s.bondDenom, math.NewInt(1e18))) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - // wait to accrue some rewards for key 1 - _, err := testutils.WaitToAccrueRewards(s.network, s.grpcHandler, s.keyring.GetAccAddr(1).String(), minExpRewardOrCommission) - Expect(err).To(BeNil()) - }) - - DescribeTable("claimRewards with transfer to withdrawer", func(tc testCase) { - txSender := s.keyring.GetAccAddr(1) - txSenderKey := s.keyring.GetPrivKey(1) - - txSenderInitialBalance := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), txSender, s.bondDenom) - contractInitialBalance := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), contractAccAddr, s.bondDenom) - - // get the pending rewards to claim - res, err := s.grpcHandler.GetDelegationTotalRewards(contractAccAddr.String()) - Expect(err).To(BeNil()) - expRewards := res.Total.AmountOf(s.bondDenom).TruncateInt() - - callArgs.Args = []interface{}{uint32(2), tc.before, tc.after} - - logCheckArgs := passCheck. - WithExpEvents(distribution.EventTypeClaimRewards) - txArgs.GasLimit = 400_000 // set gas limit to avoid out of gas error - _, evmRes, err := s.factory.CallContractAndCheckLogs( - txSenderKey, - txArgs, - callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - err = s.network.NextBlock() - Expect(err).To(BeNil()) - - fees := math.NewIntFromUint64(evmRes.GasUsed).Mul(math.NewIntFromBigInt(txArgs.GasPrice)) - - // calculate the transferred amt during the call - contractTransferredAmt := math.ZeroInt() - for _, transferred := range []bool{tc.before, tc.after} { - if transferred { - contractTransferredAmt = contractTransferredAmt.AddRaw(15) - } - } - - // check balances - expContractFinalBalance := contractInitialBalance.Amount.Sub(contractTransferredAmt).Add(expRewards) - expTxSenderFinalBalance := txSenderInitialBalance.Amount.Sub(fees).Add(contractTransferredAmt) - - contractFinalBalance := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), contractAccAddr, s.bondDenom) - Expect(contractFinalBalance.Amount).To(Equal(expContractFinalBalance), "expected final balance to be greater than initial balance after claiming rewards") - - txSenderFinalBalance := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), txSender, s.bondDenom) - Expect(txSenderFinalBalance.Amount).To(Equal(expTxSenderFinalBalance), "expected final balance to be greater than initial balance after claiming rewards") - }, - Entry("claim rewards with transfer to withdrawer before and after precompile call", testCase{ - before: true, - after: true, - }), - Entry("claim rewards with transfer to withdrawer before precompile call", testCase{ - before: true, - after: false, - }), - Entry("claim rewards with transfer to withdrawer after precompile call", testCase{ - before: false, - after: true, - }), - ) - }) - }) - - Context("tryClaimRewards", func() { - var ( - // initialBalance is the initial balance of the delegator - initialBalance *sdk.Coin - // diffAddrInitialBalance is the initial balance of the different address - // diffInitialBalance *sdk.Coin - accruedRewardsAmt math.Int - ) - - BeforeEach(func() { - // fund the diffAddr - err := testutils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), differentAddr.Bytes(), math.NewInt(2e18)) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - // make a delegation - err = s.factory.Delegate(diffKey, s.network.GetValidators()[0].OperatorAddress, sdk.NewCoin(s.bondDenom, math.NewInt(1e18))) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - // wait to accrue some rewards for s.keyring.GetAddr(0) & another address - _, err = testutils.WaitToAccrueRewards(s.network, s.grpcHandler, sdk.AccAddress(differentAddr.Bytes()).String(), minExpRewardOrCommission) - Expect(err).To(BeNil()) - - // check if s.keyring.GetAddr(0) accrued rewards too - res, err := s.grpcHandler.GetDelegationTotalRewards(s.keyring.GetAccAddr(0).String()) - Expect(err).To(BeNil()) - - accruedRewardsAmt = res.Total.AmountOf(s.bondDenom).TruncateInt() - Expect(accruedRewardsAmt.IsPositive()).To(BeTrue()) - - balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - initialBalance = balRes.Balance - - // populate default arguments - callArgs.MethodName = "testTryClaimRewards" - txArgs.GasPrice = gasPrice.BigInt() - }) - It("should claim rewards successfully", func() { - callArgs.Args = []interface{}{s.keyring.GetAddr(0), uint32(10)} - - // no logs should be emitted since the precompile call runs out of gas - logCheckArgs := passCheck //. - // WithExpEvents(distribution.EventTypeClaimRewards) - - res, err := s.grpcHandler.GetDelegationTotalRewards(s.keyring.GetAccAddr(0).String()) - Expect(err).To(BeNil()) - - accruedRewardsAmt = res.Total.AmountOf(s.bondDenom).TruncateInt() - Expect(accruedRewardsAmt.IsPositive()).To(BeTrue()) - - // set gas such that the internal keeper function called by the precompile fails out mid-execution - txArgs.GasLimit = 80_000 - _, _, err = s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - finalBalance := balRes.Balance - expectedGasCost := math.NewInt(79_416_000_000_000) - Expect(finalBalance.Amount.Equal(initialBalance.Amount.Sub(expectedGasCost))).To(BeTrue(), "expected final balance must be initial balance minus any gas spent") - - res, err = s.grpcHandler.GetDelegationTotalRewards(s.keyring.GetAccAddr(0).String()) - Expect(err).To(BeNil()) - - // accrued rewards should still be increasing - secondAccruedRewardsAmt := res.Total.AmountOf(s.bondDenom).TruncateInt() - Expect(secondAccruedRewardsAmt.IsPositive()).To(BeTrue()) - Expect(secondAccruedRewardsAmt.GTE(accruedRewardsAmt)).To(BeTrue()) - }) - }) - - Context("claimRewards with contract as delegator", func() { - var ( - initialBalance *sdk.Coin - accruedRewardsAmt math.Int - ) - - BeforeEach(func() { //nolint:dupl - // send funds to the contract - err := testutils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), contractAddr.Bytes(), math.NewInt(2e18)) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - stkPrecompile, err := s.getStakingPrecompile() - Expect(err).To(BeNil()) - // make a delegation with contract as delegator - logCheck := testutil.LogCheckArgs{ - ExpPass: true, - ABIEvents: stkPrecompile.ABI.Events, - ExpEvents: []string{staking.EventTypeDelegate}, - } - txArgs.GasLimit = 500_000 - _, _, err = s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - factory.CallArgs{ - ContractABI: distrCallerContract.ABI, - MethodName: "testDelegateFromContract", - Args: []interface{}{ - s.network.GetValidators()[0].OperatorAddress, - big.NewInt(1e18), - }, - }, - logCheck, - ) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - // wait to accrue some rewards for contract address - rwRes, err := testutils.WaitToAccrueRewards(s.network, s.grpcHandler, sdk.AccAddress(contractAddr.Bytes()).String(), minExpRewardOrCommission) - Expect(err).To(BeNil()) - - // contract's accrued rewards amt - accruedRewardsAmt = rwRes.AmountOf(s.bondDenom).TruncateInt() - - balRes, err := s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - initialBalance = balRes.Balance - - // populate default arguments - callArgs.MethodName = "testClaimRewards" - }) - - It("should withdraw rewards successfully", func() { - balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - signerInitialBalance := balRes.Balance - - callArgs.Args = []interface{}{contractAddr, uint32(2)} - txArgs.GasPrice = gasPrice.BigInt() - - logCheckArgs := passCheck.WithExpEvents(distribution.EventTypeClaimRewards) - - res, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - // tx signer should have paid the fees - fees := gasPrice.Mul(math.NewInt(res.GasUsed)) - balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - signerFinalBalance := balRes.Balance - Expect(signerFinalBalance.Amount).To(Equal(signerInitialBalance.Amount.Sub(fees))) - - // contract's balance should increase - balRes, err = s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - finalBalance := balRes.Balance - Expect(finalBalance.Amount).To(Equal(initialBalance.Amount.Add(accruedRewardsAmt)), "expected final balance to be greater than initial balance after withdrawing rewards") - }) - - It("should withdraw rewards successfully to a different address", func() { - balanceRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - signerInitialBalance := balanceRes.Balance - - balRes, err := s.grpcHandler.GetBalanceFromBank(differentAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - withdrawerInitialBalance := balRes.Balance - - balRes, err = s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - contractInitialBalance := balRes.Balance - - txArgs.GasPrice = gasPrice.BigInt() - - // Set new withdrawer address for the contract - setWithdrawCheck := passCheck.WithExpEvents(distribution.EventTypeSetWithdrawAddress) - res1, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - factory.CallArgs{ - ContractABI: distrCallerContract.ABI, - MethodName: "testSetWithdrawAddressFromContract", - Args: []interface{}{differentAddr.String()}, - }, - setWithdrawCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - callArgs.Args = []interface{}{contractAddr, uint32(2)} - - logCheckArgs := passCheck.WithExpEvents(distribution.EventTypeClaimRewards) - - rwRes, err := s.grpcHandler.GetDelegationRewards(sdk.AccAddress(contractAddr.Bytes()).String(), s.network.GetValidators()[0].OperatorAddress) - Expect(err).To(BeNil()) - accruedRewardsAmt = rwRes.Rewards.AmountOf(s.bondDenom).TruncateInt() - - txArgs.GasLimit = 200_000 - res2, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - // signer balance should decrease - paid for fees - fees := gasPrice.Mul(math.NewInt(res1.GasUsed)).Add(gasPrice.Mul(math.NewInt(res2.GasUsed))) - - balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - signerFinalBalance := balRes.Balance - Expect(signerFinalBalance.Amount).To(Equal(signerInitialBalance.Amount.Sub(fees)), "expected signer's final balance to be less than initial balance after withdrawing rewards") - - // withdrawer balance should increase - balRes, err = s.grpcHandler.GetBalanceFromBank(differentAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - withdrawerFinalBalance := balRes.Balance - Expect(withdrawerFinalBalance.Amount).To(Equal(withdrawerInitialBalance.Amount.Add(accruedRewardsAmt))) - - // contract balance should remain unchanged - balRes, err = s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - contractFinalBalance := balRes.Balance - Expect(contractFinalBalance.Amount).To(Equal(contractInitialBalance.Amount)) - }) - }) - - Context("depositValidatorRewardsPool", func() { - var depositAmt *big.Int - - BeforeEach(func() { //nolint:dupl - depositAmt = big.NewInt(1_000_000) - - // populate default arguments - callArgs.MethodName = "testDepositValidatorRewardsPool" - }) - - When("depositor is different from the depositing contract", func() { - It("should fail to deposit rewards to the validator rewards pool", func() { - callArgs.Args = []interface{}{ - differentAddr, - s.network.GetValidators()[0].OperatorAddress, - []cmn.Coin{ - {Denom: s.bondDenom, Amount: depositAmt}, - }, - } - txArgs.GasPrice = gasPrice.BigInt() - - failureCheck := defaultLogCheck.WithErrContains(vm.ErrExecutionReverted.Error()) - - _, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - failureCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - // check that the contract balance didn't change - balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - signerFinalBalance := balRes.Balance - Expect(signerFinalBalance.Amount).To(Equal(signerFinalBalance.Amount)) - }) - }) - - // Specific BeforeEach for table-driven tests - Context("Table-driven tests for DepositValidatorRewardsPool", func() { - BeforeEach(func() { - callArgs.MethodName = "testDepositValidatorRewardsPoolWithTransfer" - - // send some funds to the contract - err := testutils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), contractAddr.Bytes(), math.NewInt(2e18)) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - }) - - DescribeTable("deposit vaidator rewards pool with internal transfers to delegator - should withdraw rewards successfully to the withdrawer address", - func(tc testCase) { - txSender := s.keyring.GetAccAddr(0) - txSenderKey := s.keyring.GetPrivKey(0) - - balRes, err := s.grpcHandler.GetBalanceFromBank(contractAccAddr, s.bondDenom) - Expect(err).To(BeNil()) - contractInitialBalance := balRes.Balance - balRes, err = s.grpcHandler.GetBalanceFromBank(txSender, s.bondDenom) - Expect(err).To(BeNil()) - txSenderInitialBalance := balRes.Balance - - callArgs.Args = []interface{}{ - s.network.GetValidators()[0].OperatorAddress, - []cmn.Coin{ - {Denom: s.bondDenom, Amount: depositAmt}, - }, - tc.before, - tc.after, - } - - txArgs.GasPrice = gasPrice.BigInt() - - logCheckArgs := passCheck. - WithExpEvents(distribution.EventTypeDepositValidatorRewardsPool) - - res, _, err := s.factory.CallContractAndCheckLogs( - txSenderKey, - txArgs, - callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) - - fees := math.NewIntFromBigInt(txArgs.GasPrice).MulRaw(res.GasUsed) - - // check balances - contractTransferredAmt := math.ZeroInt() - for _, transferred := range []bool{tc.before, tc.after} { - if transferred { - contractTransferredAmt = contractTransferredAmt.AddRaw(15) - } - } - // contract balance be updated according to the transferred amount and deposit amount - balRes, err = s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - contractFinalBalance := balRes.Balance - Expect(contractFinalBalance.Amount).To(Equal( - contractInitialBalance.Amount. - Sub(math.NewIntFromBigInt(depositAmt)). - Sub(contractTransferredAmt))) - - // tx sender balance should be updated according to the transferred amount and fees - balRes, err = s.grpcHandler.GetBalanceFromBank(txSender, s.bondDenom) - Expect(err).To(BeNil()) - txSenderFinalBalance := balRes.Balance - Expect(txSenderFinalBalance.Amount).To(Equal( - txSenderInitialBalance.Amount. - Sub(fees). - Add(contractTransferredAmt))) - }, - - Entry("delegator == withdrawer - with internal transfers before and after precompile call", testCase{ - before: true, - after: true, - }), - - Entry("delegator == withdrawer - with internal transfers before precompile call", testCase{ - before: true, - after: false, - }), - - Entry("delegator == withdrawer - with internal transfers after precompile call", testCase{ - before: false, - after: true, - }), - ) - }) - }) - - Context("depositValidatorRewardsPool with contract as depositor", func() { - var ( - contractInitialBalance *sdk.Coin - depositAmt *big.Int - ) - - BeforeEach(func() { //nolint:dupl - // send funds to the contract - err := testutils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), contractAddr.Bytes(), math.NewInt(2e18)) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - balRes, err := s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - contractInitialBalance = balRes.Balance - - depositAmt = big.NewInt(1_000_000) - - // populate default arguments - callArgs.MethodName = "testDepositValidatorRewardsPool" - }) - - It("should deposit rewards to the validator rewards pool", func() { - callArgs.Args = []interface{}{ - contractAddr, - s.network.GetValidators()[0].OperatorAddress, - []cmn.Coin{ - {Denom: s.bondDenom, Amount: depositAmt}, - }, - } - txArgs.GasPrice = gasPrice.BigInt() - - logCheckArgs := passCheck.WithExpEvents(distribution.EventTypeDepositValidatorRewardsPool) - - _, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - // tx signer should have paid the fees - balRes, err := s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - contractFinalBalance := balRes.Balance - Expect(contractFinalBalance.Amount).To(Equal(contractInitialBalance.Amount.Sub(math.NewIntFromBigInt(depositAmt)))) - }) - }) - - Context("Forbidden operations", func() { - It("should revert state: modify withdraw address & then try to withdraw rewards corresponding to another user", func() { - // check signer address balance should've decreased (fees paid) - balanceRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - initBalanceAmt := balanceRes.Balance.Amount - - _, err = testutils.WaitToAccrueRewards(s.network, s.grpcHandler, s.keyring.GetAccAddr(0).String(), minExpRewardOrCommission) - Expect(err).To(BeNil()) - - callArgs.MethodName = "testRevertState" - callArgs.Args = []interface{}{ - differentAddr.String(), differentAddr, s.network.GetValidators()[0].OperatorAddress, - } - - _, _, err = s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - execRevertedCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - // check withdraw address didn't change - res, err := s.grpcHandler.GetDelegatorWithdrawAddr(s.keyring.GetAccAddr(0).String()) - Expect(err).To(BeNil(), "error while calling the precompile") - Expect(res.WithdrawAddress).To(Equal(s.keyring.GetAccAddr(0).String())) - - // check signer address balance should've decreased (fees paid) - balanceRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - Expect(balanceRes.Balance.Amount.LTE(initBalanceAmt)).To(BeTrue()) - - // check other address' balance remained unchanged - balanceRes, err = s.grpcHandler.GetBalanceFromBank(differentAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - Expect(balanceRes.Balance.Amount).To(Equal(math.ZeroInt())) - }) - - It("should not allow to call SetWithdrawAddress using delegatecall", func() { - callArgs.MethodName = "delegateCallSetWithdrawAddress" - callArgs.Args = []interface{}{s.keyring.GetAddr(0), differentAddr.String()} - - _, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - execRevertedCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - // check withdraw address didn't change - res, err := s.grpcHandler.GetDelegatorWithdrawAddr(s.keyring.GetAccAddr(0).String()) - Expect(err).To(BeNil(), "error while calling the precompile") - Expect(res.WithdrawAddress).To(Equal(s.keyring.GetAccAddr(0).String())) - }) - - It("should not allow to call txs (SetWithdrawAddress) using staticcall", func() { - callArgs.MethodName = "staticCallSetWithdrawAddress" - callArgs.Args = []interface{}{s.keyring.GetAddr(0), differentAddr.String()} - - _, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - execRevertedCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - // check withdraw address didn't change - res, err := s.grpcHandler.GetDelegatorWithdrawAddr(s.keyring.GetAccAddr(0).String()) - Expect(err).To(BeNil(), "error while calling the precompile") - Expect(res.WithdrawAddress).To(Equal(s.keyring.GetAccAddr(0).String())) - }) - }) - - // =================================== - // QUERIES - // =================================== - Context("Distribution precompile queries", Ordered, func() { - It("should get validator distribution info", func() { - // fund validator account to make self-delegation - err := testutils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), s.validatorsKeys[0].AccAddr, math.NewInt(1e17)) - Expect(err).To(BeNil()) - // persist changes - Expect(s.network.NextBlock()).To(BeNil()) - - opAddr := s.network.GetValidators()[0].OperatorAddress - // use the validator priv key - // make a self delegation - err = s.factory.Delegate(s.validatorsKeys[0].Priv, opAddr, sdk.NewCoin(s.bondDenom, math.NewInt(1))) - Expect(err).To(BeNil()) - // persist changes - Expect(s.network.NextBlock()).To(BeNil()) - - callArgs.MethodName = "getValidatorDistributionInfo" - callArgs.Args = []interface{}{opAddr} - txArgs.GasLimit = 200_000 - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.validatorsKeys[0].Priv, - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var out distribution.ValidatorDistributionInfoOutput - err = s.precompile.UnpackIntoInterface(&out, distribution.ValidatorDistributionInfoMethod, ethRes.Ret) - Expect(err).To(BeNil()) - - expAddr := s.validatorsKeys[0].AccAddr.String() - - Expect(expAddr).To(Equal(out.DistributionInfo.OperatorAddress)) - Expect(1).To(Equal(len(out.DistributionInfo.Commission))) - Expect(1).To(Equal(len(out.DistributionInfo.SelfBondRewards))) - }) - - It("should get validator outstanding rewards", func() { - opAddr := s.network.GetValidators()[0].OperatorAddress - callArgs.MethodName = "getValidatorOutstandingRewards" - callArgs.Args = []interface{}{opAddr} - - _, err := testutils.WaitToAccrueRewards(s.network, s.grpcHandler, s.keyring.GetAccAddr(0).String(), minExpRewardOrCommission) - Expect(err).To(BeNil(), "error while calling the precompile") - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var rewards []cmn.DecCoin - err = s.precompile.UnpackIntoInterface(&rewards, distribution.ValidatorOutstandingRewardsMethod, ethRes.Ret) - Expect(err).To(BeNil()) - Expect(len(rewards)).To(Equal(1)) - Expect(uint8(18)).To(Equal(rewards[0].Precision)) - Expect(s.bondDenom).To(Equal(rewards[0].Denom)) - - res, err := s.grpcHandler.GetValidatorOutstandingRewards(opAddr) - Expect(err).To(BeNil()) - - expRewardsAmt := res.Rewards.Rewards.AmountOf(s.bondDenom).TruncateInt() - Expect(expRewardsAmt.IsPositive()).To(BeTrue()) - Expect(rewards[0].Amount).To(Equal(expRewardsAmt.BigInt())) - }) - - Context("get validator commission", func() { - BeforeEach(func() { - callArgs.MethodName = "getValidatorCommission" - callArgs.Args = []interface{}{s.network.GetValidators()[0].OperatorAddress} - }) - - // // TODO: currently does not work because the minting happens on the Beginning of each block - // // In future SDK releases this will be possible to adjust by passing a custom `MintFn` -> check - // // https://docs.cosmos.network/main/build/modules/mint#epoch-minting - // - // It("should not get commission - validator without commission", func() { - // // fund validator account to claim commission (if any) - // err = testutils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), s.validatorsKeys[0].AccAddr, math.NewInt(1e18)) - // Expect(err).To(BeNil()) - // Expect(s.network.NextBlock()).To(BeNil()) - // - // // withdraw validator commission - // err = s.factory.WithdrawValidatorCommission(s.validatorsKeys[0].Priv) - // Expect(err).To(BeNil()) - // Expect(s.network.NextBlock()).To(BeNil()) - // - // _, ethRes, err := s.factory.CallContractAndCheckLogs( - // s.keyring.GetPrivKey(0), - // txArgs, - // callArgs, - // passCheck, - // ) - // Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - // - // var commission []cmn.DecCoin - // err = s.precompile.UnpackIntoInterface(&commission, distribution.ValidatorCommissionMethod, ethRes.Ret) - // Expect(err).To(BeNil()) - // Expect(len(commission)).To(Equal(1)) - // Expect(commission[0].Amount.Int64()).To(Equal(int64(0))) - // }) - - It("should get commission - validator with commission", func() { - _, err = testutils.WaitToAccrueCommission(s.network, s.grpcHandler, s.network.GetValidators()[0].OperatorAddress, minExpRewardOrCommission) - Expect(err).To(BeNil()) - - commRes, err := s.grpcHandler.GetValidatorCommission(s.network.GetValidators()[0].OperatorAddress) - Expect(err).To(BeNil()) - - accruedCommission := commRes.Commission.Commission - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var commission []cmn.DecCoin - err = s.precompile.UnpackIntoInterface(&commission, distribution.ValidatorCommissionMethod, ethRes.Ret) - Expect(err).To(BeNil()) - Expect(len(commission)).To(Equal(1)) - Expect(uint8(18)).To(Equal(commission[0].Precision)) - Expect(s.bondDenom).To(Equal(commission[0].Denom)) - - accruedCommissionAmt := accruedCommission.AmountOf(s.bondDenom).TruncateInt() - - Expect(commission[0].Amount).To(Equal(accruedCommissionAmt.BigInt())) - }) - }) - - Context("get validator slashing events", Ordered, func() { - BeforeEach(func() { - callArgs.MethodName = "getValidatorSlashes" - callArgs.Args = []interface{}{ - s.network.GetValidators()[0].OperatorAddress, - uint64(1), uint64(5), - query.PageRequest{}, - } - }) - - AfterEach(func() { - // NOTE: The first test case will not have the slashes - // so keep this in mind when adding/removing new testcases - s.withValidatorSlashes = true - }) - - AfterAll(func() { - s.withValidatorSlashes = false - }) - - It("should not get slashing events - validator without slashes", func() { - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var out distribution.ValidatorSlashesOutput - err = s.precompile.UnpackIntoInterface(&out, distribution.ValidatorSlashesMethod, ethRes.Ret) - Expect(err).To(BeNil()) - Expect(len(out.Slashes)).To(Equal(0)) - }) - - It("should get slashing events - validator with slashes (default pagination)", func() { - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var out distribution.ValidatorSlashesOutput - err = s.precompile.UnpackIntoInterface(&out, distribution.ValidatorSlashesMethod, ethRes.Ret) - Expect(err).To(BeNil()) - Expect(len(out.Slashes)).To(Equal(2)) - // expected values according to the values used on test setup (custom genesis) - for _, s := range out.Slashes { - Expect(s.Fraction.Value).To(Equal(math.LegacyNewDecWithPrec(5, 2).BigInt())) - Expect(s.ValidatorPeriod).To(Equal(uint64(1))) - } - Expect(uint64(2)).To(Equal(out.PageResponse.Total)) - Expect(out.PageResponse.NextKey).To(BeEmpty()) - }) - - It("should get slashing events - validator with slashes w/pagination", func() { - // set pagination - callArgs.Args = []interface{}{ - s.network.GetValidators()[0].OperatorAddress, - uint64(1), uint64(5), - query.PageRequest{ - Limit: 1, - CountTotal: true, - }, - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var out distribution.ValidatorSlashesOutput - err = s.precompile.UnpackIntoInterface(&out, distribution.ValidatorSlashesMethod, ethRes.Ret) - Expect(err).To(BeNil()) - Expect(len(out.Slashes)).To(Equal(1)) - Expect(out.Slashes[0].Fraction.Value).To(Equal(math.LegacyNewDecWithPrec(5, 2).BigInt())) - Expect(out.Slashes[0].ValidatorPeriod).To(Equal(uint64(1))) - Expect(uint64(2)).To(Equal(out.PageResponse.Total)) - Expect(out.PageResponse.NextKey).NotTo(BeEmpty()) - }) - }) - - Context("get delegation rewards", func() { - BeforeEach(func() { - callArgs.MethodName = "getDelegationRewards" - callArgs.Args = []interface{}{s.keyring.GetAddr(0), s.network.GetValidators()[0].OperatorAddress} - }) - - // // TODO: currently does not work because the minting happens on the Beginning of each block - // // In future SDK releases this will be possible to adjust by passing a custom `MintFn` -> check - // // https://docs.cosmos.network/main/build/modules/mint#epoch-minting - // - // It("should not get rewards - no rewards available", func() { - // // withdraw rewards if available - // err := s.factory.WithdrawDelegationRewards(s.keyring.GetPrivKey(0), s.network.GetValidators()[0].OperatorAddress) - // Expect(err).To(BeNil()) - // Expect(s.network.NextBlock()).To(BeNil()) - // - // // add gas limit to avoid out of gas error - // txArgs.GasLimit = 200_000 - // _, ethRes, err := s.factory.CallContractAndCheckLogs( - // s.keyring.GetPrivKey(0), - // txArgs, - // callArgs, - // passCheck, - // ) - // Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - // - // var rewards []cmn.DecCoin - // err = s.precompile.UnpackIntoInterface(&rewards, distribution.DelegationRewardsMethod, ethRes.Ret) - // Expect(err).To(BeNil()) - // Expect(len(rewards)).To(Equal(0)) - // }) - - It("should get rewards", func() { - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var rewards []cmn.DecCoin - err = s.precompile.UnpackIntoInterface(&rewards, distribution.DelegationRewardsMethod, ethRes.Ret) - Expect(err).To(BeNil()) - Expect(len(rewards)).To(Equal(1)) - Expect(len(rewards)).To(Equal(1)) - Expect(rewards[0].Denom).To(Equal(s.bondDenom)) - Expect(rewards[0].Amount.Int64()).To(BeNumerically(">", 0), "expected rewards amount to be greater than 0") - }) - }) - - Context("get delegator's total rewards", func() { - BeforeEach(func() { - callArgs.MethodName = "getDelegationTotalRewards" - callArgs.Args = []interface{}{s.keyring.GetAddr(0)} - }) - - // // TODO: currently does not work because the minting happens on the Beginning of each block - // // In future SDK releases this will be possible to adjust by passing a custom `MintFn` -> check - // // https://docs.cosmos.network/main/build/modules/mint#epoch-minting - // - // It("should not get rewards - no rewards available", func() { - // // Create a delegation - // err := s.factory.Delegate(s.keyring.GetPrivKey(1), s.network.GetValidators()[0].OperatorAddress, sdk.NewCoin(s.bondDenom, math.NewInt(1))) - // Expect(err).To(BeNil()) - // Expect(s.network.NextBlock()).To(BeNil()) - // - // callArgs.Args = []interface{}{s.keyring.GetAddr(1)} - // txArgs.GasLimit = 200_000 // set gas limit to avoid out of gas error - // _, ethRes, err := s.factory.CallContractAndCheckLogs( - // s.keyring.GetPrivKey(1), - // txArgs, - // callArgs, - // passCheck, - // ) - // Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - // - // var out distribution.DelegationTotalRewardsOutput - // err = s.precompile.UnpackIntoInterface(&out, distribution.DelegationTotalRewardsMethod, ethRes.Ret) - // Expect(err).To(BeNil()) - // Expect(len(out.Rewards)).To(Equal(1)) - // Expect(len(out.Rewards[0].Reward)).To(Equal(0)) - // }) - - It("should get total rewards", func() { - // wait to get rewards - accruedRewards, err := testutils.WaitToAccrueRewards(s.network, s.grpcHandler, s.keyring.GetAccAddr(0).String(), minExpRewardOrCommission) - Expect(err).To(BeNil()) - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var out distribution.DelegationTotalRewardsOutput - - err = s.precompile.UnpackIntoInterface(&out, distribution.DelegationTotalRewardsMethod, ethRes.Ret) - Expect(err).To(BeNil()) - - // The accrued rewards are based on 3 equal delegations to the existing 3 validators - accruedRewardsAmt := accruedRewards.AmountOf(s.bondDenom) - - // the response order may change - for _, or := range out.Rewards { - Expect(1).To(Equal(len(or.Reward))) - Expect(or.Reward[0].Denom).To(Equal(s.bondDenom)) - Expect(or.Reward[0].Amount.Int64()).To(BeNumerically(">", 0), "expected rewards amount to be greater than 0") - } - - Expect(1).To(Equal(len(out.Total))) - Expect(out.Total[0].Amount).To(Equal(accruedRewardsAmt.TruncateInt().BigInt())) - }) - - Context("query call with revert - all changes should revert to corresponding stateDB snapshot", func() { - var ( - reverterContract evmtypes.CompiledContract - reverterAddr common.Address - testContractInitialBalance = math.NewInt(1000) - ) - BeforeEach(func() { - var err error - // Deploy Reverter contract - reverterContract, err = contracts.LoadReverterContract() - Expect(err).To(BeNil(), "error while loading the Reverter contract") - - reverterAddr, err = s.factory.DeployContract( - s.keyring.GetPrivKey(0), - evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values - factory.ContractDeploymentData{ - Contract: reverterContract, - }, - ) - Expect(err).To(BeNil(), "error while deploying the smart contract: %v", err) - // persist state change - Expect(s.network.NextBlock()).To(BeNil()) - - // send some funds to the Reverter contracts to transfer to the - // delegator during the tx - err = testutils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), reverterAddr.Bytes(), testContractInitialBalance) - Expect(err).To(BeNil(), "error while funding the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - }) - - It("should revert the execution - Reverter contract", func() { - args := factory.CallArgs{ - ContractABI: reverterContract.ABI, - MethodName: "run", - } - _, _, err = s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - evmtypes.EvmTxArgs{ - To: &reverterAddr, - GasPrice: gasPrice.BigInt(), - }, - args, - execRevertedCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - balRes, err := s.grpcHandler.GetBalanceFromBank(reverterAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - - contractFinalBalance := balRes.Balance - Expect(contractFinalBalance.Amount).To(Equal(testContractInitialBalance)) - }) - }) - }) - - Context("get all delegator validators", func() { - BeforeEach(func() { - callArgs.MethodName = "getDelegatorValidators" - callArgs.Args = []interface{}{s.keyring.GetAddr(0)} - }) - - It("should get all validators a delegator has delegated to", func() { - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var validators []string - err = s.precompile.UnpackIntoInterface(&validators, distribution.DelegatorValidatorsMethod, ethRes.Ret) - Expect(err).To(BeNil()) - Expect(3).To(Equal(len(validators))) - }) - }) - - Context("get withdraw address", func() { - BeforeEach(func() { - callArgs.MethodName = "getDelegatorWithdrawAddress" - callArgs.Args = []interface{}{s.keyring.GetAddr(0)} - }) - - It("should get withdraw address", func() { - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - withdrawAddr, err := s.precompile.Unpack(distribution.DelegatorWithdrawAddressMethod, ethRes.Ret) - Expect(err).To(BeNil()) - // get the bech32 encoding - expAddr := sdk.AccAddress(s.keyring.GetAddr(0).Bytes()) - Expect(withdrawAddr[0]).To(Equal(expAddr.String())) - }) - - It("should call GetWithdrawAddress using staticcall", func() { - callArgs.MethodName = "staticCallGetWithdrawAddress" - callArgs.Args = []interface{}{s.keyring.GetAddr(0)} - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - withdrawAddr, err := s.precompile.Unpack(distribution.DelegatorWithdrawAddressMethod, ethRes.Ret) - Expect(err).To(BeNil()) - // get the bech32 encoding - expAddr := sdk.AccAddress(s.keyring.GetAddr(0).Bytes()) - Expect(withdrawAddr[0]).To(ContainSubstring(expAddr.String())) - }) - }) - - Context("get community pool coins", func() { - It("should get community pool coins", func() { - callArgs.MethodName = "getCommunityPool" - callArgs.Args = []interface{}{} - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var coins []cmn.DecCoin - err = s.precompile.UnpackIntoInterface(&coins, distribution.CommunityPoolMethod, ethRes.Ret) - Expect(err).To(BeNil()) - Expect(len(coins)).To(Equal(1)) - Expect(s.bondDenom).To(Equal(coins[0].Denom)) - }) - }) - }) -}) diff --git a/precompiles/erc20/integration_test.go b/precompiles/erc20/integration_test.go deleted file mode 100644 index 4ec3828e7..000000000 --- a/precompiles/erc20/integration_test.go +++ /dev/null @@ -1,2789 +0,0 @@ -package erc20_test - -import ( - "fmt" - "math/big" - "slices" - "strings" - "testing" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/vm" - - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" - - "github.com/cosmos/evm/contracts" - "github.com/cosmos/evm/precompiles/erc20" - "github.com/cosmos/evm/precompiles/erc20/testdata" - "github.com/cosmos/evm/precompiles/testutil" - testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" - integrationutils "github.com/cosmos/evm/testutil/integration/os/utils" - utiltx "github.com/cosmos/evm/testutil/tx" - erc20types "github.com/cosmos/evm/x/erc20/types" - evmtypes "github.com/cosmos/evm/x/vm/types" - - "cosmossdk.io/math" - - sdk "github.com/cosmos/cosmos-sdk/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" -) - -var is *IntegrationTestSuite - -type IntegrationTestSuite struct { - // NOTE: we have to use the Unit testing network because we access a keeper in a setup function. - // Might adjust this on a follow-up PR. - network *network.UnitTestNetwork - handler grpc.Handler - keyring keyring.Keyring - factory factory.TxFactory - - bondDenom string - tokenDenom string // erc20 precompile denom with supply - tokenDenomTwo string // erc20 precompile denom with zero supply - - precompile *erc20.Precompile // erc20 precompile with supply - precompileTwo *erc20.Precompile // erc20 precompile with zero supply -} - -func (is *IntegrationTestSuite) SetupTest() { - is.tokenDenom = "xmpl" - is.tokenDenomTwo = "xmpl2" - - keys := keyring.New(2) - genesis := integrationutils.CreateGenesisWithTokenPairs(keys, is.tokenDenom, is.tokenDenomTwo) - - nw := network.NewUnitTestNetwork( - network.WithPreFundedAccounts(keys.GetAllAccAddrs()...), - network.WithOtherDenoms([]string{is.tokenDenom}), // add balance (supply) to is.tokenDenom - network.WithCustomGenesis(genesis), - ) - gh := grpc.NewIntegrationHandler(nw) - tf := factory.New(nw, gh) - - is.network = nw - is.factory = tf - is.handler = gh - is.keyring = keys - - is.bondDenom = nw.GetBaseDenom() - - erc20Gen := genesis[erc20types.ModuleName].(*erc20types.GenesisState) - is.precompile = is.setupERC20Precompile(is.tokenDenom, erc20Gen.TokenPairs) - is.precompileTwo = is.setupERC20Precompile(is.tokenDenomTwo, erc20Gen.TokenPairs) -} - -func TestIntegrationSuite(t *testing.T) { - is = new(IntegrationTestSuite) - - // Run Ginkgo integration tests - RegisterFailHandler(Fail) - RunSpecs(t, "ERC20 Extension Suite") -} - -var ( - revertContractAddr common.Address - gasLimit = uint64(5000000) - gasPrice = big.NewInt(800_000_000) -) - -var _ = Describe("ERC20 Extension -", func() { - var ( - // contractsData holds the addresses and ABIs for the different - // contract instances that are subject to testing here. - contractsData ContractsData - - allowanceCallerContract evmtypes.CompiledContract - revertCallerContract evmtypes.CompiledContract - erc20MinterV5Contract evmtypes.CompiledContract - - execRevertedCheck testutil.LogCheckArgs - failCheck testutil.LogCheckArgs - passCheck testutil.LogCheckArgs - ) - - BeforeEach(func() { - is.SetupTest() - - var err error - allowanceCallerContract, err = testdata.LoadERC20AllowanceCaller() - Expect(err).ToNot(HaveOccurred(), "failed to load ERC20 allowance caller contract") - - erc20MinterV5Contract, err = testdata.LoadERC20MinterV5Contract() - Expect(err).ToNot(HaveOccurred(), "failed to load ERC20 minter contract") - - revertCallerContract, err = testdata.LoadERC20TestCaller() - Expect(err).ToNot(HaveOccurred(), "failed to load ERC20 allowance caller contract") - - sender := is.keyring.GetKey(0) - contractAddr, err := is.factory.DeployContract( - sender.Priv, - evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values - factory.ContractDeploymentData{ - Contract: allowanceCallerContract, - // NOTE: we're passing the precompile address to the constructor because that initiates the contract - // to make calls to the correct ERC20 precompile. - ConstructorArgs: []interface{}{is.precompile.Address()}, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to deploy contract") - - // commit the changes to update state (account nonce mostly) - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "failed to advance block") - - contractAddrTokenTwo, err := is.factory.DeployContract( - sender.Priv, - evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values - factory.ContractDeploymentData{ - Contract: allowanceCallerContract, - // NOTE: we're passing the precompile address to the constructor because that initiates the contract - // to make calls to the correct ERC20 precompile. - ConstructorArgs: []interface{}{is.precompileTwo.Address()}, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to deploy contract") - - // commit the changes to update state (account nonce mostly) - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "failed to advance block") - - erc20MinterBurnerAddr, err := is.factory.DeployContract( - sender.Priv, - evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values - factory.ContractDeploymentData{ - Contract: contracts.ERC20MinterBurnerDecimalsContract, - ConstructorArgs: []interface{}{ - "Xmpl", "Xmpl", uint8(6), - }, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to deploy ERC20 minter burner contract") - - // commit the changes to update state (account nonce mostly) - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "failed to advance block") - - ERC20MinterV5Addr, err := is.factory.DeployContract( - sender.Priv, - evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values - factory.ContractDeploymentData{ - Contract: erc20MinterV5Contract, - ConstructorArgs: []interface{}{ - "Xmpl", "Xmpl", - }, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to deploy ERC20 minter contract") - - // commit the changes to update state (account nonce mostly) - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "failed to advance block") - - erc20MinterV5CallerAddr, err := is.factory.DeployContract( - sender.Priv, - evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values - factory.ContractDeploymentData{ - Contract: allowanceCallerContract, - ConstructorArgs: []interface{}{ - ERC20MinterV5Addr, - }, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to deploy ERC20 minter caller contract") - - // commit the changes to update state (account nonce mostly) - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "failed to advance block") - - // Store the data of the deployed contracts - contractsData = ContractsData{ - ownerPriv: sender.Priv, - contractData: map[CallType]ContractData{ - directCall: { - Address: is.precompile.Address(), - ABI: is.precompile.ABI, - }, - directCallToken2: { - Address: is.precompileTwo.Address(), - ABI: is.precompileTwo.ABI, - }, - contractCall: { - Address: contractAddr, - ABI: allowanceCallerContract.ABI, - }, - contractCallToken2: { - Address: contractAddrTokenTwo, - ABI: allowanceCallerContract.ABI, - }, - erc20Call: { - Address: erc20MinterBurnerAddr, - ABI: contracts.ERC20MinterBurnerDecimalsContract.ABI, - }, - erc20V5Call: { - Address: ERC20MinterV5Addr, - ABI: erc20MinterV5Contract.ABI, - }, - erc20V5CallerCall: { - Address: erc20MinterV5CallerAddr, - ABI: allowanceCallerContract.ABI, - }, - }, - } - - failCheck = testutil.LogCheckArgs{ABIEvents: is.precompile.Events} - execRevertedCheck = failCheck.WithErrContains("execution reverted") - passCheck = failCheck.WithExpPass(true) - - erc20Params := is.network.App.Erc20Keeper.GetParams(is.network.GetContext()) - Expect(len(erc20Params.NativePrecompiles)).To(Equal(1)) - Expect(common.HexToAddress(erc20Params.NativePrecompiles[0])).To(Equal(common.HexToAddress(testconstants.WEVMOSContractMainnet))) - - revertContractAddr, err = is.factory.DeployContract( - sender.Priv, - evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values - factory.ContractDeploymentData{ - Contract: revertCallerContract, - // NOTE: we're passing the precompile address to the constructor because that initiates the contract - // to make calls to the correct ERC20 precompile. - ConstructorArgs: []interface{}{common.HexToAddress(erc20Params.NativePrecompiles[0])}, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to deploy reverter contract") - - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "failed to advance block") - }) - - Context("basic functionality -", func() { - When("sending tokens to contract", func() { - It("it should return error", func() { - sender := is.keyring.GetKey(0) - fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)} - - // Fund account with some tokens - is.fundWithTokens(directCall, contractsData, sender.Addr, fundCoins) - - // Taking custom args from the table entry - txArgs := evmtypes.EvmTxArgs{} - txArgs.Amount = big.NewInt(int64(1000)) - precompileAddress := is.precompile.Address() - txArgs.To = &precompileAddress - - _, err := is.factory.ExecuteEthTx(sender.Priv, txArgs) - // Currently, this check pass because the erc20 precompile does - // not expose a fallback handler. Adding a fallback handler, the - // test should pass again because of the check on the message - // value in the precompile before the setup. - Expect(err.Error()).To(ContainSubstring(vm.ErrExecutionReverted.Error()), "precompile should not accept transfers") - }, - ) - }) - When("transferring tokens", func() { - DescribeTable("it should transfer tokens to a non-existing address", func(callType CallType, expGasUsedLowerBound int64, expGasUsedUpperBound int64) { - sender := is.keyring.GetKey(0) - receiver := utiltx.GenerateAddress() - fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)} - transferCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)} - - senderInitialAmt := is.fundWithTokens(callType, contractsData, sender.Addr, fundCoins) - senderInitialBalance := sdk.Coins{sdk.NewCoin(is.tokenDenom, senderInitialAmt)} - - // Transfer tokens - txArgs, transferArgs := is.getTxAndCallArgs(callType, contractsData, erc20.TransferMethod, receiver, transferCoins[0].Amount.BigInt()) - - transferCheck := passCheck.WithExpEvents(erc20.EventTypeTransfer) - - res, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, transferArgs, transferCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.TransferMethod) - is.ExpectBalancesForContract( - callType, contractsData, - []ExpectedBalance{ - {address: sender.AccAddr, expCoins: senderInitialBalance.Sub(transferCoins...)}, - {address: receiver.Bytes(), expCoins: transferCoins}, - }, - ) - - Expect(res.GasUsed > expGasUsedLowerBound).To(BeTrue(), "expected different gas used") - Expect(res.GasUsed < expGasUsedUpperBound).To(BeTrue(), "expected different gas used") - }, - // FIXME: The gas used on the precompile is much higher than on the EVM - Entry(" - direct call", directCall, int64(3_021_000), int64(3_022_000)), - Entry(" - through erc20 contract", erc20Call, int64(54_000), int64(54_500)), - Entry(" - through erc20 v5 contract", erc20V5Call, int64(52_000), int64(52_200)), - ) - - DescribeTable("it should transfer tokens to an existing address", func(callType CallType) { - sender := is.keyring.GetKey(0) - receiver := is.keyring.GetKey(1) - fundCoinsSender := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)} - fundCoinsReceiver := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 500)} - transferCoin := sdk.NewInt64Coin(is.tokenDenom, 100) - - // Fund accounts with some tokens - receiverInitialAmt := is.fundWithTokens(callType, contractsData, receiver.Addr, fundCoinsReceiver) - receiverInitialBalance := sdk.Coins{sdk.NewCoin(is.tokenDenom, receiverInitialAmt)} - - senderInitialAmt := is.fundWithTokens(callType, contractsData, sender.Addr, fundCoinsSender) - senderInitialBalance := sdk.Coins{sdk.NewCoin(is.tokenDenom, senderInitialAmt)} - - // Transfer tokens - txArgs, transferArgs := is.getTxAndCallArgs(callType, contractsData, erc20.TransferMethod, receiver.Addr, transferCoin.Amount.BigInt()) - - transferCheck := passCheck.WithExpEvents(erc20.EventTypeTransfer) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, transferArgs, transferCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.TransferMethod) - is.ExpectBalancesForContract( - callType, contractsData, - []ExpectedBalance{ - {address: sender.AccAddr, expCoins: senderInitialBalance.Sub(transferCoin)}, - {address: receiver.AccAddr, expCoins: receiverInitialBalance.Add(transferCoin)}, - }, - ) - }, - Entry(" - direct call", directCall), - // NOTE: we are not passing the contract call here because transferring using a caller contract - // is only supported through transferFrom method. - Entry(" - through erc20 contract", erc20Call), - Entry(" - through erc20 v5 contract", erc20V5Call), - ) - - DescribeTable("it should return an error trying to call from a smart contract", func(callType CallType) { - sender := is.keyring.GetKey(0) - receiver := is.keyring.GetAddr(1) - fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)} - transferAmount := big.NewInt(100) - - // Fund account with some tokens - is.fundWithTokens(callType, contractsData, sender.Addr, fundCoins) - - // Transfer tokens - txArgs, transferArgs := is.getTxAndCallArgs(callType, contractsData, erc20.TransferMethod, receiver, transferAmount) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, transferArgs, execRevertedCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - Expect(ethRes).To(BeNil(), "expected empty result") - }, - // NOTE: we are not passing the direct call here because this test is specific to the contract calls - Entry(" - through contract", contractCall), - Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), - ) - - DescribeTable("it should return an error if the sender does not have enough tokens", func(callType CallType) { - sender := is.keyring.GetKey(0) - receiver := is.keyring.GetAddr(1) - fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 200)} - - // Fund account with some tokens - senderInitialAmt := is.fundWithTokens(callType, contractsData, sender.Addr, fundCoins) - transferAmt := new(big.Int).Add(senderInitialAmt.BigInt(), big.NewInt(100)) - - // Transfer tokens - txArgs, transferArgs := is.getTxAndCallArgs(callType, contractsData, erc20.TransferMethod, receiver, transferAmt) - - insufficientBalanceCheck := failCheck.WithErrContains( - erc20.ErrTransferAmountExceedsBalance.Error(), - ) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, transferArgs, insufficientBalanceCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - Expect(ethRes).To(BeNil(), "expected empty result") - }, - Entry(" - direct call", directCall), - // NOTE: we are not passing the contract call here because this test is for direct calls only - - Entry(" - through erc20 contract", erc20Call), - // // TODO: The ERC20 V5 contract is raising the ERC-6093 standardized error which we are not as of yet - // Entry(" - through erc20 v5 contract", erc20V5Call), - ) - }) - When("calling reverter contract", func() { - Context("in a direct call to the WEVMOS contract", func() { - var ( - args factory.CallArgs - txArgs evmtypes.EvmTxArgs - ) - BeforeEach(func() { - args = factory.CallArgs{ - ContractABI: revertCallerContract.ABI, - } - - txArgs = evmtypes.EvmTxArgs{ - To: &revertContractAddr, - GasLimit: gasLimit, - GasPrice: gasPrice, - } - }) - It("should transfer tokens", func() { - sender := is.keyring.GetKey(0) - receiver := is.keyring.GetKey(1) - amountToSend := big.NewInt(100) - - balRes, err := is.handler.GetBalanceFromBank(receiver.AccAddr, is.bondDenom) - Expect(err).To(BeNil()) - denomInitialBalance := balRes.Balance - balRes, err = is.handler.GetBalanceFromBank(sender.AccAddr, is.bondDenom) - Expect(err).To(BeNil()) - senderInitialBalance := balRes.Balance - - args.MethodName = "transferWithRevert" - args.Args = []interface{}{ - receiver.Addr, - amountToSend, - false, - false, - } - txArgs.Amount = amountToSend - - transferCheck := passCheck.WithExpEvents(erc20.EventTypeTransfer) - res, _, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, args, transferCheck) - Expect(err).To(BeNil()) - Expect(is.network.NextBlock()).To(BeNil()) - fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed) - - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "failed to advance block") - - balRes, err = is.handler.GetBalanceFromBank(receiver.AccAddr, is.bondDenom) - Expect(err).To(BeNil()) - denomFinalBalance := balRes.Balance - Expect(denomFinalBalance.Amount).To(Equal(denomInitialBalance.Amount.Add(math.NewInt(amountToSend.Int64())))) - - balRes, err = is.handler.GetBalanceFromBank(revertContractAddr.Bytes(), is.bondDenom) - Expect(err).To(BeNil()) - contractBalance := balRes.Balance - Expect(contractBalance.Amount).To(Equal(math.ZeroInt())) - - balRes, err = is.handler.GetBalanceFromBank(sender.AccAddr, is.bondDenom) - Expect(err).To(BeNil()) - senderFinalBalance := balRes.Balance - denomSpent := fees.Add(math.NewIntFromBigInt(amountToSend)) - Expect(senderFinalBalance.Amount).To(Equal(senderInitialBalance.Amount.Sub(denomSpent))) - }, - ) - DescribeTable("it should revert token transfer from the WEVMOS contract", func(before bool, after bool) { - sender := is.keyring.GetKey(0) - receiver := is.keyring.GetAddr(1) - amountToSend := big.NewInt(100) - balRes, err := is.handler.GetBalanceFromBank(receiver.Bytes(), is.bondDenom) - Expect(err).To(BeNil()) - denomInitialBalance := balRes.Balance - balRes, err = is.handler.GetBalanceFromBank(sender.AccAddr, is.bondDenom) - Expect(err).To(BeNil()) - senderInitialBalance := balRes.Balance - - args.MethodName = "transferWithRevert" - args.Args = []interface{}{ - receiver, - amountToSend, - before, - after, - } - txArgs.Amount = amountToSend - - res, _, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, args, execRevertedCheck) - Expect(err).To(BeNil()) - Expect(is.network.NextBlock()).To(BeNil()) - - fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed) - - // contract balance should remain unchanged - balRes, err = is.handler.GetBalanceFromBank(receiver.Bytes(), is.bondDenom) - Expect(err).To(BeNil()) - denomFinalBalance := balRes.Balance - Expect(denomFinalBalance.Amount).To(Equal(denomInitialBalance.Amount)) - - balRes, err = is.handler.GetBalanceFromBank(revertContractAddr.Bytes(), is.bondDenom) - Expect(err).To(BeNil()) - contractBalance := balRes.Balance - Expect(contractBalance.Amount).To(Equal(math.ZeroInt())) - - balRes, err = is.handler.GetBalanceFromBank(sender.AccAddr, is.bondDenom) - Expect(err).To(BeNil()) - senderFinalBalance := balRes.Balance - Expect(senderFinalBalance.Amount).To(Equal(senderInitialBalance.Amount.Sub(fees))) - }, - Entry("revert before", true, false), - Entry("revert after", false, true), - ) - It("it should send token transfer and send from WEVMOS contract", func() { - sender := is.keyring.GetKey(0) - receiver := is.keyring.GetAddr(1) - totalToSend := int64(350) - balRes, err := is.handler.GetBalanceFromBank(receiver.Bytes(), is.bondDenom) - Expect(err).To(BeNil()) - denomInitialBalance := balRes.Balance - balRes, err = is.handler.GetBalanceFromBank(sender.AccAddr, is.bondDenom) - Expect(err).To(BeNil()) - senderInitialBalance := balRes.Balance - - args.MethodName = "testTransferAndSend" - args.Args = []interface{}{ - receiver, - big.NewInt(100), - big.NewInt(100), - big.NewInt(150), - false, - false, - } - txArgs.Amount = big.NewInt(totalToSend) - - transferCheck := passCheck.WithExpEvents(erc20.EventTypeTransfer) - res, _, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, args, transferCheck) - Expect(err).To(BeNil()) - Expect(is.network.NextBlock()).To(BeNil()) - fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed) - - // contract balance should remain unchanged - balRes, err = is.handler.GetBalanceFromBank(receiver.Bytes(), is.bondDenom) - Expect(err).To(BeNil()) - denomFinalBalance := balRes.Balance - Expect(denomFinalBalance.Amount).To(Equal(denomInitialBalance.Amount.Add(math.NewInt(totalToSend)))) - - balRes, err = is.handler.GetBalanceFromBank(revertContractAddr.Bytes(), is.bondDenom) - Expect(err).To(BeNil()) - contractBalance := balRes.Balance - Expect(contractBalance.Amount).To(Equal(math.ZeroInt())) - - balRes, err = is.handler.GetBalanceFromBank(sender.AccAddr, is.bondDenom) - Expect(err).To(BeNil()) - senderFinalBalance := balRes.Balance - denomSpent := fees.AddRaw(totalToSend) - Expect(senderFinalBalance.Amount).To(Equal(senderInitialBalance.Amount.Sub(denomSpent))) - }, - ) - DescribeTable("it should revert token transfer and send from WEVMOS contract", func(before bool, after bool) { - sender := is.keyring.GetKey(0) - receiver := is.keyring.GetAddr(1) - balRes, err := is.handler.GetBalanceFromBank(receiver.Bytes(), is.bondDenom) - Expect(err).To(BeNil()) - denomInitialBalance := balRes.Balance - balRes, err = is.handler.GetBalanceFromBank(sender.AccAddr, is.bondDenom) - Expect(err).To(BeNil()) - senderInitialBalance := balRes.Balance - - args.MethodName = "testTransferAndSend" - args.Args = []interface{}{ - receiver, - big.NewInt(100), - big.NewInt(100), - big.NewInt(100), - before, - after, - } - txArgs.Amount = big.NewInt(300) - - res, _, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, args, execRevertedCheck) - Expect(err).To(BeNil()) - Expect(is.network.NextBlock()).To(BeNil()) - fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed) - - // contract balance should remain unchanged - balRes, err = is.handler.GetBalanceFromBank(receiver.Bytes(), is.bondDenom) - Expect(err).To(BeNil()) - denomFinalBalance := balRes.Balance - Expect(denomFinalBalance.Amount).To(Equal(denomInitialBalance.Amount)) - - balRes, err = is.handler.GetBalanceFromBank(revertContractAddr.Bytes(), is.bondDenom) - Expect(err).To(BeNil()) - contractBalance := balRes.Balance - Expect(contractBalance.Amount).To(Equal(math.ZeroInt())) - - balRes, err = is.handler.GetBalanceFromBank(sender.AccAddr, is.bondDenom) - Expect(err).To(BeNil()) - senderFinalBalance := balRes.Balance - Expect(senderFinalBalance.Amount).To(Equal(senderInitialBalance.Amount.Sub(fees))) - }, - Entry("revert before", true, false), - Entry("revert after", false, true), - ) - It("revert when transfer with try", func() { - sender := is.keyring.GetKey(0) - receiver := is.keyring.GetAddr(1) - amountToSend := big.NewInt(100) - balRes, err := is.handler.GetBalanceFromBank(receiver.Bytes(), is.bondDenom) - Expect(err).To(BeNil()) - denomInitialBalance := balRes.Balance - balRes, err = is.handler.GetBalanceFromBank(sender.AccAddr, is.bondDenom) - Expect(err).To(BeNil()) - senderInitialBalance := balRes.Balance - - args.MethodName = "transfersWithTry" - args.Args = []interface{}{ - receiver, - amountToSend, - amountToSend, - } - txArgs.Amount = big.NewInt(200) - - transferCheck := passCheck.WithExpEvents(erc20.EventTypeTransfer) - res, _, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, args, transferCheck) - Expect(err).To(BeNil()) - Expect(is.network.NextBlock()).To(BeNil()) - fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed) - - balRes, err = is.handler.GetBalanceFromBank(receiver.Bytes(), is.bondDenom) - Expect(err).To(BeNil()) - denomFinalBalance := balRes.Balance - Expect(denomFinalBalance.Amount).To(Equal(denomInitialBalance.Amount.Add(math.NewInt(amountToSend.Int64())))) - - balRes, err = is.handler.GetBalanceFromBank(revertContractAddr.Bytes(), is.bondDenom) - Expect(err).To(BeNil()) - contractBalance := balRes.Balance - Expect(contractBalance.Amount.Int64()).To(Equal(amountToSend.Int64())) - - balRes, err = is.handler.GetBalanceFromBank(sender.AccAddr, is.bondDenom) - Expect(err).To(BeNil()) - senderFinalBalance := balRes.Balance - denomSpent := fees.AddRaw(amountToSend.Int64() + amountToSend.Int64()) - Expect(senderFinalBalance.Amount).To(Equal(senderInitialBalance.Amount.Sub(denomSpent))) - }) - }) - }) - - When("transferring tokens from another account", func() { - Context("in a direct call to the token contract", func() { - DescribeTable("it should transfer tokens from another account with a sufficient approval set", func(callType CallType) { - owner := is.keyring.GetKey(0) - spender := is.keyring.GetKey(1) - receiver := utiltx.GenerateAddress() - - fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)} - transferAmount := big.NewInt(100) - transferCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, transferAmount.Int64())} - - // Fund account with some tokens - ownerInitialAmt := is.fundWithTokens(callType, contractsData, owner.Addr, fundCoins) - ownerInitialBalance := sdk.Coins{sdk.NewCoin(is.tokenDenom, ownerInitialAmt)} - - // Set allowance - is.setAllowanceForContract(callType, contractsData, owner.Priv, spender.Addr, transferAmount) - - // Transfer tokens - txArgs, transferArgs := is.getTxAndCallArgs( - callType, contractsData, - erc20.TransferFromMethod, - owner.Addr, receiver, transferAmount, - ) - - transferCheck := passCheck.WithExpEvents( - erc20.EventTypeTransfer, - erc20.EventTypeApproval, - ) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(spender.Priv, txArgs, transferArgs, transferCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit the changes to the chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.TransferFromMethod) - is.ExpectBalancesForContract( - callType, contractsData, - []ExpectedBalance{ - {address: owner.AccAddr, expCoins: ownerInitialBalance.Sub(transferCoins...)}, - {address: receiver.Bytes(), expCoins: transferCoins}, - }, - ) - - // Check that the allowance was removed since we approved only the transferred amount - is.ExpectAllowanceForContract( - callType, contractsData, - spender.Addr, owner.Addr, common.Big0, - ) - }, - Entry(" - direct call", directCall), - // NOTE: we are not passing the contract call here because this test is for direct calls only - - Entry(" - through erc20 contract", erc20Call), - Entry(" - through erc20 v5 contract", erc20V5Call), - ) - - When("the spender is the same as the sender", func() { - It("should return an error when transfer funds without an approval when calling the erc20 precompile", func() { - owner := is.keyring.GetKey(0) - spender := owner - receiver := utiltx.GenerateAddress() - - fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)} - transferCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)} - - // Fund account with some tokens - ownerInitialAmt := is.fundWithTokens(directCall, contractsData, owner.Addr, fundCoins) - ownerInitialBalance := sdk.Coins{sdk.NewCoin(is.tokenDenom, ownerInitialAmt)} - - // Transfer tokens - txArgs, transferArgs := is.getTxAndCallArgs( - directCall, contractsData, - erc20.TransferFromMethod, - owner.Addr, receiver, transferCoins[0].Amount.BigInt(), - ) - - insufficientAllowanceCheck := failCheck.WithErrContains( - erc20.ErrInsufficientAllowance.Error(), - ) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(spender.Priv, txArgs, transferArgs, insufficientAllowanceCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - Expect(ethRes).To(BeNil(), "expected empty result") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectBalancesForContract( - directCall, contractsData, - []ExpectedBalance{ - {address: owner.AccAddr, expCoins: ownerInitialBalance}, - {address: receiver.Bytes(), expCoins: sdk.NewCoins(sdk.NewCoin(is.tokenDenom, math.ZeroInt()))}, - }, - ) - }) - - DescribeTable("it should transfer funds from the own account in case sufficient approval is set", func(callType CallType) { - owner := is.keyring.GetKey(0) - receiver := utiltx.GenerateAddress() - - fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)} - transferCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)} - - // Fund account with some tokens - ownerInitialAmt := is.fundWithTokens(callType, contractsData, owner.Addr, fundCoins) - ownerInitialBalance := sdk.Coins{sdk.NewCoin(is.tokenDenom, ownerInitialAmt)} - - is.setAllowanceForContract( - callType, contractsData, - owner.Priv, owner.Addr, transferCoins[0].Amount.BigInt(), - ) - - is.ExpectAllowanceForContract( - callType, contractsData, - owner.Addr, owner.Addr, transferCoins[0].Amount.BigInt(), - ) - - err := is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - // Transfer tokens - txArgs, transferArgs := is.getTxAndCallArgs( - callType, contractsData, - erc20.TransferFromMethod, - owner.Addr, receiver, transferCoins[0].Amount.BigInt(), - ) - - transferCheck := passCheck.WithExpEvents( - erc20.EventTypeTransfer, - erc20.EventTypeApproval, - ) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, transferArgs, transferCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.TransferFromMethod) - is.ExpectBalancesForContract( - callType, contractsData, - []ExpectedBalance{ - {address: owner.AccAddr, expCoins: ownerInitialBalance.Sub(transferCoins...)}, - {address: receiver.Bytes(), expCoins: transferCoins}, - }, - ) - - // Check that the allowance was removed since we approved only the transferred amount - // FIXME: This is not working for the case where we transfer from the own account - // because the allowance is not removed on the SDK side. - is.ExpectAllowanceForContract( - callType, contractsData, - owner.Addr, owner.Addr, common.Big0, - ) - }, - Entry(" - through erc20 contract", erc20Call), - Entry(" - through erc20 v5 contract", erc20V5Call), - ) - }) - - DescribeTable("it should return an error when the spender does not have enough allowance", func(callType CallType) { - owner := is.keyring.GetKey(0) - spender := is.keyring.GetKey(1) - receiver := utiltx.GenerateAddress() - fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)} - approveAmount := big.NewInt(100) - transferAmount := big.NewInt(200) - - // Fund account with some tokens - is.fundWithTokens(callType, contractsData, owner.Addr, fundCoins) - // Set allowance - is.setAllowanceForContract( - callType, contractsData, - owner.Priv, spender.Addr, approveAmount, - ) - - // Transfer tokens - txArgs, transferArgs := is.getTxAndCallArgs( - callType, contractsData, - erc20.TransferFromMethod, - owner.Addr, receiver, transferAmount, - ) - - insufficientAllowanceCheck := failCheck.WithErrContains(erc20.ErrInsufficientAllowance.Error()) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(spender.Priv, txArgs, transferArgs, insufficientAllowanceCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - Expect(ethRes).To(BeNil(), "expected empty result") - }, - Entry(" - direct call", directCall), - // NOTE: we are not passing the contract call here because this test case only covers direct calls - - Entry(" - through erc20 contract", erc20Call), - - // TODO: the ERC20 V5 contract is raising the ERC-6093 standardized error which we are not using as of yet - // Entry(" - through erc20 v5 contract", erc20V5Call), - ) - - DescribeTable("it should return an error if there is no allowance set", func(callType CallType) { - sender := is.keyring.GetKey(0) - from := is.keyring.GetKey(1) - receiver := utiltx.GenerateAddress() - fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)} - transferAmount := big.NewInt(100) - - // Fund account with some tokens - is.fundWithTokens(callType, contractsData, from.Addr, fundCoins) - - // Transfer tokens - txArgs, transferArgs := is.getTxAndCallArgs( - callType, contractsData, - erc20.TransferFromMethod, - from.Addr, receiver, transferAmount, - ) - - insufficientAllowanceCheck := failCheck.WithErrContains( - erc20.ErrInsufficientAllowance.Error(), - ) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, transferArgs, insufficientAllowanceCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - Expect(ethRes).To(BeNil(), "expected empty result") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - }, - Entry(" - direct call", directCall), - // NOTE: we are not passing the contract call here because this test case only covers direct calls - - Entry(" - through erc20 contract", erc20Call), - - // TODO: the ERC20 V5 contract is raising the ERC-6093 standardized error which we are not using as of yet - // Entry(" - through erc20 v5 contract", erc20V5Call), - ) - - DescribeTable("it should return an error if the sender does not have enough tokens", func(callType CallType) { - sender := is.keyring.GetKey(0) - from := is.keyring.GetKey(1) - receiver := utiltx.GenerateAddress() - fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 200)} - - // Fund account with some tokens - senderInitialAmt := is.fundWithTokens(callType, contractsData, from.Addr, fundCoins) - transferAmt := new(big.Int).Add(senderInitialAmt.BigInt(), big.NewInt(100)) - - // Set allowance - is.setAllowanceForContract( - callType, contractsData, - from.Priv, sender.Addr, transferAmt, - ) - - // Transfer tokens - txArgs, transferArgs := is.getTxAndCallArgs(callType, contractsData, erc20.TransferFromMethod, from.Addr, receiver, transferAmt) - - insufficientBalanceCheck := failCheck.WithErrContains( - erc20.ErrTransferAmountExceedsBalance.Error(), - ) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, transferArgs, insufficientBalanceCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - Expect(ethRes).To(BeNil(), "expected empty result") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - }, - Entry(" - direct call", directCall), - // NOTE: we are not passing the contract call here because this test case only covers direct calls - - Entry(" - through erc20 contract", erc20Call), - - // TODO: the ERC20 V5 contract is raising the ERC-6093 standardized error which we are not using as of yet - // Entry(" - through erc20 v5 contract", erc20V5Call), - ) - }) - - Context("in a call from another smart contract to the token contract", func() { - DescribeTable("it should transfer tokens with a sufficient approval set", func(callType CallType) { - owner := is.keyring.GetKey(0) - receiver := utiltx.GenerateAddress() - fundCoin := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)} - transferAmount := big.NewInt(100) - transferCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, transferAmount.Int64())} - - // NOTE: the spender will be the contract address - spender := contractsData.GetContractData(callType).Address - - // Fund account with some tokens - ownerInitialAmt := is.fundWithTokens(callType, contractsData, owner.Addr, fundCoin) - ownerInitialBalance := sdk.Coins{sdk.NewCoin(is.tokenDenom, ownerInitialAmt)} - - // Set allowance - is.setAllowanceForContract( - callType, contractsData, - owner.Priv, spender, transferAmount, - ) - - // Transfer tokens - txArgs, transferArgs := is.getTxAndCallArgs( - callType, contractsData, - erc20.TransferFromMethod, - owner.Addr, receiver, transferCoins[0].Amount.BigInt(), - ) - - transferCheck := passCheck.WithExpEvents( - erc20.EventTypeTransfer, - erc20.EventTypeApproval, - ) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, transferArgs, transferCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.TransferFromMethod) - is.ExpectBalancesForContract( - callType, contractsData, - []ExpectedBalance{ - {address: owner.AccAddr, expCoins: ownerInitialBalance.Sub(transferCoins...)}, - {address: receiver.Bytes(), expCoins: transferCoins}, - }, - ) - - // Check that the allowance was removed since we approved only the transferred amount - is.ExpectAllowanceForContract( - callType, contractsData, - spender, owner.Addr, common.Big0, - ) - }, - // Entry(" - direct call", directCall), - Entry(" - through contract", contractCall), - // NOTE: we are not passing the erc20 contract call here because this is supposed to - // test external contract calls - Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), - ) - - DescribeTable("it should transfer funds with a sufficient allowance and triggered from another account", func(callType CallType) { - msgSender := is.keyring.GetKey(0) - owner := is.keyring.GetKey(1) - receiver := utiltx.GenerateAddress() - - // NOTE: the spender will be the contract address - spender := contractsData.GetContractData(callType).Address - - fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)} - transferCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)} - - // Fund account with some tokens - ownerInitialAmt := is.fundWithTokens(callType, contractsData, owner.Addr, fundCoins) - ownerInitialBalance := sdk.Coins{sdk.NewCoin(is.tokenDenom, ownerInitialAmt)} - - // Set allowance - is.setAllowanceForContract( - callType, contractsData, - owner.Priv, spender, transferCoins.AmountOf(is.tokenDenom).BigInt(), - ) - - // Transfer tokens - txArgs, transferArgs := is.getTxAndCallArgs( - callType, contractsData, - erc20.TransferFromMethod, - owner.Addr, receiver, transferCoins[0].Amount.BigInt(), - ) - - transferCheck := passCheck.WithExpEvents( - erc20.EventTypeTransfer, - erc20.EventTypeApproval, - ) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(msgSender.Priv, txArgs, transferArgs, transferCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.TransferFromMethod) - is.ExpectBalancesForContract( - callType, contractsData, - []ExpectedBalance{ - {address: owner.AccAddr, expCoins: ownerInitialBalance.Sub(transferCoins...)}, - {address: receiver.Bytes(), expCoins: transferCoins}, - }, - ) - - // Check that the allowance was removed since we approved only the transferred amount - is.ExpectAllowanceForContract( - callType, contractsData, - spender, owner.Addr, common.Big0, - ) - }, - // NOTE: we are not passing the direct call here because this test is specific to the contract calls - - Entry(" - through contract", contractCall), - Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), - ) - - DescribeTable("it should return an error when the spender does not have enough allowance", func(callType CallType) { - from := is.keyring.GetKey(0) - receiver := utiltx.GenerateAddress() - fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 400)} - approveAmount := big.NewInt(100) - transferAmount := big.NewInt(300) - - // NOTE: the spender will be the contract address - spender := contractsData.GetContractData(callType).Address - - // Fund account with some tokens - is.fundWithTokens(callType, contractsData, from.Addr, fundCoins) - - // Set allowance - is.setAllowanceForContract(callType, contractsData, from.Priv, spender, approveAmount) - - // Transfer tokens - txArgs, transferArgs := is.getTxAndCallArgs( - callType, contractsData, - erc20.TransferFromMethod, - from.Addr, receiver, transferAmount, - ) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(from.Priv, txArgs, transferArgs, execRevertedCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - Expect(ethRes).To(BeNil(), "expected empty result") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - }, - // NOTE: we are not passing the direct call here because this test is for contract calls only - Entry(" - through contract", contractCall), - Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), - ) - }) - }) - - When("querying balance", func() { - DescribeTable("it should return an existing balance", func(callType CallType) { - sender := is.keyring.GetKey(0) - addedAmt := big.NewInt(100) - fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, addedAmt.Int64())} - - // Fund account with some tokens - ownerInitialAmt := is.fundWithTokens(callType, contractsData, sender.Addr, fundCoins) - - // Query the balance - txArgs, balancesArgs := is.getTxAndCallArgs(callType, contractsData, erc20.BalanceOfMethod, sender.Addr) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, balancesArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - var balance *big.Int - err = is.precompile.UnpackIntoInterface(&balance, erc20.BalanceOfMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack result") - Expect(math.NewIntFromBigInt(balance)).To(Equal(ownerInitialAmt), "expected different balance") - }, - Entry(" - direct call", directCall), - Entry(" - through contract", contractCall), - Entry(" - through erc20 contract", erc20Call), - Entry(" - through erc20 v5 contract", erc20V5Call), - Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), - ) - - DescribeTable("it should return zero if balance only exists for other tokens", func(callType CallType) { - sender := is.keyring.GetKey(0) - address := utiltx.GenerateAddress() - fundCoins := sdk.Coins{sdk.NewInt64Coin(is.network.GetBaseDenom(), 100)} - - // Fund account with some tokens - err := is.factory.FundAccount(is.keyring.GetKey(0), sender.AccAddr, fundCoins) - Expect(err).ToNot(HaveOccurred(), "failed to fund account") - Expect(is.network.NextBlock()).To(BeNil()) - - // Query the balance - txArgs, balancesArgs := is.getTxAndCallArgs(callType, contractsData, erc20.BalanceOfMethod, address) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, balancesArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - var balance *big.Int - err = is.precompile.UnpackIntoInterface(&balance, erc20.BalanceOfMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack result") - Expect(balance.Int64()).To(BeZero(), "expected zero balance") - }, - Entry(" - direct call", directCall), - Entry(" - through contract", contractCall), - // NOTE: we are not passing the erc20 contract call here because the ERC20 contracts - // only support the actual token denomination and don't know of other balances. - ) - - DescribeTable("it should return zero if the account does not exist", func(callType CallType) { - sender := is.keyring.GetKey(0) - address := utiltx.GenerateAddress() - - // Query the balance - txArgs, balancesArgs := is.getTxAndCallArgs(callType, contractsData, erc20.BalanceOfMethod, address) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, balancesArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - var balance *big.Int - err = is.precompile.UnpackIntoInterface(&balance, erc20.BalanceOfMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack result") - Expect(balance.Int64()).To(BeZero(), "expected zero balance") - }, - Entry(" - direct call", directCall), - Entry(" - through contract", contractCall), - Entry(" - through erc20 contract", erc20Call), - Entry(" - through erc20 v5 contract", erc20V5Call), - Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), - ) - }) - - When("querying allowance", func() { - DescribeTable("it should return an existing allowance", func(callType CallType) { - spender := utiltx.GenerateAddress() - owner := is.keyring.GetKey(0) - approveAmount := big.NewInt(100) - - is.setAllowanceForContract(callType, contractsData, owner.Priv, spender, approveAmount) - - txArgs, allowanceArgs := is.getTxAndCallArgs(callType, contractsData, erc20.AllowanceMethod, owner.Addr, spender) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, allowanceArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - var allowance *big.Int - err = is.precompile.UnpackIntoInterface(&allowance, erc20.AllowanceMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack result") - Expect(allowance).To(Equal(approveAmount), "expected different allowance") - }, - Entry(" - direct call", directCall), - Entry(" - through contract", contractCall), - Entry(" - through erc20 contract", erc20Call), - Entry(" - through erc20 v5 contract", erc20V5Call), - Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), - ) - - When("querying the allowance for the own address", func() { - It("should return the 0 value when calling the erc20 precompile", func() { - spender := is.keyring.GetAddr(0) - owner := is.keyring.GetKey(0) - - txArgs, allowanceArgs := is.getTxAndCallArgs(directCall, contractsData, erc20.AllowanceMethod, spender, spender) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, allowanceArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - var allowance *big.Int - err = is.precompile.UnpackIntoInterface(&allowance, erc20.AllowanceMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack result") - Expect(allowance.Sign()).To(Equal(0), "expected different allowance") - }) - - // NOTE: Since it's possible to set an allowance for the own address with the Solidity ERC20 contracts, - // we describe this case here for completion purposes, to describe the difference in behavior. - DescribeTable("should return the actual allowance value when calling the ERC20 contract", func(callType CallType) { - owner := is.keyring.GetKey(0) - approveAmount := big.NewInt(100) - - is.setAllowanceForContract(callType, contractsData, owner.Priv, owner.Addr, approveAmount) - - txArgs, allowanceArgs := is.getTxAndCallArgs(callType, contractsData, erc20.AllowanceMethod, owner.Addr, owner.Addr) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, allowanceArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - var allowance *big.Int - err = is.precompile.UnpackIntoInterface(&allowance, erc20.AllowanceMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack result") - Expect(allowance).To(Equal(approveAmount), "expected different allowance") - }, - Entry(" - through erc20 contract", erc20Call), - Entry(" - through erc20 v5 contract", erc20V5Call), - ) - }) - - DescribeTable("it should return zero if no allowance exists", func(callType CallType) { - spender := is.keyring.GetAddr(1) - owner := is.keyring.GetKey(0) - - txArgs, allowanceArgs := is.getTxAndCallArgs(callType, contractsData, erc20.AllowanceMethod, owner.Addr, spender) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, allowanceArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - var allowance *big.Int - err = is.precompile.UnpackIntoInterface(&allowance, erc20.AllowanceMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack result") - Expect(allowance.Int64()).To(BeZero(), "expected zero allowance") - }, - Entry(" - direct call", directCall), - Entry(" - through contract", contractCall), - Entry(" - through erc20 contract", erc20Call), - Entry(" - through erc20 v5 contract", erc20V5Call), - Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), - ) - - DescribeTable("it should return zero if the account does not exist", func(callType CallType) { - spender := utiltx.GenerateAddress() - owner := is.keyring.GetKey(0) - - txArgs, allowanceArgs := is.getTxAndCallArgs(callType, contractsData, erc20.AllowanceMethod, owner.Addr, spender) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, allowanceArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - var allowance *big.Int - err = is.precompile.UnpackIntoInterface(&allowance, erc20.AllowanceMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack result") - Expect(allowance.Int64()).To(BeZero(), "expected zero allowance") - }, - Entry(" - direct call", directCall), - Entry(" - through contract", contractCall), - Entry(" - through erc20 contract", erc20Call), - Entry(" - through erc20 v5 contract", erc20V5Call), - Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), - ) - }) - - When("querying total supply", func() { - DescribeTable("it should return the total supply", func(callType CallType) { - sender := is.keyring.GetKey(0) - expSupply := big.NewInt(100) - fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, expSupply.Int64())} - - // Fund account with some tokens - is.fundWithTokens(callType, contractsData, sender.Addr, fundCoins) - - // if is native coin, get expSupply from the bank mod - if slices.Contains(nativeCallTypes, callType) { - qc := is.network.GetBankClient() - qRes, err := qc.SupplyOf(is.network.GetContext(), &banktypes.QuerySupplyOfRequest{Denom: is.tokenDenom}) - Expect(err).To(BeNil()) - Expect(qRes).NotTo(BeNil()) - expSupply = qRes.Amount.Amount.BigInt() - } - - // Query the balance - txArgs, supplyArgs := is.getTxAndCallArgs(callType, contractsData, erc20.TotalSupplyMethod) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, supplyArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - var supply *big.Int - err = is.precompile.UnpackIntoInterface(&supply, erc20.TotalSupplyMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack result") - Expect(supply).To(Equal(expSupply), "expected different supply") - }, - Entry(" - direct call", directCall), - Entry(" - through contract", contractCall), - Entry(" - through erc20 contract", erc20Call), - Entry(" - through erc20 v5 contract", erc20V5Call), - Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), - ) - - DescribeTable("it should return zero if no tokens exist", func(callType CallType) { - sender := is.keyring.GetKey(0) - txArgs, supplyArgs := is.getTxAndCallArgs(callType, contractsData, erc20.TotalSupplyMethod) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, supplyArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - var supply *big.Int - err = is.precompile.UnpackIntoInterface(&supply, erc20.TotalSupplyMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack result") - Expect(supply.Int64()).To(BeZero(), "expected zero supply") - }, - Entry(" - direct call", directCallToken2), - Entry(" - through contract", contractCallToken2), - Entry(" - through erc20 contract", erc20Call), - Entry(" - through erc20 v5 contract", erc20V5Call), - Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), - ) - }) - - When("approving an allowance", func() { - Context("in a call to the token contract", func() { - DescribeTable("it should approve an allowance", func(callType CallType) { - spender := is.keyring.GetKey(0) - owner := is.keyring.GetKey(1) - approveAmount := big.NewInt(200) - - // Approve allowance - txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, erc20.ApproveMethod, spender.Addr, approveAmount) - - approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, approveArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) - is.ExpectAllowanceForContract( - callType, contractsData, - owner.Addr, spender.Addr, approveAmount, - ) - }, - Entry(" - direct call", directCall), - Entry(" - through erc20 contract", erc20Call), - Entry(" - through erc20 v5 contract", erc20V5Call), - ) - - DescribeTable("it should set the new spend limit for an existing allowance", func(callType CallType) { - spender := is.keyring.GetKey(1) - owner := is.keyring.GetKey(0) - prevAllowance := big.NewInt(200) - approveAmount := big.NewInt(100) - - // set up a previous allowance - is.setAllowanceForContract(callType, contractsData, owner.Priv, spender.Addr, prevAllowance) - - // Approve allowance - txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, erc20.ApproveMethod, spender.Addr, approveAmount) - - approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, approveArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) - // Check allowance contains both spend limits - is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, approveAmount) - }, - Entry(" - direct call", directCall), - Entry(" - through erc20 contract", erc20Call), - Entry(" - through erc20 v5 contract", erc20V5Call), - ) - - DescribeTable("it should remove the token from the spend limit of an existing allowance when approving zero", func(callType CallType) { - owner := is.keyring.GetKey(0) - spender := is.keyring.GetKey(1) - approveAmount := big.NewInt(100) - - // set up a previous allowance - is.setAllowanceForContract(callType, contractsData, owner.Priv, spender.Addr, approveAmount) - - // Approve allowance - txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, erc20.ApproveMethod, spender.Addr, common.Big0) - - approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, approveArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) - - // commit the changes to state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") - - // Check allowance is set to zero - is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, common.Big0) - }, - Entry(" - direct call", directCall), - // NOTE: we are not passing the erc20 contract call here because the ERC20 contract - // only supports the actual token denomination and doesn't know of other allowances. - ) - - DescribeTable("it should delete the allowance when approving zero with no other spend limits", func(callType CallType) { - spender := is.keyring.GetKey(1) - owner := is.keyring.GetKey(0) - allowance := big.NewInt(100) - - // set up a previous allowance - is.setAllowanceForContract(callType, contractsData, owner.Priv, spender.Addr, allowance) - - // Approve allowance - txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, erc20.ApproveMethod, spender.Addr, common.Big0) - - approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, approveArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) - // Check allowance was deleted - is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, common.Big0) - }, - Entry(" - direct call", directCall), - Entry(" - through erc20 contract", erc20Call), - Entry(" - through erc20 v5 contract", erc20V5Call), - ) - - DescribeTable("it should no-op if approving 0 and no allowance exists", func(callType CallType) { - spender := is.keyring.GetKey(1) - owner := is.keyring.GetKey(0) - - // Approve allowance - txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, erc20.ApproveMethod, spender.Addr, common.Big0) - - // We are expecting an approval to be made, but no allowance stored since it's 0 - approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, approveArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) - // Check still no allowance exists - is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, common.Big0) - }, - Entry(" - direct call", directCall), - Entry(" - through erc20 contract", erc20Call), - Entry(" - through erc20 v5 contract", erc20V5Call), - ) - - When("the spender is the same as the owner", func() { - It("should return an error when calling the erc20 precompile", func() { - spender := is.keyring.GetKey(0) - owner := is.keyring.GetKey(0) - approveAmount := big.NewInt(100) - - // Approve allowance - txArgs, approveArgs := is.getTxAndCallArgs( - directCall, contractsData, - erc20.ApproveMethod, - spender.Addr, approveAmount, - ) - - approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, approveArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) - is.ExpectAllowanceForContract( - directCall, contractsData, - owner.Addr, spender.Addr, approveAmount, - ) - }) - - DescribeTable("it should create an allowance", func(callType CallType) { - spender := is.keyring.GetKey(0) - owner := is.keyring.GetKey(0) - allowance := big.NewInt(100) - - // Approve allowance - txArgs, approveArgs := is.getTxAndCallArgs( - callType, contractsData, - erc20.ApproveMethod, - spender.Addr, allowance, - ) - - approvalCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, approveArgs, approvalCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) - is.ExpectAllowanceForContract( - callType, contractsData, - owner.Addr, spender.Addr, allowance, - ) - }, - Entry(" - through erc20 contract", erc20Call), - Entry(" - through erc20 v5 contract", erc20V5Call), - ) - }) - - DescribeTable("it should return an error if approving 0 and allowance only exists for other tokens", func(callType CallType) { - owner := is.keyring.GetKey(0) - spender := is.keyring.GetKey(1) - prevAllowance := big.NewInt(200) - - callTypeForOtherToken := directCallToken2 - - // set up a previous allowance for other token - is.setAllowanceForContract(callTypeForOtherToken, contractsData, owner.Priv, spender.Addr, prevAllowance) - - // Approve allowance for target token - txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, erc20.ApproveMethod, spender.Addr, common.Big0) - - approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, approveArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) - is.ExpectAllowanceForContract( - callType, contractsData, - owner.Addr, spender.Addr, common.Big0, - ) - - // Check allowance of other token is not chaged - is.ExpectAllowanceForContract( - callTypeForOtherToken, contractsData, - owner.Addr, spender.Addr, prevAllowance, - ) - }, - Entry(" - direct call", directCall), - // NOTE: we are not passing the erc20 contract call here because the ERC20 contract - // only supports the actual token denomination and doesn't know of other allowances. - ) - }) - - // NOTE: We have to split the tests for contract calls into a separate context because - // when approving through a smart contract, the approval is created between the contract address and the - // spender, instead of the sender address and the spender. - Context("in a contract call", func() { - DescribeTable("it should approve an allowance", func(callType CallType) { - sender := is.keyring.GetKey(0) - spender := is.keyring.GetKey(1) - owner := contractsData.GetContractData(callType).Address // the owner will be the contract address - transferAmount := big.NewInt(200) - - // Approve allowance - txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, erc20.ApproveMethod, spender.Addr, transferAmount) - - approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, approveArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) - // Check allowance - is.ExpectAllowanceForContract( - callType, contractsData, - owner, spender.Addr, transferAmount, - ) - }, - Entry(" - through contract", contractCall), - Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), - ) - - DescribeTable("it should set the new spend limit for an existing allowance with the same token", func(callType CallType) { - sender := is.keyring.GetKey(0) - spender := is.keyring.GetKey(1) - owner := contractsData.GetContractData(callType).Address // the owner will be the contract address - initialAmount := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)} - newAmount := big.NewInt(200) - - // Set up a first approval - txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, erc20.ApproveMethod, spender.Addr, initialAmount[0].Amount.BigInt()) - approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, approveArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) - - // Set up a second approval which should overwrite the initial one - txArgs, approveArgs = is.getTxAndCallArgs(callType, contractsData, erc20.ApproveMethod, spender.Addr, newAmount) - approveCheck = passCheck.WithExpEvents(erc20.EventTypeApproval) - _, ethRes, err = is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, approveArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - // Check allowance has been updated - is.ExpectAllowanceForContract( - callType, contractsData, - owner, spender.Addr, newAmount, - ) - }, - Entry(" - through contract", contractCall), - Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), - ) - - DescribeTable("it should delete the allowance when approving zero with no other spend limits", func(callType CallType) { - sender := is.keyring.GetKey(0) - spender := is.keyring.GetKey(1) - owner := contractsData.GetContractData(callType).Address // the owner will be the contract address - approveAmount := big.NewInt(100) - - // set up a previous allowance - // - // TODO: refactor using helper - txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, erc20.ApproveMethod, spender.Addr, approveAmount) - approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, approveArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) - - // Approve allowance - txArgs, approveArgs = is.getTxAndCallArgs(callType, contractsData, erc20.ApproveMethod, spender.Addr, common.Big0) - _, ethRes, err = is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, approveArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) - - // Check allowance was deleted from the keeper / is returning 0 for smart contracts - is.ExpectAllowanceForContract(callType, contractsData, owner, spender.Addr, common.Big0) - }, - Entry(" - through contract", contractCall), - Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), - ) - - DescribeTable("it should no-op if approving 0 and no allowance exists", func(callType CallType) { - sender := is.keyring.GetKey(0) - spender := is.keyring.GetKey(1) - owner := contractsData.GetContractData(callType).Address // the owner will be the contract address - - // Approve allowance - txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, erc20.ApproveMethod, spender.Addr, common.Big0) - - // We are expecting an approval event to be emitted, but no allowance to be stored - approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, approveArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) - // Check still no allowance exists - is.ExpectAllowanceForContract(callType, contractsData, owner, spender.Addr, common.Big0) - }, - Entry(" - through contract", contractCall), - Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), - ) - - When("the spender is the same as the owner", func() { - It("should approve an allowance", func() { - callType := contractCall - sender := is.keyring.GetKey(0) - owner := contractsData.GetContractData(callType).Address // the owner will be the contract address - spender := owner - approveAmount := big.NewInt(100) - - // Approve allowance - txArgs, approveArgs := is.getTxAndCallArgs( - callType, contractsData, - erc20.ApproveMethod, - spender, approveAmount, - ) - - approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, approveArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) - is.ExpectAllowanceForContract( - callType, contractsData, - owner, spender, approveAmount, - ) - }) - - DescribeTable("it should create an allowance when calling an ERC20 Solidity contract", func(callType CallType) { - sender := is.keyring.GetKey(0) - owner := contractsData.GetContractData(callType).Address // the owner will be the contract address - spender := owner - allowance := big.NewInt(100) - - // Approve allowance - txArgs, approveArgs := is.getTxAndCallArgs( - callType, contractsData, - erc20.ApproveMethod, - spender, allowance, - ) - - approvalCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, approveArgs, approvalCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) - is.ExpectAllowanceForContract( - callType, contractsData, - owner, spender, allowance, - ) - }, - Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), - ) - }) - }) - }) - }) - - Context("metadata query -", func() { - Context("for a token without registered metadata", func() { - BeforeEach(func() { - // Deploy ERC20NoMetadata contract for this test - erc20NoMetadataContract, err := testdata.LoadERC20NoMetadataContract() - Expect(err).ToNot(HaveOccurred(), "failed to load contract") - - erc20NoMetadataAddr, err := is.factory.DeployContract( - is.keyring.GetPrivKey(0), - evmtypes.EvmTxArgs{}, - factory.ContractDeploymentData{ - Contract: erc20NoMetadataContract, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to deploy contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - // NOTE: update the address but leave the ABI as it is, so that the ABI includes - // the metadata methods but the contract doesn't have them. - contractsData.contractData[erc20Call] = ContractData{ - Address: erc20NoMetadataAddr, - ABI: contracts.ERC20MinterBurnerDecimalsContract.ABI, - } - }) - - DescribeTable("querying the name should return an error", func(callType CallType) { - txArgs, nameArgs := is.getTxAndCallArgs(callType, contractsData, erc20.NameMethod) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(is.keyring.GetPrivKey(0), txArgs, nameArgs, execRevertedCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - Expect(ethRes).To(BeNil(), "expected empty result") - }, - Entry(" - direct call", directCall), - Entry(" - through contract", contractCall), - Entry(" - through erc20 contract", erc20Call), // NOTE: we're passing the ERC20 contract call here which was adjusted to point to a contract without metadata to expect the same errors - ) - - DescribeTable("querying the symbol should return an error", func(callType CallType) { - txArgs, symbolArgs := is.getTxAndCallArgs(callType, contractsData, erc20.SymbolMethod) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(is.keyring.GetPrivKey(0), txArgs, symbolArgs, execRevertedCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - Expect(ethRes).To(BeNil(), "expected empty result") - }, - Entry(" - direct call", directCall), - Entry(" - through contract", contractCall), - Entry(" - through erc20 contract", erc20Call), // NOTE: we're passing the ERC20 contract call here which was adjusted to point to a contract without metadata to expect the same errors - ) - - DescribeTable("querying the decimals should return an error", func(callType CallType) { - txArgs, decimalsArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecimalsMethod) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(is.keyring.GetPrivKey(0), txArgs, decimalsArgs, execRevertedCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - Expect(ethRes).To(BeNil(), "expected empty result") - }, - Entry(" - direct call", directCall), - Entry(" - through contract", contractCall), - Entry(" - through erc20 contract", erc20Call), // NOTE: we're passing the ERC20 contract call here which was adjusted to point to a contract without metadata to expect the same errors - ) - }) - - Context("for a token with available metadata", func() { - const ( - expSymbol = "Xmpl" - expDecimals = uint8(18) - ) - - var ( - erc20Addr common.Address - expName string - ) - - BeforeEach(func() { - erc20Addr = contractsData.GetContractData(erc20V5Call).Address - expName = erc20types.CreateDenom(erc20Addr.String()) - - // Register ERC20 token pair for this test - tokenPairs, err := integrationutils.RegisterERC20(is.factory, is.network, integrationutils.ERC20RegistrationData{ - Addresses: []string{erc20Addr.Hex()}, - ProposerPriv: is.keyring.GetPrivKey(0), - }) - Expect(err).ToNot(HaveOccurred(), "failed to register ERC20 token") - Expect(tokenPairs).To(HaveLen(1)) - - // overwrite the other precompile with this one, so that the test utils like is.getTxAndCallArgs still work. - is.precompile, err = setupNewERC20PrecompileForTokenPair(is.keyring.GetPrivKey(0), is.network, is.factory, tokenPairs[0]) - Expect(err).ToNot(HaveOccurred(), "failed to set up erc20 precompile") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - // update this in the global contractsData - contractsData.contractData[directCall] = ContractData{ - Address: is.precompile.Address(), - ABI: is.precompile.ABI, - } - - // Deploy contract calling the ERC20 precompile - callerAddr, err := is.factory.DeployContract( - is.keyring.GetPrivKey(0), - evmtypes.EvmTxArgs{}, - factory.ContractDeploymentData{ - Contract: allowanceCallerContract, - ConstructorArgs: []interface{}{ - is.precompile.Address(), - }, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to deploy contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - contractsData.contractData[contractCall] = ContractData{ - Address: callerAddr, - ABI: allowanceCallerContract.ABI, - } - }) - - DescribeTable("querying the name should return the name", func(callType CallType) { - txArgs, nameArgs := is.getTxAndCallArgs(callType, contractsData, erc20.NameMethod) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(is.keyring.GetPrivKey(0), txArgs, nameArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - var name string - err = is.precompile.UnpackIntoInterface(&name, erc20.NameMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack result") - Expect(name).To(Equal(expName), "expected different name") - }, - Entry(" - direct call", directCall), - Entry(" - through contract", contractCall), - Entry(" - through erc20 v5 contract", erc20V5Call), - ) - - DescribeTable("querying the symbol should return the symbol", func(callType CallType) { - txArgs, symbolArgs := is.getTxAndCallArgs(callType, contractsData, erc20.SymbolMethod) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(is.keyring.GetPrivKey(0), txArgs, symbolArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - var symbol string - err = is.precompile.UnpackIntoInterface(&symbol, erc20.SymbolMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack result") - Expect(symbol).To(Equal(expSymbol), "expected different symbol") - }, - Entry(" - direct call", directCall), - Entry(" - through contract", contractCall), - Entry(" - through erc20 v5 contract", erc20V5Call), - ) - - DescribeTable("querying the decimals should return the decimals", func(callType CallType) { - txArgs, decimalsArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecimalsMethod) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(is.keyring.GetPrivKey(0), txArgs, decimalsArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - var decimals uint8 - err = is.precompile.UnpackIntoInterface(&decimals, erc20.DecimalsMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack result") - Expect(decimals).To(Equal(expDecimals), "expected different decimals") - }, - Entry(" - direct call", directCall), - Entry(" - through contract", contractCall), - Entry(" - through erc20 v5 contract", erc20V5Call), - ) - }) - }) - - Context("allowance adjustments -", func() { - var ( - spender keyring.Key - owner keyring.Key - ) - - BeforeEach(func() { - // Deploying the contract which has the increase / decrease allowance methods - contractAddr, err := is.factory.DeployContract( - is.keyring.GetPrivKey(0), - evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values - factory.ContractDeploymentData{ - Contract: allowanceCallerContract, - ConstructorArgs: []interface{}{is.precompile.Address()}, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to deploy contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - contractsData.contractData[erc20CallerCall] = ContractData{ - Address: contractAddr, - ABI: allowanceCallerContract.ABI, - } - - spender = is.keyring.GetKey(0) - owner = is.keyring.GetKey(1) - }) - - When("the spender is the same as the owner", func() { - Context("increasing allowance", func() { - It("should approve an allowance", func() { - owner := is.keyring.GetKey(0) - spender := owner - allowance := big.NewInt(100) - - txArgs, increaseArgs := is.getTxAndCallArgs( - directCall, contractsData, - erc20.IncreaseAllowanceMethod, - spender.Addr, allowance, - ) - - transferCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, increaseArgs, transferCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.IncreaseAllowanceMethod) - is.ExpectAllowanceForContract( - directCall, contractsData, - owner.Addr, spender.Addr, allowance, - ) - }) - - DescribeTable("it should create an allowance if none existed before", func(callType CallType) { - owner := is.keyring.GetKey(0) - spender := owner - allowance := big.NewInt(100) - - txArgs, increaseArgs := is.getTxAndCallArgs( - callType, contractsData, - erc20.IncreaseAllowanceMethod, - spender.Addr, allowance, - ) - - approvalCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, increaseArgs, approvalCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.IncreaseAllowanceMethod) - is.ExpectAllowanceForContract( - callType, contractsData, - owner.Addr, spender.Addr, allowance, - ) - }, - Entry(" - through erc20 contract", erc20Call), - Entry(" - through erc20 v5 contract", erc20V5Call), - ) - }) - - Context("decreasing allowance", func() { - It("should return an error when allowance does not exist", func() { - owner := is.keyring.GetKey(0) - spender := owner - allowance := big.NewInt(100) - - txArgs, decreaseArgs := is.getTxAndCallArgs( - directCall, contractsData, - erc20.DecreaseAllowanceMethod, - spender.Addr, allowance, - ) - - noAllowanceCheck := failCheck.WithErrContains( - fmt.Sprintf(erc20.ErrNoAllowanceForToken, is.tokenDenom), - ) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, decreaseArgs, noAllowanceCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - Expect(ethRes).To(BeNil(), "expected empty result") - - is.ExpectAllowanceForContract( - directCall, contractsData, - owner.Addr, spender.Addr, common.Big0, - ) - // commit the changes to state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") - }) - - DescribeTable("it should decrease an existing allowance", func(callType CallType) { - owner := is.keyring.GetKey(0) - spender := owner - approveAmount := big.NewInt(200) - decreaseAmount := big.NewInt(100) - - is.setAllowanceForContract( - callType, contractsData, - owner.Priv, spender.Addr, approveAmount, - ) - - txArgs, decreaseArgs := is.getTxAndCallArgs( - callType, contractsData, - erc20.DecreaseAllowanceMethod, - spender.Addr, decreaseAmount, - ) - - approvalCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, decreaseArgs, approvalCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit the changes to state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") - - is.ExpectTrueToBeReturned(ethRes, erc20.IncreaseAllowanceMethod) - is.ExpectAllowanceForContract( - callType, contractsData, - owner.Addr, spender.Addr, decreaseAmount, - ) - }, - Entry(" - through erc20 contract", erc20Call), - Entry(" - through erc20 v5 contract", erc20V5Call), - ) - }) - }) - - When("no allowance exists", func() { - DescribeTable("decreasing the allowance should return an error", func(callType CallType) { - approveAmount := big.NewInt(100) - - txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecreaseAllowanceMethod, spender.Addr, approveAmount) - - notFoundCheck := execRevertedCheck - if callType == directCall { - notFoundCheck = failCheck.WithErrContains( - fmt.Sprintf(erc20.ErrNoAllowanceForToken, is.tokenDenom), - ) - } - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, decreaseArgs, notFoundCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - Expect(ethRes).To(BeNil(), "expected empty result") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - }, - Entry(" - direct call", directCall), - Entry(" - through erc20 contract", erc20Call), - // NOTE: The ERC20 V5 contract does not contain these methods - // Entry(" - through erc20 v5 contract", erc20V5Call), - Entry(" - contract call", contractCall), - Entry(" - through erc20 caller contract", erc20CallerCall), - ) - - // NOTE: We have to split between direct and contract calls here because the ERC20 behavior - // for approvals is different, so we expect different allowances here - Context("in direct calls", func() { - DescribeTable("increasing the allowance should create a new allowance", func(callType CallType) { - approveAmount := big.NewInt(100) - - txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.IncreaseAllowanceMethod, spender.Addr, approveAmount) - - approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, increaseArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) - is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, approveAmount) - }, - Entry(" - direct call", directCall), - Entry(" - through erc20 contract", erc20Call), - // NOTE: The ERC20 V5 contract does not contain these methods - // Entry(" - through erc20 v5 contract", erc20V5Call), - ) - }) - - Context("in contract calls", func() { - DescribeTable("increasing the allowance should create a new allowance", func(callType CallType) { - contractAddr := contractsData.GetContractData(callType).Address - approveAmount := big.NewInt(100) - - txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.IncreaseAllowanceMethod, spender.Addr, approveAmount) - - approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, increaseArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.IncreaseAllowanceMethod) - is.ExpectAllowanceForContract(callType, contractsData, contractAddr, spender.Addr, approveAmount) - }, - Entry(" - contract call", contractCall), - Entry(" - through erc20 caller contract", erc20CallerCall), - ) - }) - }) - - When("an allowance exists for other tokens", func() { - var prevAllowance *big.Int - - BeforeEach(func() { - prevAllowance = big.NewInt(200) - }) - - DescribeTable("increasing the allowance should add the token to the spend limit", func(callType, callTypeForOtherToken CallType) { - is.setAllowanceForContract(callTypeForOtherToken, contractsData, owner.Priv, spender.Addr, prevAllowance) - - // Increase the allowance for target token - increaseAmount := big.NewInt(100) - - txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.IncreaseAllowanceMethod, spender.Addr, increaseAmount) - - approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, increaseArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.IncreaseAllowanceMethod) - is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, increaseAmount) - - // Check that the other token allowance is not affected - is.ExpectAllowanceForContract(callTypeForOtherToken, contractsData, owner.Addr, spender.Addr, prevAllowance) - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - }, - Entry(" - direct call", directCall, directCallToken2), - // NOTE: we are not passing the erc20 contract call here because the ERC20 contract - // only supports the actual token denomination and doesn't know of other allowances. - ) - - DescribeTable("decreasing the allowance should return an error", func(callType, callTypeForOtherToken CallType) { - is.setAllowanceForContract(callTypeForOtherToken, contractsData, owner.Priv, spender.Addr, prevAllowance) - - // Decrease the allowance for target token - decreaseAmount := big.NewInt(100) - - txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecreaseAllowanceMethod, spender.Addr, decreaseAmount) - - noAllowanceCheck := failCheck.WithErrContains(erc20.ErrNoAllowanceForToken, is.tokenDenom) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, decreaseArgs, noAllowanceCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - Expect(ethRes).To(BeNil(), "expected empty result") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, common.Big0) - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - // Check that the other token allowance is not affected - is.ExpectAllowanceForContract(callTypeForOtherToken, contractsData, owner.Addr, spender.Addr, prevAllowance) - }, - Entry(" - direct call", directCall, directCallToken2), - // NOTE: we are not passing the erc20 contract call here because the ERC20 contract - // only supports the actual token denomination and doesn't know of other allowances. - ) - }) - - When("an allowance exists for the same token", func() { - var approveAmount *big.Int - - BeforeEach(func() { - approveAmount = big.NewInt(200) - is.setAllowanceForContract(directCall, contractsData, owner.Priv, spender.Addr, approveAmount) - }) - - DescribeTable("increasing the allowance should increase the spend limit", func(callType CallType) { - increaseAmount := big.NewInt(100) - - txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.IncreaseAllowanceMethod, spender.Addr, increaseAmount) - - approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, increaseArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.IncreaseAllowanceMethod) - is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, new(big.Int).Add(approveAmount, increaseAmount)) - }, - Entry(" - direct call", directCall), - // NOTE: we are not passing the erc20 contract call here because the ERC20 contract - // only supports the actual token denomination and doesn't know of other allowances. - ) - - DescribeTable("decreasing the allowance should decrease the spend limit", func(callType CallType) { - decreaseAmount := big.NewInt(100) - - txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecreaseAllowanceMethod, spender.Addr, decreaseAmount) - - approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, decreaseArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - is.ExpectTrueToBeReturned(ethRes, erc20.DecreaseAllowanceMethod) - is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, new(big.Int).Sub(approveAmount, decreaseAmount)) - }, - Entry(" - direct call", directCall), - // NOTE: we are not passing the erc20 contract call here because the ERC20 contract - // only supports the actual token denomination and doesn't know of other allowances. - ) - - DescribeTable("increasing the allowance beyond the max uint256 value should return an error", func(callType CallType) { - increaseAmount := abi.MaxUint256 - - txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.IncreaseAllowanceMethod, spender.Addr, increaseAmount) - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, increaseArgs, execRevertedCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - Expect(ethRes).To(BeNil(), "expected empty result") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - }, - Entry(" - direct call", directCall), - // NOTE: we are not passing the erc20 contract call here because the ERC20 contract - // only supports the actual token denomination and doesn't know of other allowances. - ) - - DescribeTable("decreasing the allowance to zero should remove the token from the spend limit", func(callType CallType) { - txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecreaseAllowanceMethod, spender.Addr, approveAmount) - - approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, decreaseArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - is.ExpectTrueToBeReturned(ethRes, erc20.DecreaseAllowanceMethod) - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - // Check that only the spend limit in the network denomination remains - expAllowance := common.Big0 - is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, expAllowance) - }, - Entry(" - direct call", directCall), - // NOTE: we are not passing the erc20 contract call here because the ERC20 contract - // only supports the actual token denomination and doesn't know of other allowances. - ) - - DescribeTable("decreasing the allowance below zero should return an error", func(callType CallType) { - decreaseAmount := new(big.Int).Add(approveAmount, big.NewInt(100)) - - txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecreaseAllowanceMethod, spender.Addr, decreaseAmount) - belowZeroCheck := failCheck.WithErrContains(erc20.ErrDecreasedAllowanceBelowZero.Error()) - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, decreaseArgs, belowZeroCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - Expect(ethRes).To(BeNil(), "expected empty result") - - // commit changes to chain state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") - - // Check that the allowance was not changed - is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, approveAmount) - }, - Entry(" - direct call", directCall), - ) - }) - - When("an allowance exists for only the same token", func() { - // NOTE: we have to split between direct and contract calls here because the ERC20 contract - // handles the allowance differently by creating an approval between the contract and the spender, instead - // of the message sender and the spender, so we expect different allowances. - Context("in direct calls", func() { - var approveAmount *big.Int - - BeforeEach(func() { - approveAmount = big.NewInt(100) - - // NOTE: We set up the allowance here for the erc20 precompile and then also - // set up the allowance for the ERC20 contract, so that we can test both. - is.setAllowanceForContract(directCall, contractsData, owner.Priv, spender.Addr, approveAmount) - is.setAllowanceForContract(erc20Call, contractsData, owner.Priv, spender.Addr, approveAmount) - }) - - DescribeTable("increasing the allowance should increase the spend limit", func(callType CallType) { - increaseAmount := big.NewInt(100) - - txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.IncreaseAllowanceMethod, spender.Addr, increaseAmount) - approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, increaseArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit the changes to state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") - - is.ExpectTrueToBeReturned(ethRes, erc20.DecreaseAllowanceMethod) - is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, new(big.Int).Add(approveAmount, increaseAmount)) - }, - Entry(" - direct call", directCall), - Entry(" - through erc20 contract", erc20Call), - // NOTE: The ERC20 V5 contract does not contain these methods - // Entry(" - through erc20 v5 contract", erc20V5Call), - ) - - DescribeTable("decreasing the allowance should decrease the spend limit", func(callType CallType) { - decreaseAmount := big.NewInt(50) - - txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecreaseAllowanceMethod, spender.Addr, decreaseAmount) - approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, decreaseArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit the changes to state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") - - is.ExpectTrueToBeReturned(ethRes, erc20.DecreaseAllowanceMethod) - is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, new(big.Int).Sub(approveAmount, decreaseAmount)) - }, - Entry(" - direct call", directCall), - Entry(" - through erc20 contract", erc20Call), - // NOTE: The ERC20 V5 contract does not contain these methods - // Entry(" - through erc20 v5 contract", erc20V5Call), - ) - - DescribeTable("decreasing the allowance to zero should delete the allowance", func(callType CallType) { - txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecreaseAllowanceMethod, spender.Addr, approveAmount) - approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, decreaseArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit the changes to state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") - - is.ExpectTrueToBeReturned(ethRes, erc20.DecreaseAllowanceMethod) - is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, common.Big0) - }, - Entry(" - direct call", directCall), - Entry(" - through erc20 contract", erc20Call), - // NOTE: The ERC20 V5 contract does not contain these methods - // Entry(" - through erc20 v5 contract", erc20V5Call), - ) - - DescribeTable("decreasing the allowance below zero should return an error", func(callType CallType) { - decreaseAmount := big.NewInt(200) - - txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecreaseAllowanceMethod, spender.Addr, decreaseAmount) - - belowZeroCheck := failCheck.WithErrContains(erc20.ErrDecreasedAllowanceBelowZero.Error()) - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, decreaseArgs, belowZeroCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - Expect(ethRes).To(BeNil(), "expected empty result") - - // commit the changes to state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") - - // Check that the allowance was not changed - is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, approveAmount) - }, - Entry(" - direct call", directCall), - Entry(" - through erc20 contract", erc20Call), - // NOTE: The ERC20 V5 contract does not contain these methods - // Entry(" - through erc20 v5 contract", erc20V5Call), - ) - - DescribeTable("increasing the allowance beyond the max uint256 value should return an error", func(callType CallType) { - increaseAmount := abi.MaxUint256 - - txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.IncreaseAllowanceMethod, spender.Addr, increaseAmount) - _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, increaseArgs, execRevertedCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - Expect(ethRes).To(BeNil(), "expected empty result") - - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") - - // Check that the allowance was not changed - is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, approveAmount) - }, - Entry(" - direct call", directCall), - Entry(" - through erc20 contract", erc20Call), - // NOTE: The ERC20 V5 contract does not contain these methods - // Entry(" - through erc20 v5 contract", erc20V5Call), - ) - }) - - Context("in contract calls", func() { - var ( - approveAmount *big.Int - spender keyring.Key - ) - - BeforeEach(func() { - approveAmount = big.NewInt(100) - - spender = is.keyring.GetKey(1) - callerContractAddr := contractsData.GetContractData(contractCall).Address - erc20CallerContractAddr := contractsData.GetContractData(erc20CallerCall).Address - - // NOTE: Here we create an allowance between the contract and the spender for both contracts. - // This is different from the direct calls, where the allowance is created between the - // message sender and the spender. - txArgs, approveArgs := is.getTxAndCallArgs(contractCall, contractsData, erc20.ApproveMethod, spender.Addr, approveAmount) - approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - _, _, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, approveArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit the changes to state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") - - is.ExpectAllowanceForContract(contractCall, contractsData, callerContractAddr, spender.Addr, approveAmount) - - // Create the allowance for the ERC20 caller contract - txArgs, approveArgs = is.getTxAndCallArgs(erc20CallerCall, contractsData, erc20.ApproveMethod, spender.Addr, approveAmount) - _, _, err = is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, approveArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit the changes to state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") - - is.ExpectAllowanceForContract(erc20CallerCall, contractsData, erc20CallerContractAddr, spender.Addr, approveAmount) - }) - - DescribeTable("increasing the allowance should increase the spend limit", func(callType CallType) { //nolint:dupl - senderPriv := is.keyring.GetPrivKey(0) - ownerAddr := contractsData.GetContractData(callType).Address - increaseAmount := big.NewInt(100) - - txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.IncreaseAllowanceMethod, spender.Addr, increaseAmount) - approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - _, ethRes, err := is.factory.CallContractAndCheckLogs(senderPriv, txArgs, increaseArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit the changes to state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") - - is.ExpectTrueToBeReturned(ethRes, erc20.IncreaseAllowanceMethod) - is.ExpectAllowanceForContract(callType, contractsData, ownerAddr, spender.Addr, new(big.Int).Add(approveAmount, increaseAmount)) - }, - Entry(" - contract call", contractCall), - Entry(" - through erc20 caller contract", erc20CallerCall), - ) - - DescribeTable("increasing the allowance beyond the max uint256 value should return an error", func(callType CallType) { - senderPriv := is.keyring.GetPrivKey(0) - ownerAddr := contractsData.GetContractData(callType).Address - increaseAmount := abi.MaxUint256 - - txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.IncreaseAllowanceMethod, spender.Addr, increaseAmount) - _, ethRes, err := is.factory.CallContractAndCheckLogs(senderPriv, txArgs, increaseArgs, execRevertedCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - Expect(ethRes).To(BeNil(), "expected empty result") - - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") - - // Check that the allowance was not changed - is.ExpectAllowanceForContract(callType, contractsData, ownerAddr, spender.Addr, approveAmount) - }, - Entry(" - contract call", contractCall), - Entry(" - through erc20 caller contract", erc20CallerCall), - ) - - DescribeTable("decreasing the allowance should decrease the spend limit", func(callType CallType) { //nolint:dupl - senderPriv := is.keyring.GetPrivKey(0) - ownerAddr := contractsData.GetContractData(callType).Address - decreaseAmount := big.NewInt(50) - - txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecreaseAllowanceMethod, spender.Addr, decreaseAmount) - approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - _, ethRes, err := is.factory.CallContractAndCheckLogs(senderPriv, txArgs, decreaseArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit the changes to state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") - - is.ExpectTrueToBeReturned(ethRes, erc20.DecreaseAllowanceMethod) - is.ExpectAllowanceForContract(callType, contractsData, ownerAddr, spender.Addr, new(big.Int).Sub(approveAmount, decreaseAmount)) - }, - Entry(" - contract call", contractCall), - Entry(" - through erc20 caller contract", erc20CallerCall), - ) - - DescribeTable("decreasing the allowance to zero should delete the allowance", func(callType CallType) { - senderPriv := is.keyring.GetPrivKey(0) - ownerAddr := contractsData.GetContractData(callType).Address - - txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecreaseAllowanceMethod, spender.Addr, approveAmount) - approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) - _, ethRes, err := is.factory.CallContractAndCheckLogs(senderPriv, txArgs, decreaseArgs, approveCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - // commit the changes to state - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") - - is.ExpectTrueToBeReturned(ethRes, erc20.DecreaseAllowanceMethod) - is.ExpectAllowanceForContract(callType, contractsData, ownerAddr, spender.Addr, common.Big0) - }, - Entry(" - contract call", contractCall), - Entry(" - through erc20 caller contract", erc20CallerCall), - ) - - DescribeTable("decreasing the allowance below zero should return an error", func(callType CallType) { - senderPriv := is.keyring.GetPrivKey(0) - ownerAddr := contractsData.GetContractData(callType).Address - decreaseAmount := new(big.Int).Add(approveAmount, big.NewInt(100)) - - txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecreaseAllowanceMethod, spender.Addr, decreaseAmount) - _, ethRes, err := is.factory.CallContractAndCheckLogs(senderPriv, txArgs, decreaseArgs, execRevertedCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - Expect(ethRes).To(BeNil(), "expected empty result") - - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") - - // Check that the allowance was not changed - is.ExpectAllowanceForContract(callType, contractsData, ownerAddr, spender.Addr, approveAmount) - }, - Entry(" - contract call", contractCall), - Entry(" - through erc20 caller contract", erc20CallerCall), - ) - }) - }) - }) -}) - -var _ = Describe("ERC20 Extension migration Flows -", func() { - When("migrating an existing ERC20 token", func() { - var ( - contractData ContractsData - erc20MinterV5Contract evmtypes.CompiledContract - - tokenDenom = "xmpl" - tokenName = "Xmpl" - tokenSymbol = strings.ToUpper(tokenDenom) - - supply = sdk.NewInt64Coin(tokenDenom, 1000000000000000000) - ) - - BeforeEach(func() { - is.SetupTest() - - var err error - erc20MinterV5Contract, err = testdata.LoadERC20MinterV5Contract() - Expect(err).ToNot(HaveOccurred(), "failed to load ERC20 minter contract") - - contractOwner := is.keyring.GetKey(0) - - // Deploy an ERC20 contract - erc20Addr, err := is.factory.DeployContract( - contractOwner.Priv, - evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values - factory.ContractDeploymentData{ - Contract: erc20MinterV5Contract, - ConstructorArgs: []interface{}{ - tokenName, tokenSymbol, - }, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to deploy contract") - - // NOTE: We need to overwrite the information in the contractData here for this specific - // deployed contract. - contractData = ContractsData{ - ownerPriv: contractOwner.Priv, - contractData: map[CallType]ContractData{ - erc20V5Call: { - Address: erc20Addr, - ABI: erc20MinterV5Contract.ABI, - }, - }, - } - - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "failed to commit block") - - // Register the deployed erc20 contract as a token pair - _, err = integrationutils.RegisterERC20(is.factory, is.network, integrationutils.ERC20RegistrationData{ - Addresses: []string{erc20Addr.Hex()}, - ProposerPriv: contractOwner.Priv, - }) - Expect(err).ToNot(HaveOccurred(), "failed to register ERC20 token") - - err = is.network.NextBlock() - Expect(err).ToNot(HaveOccurred(), "failed to commit block") - - // Mint the supply of tokens - err = is.MintERC20(erc20V5Call, contractData, contractOwner.Addr, supply.Amount.BigInt()) - Expect(err).ToNot(HaveOccurred(), "failed to mint tokens") - - // Check that the supply was minted - is.ExpectBalancesForERC20(erc20V5Call, contractData, []ExpectedBalance{{ - address: contractOwner.AccAddr, - expCoins: sdk.Coins{supply}, - }}) - }) - - It("should migrate the full token balance to the bank module", func() { - // TODO: implement test on follow-up PR - Skip("will be addressed on follow-up PR") - - Expect(true).To(BeFalse(), "not implemented") - }) - }) - - When("migrating an extended ERC20 token (e.g. ERC20Votes)", func() { - It("should migrate the full token balance to the bank module", func() { - // TODO: make sure that extended tokens are compatible with the ERC20 extensions - Skip("not included in first tranche") - - Expect(true).To(BeFalse(), "not implemented") - }) - }) - - When("running the migration logic for a set of existing ERC20 tokens", func() { - BeforeEach(func() { - // TODO: Add some ERC20 tokens and then run migration logic - // TODO: check here that the balance cannot be queried from the bank keeper before migrating the token - }) - - It("should add and enable the corresponding erc20 precompiles", func() { - Skip("will be addressed in follow-up PR") - - Expect(true).To(BeFalse(), "not implemented") - }) - - It("should be possible to query the balances through the bank module", func() { - Skip("will be addressed in follow-up PR") - - Expect(true).To(BeFalse(), "not implemented") - }) - - It("should return all tokens when querying all balances for an account", func() { - Skip("will be addressed in follow-up PR") - - Expect(true).To(BeFalse(), "not implemented") - }) - }) - - When("registering a native IBC coin", func() { - BeforeEach(func() { - // TODO: Add some IBC coins, register the token pair and then run migration logic - }) - - It("should add the corresponding erc20 precompiles", func() { - Skip("will be addressed in follow-up PR") - - Expect(true).To(BeFalse(), "not implemented") - }) - - It("should be possible to query the balances using an EVM transaction", func() { - Skip("will be addressed in follow-up PR") - - Expect(true).To(BeFalse(), "not implemented") - }) - }) - - When("using Evmos (not wEvmos) in smart contracts", func() { - It("should be using straight Evmos for sending funds in smart contracts", func() { - Skip("will be addressed in follow-up PR") - - Expect(true).To(BeFalse(), "not implemented") - }) - }) -}) diff --git a/precompiles/gov/integration_test.go b/precompiles/gov/integration_test.go deleted file mode 100644 index 6a8071912..000000000 --- a/precompiles/gov/integration_test.go +++ /dev/null @@ -1,2068 +0,0 @@ -package gov_test - -import ( - "encoding/json" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/vm" - - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" - - cmn "github.com/cosmos/evm/precompiles/common" - "github.com/cosmos/evm/precompiles/gov" - "github.com/cosmos/evm/precompiles/testutil" - "github.com/cosmos/evm/precompiles/testutil/contracts" - commonfactory "github.com/cosmos/evm/testutil/integration/common/factory" - "github.com/cosmos/evm/testutil/integration/os/factory" - testutiltx "github.com/cosmos/evm/testutil/tx" - evmtypes "github.com/cosmos/evm/x/vm/types" - - "cosmossdk.io/math" - - "github.com/cosmos/cosmos-sdk/crypto/types" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/query" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" - "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" -) - -// General variables used for integration tests -var ( - // differentAddr is an address generated for testing purposes that e.g. raises the different origin error - differentAddr = testutiltx.GenerateAddress() - // defaultCallArgs are the default arguments for calling the smart contract - // - // NOTE: this has to be populated in a BeforeEach block because the contractAddr would otherwise be a nil address. - callArgs factory.CallArgs - // txArgs are the EVM transaction arguments to use in the transactions - txArgs evmtypes.EvmTxArgs - // defaultLogCheck instantiates a log check arguments struct with the precompile ABI events populated. - defaultLogCheck testutil.LogCheckArgs - // passCheck defines the arguments to check if the precompile returns no error - passCheck testutil.LogCheckArgs - // outOfGasCheck defines the arguments to check if the precompile returns out of gas error - outOfGasCheck testutil.LogCheckArgs - // govModuleAddr is the address of the gov module account - govModuleAddr sdk.AccAddress -) - -const ( - testSubmitProposalFromContract = "testSubmitProposalFromContract" -) - -func TestKeeperIntegrationTestSuite(t *testing.T) { - // Run Ginkgo integration tests - RegisterFailHandler(Fail) - RunSpecs(t, "Keeper Suite") -} - -var _ = Describe("Calling governance precompile from EOA", func() { - var ( - s *PrecompileTestSuite - proposerKey types.PrivKey - proposerAddr common.Address - proposerAccAddr sdk.AccAddress - ) - const ( - proposalID uint64 = 1 - option uint8 = 1 - metadata = "metadata" - ) - BeforeEach(func() { - s = new(PrecompileTestSuite) - s.SetupTest() - - // set the default call arguments - callArgs = factory.CallArgs{ - ContractABI: s.precompile.ABI, - } - defaultLogCheck = testutil.LogCheckArgs{ - ABIEvents: s.precompile.ABI.Events, - } - passCheck = defaultLogCheck.WithExpPass(true) - outOfGasCheck = defaultLogCheck.WithErrContains(vm.ErrOutOfGas.Error()) - - // reset tx args each test to avoid keeping custom - // values of previous tests (e.g. gasLimit) - precompileAddr := s.precompile.Address() - txArgs = evmtypes.EvmTxArgs{ - To: &precompileAddr, - } - txArgs.GasLimit = 200_000 - - proposerKey = s.keyring.GetPrivKey(0) - proposerAddr = s.keyring.GetAddr(0) - proposerAccAddr = sdk.AccAddress(proposerAddr.Bytes()) - govModuleAddr = authtypes.NewModuleAddress(govtypes.ModuleName) - }) - - // ===================================== - // TRANSACTIONS - // ===================================== - Describe("Execute SubmitProposal transaction", func() { - const method = gov.SubmitProposalMethod - - BeforeEach(func() { callArgs.MethodName = method }) - - It("fails with low gas", func() { - txArgs.GasLimit = 30_000 - jsonBlob := minimalBankSendProposalJSON(proposerAccAddr, s.network.GetBaseDenom(), "50") - callArgs.Args = []interface{}{proposerAddr, jsonBlob, minimalDeposit(s.network.GetBaseDenom(), big.NewInt(1))} - - _, _, err := s.factory.CallContractAndCheckLogs(proposerKey, txArgs, callArgs, outOfGasCheck) - Expect(err).To(BeNil()) - }) - - It("creates a proposal and emits event", func() { - jsonBlob := minimalBankSendProposalJSON(proposerAccAddr, s.network.GetBaseDenom(), "1") - callArgs.Args = []interface{}{proposerAddr, jsonBlob, minimalDeposit(s.network.GetBaseDenom(), big.NewInt(1))} - eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) - - _, ethRes, err := s.factory.CallContractAndCheckLogs(proposerKey, txArgs, callArgs, eventCheck) - Expect(err).To(BeNil()) - - // unpack return → proposalId - var out uint64 - err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) - Expect(err).To(BeNil()) - Expect(out).To(BeNumerically(">", 0)) - - // ensure proposal exists on-chain - prop, err := s.network.App.GovKeeper.Proposals.Get(s.network.GetContext(), out) - Expect(err).To(BeNil()) - Expect(prop.Proposer).To(Equal(sdk.AccAddress(proposerAddr.Bytes()).String())) - }) - - It("fails with invalid JSON", func() { - callArgs.Args = []interface{}{proposerAddr, []byte("{invalid}"), minimalDeposit(s.network.GetBaseDenom(), big.NewInt(1))} - errCheck := defaultLogCheck.WithErrContains("invalid proposal JSON") - _, _, err := s.factory.CallContractAndCheckLogs( - proposerKey, txArgs, callArgs, errCheck) - Expect(err).To(BeNil()) - }) - - It("fails with invalid deposit denom", func() { - jsonBlob := minimalBankSendProposalJSON(proposerAccAddr, s.network.GetBaseDenom(), "1") - invalidDep := []cmn.Coin{{Denom: "bad", Amount: big.NewInt(1)}} - callArgs.Args = []interface{}{proposerAddr, jsonBlob, invalidDep} - errCheck := defaultLogCheck.WithErrContains("invalid deposit denom") - _, _, err := s.factory.CallContractAndCheckLogs( - proposerKey, txArgs, callArgs, errCheck) - Expect(err).To(BeNil()) - }) - }) - - Describe("Execute Deposit transaction", func() { - const method = gov.DepositMethod - - BeforeEach(func() { callArgs.MethodName = method }) - - It("fails with wrong proposal id", func() { - callArgs.Args = []interface{}{proposerAddr, uint64(999), minimalDeposit(s.network.GetBaseDenom(), big.NewInt(1))} - errCheck := defaultLogCheck.WithErrContains("not found") - _, _, err := s.factory.CallContractAndCheckLogs(proposerKey, txArgs, callArgs, errCheck) - Expect(err).To(BeNil()) - }) - - It("deposits successfully and emits event", func() { - jsonBlob := minimalBankSendProposalJSON(proposerAccAddr, s.network.GetBaseDenom(), "1") - eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) - callArgs.MethodName = gov.SubmitProposalMethod - minDeposit := minimalDeposit(s.network.GetBaseDenom(), big.NewInt(1)) - callArgs.Args = []interface{}{proposerAddr, jsonBlob, minDeposit} - _, evmRes, err := s.factory.CallContractAndCheckLogs(proposerKey, txArgs, callArgs, eventCheck) - Expect(err).To(BeNil()) - var propID uint64 - err = s.precompile.UnpackIntoInterface(&propID, gov.SubmitProposalMethod, evmRes.Ret) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - // get proposal by propID - prop, err := s.network.App.GovKeeper.Proposals.Get(s.network.GetContext(), propID) - Expect(err).To(BeNil()) - Expect(prop.Status).To(Equal(govv1.StatusDepositPeriod)) - Expect(prop.Proposer).To(Equal(sdk.AccAddress(proposerAddr.Bytes()).String())) - minDepositCoins, err := cmn.NewSdkCoinsFromCoins(minDeposit) - Expect(err).To(BeNil()) - td := prop.GetTotalDeposit() - Expect(td).To(HaveLen(1)) - Expect(td[0].Denom).To(Equal(minDepositCoins[0].Denom)) - Expect(td[0].Amount.String()).To(Equal(minDepositCoins[0].Amount.String())) - - callArgs.MethodName = gov.DepositMethod - callArgs.Args = []interface{}{proposerAddr, propID, minimalDeposit(s.network.GetBaseDenom(), big.NewInt(1))} - eventCheck = passCheck.WithExpEvents(gov.EventTypeDeposit) - _, _, err = s.factory.CallContractAndCheckLogs(proposerKey, txArgs, callArgs, eventCheck) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - // Update expected total deposit - td[0].Amount = td[0].Amount.Add(minDepositCoins[0].Amount) - - // verify via query - callArgs.MethodName = gov.GetProposalMethod - callArgs.Args = []interface{}{propID} - _, ethRes, err := s.factory.CallContractAndCheckLogs(proposerKey, txArgs, callArgs, passCheck) - Expect(err).To(BeNil()) - - var out gov.ProposalOutput - err = s.precompile.UnpackIntoInterface(&out, gov.GetProposalMethod, ethRes.Ret) - Expect(err).To(BeNil()) - Expect(out.Proposal.Id).To(Equal(propID)) - Expect(out.Proposal.Status).To(Equal(uint32(govv1.StatusDepositPeriod))) - newTd := out.Proposal.TotalDeposit - Expect(newTd).To(HaveLen(1)) - Expect(newTd[0].Denom).To(Equal(minDepositCoins[0].Denom)) - Expect(newTd[0].Amount.String()).To(Equal(td[0].Amount.String())) - }) - }) - - Describe("Execute CancelProposal transaction", func() { - const method = gov.CancelProposalMethod - - BeforeEach(func() { - callArgs.MethodName = method - }) - - It("fails when called by a non-proposer", func() { - callArgs.Args = []interface{}{proposerAddr, proposalID} - notProposerKey := s.keyring.GetPrivKey(1) - notProposerAddr := s.keyring.GetAddr(1) - errCheck := defaultLogCheck.WithErrContains( - cmn.ErrRequesterIsNotMsgSender, - notProposerAddr.String(), - proposerAddr.String(), - ) - - _, _, err := s.factory.CallContractAndCheckLogs(notProposerKey, txArgs, callArgs, errCheck) - Expect(err).To(BeNil()) - }) - - It("cancels a live proposal and emits event", func() { - proposal, err := s.network.App.GovKeeper.Proposals.Get(s.network.GetContext(), proposalID) - Expect(err).To(BeNil()) - - // Cancel proposal - callArgs.Args = []interface{}{proposerAddr, proposal.Id} - eventCheck := passCheck.WithExpEvents(gov.EventTypeCancelProposal) - _, evmRes, err := s.factory.CallContractAndCheckLogs(proposerKey, txArgs, callArgs, eventCheck) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - var succeeded bool - err = s.precompile.UnpackIntoInterface(&succeeded, gov.CancelProposalMethod, evmRes.Ret) - Expect(err).To(BeNil()) - Expect(succeeded).To(BeTrue()) - - // 3. Check that the proposal is not found - _, err = s.network.App.GovKeeper.Proposals.Get(s.network.GetContext(), proposal.Id) - Expect(err.Error()).To(ContainSubstring("not found")) - }) - - It("cancels a proposal and see cancellation fee charged", func() { - // Fix the gas limit and gas price for predictable gas usage. - // This is for calculating expected cancellation fee. - baseFee := s.network.App.FeeMarketKeeper.GetBaseFee(s.network.GetContext()) - baseFeeInt := baseFee.TruncateInt64() - txArgs.GasPrice = new(big.Int).SetInt64(baseFeeInt) - txArgs.GasLimit = 500_000 - - // Get the prposal for cancellation - proposal, err := s.network.App.GovKeeper.Proposals.Get(s.network.GetContext(), 1) - Expect(err).To(BeNil()) - - // Calc cancellation fee - proposalDeposits, err := s.network.App.GovKeeper.GetDeposits(s.network.GetContext(), proposal.Id) - Expect(err).To(BeNil()) - proposalDepositAmt := proposalDeposits[0].Amount[0].Amount - params, err := s.network.App.GovKeeper.Params.Get(s.network.GetContext()) - Expect(err).To(BeNil()) - rate := math.LegacyMustNewDecFromStr(params.ProposalCancelRatio) - cancelFee := proposalDepositAmt.ToLegacyDec().Mul(rate).TruncateInt() - remaining := proposalDepositAmt.Sub(cancelFee) - - // Cancel it - callArgs.Args = []interface{}{proposerAddr, proposal.Id} - eventCheck := passCheck.WithExpEvents(gov.EventTypeCancelProposal) - // Balance of proposer - proposalBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), proposerAccAddr, s.network.GetBaseDenom()) - res, _, err := s.factory.CallContractAndCheckLogs(proposerKey, txArgs, callArgs, eventCheck) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - gasCost := math.NewInt(res.GasUsed).Mul(math.NewInt(txArgs.GasPrice.Int64())) - - // 6. Check that the cancellation fee is charged, diff should be less than the deposit amount - afterCancelBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), proposerAccAddr, s.network.GetBaseDenom()) - Expect(afterCancelBal.Amount).To(Equal( - proposalBal.Amount. - Sub(gasCost). - Add(remaining), - ), - "expected cancellation fee to be deducted from proposer balance") - - // 7. Check that the proposal is not found - _, err = s.network.App.GovKeeper.Proposals.Get(s.network.GetContext(), proposal.Id) - Expect(err.Error()).To(ContainSubstring("not found")) - }) - }) - - Describe("Execute Vote transaction", func() { - const method = gov.VoteMethod - - BeforeEach(func() { - // set the default call arguments - callArgs.MethodName = method - }) - - It("should return error if the provided gasLimit is too low", func() { - txArgs.GasLimit = 30000 - callArgs.Args = []interface{}{ - s.keyring.GetAddr(0), proposalID, option, metadata, - } - - _, _, err := s.factory.CallContractAndCheckLogs(s.keyring.GetPrivKey(0), txArgs, callArgs, outOfGasCheck) - Expect(err).To(BeNil()) - - // tally result yes count should remain unchanged - proposal, _ := s.network.App.GovKeeper.Proposals.Get(s.network.GetContext(), proposalID) - _, _, tallyResult, err := s.network.App.GovKeeper.Tally(s.network.GetContext(), proposal) - Expect(err).To(BeNil()) - Expect(tallyResult.YesCount).To(Equal("0"), "expected tally result yes count to remain unchanged") - }) - - It("should return error if the origin is different than the voter", func() { - callArgs.Args = []interface{}{ - differentAddr, proposalID, option, metadata, - } - - voterSetCheck := defaultLogCheck.WithErrContains(cmn.ErrRequesterIsNotMsgSender, s.keyring.GetAddr(0).String(), differentAddr.String()) - - _, _, err := s.factory.CallContractAndCheckLogs(s.keyring.GetPrivKey(0), txArgs, callArgs, voterSetCheck) - Expect(err).To(BeNil()) - }) - - It("should vote success", func() { - callArgs.Args = []interface{}{ - s.keyring.GetAddr(0), proposalID, option, metadata, - } - - voterSetCheck := passCheck.WithExpEvents(gov.EventTypeVote) - - _, _, err := s.factory.CallContractAndCheckLogs(s.keyring.GetPrivKey(0), txArgs, callArgs, voterSetCheck) - Expect(err).To(BeNil(), "error while calling the precompile") - - // tally result yes count should updated - proposal, _ := s.network.App.GovKeeper.Proposals.Get(s.network.GetContext(), proposalID) - _, _, tallyResult, err := s.network.App.GovKeeper.Tally(s.network.GetContext(), proposal) - Expect(err).To(BeNil()) - - Expect(tallyResult.YesCount).To(Equal(math.NewInt(3e18).String()), "expected tally result yes count updated") - }) - }) - - Describe("Execute VoteWeighted transaction", func() { - const method = gov.VoteWeightedMethod - - BeforeEach(func() { - callArgs.MethodName = method - }) - - It("should return error if the provided gasLimit is too low", func() { - txArgs.GasLimit = 30000 - callArgs.Args = []interface{}{ - s.keyring.GetAddr(0), - proposalID, - []gov.WeightedVoteOption{ - {Option: 1, Weight: "0.5"}, - {Option: 2, Weight: "0.5"}, - }, - metadata, - } - - _, _, err := s.factory.CallContractAndCheckLogs(s.keyring.GetPrivKey(0), txArgs, callArgs, outOfGasCheck) - Expect(err).To(BeNil()) - - // tally result should remain unchanged - proposal, _ := s.network.App.GovKeeper.Proposals.Get(s.network.GetContext(), proposalID) - _, _, tallyResult, err := s.network.App.GovKeeper.Tally(s.network.GetContext(), proposal) - Expect(err).To(BeNil()) - Expect(tallyResult.YesCount).To(Equal("0"), "expected tally result to remain unchanged") - }) - - It("should return error if the origin is different than the voter", func() { - callArgs.Args = []interface{}{ - differentAddr, - proposalID, - []gov.WeightedVoteOption{ - {Option: 1, Weight: "0.5"}, - {Option: 2, Weight: "0.5"}, - }, - metadata, - } - - voterSetCheck := defaultLogCheck.WithErrContains(cmn.ErrRequesterIsNotMsgSender, s.keyring.GetAddr(0).String(), differentAddr.String()) - - _, _, err := s.factory.CallContractAndCheckLogs(s.keyring.GetPrivKey(0), txArgs, callArgs, voterSetCheck) - Expect(err).To(BeNil()) - }) - - It("should vote weighted success", func() { - callArgs.Args = []interface{}{ - s.keyring.GetAddr(0), - proposalID, - []gov.WeightedVoteOption{ - {Option: 1, Weight: "0.7"}, - {Option: 2, Weight: "0.3"}, - }, - metadata, - } - - voterSetCheck := passCheck.WithExpEvents(gov.EventTypeVoteWeighted) - - _, _, err := s.factory.CallContractAndCheckLogs(s.keyring.GetPrivKey(0), txArgs, callArgs, voterSetCheck) - Expect(err).To(BeNil(), "error while calling the precompile") - - // tally result should be updated - proposal, _ := s.network.App.GovKeeper.Proposals.Get(s.network.GetContext(), proposalID) - _, _, tallyResult, err := s.network.App.GovKeeper.Tally(s.network.GetContext(), proposal) - Expect(err).To(BeNil()) - - expectedYesCount := math.NewInt(21e17) // 70% of 3e18 - Expect(tallyResult.YesCount).To(Equal(expectedYesCount.String()), "expected tally result yes count updated") - - expectedAbstainCount := math.NewInt(9e17) // 30% of 3e18 - Expect(tallyResult.AbstainCount).To(Equal(expectedAbstainCount.String()), "expected tally result no count updated") - }) - }) - - // ===================================== - // QUERIES - // ===================================== - Describe("Execute queries", func() { - Context("vote query", func() { - method := gov.GetVoteMethod - BeforeEach(func() { - // submit a vote - voteArgs := factory.CallArgs{ - ContractABI: s.precompile.ABI, - MethodName: gov.VoteMethod, - Args: []interface{}{ - s.keyring.GetAddr(0), proposalID, option, metadata, - }, - } - - voterSetCheck := passCheck.WithExpEvents(gov.EventTypeVote) - - _, _, err := s.factory.CallContractAndCheckLogs(s.keyring.GetPrivKey(0), txArgs, voteArgs, voterSetCheck) - Expect(err).To(BeNil(), "error while calling the precompile") - Expect(s.network.NextBlock()).To(BeNil()) - }) - It("should return a vote", func() { - callArgs.MethodName = method - callArgs.Args = []interface{}{proposalID, s.keyring.GetAddr(0)} - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var out gov.VoteOutput - err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) - Expect(err).To(BeNil()) - - Expect(out.Vote.Voter).To(Equal(s.keyring.GetAddr(0))) - Expect(out.Vote.ProposalId).To(Equal(proposalID)) - Expect(out.Vote.Metadata).To(Equal(metadata)) - Expect(out.Vote.Options).To(HaveLen(1)) - Expect(out.Vote.Options[0].Option).To(Equal(option)) - Expect(out.Vote.Options[0].Weight).To(Equal(math.LegacyOneDec().String())) - }) - }) - - Context("weighted vote query", func() { - method := gov.GetVoteMethod - BeforeEach(func() { - // submit a weighted vote - voteArgs := factory.CallArgs{ - ContractABI: s.precompile.ABI, - MethodName: gov.VoteWeightedMethod, - Args: []interface{}{ - s.keyring.GetAddr(0), - proposalID, - []gov.WeightedVoteOption{ - {Option: 1, Weight: "0.7"}, - {Option: 2, Weight: "0.3"}, - }, - metadata, - }, - } - - voterSetCheck := passCheck.WithExpEvents(gov.EventTypeVoteWeighted) - - _, _, err := s.factory.CallContractAndCheckLogs(s.keyring.GetPrivKey(0), txArgs, voteArgs, voterSetCheck) - Expect(err).To(BeNil(), "error while calling the precompile") - Expect(s.network.NextBlock()).To(BeNil()) - }) - - It("should return a weighted vote", func() { - callArgs.MethodName = method - callArgs.Args = []interface{}{proposalID, s.keyring.GetAddr(0)} - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var out gov.VoteOutput - err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) - Expect(err).To(BeNil()) - - Expect(out.Vote.Voter).To(Equal(s.keyring.GetAddr(0))) - Expect(out.Vote.ProposalId).To(Equal(proposalID)) - Expect(out.Vote.Metadata).To(Equal(metadata)) - Expect(out.Vote.Options).To(HaveLen(2)) - Expect(out.Vote.Options[0].Option).To(Equal(uint8(1))) - Expect(out.Vote.Options[0].Weight).To(Equal("0.7")) - Expect(out.Vote.Options[1].Option).To(Equal(uint8(2))) - Expect(out.Vote.Options[1].Weight).To(Equal("0.3")) - }) - }) - - Context("votes query", func() { - method := gov.GetVotesMethod - BeforeEach(func() { - // submit votes - for _, key := range s.keyring.GetKeys() { - voteArgs := factory.CallArgs{ - ContractABI: s.precompile.ABI, - MethodName: gov.VoteMethod, - Args: []interface{}{ - key.Addr, proposalID, option, metadata, - }, - } - - voterSetCheck := passCheck.WithExpEvents(gov.EventTypeVote) - - _, _, err := s.factory.CallContractAndCheckLogs(key.Priv, txArgs, voteArgs, voterSetCheck) - Expect(err).To(BeNil(), "error while calling the precompile") - Expect(s.network.NextBlock()).To(BeNil()) - } - }) - It("should return all votes", func() { - callArgs.MethodName = method - callArgs.Args = []interface{}{ - proposalID, - query.PageRequest{ - CountTotal: true, - }, - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var out gov.VotesOutput - err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) - Expect(err).To(BeNil()) - - votersCount := len(s.keyring.GetKeys()) - Expect(out.PageResponse.Total).To(Equal(uint64(votersCount))) - Expect(out.PageResponse.NextKey).To(Equal([]byte{})) - Expect(out.Votes).To(HaveLen(votersCount)) - for _, v := range out.Votes { - Expect(v.ProposalId).To(Equal(proposalID)) - Expect(v.Metadata).To(Equal(metadata)) - Expect(v.Options).To(HaveLen(1)) - Expect(v.Options[0].Option).To(Equal(option)) - Expect(v.Options[0].Weight).To(Equal(math.LegacyOneDec().String())) - } - }) - }) - - Context("deposit query", func() { - method := gov.GetDepositMethod - BeforeEach(func() { - callArgs.MethodName = method - }) - - It("should return a deposit", func() { - callArgs.Args = []interface{}{proposalID, s.keyring.GetAddr(0)} - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var out gov.DepositOutput - err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) - Expect(err).To(BeNil()) - - Expect(out.Deposit.ProposalId).To(Equal(proposalID)) - Expect(out.Deposit.Depositor).To(Equal(s.keyring.GetAddr(0))) - Expect(out.Deposit.Amount).To(HaveLen(1)) - Expect(out.Deposit.Amount[0].Denom).To(Equal(s.network.GetBaseDenom())) - Expect(out.Deposit.Amount[0].Amount.Cmp(big.NewInt(100))).To(Equal(0)) - }) - }) - - Context("deposits query", func() { - method := gov.GetDepositsMethod - BeforeEach(func() { - callArgs.MethodName = method - }) - - It("should return all deposits", func() { - callArgs.Args = []interface{}{ - proposalID, - query.PageRequest{ - CountTotal: true, - }, - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var out gov.DepositsOutput - err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) - Expect(err).To(BeNil()) - - Expect(out.PageResponse.Total).To(Equal(uint64(1))) - Expect(out.PageResponse.NextKey).To(Equal([]byte{})) - Expect(out.Deposits).To(HaveLen(1)) - for _, d := range out.Deposits { - Expect(d.ProposalId).To(Equal(proposalID)) - Expect(d.Amount).To(HaveLen(1)) - Expect(d.Amount[0].Denom).To(Equal(s.network.GetBaseDenom())) - Expect(d.Amount[0].Amount.Cmp(big.NewInt(100))).To(Equal(0)) - } - }) - }) - - Context("tally result query", func() { - method := gov.GetTallyResultMethod - BeforeEach(func() { - callArgs.MethodName = method - voteArgs := factory.CallArgs{ - ContractABI: s.precompile.ABI, - MethodName: gov.VoteMethod, - Args: []interface{}{ - s.keyring.GetAddr(0), proposalID, option, metadata, - }, - } - - voterSetCheck := passCheck.WithExpEvents(gov.EventTypeVote) - - _, _, err := s.factory.CallContractAndCheckLogs(s.keyring.GetPrivKey(0), txArgs, voteArgs, voterSetCheck) - Expect(err).To(BeNil(), "error while calling the precompile") - Expect(s.network.NextBlock()).To(BeNil()) - }) - - It("should return the tally result", func() { - callArgs.Args = []interface{}{proposalID} - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var out gov.TallyResultOutput - err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) - Expect(err).To(BeNil()) - - Expect(out.TallyResult.Yes).To(Equal("3000000000000000000")) - Expect(out.TallyResult.Abstain).To(Equal("0")) - Expect(out.TallyResult.No).To(Equal("0")) - Expect(out.TallyResult.NoWithVeto).To(Equal("0")) - }) - }) - - Context("proposal query", func() { - method := gov.GetProposalMethod - BeforeEach(func() { - callArgs.MethodName = method - }) - - It("should return a proposal", func() { - callArgs.Args = []interface{}{uint64(1)} - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var out gov.ProposalOutput - err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) - Expect(err).To(BeNil()) - - // Check proposal details - Expect(out.Proposal.Id).To(Equal(uint64(1))) - Expect(out.Proposal.Status).To(Equal(uint32(govv1.StatusVotingPeriod))) - Expect(out.Proposal.Proposer).To(Equal(s.keyring.GetAddr(0))) - Expect(out.Proposal.Metadata).To(Equal("ipfs://CID")) - Expect(out.Proposal.Title).To(Equal("test prop")) - Expect(out.Proposal.Summary).To(Equal("test prop")) - Expect(out.Proposal.Messages).To(HaveLen(1)) - Expect(out.Proposal.Messages[0]).To(Equal("/cosmos.bank.v1beta1.MsgSend")) - - // Check tally result - Expect(out.Proposal.FinalTallyResult.Yes).To(Equal("0")) - Expect(out.Proposal.FinalTallyResult.Abstain).To(Equal("0")) - Expect(out.Proposal.FinalTallyResult.No).To(Equal("0")) - Expect(out.Proposal.FinalTallyResult.NoWithVeto).To(Equal("0")) - }) - - It("should fail when proposal doesn't exist", func() { - callArgs.Args = []interface{}{uint64(999)} - - _, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - defaultLogCheck.WithErrContains("proposal 999 doesn't exist"), - ) - Expect(err).To(BeNil()) - }) - }) - - Context("proposals query", func() { - method := gov.GetProposalsMethod - BeforeEach(func() { - callArgs.MethodName = method - }) - - It("should return all proposals", func() { - callArgs.Args = []interface{}{ - uint32(0), // StatusNil to get all proposals - common.Address{}, - common.Address{}, - query.PageRequest{ - CountTotal: true, - }, - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var out gov.ProposalsOutput - err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) - Expect(err).To(BeNil()) - - Expect(out.Proposals).To(HaveLen(2)) - Expect(out.PageResponse.Total).To(Equal(uint64(2))) - - proposal := out.Proposals[0] - Expect(proposal.Id).To(Equal(uint64(1))) - Expect(proposal.Status).To(Equal(uint32(govv1.StatusVotingPeriod))) - Expect(proposal.Proposer).To(Equal(s.keyring.GetAddr(0))) - Expect(proposal.Messages).To(HaveLen(1)) - Expect(proposal.Messages[0]).To(Equal("/cosmos.bank.v1beta1.MsgSend")) - }) - - It("should filter proposals by status", func() { - callArgs.Args = []interface{}{ - uint32(govv1.StatusVotingPeriod), - common.Address{}, - common.Address{}, - query.PageRequest{ - CountTotal: true, - }, - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil()) - - var out gov.ProposalsOutput - err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) - Expect(err).To(BeNil()) - - Expect(out.Proposals).To(HaveLen(2)) - Expect(out.Proposals[0].Status).To(Equal(uint32(govv1.StatusVotingPeriod))) - Expect(out.Proposals[1].Status).To(Equal(uint32(govv1.StatusVotingPeriod))) - }) - - It("should filter proposals by voter", func() { - // First add a vote - voteArgs := factory.CallArgs{ - ContractABI: s.precompile.ABI, - MethodName: gov.VoteMethod, - Args: []interface{}{ - s.keyring.GetAddr(0), uint64(1), uint8(govv1.OptionYes), "", - }, - } - _, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - voteArgs, - passCheck.WithExpEvents(gov.EventTypeVote), - ) - Expect(err).To(BeNil()) - - // Wait for the vote to be included in the block - Expect(s.network.NextBlock()).To(BeNil()) - - // Query proposals filtered by voter - callArgs.Args = []interface{}{ - uint32(0), // StatusNil - s.keyring.GetAddr(0), - common.Address{}, - query.PageRequest{ - CountTotal: true, - }, - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil()) - - var out gov.ProposalsOutput - err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) - Expect(err).To(BeNil()) - - Expect(out.Proposals).To(HaveLen(1)) - }) - - It("should filter proposals by depositor", func() { - callArgs.Args = []interface{}{ - uint32(0), // StatusNil - common.Address{}, - s.keyring.GetAddr(0), - query.PageRequest{ - CountTotal: true, - }, - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil()) - - var out gov.ProposalsOutput - err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) - Expect(err).To(BeNil()) - - Expect(out.Proposals).To(HaveLen(1)) - }) - }) - - Context("params query", func() { - var ( - err error - callsData CallsData - govCallerContractAddr common.Address - govCallerContract evmtypes.CompiledContract - ) - - BeforeEach(func() { - // Setting gas tip cap to zero to have zero gas price. - txArgs.GasTipCap = new(big.Int).SetInt64(0) - - govCallerContract, err = contracts.LoadGovCallerContract() - Expect(err).ToNot(HaveOccurred(), "failed to load GovCaller contract") - - govCallerContractAddr, err = s.factory.DeployContract( - s.keyring.GetPrivKey(0), - evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values - factory.ContractDeploymentData{ - Contract: govCallerContract, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to deploy gov caller contract") - Expect(s.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - callsData = CallsData{ - precompileAddr: s.precompile.Address(), - precompileABI: s.precompile.ABI, - - precompileCallerAddr: govCallerContractAddr, - precompileCallerABI: govCallerContract.ABI, - } - }) - - DescribeTable("should return all params", func(callType callType) { - txArgs, callArgs = callsData.getTxAndCallArgs(callArgs, txArgs, callType) - - switch callType { - case directCall: - callArgs.MethodName = gov.GetParamsMethod - case contractCall: - callArgs.MethodName = "getParams" - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil()) - - var output struct { - Params gov.ParamsOutput `json:"params"` - } - err = s.precompile.UnpackIntoInterface(&output, gov.GetParamsMethod, ethRes.Ret) - Expect(err).To(BeNil()) - - params, err := s.network.GetGovClient().Params(s.network.GetContext(), &govv1.QueryParamsRequest{}) - Expect(err).To(BeNil()) - - Expect(output.Params.MinDeposit).To(HaveLen(len(params.Params.MinDeposit)), "expected min deposit to have same amount of token") - Expect(output.Params.MinDeposit[0].Denom).To(Equal(params.Params.MinDeposit[0].Denom), "expected min deposit to have same denom") - Expect(output.Params.MinDeposit[0].Amount.String()).To(Equal(params.Params.MinDeposit[0].Amount.String()), "expected min deposit to have same amount") - Expect(output.Params.MaxDepositPeriod).To(Equal(int64(*params.Params.MaxDepositPeriod)), "expected max deposit period to be equal") - Expect(output.Params.VotingPeriod).To(Equal(int64(*params.Params.VotingPeriod)), "expected voting period to be equal") - Expect(output.Params.Quorum).To(Equal(params.Params.Quorum), "expected quorum to be equal") - Expect(output.Params.Threshold).To(Equal(params.Params.Threshold), "expected threshold to be equal") - Expect(output.Params.VetoThreshold).To(Equal(params.Params.VetoThreshold), "expected veto threshold to be equal") - Expect(output.Params.MinDepositRatio).To(Equal(params.Params.MinDepositRatio), "expected min deposit ratio to be equal") - Expect(output.Params.ProposalCancelRatio).To(Equal(params.Params.ProposalCancelRatio), "expected proposal cancel ratio to be equal") - Expect(output.Params.ProposalCancelDest).To(Equal(params.Params.ProposalCancelDest), "expected proposal cancel dest to be equal") - Expect(output.Params.ExpeditedVotingPeriod).To(Equal(int64(*params.Params.ExpeditedVotingPeriod)), "expected expedited voting period to be equal") - Expect(output.Params.ExpeditedThreshold).To(Equal(params.Params.ExpeditedThreshold), "expected expedited threshold to be equal") - Expect(output.Params.ExpeditedMinDeposit).To(HaveLen(len(params.Params.ExpeditedMinDeposit)), "expected expedited min deposit to have same amount of token") - Expect(output.Params.ExpeditedMinDeposit[0].Denom).To(Equal(params.Params.ExpeditedMinDeposit[0].Denom), "expected expedited min deposit to have same denom") - Expect(output.Params.ExpeditedMinDeposit[0].Amount.String()).To(Equal(params.Params.ExpeditedMinDeposit[0].Amount.String()), "expected expedited min deposit to have same amount") - Expect(output.Params.BurnVoteQuorum).To(Equal(params.Params.BurnVoteQuorum), "expected burn vote quorum to be equal") - Expect(output.Params.BurnProposalDepositPrevote).To(Equal(params.Params.BurnProposalDepositPrevote), "expected burn proposal deposit prevote to be equal") - Expect(output.Params.BurnVoteVeto).To(Equal(params.Params.BurnVoteVeto), "expected burn vote veto to be equal") - Expect(output.Params.MinDepositRatio).To(Equal(params.Params.MinDepositRatio), "expected min deposit ratio to be equal") - }, - Entry("directly calling the precompile", directCall), - Entry("through a caller contract", contractCall), - ) - }) - - Context("constitution query", func() { - method := gov.GetConstitutionMethod - BeforeEach(func() { - callArgs.MethodName = method - }) - - It("should return a constitution", func() { - callArgs.Args = []interface{}{} - - _, ethRes, err := s.factory.CallContractAndCheckLogs(proposerKey, txArgs, callArgs, passCheck) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var out string - err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) - Expect(err).To(BeNil()) - }) - }) - }) -}) - -var _ = Describe("Calling governance precompile from contract", Ordered, func() { - s := new(PrecompileTestSuite) - // testCase is a struct used for cases of contracts calls that have some operation - // performed before and/or after the precompile call - type testCase struct { - before bool - after bool - } - - var ( - govCallerContract evmtypes.CompiledContract - contractAddr common.Address - contractAccAddr sdk.AccAddress - txSenderKey types.PrivKey - txSenderAddr common.Address - err error - - proposalID uint64 // proposal id submitted by eoa - contractProposalID uint64 // proposal id submitted by contract account - - cancelFee math.Int - remaining math.Int - - depositor1 sdk.AccAddress - depositorKey1 types.PrivKey - - // The following variables are used to check the cancellation fees and - // remaining fess for multiple deposits case - // key: acc address - // value: fee amount - cancelFees map[string]math.Int - remainingFees map[string]math.Int - ) - - BeforeAll(func() { - govCallerContract, err = contracts.LoadGovCallerContract() - Expect(err).ToNot(HaveOccurred(), "failed to load GovCaller contract") - }) - - BeforeEach(func() { - s.SetupTest() - - txSenderKey = s.keyring.GetPrivKey(0) - txSenderAddr = s.keyring.GetAddr(0) - contractAddr, err = s.factory.DeployContract( - txSenderKey, - evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values - factory.ContractDeploymentData{ - Contract: govCallerContract, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to deploy gov caller contract") - Expect(s.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - contractAccAddr = sdk.AccAddress(contractAddr.Bytes()) - - cAcc := s.network.App.EVMKeeper.GetAccount(s.network.GetContext(), contractAddr) - Expect(cAcc).ToNot(BeNil(), "failed to get contract account") - Expect(cAcc.IsContract()).To(BeTrue(), "expected contract account") - - callArgs = factory.CallArgs{ - ContractABI: govCallerContract.ABI, - } - - txArgs = evmtypes.EvmTxArgs{ - To: &contractAddr, - GasLimit: 200_000, - } - govModuleAddr = authtypes.NewModuleAddress(govtypes.ModuleName) - - defaultLogCheck = testutil.LogCheckArgs{ABIEvents: s.precompile.Events} - passCheck = defaultLogCheck.WithExpPass(true) - }) - - // ===================================== - // TRANSACTIONS - // ===================================== - Context("submitProposal as a contract proposer", func() { - BeforeEach(func() { callArgs.MethodName = testSubmitProposalFromContract }) - It("should submit proposal successfully", func() { - // Prepare the proposal - toAddr := s.keyring.GetAccAddr(1) - denom := s.network.GetBaseDenom() - amount := "100" - jsonBlob := minimalBankSendProposalJSON(toAddr, denom, amount) - callArgs.Args = []interface{}{ - jsonBlob, - minimalDeposit(s.network.GetBaseDenom(), big.NewInt(100)), - } - - eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) - - txArgs := evmtypes.EvmTxArgs{ - To: &contractAddr, - GasLimit: 500_000, - Amount: big.NewInt(1000), - } - _, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - var proposalID uint64 - err = s.precompile.UnpackIntoInterface(&proposalID, gov.SubmitProposalMethod, evmRes.Ret) - Expect(err).To(BeNil()) - // Expect ProposalID greater than 0 - Expect(proposalID).To(BeNumerically(">", 0)) - - contractProposer := sdk.AccAddress(contractAddr.Bytes()).String() - // ensure proposal exists on-chain - prop, err := s.network.App.GovKeeper.Proposals.Get(s.network.GetContext(), proposalID) - Expect(err).To(BeNil()) - Expect(prop.Id).To(Equal(proposalID)) - Expect(prop.Proposer).To(Equal(contractProposer), "expected contract proposer to be equal") - }) - }) - - Context("cancelProposal as contract proposer", func() { - BeforeEach(func() { callArgs.MethodName = "testCancelProposalFromContract" }) - It("should cancel proposal successfully", func() { - // submit a proposal - toAddr := s.keyring.GetAccAddr(1) - denom := s.network.GetBaseDenom() - jsonBlob := minimalBankSendProposalJSON(toAddr, denom, "100") - callArgs.MethodName = testSubmitProposalFromContract - minDepositAmt := math.NewInt(100) - callArgs.Args = []interface{}{ - jsonBlob, - minimalDeposit(s.network.GetBaseDenom(), minDepositAmt.BigInt()), - } - - eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) - - txArgs := evmtypes.EvmTxArgs{ - To: &contractAddr, - GasLimit: 500_000, - Amount: minDepositAmt.BigInt(), - } - _, evmRes, _ := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) - Expect(s.network.NextBlock()).To(BeNil()) - - var proposalID uint64 - Expect(s.precompile.UnpackIntoInterface(&proposalID, gov.SubmitProposalMethod, evmRes.Ret)).To(BeNil()) - - // Get the proposal for cancellation - proposal, err := s.network.App.GovKeeper.Proposals.Get(s.network.GetContext(), proposalID) - Expect(err).To(BeNil()) - - // Calc cancellation fee - proposalDeposits, err := s.network.App.GovKeeper.GetDeposits(s.network.GetContext(), proposal.Id) - Expect(err).To(BeNil()) - proposalDepositAmt := proposalDeposits[0].Amount[0].Amount - params, err := s.network.App.GovKeeper.Params.Get(s.network.GetContext()) - Expect(err).To(BeNil()) - rate := math.LegacyMustNewDecFromStr(params.ProposalCancelRatio) - cancelFee := proposalDepositAmt.ToLegacyDec().Mul(rate).TruncateInt() - - // Cancel it - callArgs.MethodName = "testCancelProposalFromContract" - callArgs.Args = []interface{}{proposal.Id} - eventCheck = passCheck.WithExpEvents(gov.EventTypeCancelProposal) - // Balance of contract proposer - proposerBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), contractAccAddr, s.network.GetBaseDenom()) - txArgs.Amount = common.Big0 - _, _, err = s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - // 6. Check that the cancellation fee is charged, diff should be less than the deposit amount - afterCancelBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), contractAccAddr, s.network.GetBaseDenom()) - Expect(afterCancelBal.Amount).To(Equal( - proposerBal.Amount. - Sub(cancelFee). - Add(proposalDepositAmt)), - "expected cancellation fee to be deducted from proposer balance") - - // 7. Check that the proposal is not found - _, err = s.network.App.GovKeeper.Proposals.Get(s.network.GetContext(), proposal.Id) - Expect(err.Error()).To(ContainSubstring("not found")) - }) - }) - - Context("deposit as contract proposer", func() { - BeforeEach(func() { callArgs.MethodName = "testDepositFromContract" }) - It("should deposit successfully", func() { - // submit a proposal - toAddr := s.keyring.GetAccAddr(1) - denom := s.network.GetBaseDenom() - jsonBlob := minimalBankSendProposalJSON(toAddr, denom, "100") - callArgs.MethodName = testSubmitProposalFromContract - minDepositAmt := math.NewInt(100) - callArgs.Args = []interface{}{ - jsonBlob, - minimalDeposit(s.network.GetBaseDenom(), minDepositAmt.BigInt()), - } - - eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) - txArgs := evmtypes.EvmTxArgs{ - To: &contractAddr, - GasLimit: 500_000, - Amount: minDepositAmt.BigInt(), - } - _, evmRes, _ := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) - Expect(s.network.NextBlock()).To(BeNil()) - - var proposalID uint64 - Expect(s.precompile.UnpackIntoInterface(&proposalID, gov.SubmitProposalMethod, evmRes.Ret)).To(BeNil()) - - // Get the proposal for deposit - proposal, err := s.network.App.GovKeeper.Proposals.Get(s.network.GetContext(), proposalID) - Expect(err).To(BeNil()) - - // Deposit it - callArgs.MethodName = "testDepositFromContract" - callArgs.Args = []interface{}{ - proposal.Id, - minimalDeposit(s.network.GetBaseDenom(), big.NewInt(100)), - } - eventCheck = passCheck.WithExpEvents(gov.EventTypeDeposit) - _, _, err = s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - // Check that the deposit is found - deposits, err := s.network.App.GovKeeper.GetDeposits(s.network.GetContext(), proposal.Id) - Expect(err).To(BeNil()) - Expect(deposits).To(HaveLen(1)) - Expect(deposits[0].Amount[0].Amount).To(Equal(math.NewInt(200))) - }) - }) - - Context("testSubmitProposal with transfer", func() { - BeforeEach(func() { callArgs.MethodName = "testSubmitProposalWithTransfer" }) - - DescribeTable("contract proposer should submit proposal with transfer", - func(tc testCase) { - // Fix the gas limit and gas price for predictable gas usage. - // This is for calculating expected cancellation fee. - baseFee := s.network.App.FeeMarketKeeper.GetBaseFee(s.network.GetContext()) - baseFeeInt := baseFee.TruncateInt64() - txArgs.GasPrice = new(big.Int).SetInt64(baseFeeInt) - txArgs.GasLimit = 500_000 - - // Prepare the proposal - toAddr := s.keyring.GetAccAddr(1) - denom := s.network.GetBaseDenom() - amount := "100" - jsonBlob := minimalBankSendProposalJSON(toAddr, denom, amount) - minDepositAmt := math.NewInt(100) - callArgs.Args = []interface{}{ - jsonBlob, minimalDeposit(s.network.GetBaseDenom(), minDepositAmt.BigInt()), - tc.before, tc.after, - } - txArgs.Amount = minDepositAmt.Mul(math.NewInt(2)).BigInt() - eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) - txArgs.To = &contractAddr - baseDenom := s.network.GetBaseDenom() - txSender := s.keyring.GetAccAddr(0) - txSenderKey := s.keyring.GetPrivKey(0) - txSenderBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), txSender, baseDenom) - contractBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) - res, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - fees := math.NewInt(res.GasUsed).Mul(math.NewInt(txArgs.GasPrice.Int64())) - - // check submitted proposal - var proposalID uint64 - err = s.precompile.UnpackIntoInterface(&proposalID, gov.SubmitProposalMethod, evmRes.Ret) - Expect(err).To(BeNil()) - Expect(proposalID).To(BeNumerically(">", 0)) - - afterSubmitTxSenderBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), txSender, baseDenom) - afterSubmitContractBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) - - amtFromContract := math.ZeroInt() - for _, transferred := range []bool{tc.before, tc.after} { - if transferred { - amtFromContract = amtFromContract.AddRaw(15) - } - } - Expect(afterSubmitTxSenderBal.Amount).To(Equal( - txSenderBal.Amount.Sub(math.NewIntFromBigInt(txArgs.Amount)). - Sub(fees).Add(amtFromContract))) - Expect(afterSubmitContractBal.Amount).To(Equal( - contractBal.Amount. - Add(math.NewIntFromBigInt(txArgs.Amount). - Sub(amtFromContract)).Sub(minDepositAmt), - )) - }, - Entry("with internal transfers before and after precompile call", testCase{ - before: true, - after: true, - }), - Entry("with internal transfers before precompile call", testCase{ - before: true, - after: false, - }), - Entry("with internal transfers after precompile call", testCase{ - before: false, - after: true, - }), - ) - }) - - Context("testSubmitProposalFromContract with transfer", func() { - BeforeEach(func() { callArgs.MethodName = "testSubmitProposalFromContractWithTransfer" }) - - DescribeTable("contract proposer should submit proposal with transfer", - func(tc testCase) { - // Fix the gas limit and gas price for predictable gas usage. - // This is for calculating expected cancellation fee. - baseFee := s.network.App.FeeMarketKeeper.GetBaseFee(s.network.GetContext()) - baseFeeInt := baseFee.TruncateInt64() - txArgs.GasPrice = new(big.Int).SetInt64(baseFeeInt) - txArgs.GasLimit = 500_000 - - // Prepare the proposal - toAddr := s.keyring.GetAccAddr(1) - denom := s.network.GetBaseDenom() - amount := "100" - jsonBlob := minimalBankSendProposalJSON(toAddr, denom, amount) - minDepositAmt := math.NewInt(100) - randomAddr := testutiltx.GenerateAddress() - callArgs.Args = []interface{}{ - randomAddr, jsonBlob, - minimalDeposit(s.network.GetBaseDenom(), minDepositAmt.BigInt()), - tc.before, tc.after, - } - extraContractFundinAmt := math.NewInt(100) - txArgs.Amount = minDepositAmt.Add(extraContractFundinAmt).BigInt() - eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) - txArgs.To = &contractAddr - baseDenom := s.network.GetBaseDenom() - contractBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) - randomAddrBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), randomAddr.Bytes(), baseDenom) - _, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - // check submitted proposal - var proposalID uint64 - err = s.precompile.UnpackIntoInterface(&proposalID, gov.SubmitProposalMethod, evmRes.Ret) - Expect(err).To(BeNil()) - Expect(proposalID).To(BeNumerically(">", 0)) - - afterSubmitRandomAddrBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), randomAddr.Bytes(), baseDenom) - afterSubmitContractBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) - - amtFromContract := math.ZeroInt() - for _, transferred := range []bool{tc.before, tc.after} { - if transferred { - amtFromContract = amtFromContract.AddRaw(15) - } - } - Expect(afterSubmitRandomAddrBal.Amount).To(Equal( - randomAddrBal.Amount. - Add(amtFromContract), - )) - - Expect(afterSubmitContractBal.Amount).To(Equal( - contractBal.Amount.Add(math.NewIntFromBigInt(txArgs.Amount).Sub(minDepositAmt).Sub(amtFromContract)), - )) - }, - Entry("with internal transfers before and after precompile call", testCase{ - before: true, - after: true, - }), - Entry("with internal transfers before precompile call", testCase{ - before: true, - after: false, - }), - Entry("with internal transfers after precompile call", testCase{ - before: false, - after: true, - }), - ) - }) - - Context("testDeposit with transfer", func() { - BeforeEach(func() { - toAddr := s.keyring.GetAccAddr(1) - denom := s.network.GetBaseDenom() - amount := "100" - jsonBlob := minimalBankSendProposalJSON(toAddr, denom, amount) - minDepositAmt := math.NewInt(100) - callArgs.MethodName = testSubmitProposalFromContract - callArgs.Args = []interface{}{ - jsonBlob, - minimalDeposit(s.network.GetBaseDenom(), minDepositAmt.BigInt()), - } - txArgs.Amount = minDepositAmt.BigInt() - eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) - txArgs.To = &contractAddr - _, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - err = s.precompile.UnpackIntoInterface(&contractProposalID, gov.SubmitProposalMethod, evmRes.Ret) - Expect(err).To(BeNil()) - - callArgs.MethodName = "testDepositWithTransfer" - }) - - DescribeTable("all balance changes should be correct", - func(tc testCase) { - // Fix the gas limit and gas price for predictable gas usage. - // This is for calculating expected cancellation fee. - baseFee := s.network.App.FeeMarketKeeper.GetBaseFee(s.network.GetContext()) - baseFeeInt := baseFee.TruncateInt64() - txArgs.GasPrice = new(big.Int).SetInt64(baseFeeInt) - txArgs.GasLimit = 500_000 - txArgs.Amount = big.NewInt(300) - - minDepositAmt := math.NewInt(100) - callArgs.Args = []interface{}{ - contractProposalID, - minimalDeposit(s.network.GetBaseDenom(), minDepositAmt.BigInt()), - tc.before, tc.after, - } - eventCheck := passCheck.WithExpEvents(gov.EventTypeDeposit) - - baseDenom := s.network.GetBaseDenom() - contractBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) - txSenderBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), txSenderAddr.Bytes(), baseDenom) - res, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - gasCost := math.NewInt(res.GasUsed).Mul(math.NewInt(txArgs.GasPrice.Int64())) - - var success bool - err = s.precompile.UnpackIntoInterface(&success, gov.DepositMethod, evmRes.Ret) - Expect(err).To(BeNil()) - Expect(success).To(BeTrue()) - - afterTxSenderBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), txSenderAddr.Bytes(), baseDenom) - afterContractBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) - - amtFromContract := math.ZeroInt() - for _, transferred := range []bool{tc.before, tc.after} { - if transferred { - amtFromContract = amtFromContract.AddRaw(15) - } - } - Expect(afterTxSenderBal.Amount).To(Equal( - txSenderBal.Amount. - Sub(gasCost). - Sub(math.NewIntFromBigInt(txArgs.Amount)). - Add(amtFromContract), - )) - - Expect(afterContractBal.Amount).To(Equal( - contractBal.Amount. - Add(math.NewIntFromBigInt(txArgs.Amount). - Sub(amtFromContract). - Sub(minDepositAmt)), - )) - }, - Entry("with internal transfers before and after precompile call", testCase{ - before: true, - after: true, - }), - Entry("with internal transfers before precompile call", testCase{ - before: true, - after: false, - }), - Entry("with internal transfers after precompile call", testCase{ - before: false, - after: true, - }), - ) - }) - - Context("testDepositFromContract with transfer", func() { - BeforeEach(func() { - toAddr := s.keyring.GetAccAddr(1) - denom := s.network.GetBaseDenom() - amount := "100" - jsonBlob := minimalBankSendProposalJSON(toAddr, denom, amount) - minDepositAmt := math.NewInt(100) - callArgs.MethodName = testSubmitProposalFromContract - callArgs.Args = []interface{}{ - jsonBlob, - minimalDeposit(s.network.GetBaseDenom(), minDepositAmt.BigInt()), - } - txArgs.Amount = minDepositAmt.BigInt() - eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) - txArgs.To = &contractAddr - _, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - err = s.precompile.UnpackIntoInterface(&contractProposalID, gov.SubmitProposalMethod, evmRes.Ret) - Expect(err).To(BeNil()) - - callArgs.MethodName = "testDepositFromContractWithTransfer" - }) - - DescribeTable("all balance changes should be correct", - func(tc testCase) { - minDepositAmt := math.NewInt(100) - randomAddr := testutiltx.GenerateAddress() - callArgs.Args = []interface{}{ - randomAddr, contractProposalID, - minimalDeposit(s.network.GetBaseDenom(), minDepositAmt.BigInt()), - tc.before, tc.after, - } - extraContractFundinAmt := math.NewInt(100) - txArgs.Amount = minDepositAmt.Add(extraContractFundinAmt).BigInt() - eventCheck := passCheck.WithExpEvents(gov.EventTypeDeposit) - - baseDenom := s.network.GetBaseDenom() - randomAddrBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), randomAddr.Bytes(), baseDenom) - contractBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) - - _, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - var success bool - err = s.precompile.UnpackIntoInterface(&success, gov.DepositMethod, evmRes.Ret) - Expect(err).To(BeNil()) - Expect(success).To(BeTrue()) - - afterRandomAddrBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), randomAddr.Bytes(), baseDenom) - afterContractBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) - - amtFromContract := math.ZeroInt() - for _, transferred := range []bool{tc.before, tc.after} { - if transferred { - amtFromContract = amtFromContract.AddRaw(15) - } - } - - Expect(afterRandomAddrBal.Amount).To(Equal( - randomAddrBal.Amount. - Add(amtFromContract), - )) - Expect(afterContractBal.Amount).To(Equal( - contractBal.Amount. - Add(math.NewIntFromBigInt(txArgs.Amount). - Sub(minDepositAmt). - Sub(amtFromContract)), - )) - }, - Entry("with internal transfers before and after precompile call", testCase{ - before: true, - after: true, - }), - Entry("with internal transfers before precompile call", testCase{ - before: true, - after: false, - }), - Entry("with internal transfers after precompile call", testCase{ - before: false, - after: true, - }), - ) - }) - - Context("testCancel with transfer", func() { - BeforeEach(func() { - toAddr := s.keyring.GetAccAddr(1) - denom := s.network.GetBaseDenom() - amount := "100" - jsonBlob := minimalBankSendProposalJSON(toAddr, denom, amount) - minDepositAmt := math.NewInt(100) - callArgs.MethodName = testSubmitProposalFromContract - callArgs.Args = []interface{}{ - jsonBlob, - minimalDeposit(s.network.GetBaseDenom(), minDepositAmt.BigInt()), - } - txArgs.Amount = minDepositAmt.BigInt() - eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) - txArgs.To = &contractAddr - _, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - err = s.precompile.UnpackIntoInterface(&proposalID, gov.SubmitProposalMethod, evmRes.Ret) - Expect(err).To(BeNil()) - - // Calc cancellation fee - proposalDeposits, err := s.network.App.GovKeeper.GetDeposits(s.network.GetContext(), proposalID) - Expect(err).To(BeNil()) - proposalDepositAmt := proposalDeposits[0].Amount[0].Amount - params, err := s.network.App.GovKeeper.Params.Get(s.network.GetContext()) - Expect(err).To(BeNil()) - rate := math.LegacyMustNewDecFromStr(params.ProposalCancelRatio) - cancelFee = proposalDepositAmt.ToLegacyDec().Mul(rate).TruncateInt() - remaining = proposalDepositAmt.Sub(cancelFee) - - callArgs.MethodName = "testCancelWithTransfer" - }) - - DescribeTable("eoa proposer should cancel proposal with transfer", - func(tc testCase) { - // Fix the gas limit and gas ice for predictable gas usage. - // This is for calculating expected cancellation fee. - baseFee := s.network.App.FeeMarketKeeper.GetBaseFee(s.network.GetContext()) - baseFeeInt := baseFee.TruncateInt64() - txArgs.GasPrice = new(big.Int).SetInt64(baseFeeInt) - txArgs.GasLimit = 500_000 - txArgs.Amount = big.NewInt(100) - - callArgs.Args = []interface{}{ - proposalID, - tc.before, tc.after, - } - eventCheck := passCheck.WithExpEvents(gov.EventTypeCancelProposal) - - baseDenom := s.network.GetBaseDenom() - txSenderBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), txSenderAddr.Bytes(), baseDenom) - contractBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) - - res, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - var success bool - err = s.precompile.UnpackIntoInterface(&success, gov.CancelProposalMethod, evmRes.Ret) - Expect(err).To(BeNil()) - Expect(success).To(BeTrue()) - - afterTxSenderBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), txSenderAddr.Bytes(), baseDenom) - afterContractBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) - gasCost := math.NewInt(res.GasUsed).Mul(math.NewInt(txArgs.GasPrice.Int64())) - amtFromContract := math.ZeroInt() - for _, transferred := range []bool{tc.before, tc.after} { - if transferred { - amtFromContract = amtFromContract.AddRaw(15) - } - } - - Expect(afterTxSenderBal.Amount).To(Equal( - txSenderBal.Amount. - Sub(gasCost). - Sub(math.NewIntFromBigInt(txArgs.Amount)). - Add(amtFromContract), - )) - Expect(afterContractBal.Amount).To(Equal( - contractBal.Amount. - Add(remaining). - Add(math.NewIntFromBigInt(txArgs.Amount). - Sub(amtFromContract)), - )) - }, - Entry("with internal transfers before and after precompile call", testCase{ - before: true, - after: true, - }), - Entry("with internal transfers before precompile call", testCase{ - before: true, - after: false, - }), - Entry("with internal transfers after precompile call", testCase{ - before: false, - after: true, - }), - ) - }) - - Context("testCancelFromContract with transfer", func() { - BeforeEach(func() { - toAddr := s.keyring.GetAccAddr(1) - denom := s.network.GetBaseDenom() - amount := "100" - jsonBlob := minimalBankSendProposalJSON(toAddr, denom, amount) - minDepositAmt := math.NewInt(100) - callArgs.MethodName = testSubmitProposalFromContract - callArgs.Args = []interface{}{ - jsonBlob, - minimalDeposit(s.network.GetBaseDenom(), minDepositAmt.BigInt()), - } - txArgs.Amount = minDepositAmt.BigInt() - eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) - txArgs.To = &contractAddr - _, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - err = s.precompile.UnpackIntoInterface(&contractProposalID, gov.SubmitProposalMethod, evmRes.Ret) - Expect(err).To(BeNil()) - - // Calc cancellation fee - proposalDeposits, err := s.network.App.GovKeeper.GetDeposits(s.network.GetContext(), contractProposalID) - Expect(err).To(BeNil()) - proposalDepositAmt := proposalDeposits[0].Amount[0].Amount - params, err := s.network.App.GovKeeper.Params.Get(s.network.GetContext()) - Expect(err).To(BeNil()) - rate := math.LegacyMustNewDecFromStr(params.ProposalCancelRatio) - cancelFee = proposalDepositAmt.ToLegacyDec().Mul(rate).TruncateInt() - remaining = proposalDepositAmt.Sub(cancelFee) - - callArgs.MethodName = "testCancelFromContractWithTransfer" - }) - - DescribeTable("contract proposer should cancel proposal with transfer", - func(tc testCase) { - randomAddr := testutiltx.GenerateAddress() - callArgs.Args = []interface{}{ - randomAddr, - contractProposalID, - tc.before, tc.after, - } - eventCheck := passCheck.WithExpEvents(gov.EventTypeCancelProposal) - - baseDenom := s.network.GetBaseDenom() - cancellerBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) - randomAddrBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), randomAddr.Bytes(), baseDenom) - - _, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - var success bool - err = s.precompile.UnpackIntoInterface(&success, gov.CancelProposalMethod, evmRes.Ret) - Expect(err).To(BeNil()) - Expect(success).To(BeTrue()) - - afterCancellerBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) - afterRandomAddrBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), randomAddr.Bytes(), baseDenom) - amtFromContract := math.ZeroInt() - for _, transferred := range []bool{tc.before, tc.after} { - if transferred { - amtFromContract = amtFromContract.AddRaw(15) - } - } - - Expect(afterCancellerBal.Amount).To(Equal( - cancellerBal.Amount. - Add(remaining). - Add(math.NewIntFromBigInt(txArgs.Amount). - Sub(amtFromContract)), - )) - Expect(afterRandomAddrBal.Amount).To(Equal( - randomAddrBal.Amount. - Add(amtFromContract), - )) - }, - Entry("with internal transfers before and after precompile call", testCase{ - before: true, - after: true, - }), - Entry("with internal transfers before precompile call", testCase{ - before: true, - after: false, - }), - Entry("with internal transfers after precompile call", testCase{ - before: false, - after: true, - }), - ) - }) - - Context("testCancel with transfer (multiple deposits & refund)", func() { - BeforeEach(func() { - // Submit a proposal with deposit from depositor0 - denom := s.network.GetBaseDenom() - amount := "100" - randomRecipient := sdk.AccAddress(testutiltx.GenerateAddress().Bytes()) - jsonBlob := minimalBankSendProposalJSON(randomRecipient, denom, amount) - minDepositAmt := math.NewInt(100) - callArgs.MethodName = testSubmitProposalFromContract - callArgs.Args = []interface{}{ - jsonBlob, - minimalDeposit(denom, minDepositAmt.BigInt()), - } - txArgs.Amount = minDepositAmt.BigInt() - eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) - txArgs.To = &contractAddr - _, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - err = s.precompile.UnpackIntoInterface(&proposalID, gov.SubmitProposalMethod, evmRes.Ret) - Expect(err).To(BeNil()) - - // Deposit from depositor1 - minDeposits := minimalDeposit(s.network.GetBaseDenom(), minDepositAmt.BigInt()) - minDepositCoins, err := cmn.NewSdkCoinsFromCoins(minDeposits) - Expect(err).To(BeNil()) - - depositor1 = s.keyring.GetAccAddr(1) - depositorKey1 = s.keyring.GetPrivKey(1) - - msg := &v1beta1.MsgDeposit{ - ProposalId: proposalID, - Depositor: depositor1.String(), - Amount: minDepositCoins, - } - var gas uint64 = 500_000 - res, err := s.factory.ExecuteCosmosTx(depositorKey1, commonfactory.CosmosTxArgs{ - Gas: &gas, - Msgs: []sdk.Msg{msg}, - }) - Expect(err).To(BeNil()) - Expect(res.Code).To(BeZero(), "expected no error code in response") - - // Calc cancellation fees for both deposits - params, err := s.network.App.GovKeeper.Params.Get(s.network.GetContext()) - Expect(err).To(BeNil()) - rate := math.LegacyMustNewDecFromStr(params.ProposalCancelRatio) - proposalDeposits, err := s.network.App.GovKeeper.GetDeposits(s.network.GetContext(), proposalID) - Expect(err).To(BeNil()) - Expect(proposalDeposits).To(HaveLen(2)) - - cancelFees = make(map[string]math.Int) - remainingFees = make(map[string]math.Int) - - for _, deposit := range proposalDeposits { - for _, amount := range deposit.Amount { - if amount.Denom == s.network.GetBaseDenom() { - proposalDepositAmt := amount.Amount - cancelFee = proposalDepositAmt.ToLegacyDec().Mul(rate).TruncateInt() - cancelFees[deposit.Depositor] = cancelFee - remaining = proposalDepositAmt.Sub(cancelFee) - remainingFees[deposit.Depositor] = remaining - } - } - } - Expect(cancelFees).To(HaveLen(2)) - Expect(remainingFees).To(HaveLen(2)) - - callArgs.MethodName = "testCancelWithTransfer" - }) - - DescribeTable("contract proposer should cancel proposal with transfer", - func(tc testCase) { - // Fix the gas limit and gas ice for predictable gas usage. - // This is for calculating expected cancellation fee. - baseFee := s.network.App.FeeMarketKeeper.GetBaseFee(s.network.GetContext()) - baseFeeInt := baseFee.TruncateInt64() - txArgs.GasPrice = new(big.Int).SetInt64(baseFeeInt) - txArgs.GasLimit = 500_000 - txArgs.Amount = big.NewInt(100) - - callArgs.Args = []interface{}{ - proposalID, - tc.before, tc.after, - } - eventCheck := passCheck.WithExpEvents(gov.EventTypeCancelProposal) - - baseDenom := s.network.GetBaseDenom() - contractBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) - depositor1Bal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), depositor1, baseDenom) - txSenderBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), txSenderAddr.Bytes(), baseDenom) - - res, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - var success bool - err = s.precompile.UnpackIntoInterface(&success, gov.CancelProposalMethod, evmRes.Ret) - Expect(err).To(BeNil()) - Expect(success).To(BeTrue()) - gasCost := math.NewInt(res.GasUsed).Mul(math.NewInt(txArgs.GasPrice.Int64())) - - afterContractBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) - afterDepositor1Bal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), depositor1, baseDenom) - afterTxSenderBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), txSenderAddr.Bytes(), baseDenom) - amtFromContract := math.ZeroInt() - for _, transferred := range []bool{tc.before, tc.after} { - if transferred { - amtFromContract = amtFromContract.AddRaw(15) - } - } - - Expect(afterTxSenderBal.Amount).To(Equal( - txSenderBal.Amount. - Sub(gasCost). - Sub(math.NewIntFromBigInt(txArgs.Amount)). - Add(amtFromContract), - )) - Expect(afterDepositor1Bal.Amount).To(Equal( - depositor1Bal.Amount. - Add(remainingFees[depositor1.String()]), - )) - Expect(afterContractBal.Amount).To(Equal( - contractBal.Amount. - Add(remainingFees[contractAccAddr.String()]). - Add(math.NewIntFromBigInt(txArgs.Amount). - Sub(amtFromContract)), - )) - }, - Entry("with internal transfers before and after precompile call", testCase{ - before: true, - after: true, - }), - Entry("with internal transfers before precompile call", testCase{ - before: true, - after: false, - }), - Entry("with internal transfers after precompile call", testCase{ - before: false, - after: true, - }), - ) - }) - - Context("testCancelFromContract with transfer (multiple deposits & refund)", func() { - BeforeEach(func() { - // Submit a proposal with deposit from depositor0 - denom := s.network.GetBaseDenom() - amount := "100" - randomRecipient := sdk.AccAddress(testutiltx.GenerateAddress().Bytes()) - jsonBlob := minimalBankSendProposalJSON(randomRecipient, denom, amount) - minDepositAmt := math.NewInt(100) - callArgs.MethodName = testSubmitProposalFromContract - callArgs.Args = []interface{}{ - jsonBlob, - minimalDeposit(denom, minDepositAmt.BigInt()), - } - txArgs.Amount = minDepositAmt.BigInt() - eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) - txArgs.To = &contractAddr - _, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - - err = s.precompile.UnpackIntoInterface(&proposalID, gov.SubmitProposalMethod, evmRes.Ret) - Expect(err).To(BeNil()) - - // Deposit from depositor1 - minDeposits := minimalDeposit(s.network.GetBaseDenom(), minDepositAmt.BigInt()) - minDepositCoins, err := cmn.NewSdkCoinsFromCoins(minDeposits) - Expect(err).To(BeNil()) - - depositor1 = s.keyring.GetAccAddr(1) - depositorKey1 = s.keyring.GetPrivKey(1) - - msg := &v1beta1.MsgDeposit{ - ProposalId: proposalID, - Depositor: depositor1.String(), - Amount: minDepositCoins, - } - var gas uint64 = 500_000 - res, err := s.factory.ExecuteCosmosTx(depositorKey1, commonfactory.CosmosTxArgs{ - Gas: &gas, - Msgs: []sdk.Msg{msg}, - }) - Expect(err).To(BeNil()) - Expect(res.Code).To(BeZero(), "expected no error code in response") - - // Calc cancellation fees for both deposits - params, err := s.network.App.GovKeeper.Params.Get(s.network.GetContext()) - Expect(err).To(BeNil()) - rate := math.LegacyMustNewDecFromStr(params.ProposalCancelRatio) - proposalDeposits, err := s.network.App.GovKeeper.GetDeposits(s.network.GetContext(), proposalID) - Expect(err).To(BeNil()) - Expect(proposalDeposits).To(HaveLen(2)) - - cancelFees = make(map[string]math.Int) - remainingFees = make(map[string]math.Int) - - for _, deposit := range proposalDeposits { - for _, amount := range deposit.Amount { - if amount.Denom == s.network.GetBaseDenom() { - proposalDepositAmt := amount.Amount - cancelFee = proposalDepositAmt.ToLegacyDec().Mul(rate).TruncateInt() - cancelFees[deposit.Depositor] = cancelFee - remaining = proposalDepositAmt.Sub(cancelFee) - remainingFees[deposit.Depositor] = remaining - } - } - } - Expect(cancelFees).To(HaveLen(2)) - Expect(remainingFees).To(HaveLen(2)) - - callArgs.MethodName = "testCancelFromContractWithTransfer" - }) - - DescribeTable("contract proposer should cancel proposal with transfer", - func(tc testCase) { - // Fix the gas limit and gas price for predictable gas usage. - // This is for calculating expected cancellation fee. - baseFee := s.network.App.FeeMarketKeeper.GetBaseFee(s.network.GetContext()) - baseFeeInt := baseFee.TruncateInt64() - txArgs.GasPrice = new(big.Int).SetInt64(baseFeeInt) - txArgs.GasLimit = 500_000 - txArgs.Amount = big.NewInt(100) - randomAddr := testutiltx.GenerateAddress() - callArgs.Args = []interface{}{ - randomAddr, - contractProposalID, - tc.before, tc.after, - } - eventCheck := passCheck.WithExpEvents(gov.EventTypeCancelProposal) - - baseDenom := s.network.GetBaseDenom() - cancellerBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) - depositor1Bal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), depositor1, baseDenom) - randomAccBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), randomAddr.Bytes(), baseDenom) - - txSenderKey := s.keyring.GetPrivKey(0) - _, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) - Expect(err).To(BeNil()) - Expect(s.network.NextBlock()).To(BeNil()) - var success bool - err = s.precompile.UnpackIntoInterface(&success, gov.CancelProposalMethod, evmRes.Ret) - Expect(err).To(BeNil()) - Expect(success).To(BeTrue()) - - afterCancellerBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) - afterDepositor1Bal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), depositor1, baseDenom) - afterRandomAccBal := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), randomAddr.Bytes(), baseDenom) - amtFromContract := math.ZeroInt() - for _, transferred := range []bool{tc.before, tc.after} { - if transferred { - amtFromContract = amtFromContract.AddRaw(15) - } - } - - Expect(afterCancellerBal.Amount).To(Equal( - cancellerBal.Amount. - Add(remaining). - Add(math.NewIntFromBigInt(txArgs.Amount). - Sub(amtFromContract)), - )) - Expect(afterRandomAccBal.Amount).To(Equal( - randomAccBal.Amount. - Add(amtFromContract), - )) - Expect(afterDepositor1Bal.Amount).To(Equal( - depositor1Bal.Amount. - Add(remainingFees[depositor1.String()]), - )) - }, - Entry("with internal transfers before and after precompile call", testCase{ - before: true, - after: true, - }), - Entry("with internal transfers before precompile call", testCase{ - before: true, - after: false, - }), - Entry("with internal transfers after precompile call", testCase{ - before: false, - after: true, - }), - ) - }) -}) - -// ----------------------------------------------------------------------------- -// Helper functions (test‑only) -// ----------------------------------------------------------------------------- - -func minimalDeposit(denom string, amount *big.Int) []cmn.Coin { - return []cmn.Coin{{Denom: denom, Amount: amount}} -} - -// minimalBankSendProposalJSON returns a valid governance proposal encoded as UTF‑8 bytes. -func minimalBankSendProposalJSON(to sdk.AccAddress, denom, amount string) []byte { - // proto‑JSON marshal via std JSON since test helpers don’t expose codec here. - // We craft by hand for brevity. - msgJSON, _ := json.Marshal(map[string]interface{}{ - "@type": "/cosmos.bank.v1beta1.MsgSend", - // from_address must be gov module account - "from_address": govModuleAddr.String(), - "to_address": to.String(), - "amount": []map[string]string{{"denom": denom, "amount": amount}}, - }) - - prop := map[string]interface{}{ - "messages": []json.RawMessage{msgJSON}, - "metadata": "ipfs://CID", - "title": "test prop", - "summary": "test prop", - "expedited": false, - } - blob, _ := json.Marshal(prop) - return blob -} diff --git a/precompiles/p256/integration_test.go b/precompiles/p256/integration_test.go deleted file mode 100644 index 5bbcb1ad8..000000000 --- a/precompiles/p256/integration_test.go +++ /dev/null @@ -1,201 +0,0 @@ -package p256_test - -import ( - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - - "github.com/ethereum/go-ethereum/common" - - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" - - "github.com/cometbft/cometbft/crypto" - - exampleapp "github.com/cosmos/evm/evmd" - "github.com/cosmos/evm/precompiles/p256" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" - "github.com/cosmos/evm/testutil/integration/os/utils" - evmtypes "github.com/cosmos/evm/x/vm/types" -) - -type IntegrationTestSuite struct { - network network.Network - factory factory.TxFactory - keyring testkeyring.Keyring - precompileAddress common.Address - p256Priv *ecdsa.PrivateKey -} - -var _ = Describe("Calling p256 precompile directly", Label("P256 Precompile"), Ordered, func() { - var s *IntegrationTestSuite - - BeforeAll(func() { - keyring := testkeyring.New(1) - integrationNetwork := network.New( - network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), - ) - grpcHandler := grpc.NewIntegrationHandler(integrationNetwork) - txFactory := factory.New(integrationNetwork, grpcHandler) - p256Priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - Expect(err).To(BeNil()) - - s = &IntegrationTestSuite{ - network: integrationNetwork, - factory: txFactory, - keyring: keyring, - precompileAddress: p256.Precompile{}.Address(), - p256Priv: p256Priv, - } - }) - - AfterEach(func() { - // Start each test with a fresh block - err := s.network.NextBlock() - Expect(err).To(BeNil()) - }) - - When("the precompile is enabled in the EVM params", func() { - BeforeAll(func() { - s = setupIntegrationTestSuite(nil) - }) - - DescribeTable("execute contract call", func(inputFn func() (input, expOutput []byte, expErr string)) { - senderKey := s.keyring.GetKey(0) - - input, expOutput, expErr := inputFn() - args := evmtypes.EvmTxArgs{ - To: &s.precompileAddress, - Input: input, - } - - txResult, err := s.factory.ExecuteEthTx(senderKey.Priv, args) - Expect(err).To(BeNil()) - Expect(txResult.IsOK()).To(Equal(true), "transaction should have succeeded", txResult.GetLog()) - - res, err := utils.DecodeExecTxResult(txResult) - Expect(err).To(BeNil()) - Expect(res.VmError).To(Equal(expErr), "expected different vm error") - Expect(res.Ret).To(Equal(expOutput)) - }, - Entry( - "valid signature", - func() (input, expOutput []byte, expErr string) { - input = signMsg([]byte("hello world"), s.p256Priv) - return input, trueValue, "" - }, - ), - Entry( - "invalid signature", - func() (input, expOutput []byte, expErr string) { - privB, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - Expect(err).To(BeNil()) - - hash := crypto.Sha256([]byte("hello world")) - - rInt, sInt, err := ecdsa.Sign(rand.Reader, s.p256Priv, hash) - Expect(err).To(BeNil()) - - input = make([]byte, p256.VerifyInputLength) - copy(input[0:32], hash) - copy(input[32:64], rInt.Bytes()) - copy(input[64:96], sInt.Bytes()) - copy(input[96:128], privB.PublicKey.X.Bytes()) - copy(input[128:160], privB.PublicKey.Y.Bytes()) - return input, nil, "" - }, - ), - ) - }) - - When("the precompile is not enabled in the EVM params", func() { - BeforeAll(func() { - customGenesis := exampleapp.NewEVMGenesisState() - params := customGenesis.Params - addr := s.precompileAddress.String() - var activePrecompiles []string - for _, precompile := range params.ActiveStaticPrecompiles { - if precompile != addr { - activePrecompiles = append(activePrecompiles, precompile) - } - } - params.ActiveStaticPrecompiles = activePrecompiles - customGenesis.Params = params - s = setupIntegrationTestSuite(customGenesis) - }) - - DescribeTable("execute contract call", func(inputFn func() (input []byte)) { - senderKey := s.keyring.GetKey(0) - - input := inputFn() - args := evmtypes.EvmTxArgs{ - To: &s.precompileAddress, - Input: input, - } - - _, err := s.factory.ExecuteEthTx(senderKey.Priv, args) - Expect(err).To(BeNil(), "expected no error since contract doesn't exists") - }, - Entry( - "valid signature", - func() (input []byte) { - input = signMsg([]byte("hello world"), s.p256Priv) - return input - }, - ), - Entry( - "invalid signature", - func() (input []byte) { - privB, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - Expect(err).To(BeNil()) - - hash := crypto.Sha256([]byte("hello world")) - - rInt, sInt, err := ecdsa.Sign(rand.Reader, s.p256Priv, hash) - Expect(err).To(BeNil()) - - input = make([]byte, p256.VerifyInputLength) - copy(input[0:32], hash) - copy(input[32:64], rInt.Bytes()) - copy(input[64:96], sInt.Bytes()) - copy(input[96:128], privB.PublicKey.X.Bytes()) - copy(input[128:160], privB.PublicKey.Y.Bytes()) - return input - }, - ), - ) - }) -}) - -// setupIntegrationTestSuite is a helper function to setup a integration test suite -// with a network with a specified custom genesis state for the EVM module -func setupIntegrationTestSuite(customEVMGenesis *evmtypes.GenesisState) *IntegrationTestSuite { - customGenesis := network.CustomGenesisState{} - if customEVMGenesis != nil { - customGenesis[evmtypes.ModuleName] = customEVMGenesis - } - keyring := testkeyring.New(1) - integrationNetwork := network.New( - network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), - network.WithCustomGenesis(customGenesis), - ) - grpcHandler := grpc.NewIntegrationHandler(integrationNetwork) - txFactory := factory.New(integrationNetwork, grpcHandler) - p256Priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - Expect(err).To(BeNil()) - - suite := &IntegrationTestSuite{ - network: integrationNetwork, - factory: txFactory, - keyring: keyring, - precompileAddress: p256.Precompile{}.Address(), - p256Priv: p256Priv, - } - - return suite -} diff --git a/precompiles/staking/integration_test.go b/precompiles/staking/integration_test.go deleted file mode 100644 index 1aeff01c1..000000000 --- a/precompiles/staking/integration_test.go +++ /dev/null @@ -1,3354 +0,0 @@ -package staking_test - -import ( - "fmt" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/vm" - - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" - - compiledcontracts "github.com/cosmos/evm/contracts" - "github.com/cosmos/evm/crypto/ethsecp256k1" - cmn "github.com/cosmos/evm/precompiles/common" - "github.com/cosmos/evm/precompiles/staking" - "github.com/cosmos/evm/precompiles/staking/testdata" - "github.com/cosmos/evm/precompiles/testutil" - "github.com/cosmos/evm/precompiles/testutil/contracts" - cosmosevmutil "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/os/factory" - testutils "github.com/cosmos/evm/testutil/integration/os/utils" - testutiltx "github.com/cosmos/evm/testutil/tx" - evmtypes "github.com/cosmos/evm/x/vm/types" - - "cosmossdk.io/math" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/query" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" -) - -func TestPrecompileIntegrationTestSuite(t *testing.T) { - // Run Ginkgo integration tests - RegisterFailHandler(Fail) - RunSpecs(t, "Staking Precompile Integration Tests") -} - -// General variables used for integration tests -var ( - // valAddr and valAddr2 are the two validator addresses used for testing - valAddr, valAddr2 sdk.ValAddress - - // callArgs is the default arguments for calling the smart contract. - // - // NOTE: this has to be populated in a BeforeEach block because the contractAddr would otherwise be a nil address. - callArgs factory.CallArgs - // txArgs are the EVM transaction arguments to use in the transactions - txArgs evmtypes.EvmTxArgs - // defaultLogCheck instantiates a log check arguments struct with the precompile ABI events populated. - defaultLogCheck testutil.LogCheckArgs - // passCheck defines the arguments to check if the precompile returns no error - passCheck testutil.LogCheckArgs - // outOfGasCheck defines the arguments to check if the precompile returns out of gas error - outOfGasCheck testutil.LogCheckArgs -) - -var _ = Describe("Calling staking precompile directly", func() { - // s is the precompile test suite to use for the tests - var s *PrecompileTestSuite - - BeforeEach(func() { - var err error - s = new(PrecompileTestSuite) - s.SetupTest() - - valAddr, err = sdk.ValAddressFromBech32(s.network.GetValidators()[0].GetOperator()) - Expect(err).To(BeNil()) - valAddr2, err = sdk.ValAddressFromBech32(s.network.GetValidators()[1].GetOperator()) - Expect(err).To(BeNil()) - - callArgs = factory.CallArgs{ - ContractABI: s.precompile.ABI, - } - - precompileAddr := s.precompile.Address() - txArgs = evmtypes.EvmTxArgs{ - To: &precompileAddr, - } - - defaultLogCheck = testutil.LogCheckArgs{ABIEvents: s.precompile.ABI.Events} - passCheck = defaultLogCheck.WithExpPass(true) - outOfGasCheck = defaultLogCheck.WithErrContains(vm.ErrOutOfGas.Error()) - }) - - Describe("when the precompile is not enabled in the EVM params", func() { - It("should succeed but not perform delegation", func() { - delegator := s.keyring.GetKey(0) - // disable the precompile - res, err := s.grpcHandler.GetEvmParams() - Expect(err).To(BeNil()) - - var activePrecompiles []string - for _, precompile := range res.Params.ActiveStaticPrecompiles { - if precompile != s.precompile.Address().String() { - activePrecompiles = append(activePrecompiles, precompile) - } - } - res.Params.ActiveStaticPrecompiles = activePrecompiles - - err = testutils.UpdateEvmParams(testutils.UpdateParamsInput{ - Tf: s.factory, - Network: s.network, - Pk: delegator.Priv, - Params: res.Params, - }) - Expect(err).To(BeNil(), "error while setting params") - - // get the delegation that is available prior to the test - qRes, err := s.grpcHandler.GetDelegation(delegator.AccAddr.String(), valAddr.String()) - Expect(err).To(BeNil()) - prevDelegation := qRes.DelegationResponse.Balance - // try to call the precompile - callArgs.MethodName = staking.DelegateMethod - callArgs.Args = []interface{}{delegator.Addr, valAddr.String(), big.NewInt(2e18)} - - // Contract should not be called but the transaction should be successful - // This is the expected behavior in Ethereum where there is a contract call - // to a non existing contract - expectedCheck := defaultLogCheck. - WithExpEvents([]string{}...). - WithExpPass(true) - - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, - callArgs, - expectedCheck, - ) - Expect(err).To(BeNil(), "error while calling the contract and checking logs") - qRes, err = s.grpcHandler.GetDelegation(delegator.AccAddr.String(), valAddr.String()) - Expect(err).To(BeNil()) - postDelegation := qRes.DelegationResponse.Balance - Expect(postDelegation).To(Equal(prevDelegation), "expected delegation to not change") - }) - }) - - Describe("Revert transaction", func() { - It("should run out of gas if the gas limit is too low", func() { - delegator := s.keyring.GetKey(0) - - callArgs.MethodName = staking.DelegateMethod - callArgs.Args = []interface{}{ - delegator.Addr, - valAddr.String(), - big.NewInt(2e18), - } - txArgs.GasLimit = 30000 - - _, _, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, - callArgs, - outOfGasCheck, - ) - Expect(err).To(BeNil(), "error while calling precompile") - }) - }) - - Describe("to create validator", func() { - var ( - defaultDescription = staking.Description{ - Moniker: "new node", - Identity: "", - Website: "", - SecurityContact: "", - Details: "", - } - defaultCommission = staking.Commission{ - Rate: big.NewInt(100000000000000000), - MaxRate: big.NewInt(100000000000000000), - MaxChangeRate: big.NewInt(100000000000000000), - } - defaultMinSelfDelegation = big.NewInt(1) - defaultPubkeyBase64Str = GenerateBase64PubKey() - defaultValue = big.NewInt(1) - ) - - BeforeEach(func() { - // populate the default createValidator args - callArgs.MethodName = staking.CreateValidatorMethod - }) - - Context("when validator address is the msg.sender & EoA", func() { - It("should succeed", func() { - callArgs.Args = []interface{}{ - defaultDescription, defaultCommission, defaultMinSelfDelegation, s.keyring.GetAddr(0), defaultPubkeyBase64Str, defaultValue, - } - // NOTE: increase gas limit here - txArgs.GasLimit = 2e5 - - logCheckArgs := passCheck.WithExpEvents(staking.EventTypeCreateValidator) - - _, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the contract and checking logs") - Expect(s.network.NextBlock()).To(BeNil()) - - valOperAddr := sdk.ValAddress(s.keyring.GetAccAddr(0)).String() - qc := s.network.GetStakingClient() - res, err := qc.Validator(s.network.GetContext(), &stakingtypes.QueryValidatorRequest{ValidatorAddr: valOperAddr}) - Expect(err).To(BeNil()) - Expect(res).NotTo(BeNil()) - Expect(res.Validator.OperatorAddress).To(Equal(valOperAddr)) - }) - }) - - Context("when validator address is not the msg.sender", func() { - It("should fail", func() { - differentAddr := testutiltx.GenerateAddress() - - callArgs.Args = []interface{}{ - defaultDescription, defaultCommission, defaultMinSelfDelegation, differentAddr, defaultPubkeyBase64Str, defaultValue, - } - - logCheckArgs := defaultLogCheck.WithErrContains( - fmt.Sprintf(cmn.ErrRequesterIsNotMsgSender, s.keyring.GetAddr(0), differentAddr), - ) - - _, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the contract and checking logs") - }) - }) - }) - - Describe("to edit validator", func() { - var ( - defaultDescription = staking.Description{ - Moniker: "edit node", - Identity: "[do-not-modify]", - Website: "[do-not-modify]", - SecurityContact: "[do-not-modify]", - Details: "[do-not-modify]", - } - defaultCommissionRate = big.NewInt(staking.DoNotModifyCommissionRate) - defaultMinSelfDelegation = big.NewInt(staking.DoNotModifyMinSelfDelegation) - ) - - BeforeEach(func() { - // populate the default editValidator args - callArgs.MethodName = staking.EditValidatorMethod - }) - - Context("when msg.sender is equal to validator address", func() { - It("should succeed", func() { - // create a new validator - newAddr, newPriv := testutiltx.NewAccAddressAndKey() - hexAddr := common.BytesToAddress(newAddr.Bytes()) - - err := testutils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), newAddr, math.NewInt(2e18)) - Expect(err).To(BeNil(), "error while sending coins") - Expect(s.network.NextBlock()).To(BeNil()) - - description := staking.Description{ - Moniker: "new node", - Identity: "", - Website: "", - SecurityContact: "", - Details: "", - } - commission := staking.Commission{ - Rate: big.NewInt(100000000000000000), - MaxRate: big.NewInt(100000000000000000), - MaxChangeRate: big.NewInt(100000000000000000), - } - minSelfDelegation := big.NewInt(1) - pubkeyBase64Str := "UuhHQmkUh2cPBA6Rg4ei0M2B04cVYGNn/F8SAUsYIb4=" - value := big.NewInt(1e18) - - createValidatorArgs := factory.CallArgs{ - ContractABI: s.precompile.ABI, - MethodName: staking.CreateValidatorMethod, - Args: []interface{}{description, commission, minSelfDelegation, hexAddr, pubkeyBase64Str, value}, - } - - logCheckArgs := passCheck.WithExpEvents(staking.EventTypeCreateValidator) - _, _, err = s.factory.CallContractAndCheckLogs( - newPriv, - txArgs, createValidatorArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the contract and checking logs") - Expect(s.network.NextBlock()).To(BeNil()) - - // edit validator - callArgs.Args = []interface{}{defaultDescription, hexAddr, defaultCommissionRate, defaultMinSelfDelegation} - - logCheckArgs = passCheck.WithExpEvents(staking.EventTypeEditValidator) - _, _, err = s.factory.CallContractAndCheckLogs( - newPriv, - txArgs, callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the contract and checking logs") - Expect(s.network.NextBlock()).To(BeNil()) - - valOperAddr := sdk.ValAddress(newAddr.Bytes()).String() - qc := s.network.GetStakingClient() - res, err := qc.Validator(s.network.GetContext(), &stakingtypes.QueryValidatorRequest{ValidatorAddr: valOperAddr}) - Expect(err).To(BeNil()) - Expect(res).NotTo(BeNil()) - validator := res.Validator - Expect(validator.OperatorAddress).To(Equal(valOperAddr)) - Expect(validator.Description.Moniker).To(Equal(defaultDescription.Moniker), "expected validator moniker is updated") - // Other fields should not be modified due to the value "[do-not-modify]". - Expect(validator.Description.Identity).To(Equal(description.Identity), "expected validator identity not to be updated") - Expect(validator.Description.Website).To(Equal(description.Website), "expected validator website not to be updated") - Expect(validator.Description.SecurityContact).To(Equal(description.SecurityContact), "expected validator security contact not to be updated") - Expect(validator.Description.Details).To(Equal(description.Details), "expected validator details not to be updated") - - Expect(validator.Commission.Rate.BigInt().String()).To(Equal(commission.Rate.String()), "expected validator commission rate remain unchanged") - Expect(validator.Commission.MaxRate.BigInt().String()).To(Equal(commission.MaxRate.String()), "expected validator max commission rate remain unchanged") - Expect(validator.Commission.MaxChangeRate.BigInt().String()).To(Equal(commission.MaxChangeRate.String()), "expected validator max change rate remain unchanged") - Expect(validator.MinSelfDelegation.String()).To(Equal(minSelfDelegation.String()), "expected validator min self delegation remain unchanged") - }) - }) - - Context("with msg.sender different than validator address", func() { - It("should fail", func() { - valHexAddr := common.BytesToAddress(valAddr.Bytes()) - callArgs.Args = []interface{}{ - defaultDescription, valHexAddr, defaultCommissionRate, defaultMinSelfDelegation, - } - - logCheckArgs := passCheck.WithExpEvents(staking.EventTypeEditValidator) - _, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(1), - txArgs, callArgs, - logCheckArgs, - ) - Expect(err).NotTo(BeNil(), "error while calling the contract and checking logs") - Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("msg.sender address %s does not match the requester address %s", s.keyring.GetAddr(1), valHexAddr))) - }) - }) - }) - Describe("to delegate", func() { - // prevDelegation is the delegation that is available prior to the test (an initial delegation is - // added in the test suite setup). - var prevDelegation stakingtypes.Delegation - - BeforeEach(func() { - delegator := s.keyring.GetKey(0) - - // get the delegation that is available prior to the test - res, err := s.grpcHandler.GetDelegation(delegator.AccAddr.String(), valAddr.String()) - Expect(err).To(BeNil()) - Expect(res.DelegationResponse).NotTo(BeNil()) - - prevDelegation = res.DelegationResponse.Delegation - // populate the default delegate args - callArgs.MethodName = staking.DelegateMethod - }) - - Context("as the token owner", func() { - It("should delegate", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - delegator.Addr, valAddr.String(), big.NewInt(2e18), - } - - logCheckArgs := passCheck.WithExpEvents(staking.EventTypeDelegate) - - _, _, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - res, err := s.grpcHandler.GetDelegation(delegator.AccAddr.String(), valAddr.String()) - Expect(err).To(BeNil()) - Expect(res.DelegationResponse).NotTo(BeNil()) - expShares := prevDelegation.GetShares().Add(math.LegacyNewDec(2)) - Expect(res.DelegationResponse.Delegation.GetShares()).To(Equal(expShares), "expected different delegation shares") - }) - - It("should not delegate if the account has no sufficient balance", func() { - newAddr, newAddrPriv := testutiltx.NewAccAddressAndKey() - err := testutils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), newAddr, math.NewInt(1e17)) - Expect(err).To(BeNil(), "error while sending coins") - Expect(s.network.NextBlock()).To(BeNil()) - - // try to delegate more than left in account - callArgs.Args = []interface{}{ - common.BytesToAddress(newAddr), valAddr.String(), big.NewInt(1e18), - } - - logCheckArgs := defaultLogCheck.WithErrContains("insufficient funds") - - _, _, err = s.factory.CallContractAndCheckLogs( - newAddrPriv, - txArgs, - callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - }) - - It("should not delegate if the validator does not exist", func() { - nonExistingAddr := testutiltx.GenerateAddress() - nonExistingValAddr := sdk.ValAddress(nonExistingAddr.Bytes()) - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - delegator.Addr, nonExistingValAddr.String(), big.NewInt(2e18), - } - - logCheckArgs := defaultLogCheck.WithErrContains("validator does not exist") - - _, _, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, - callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - }) - }) - - Context("on behalf of another account", func() { - It("should not delegate if delegator address is not the msg.sender", func() { - delegator := s.keyring.GetKey(0) - differentAddr := testutiltx.GenerateAddress() - - callArgs.Args = []interface{}{ - differentAddr, valAddr.String(), big.NewInt(2e18), - } - - logCheckArgs := defaultLogCheck.WithErrContains( - fmt.Sprintf(cmn.ErrRequesterIsNotMsgSender, delegator.Addr, differentAddr), - ) - - _, _, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, - callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - }) - }) - }) - - Describe("to undelegate", func() { - BeforeEach(func() { - callArgs.MethodName = staking.UndelegateMethod - }) - - Context("as the token owner", func() { - It("should undelegate", func() { - delegator := s.keyring.GetKey(0) - - valAddr, err := sdk.ValAddressFromBech32(s.network.GetValidators()[0].GetOperator()) - Expect(err).To(BeNil()) - - res, err := s.grpcHandler.GetValidatorUnbondingDelegations(valAddr.String()) - Expect(err).To(BeNil()) - Expect(res.UnbondingResponses).To(HaveLen(0), "expected no unbonding delegations before test") - - callArgs.Args = []interface{}{ - delegator.Addr, valAddr.String(), big.NewInt(1e18), - } - - logCheckArgs := passCheck.WithExpEvents(staking.EventTypeUnbond) - - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - delUbdRes, err := s.grpcHandler.GetDelegatorUnbondingDelegations(delegator.AccAddr.String()) - Expect(err).To(BeNil()) - Expect(delUbdRes.UnbondingResponses).To(HaveLen(1), "expected one undelegation") - Expect(delUbdRes.UnbondingResponses[0].ValidatorAddress).To(Equal(valAddr.String()), "expected validator address to be %s", valAddr) - }) - - It("should not undelegate if the amount exceeds the delegation", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - delegator.Addr, valAddr.String(), big.NewInt(2e18), - } - - logCheckArgs := defaultLogCheck.WithErrContains("invalid shares amount") - - _, _, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - }) - - It("should not undelegate if the validator does not exist", func() { - delegator := s.keyring.GetKey(0) - nonExistingAddr := testutiltx.GenerateAddress() - nonExistingValAddr := sdk.ValAddress(nonExistingAddr.Bytes()) - - callArgs.Args = []interface{}{ - delegator.Addr, nonExistingValAddr.String(), big.NewInt(1e18), - } - - logCheckArgs := defaultLogCheck.WithErrContains("validator does not exist") - - _, _, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - logCheckArgs) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - }) - }) - - Context("on behalf of another account", func() { - It("should not undelegate if delegator address is not the msg.sender", func() { - differentAddr := testutiltx.GenerateAddress() - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - differentAddr, valAddr.String(), big.NewInt(1e18), - } - - logCheckArgs := defaultLogCheck.WithErrContains( - fmt.Sprintf(cmn.ErrRequesterIsNotMsgSender, delegator.Addr, differentAddr), - ) - - _, _, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - }) - }) - }) - - Describe("to redelegate", func() { - BeforeEach(func() { - callArgs.MethodName = staking.RedelegateMethod - }) - - Context("as the token owner", func() { - It("should redelegate", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - delegator.Addr, valAddr.String(), valAddr2.String(), big.NewInt(1e18), - } - - logCheckArgs := passCheck. - WithExpEvents(staking.EventTypeRedelegate) - - _, _, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - res, err := s.grpcHandler.GetRedelegations(delegator.AccAddr.String(), valAddr.String(), valAddr2.String()) - Expect(err).To(BeNil()) - Expect(res.RedelegationResponses).To(HaveLen(1), "expected one redelegation to be found") - bech32Addr := delegator.AccAddr - Expect(res.RedelegationResponses[0].Redelegation.DelegatorAddress).To(Equal(bech32Addr.String()), "expected delegator address to be %s", delegator.Addr) - Expect(res.RedelegationResponses[0].Redelegation.ValidatorSrcAddress).To(Equal(valAddr.String()), "expected source validator address to be %s", valAddr) - Expect(res.RedelegationResponses[0].Redelegation.ValidatorDstAddress).To(Equal(valAddr2.String()), "expected destination validator address to be %s", valAddr2) - }) - - It("should not redelegate if the amount exceeds the delegation", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - delegator.Addr, valAddr.String(), valAddr2.String(), big.NewInt(2e18), - } - - logCheckArgs := defaultLogCheck.WithErrContains("invalid shares amount") - - _, _, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - }) - - It("should not redelegate if the validator does not exist", func() { - nonExistingAddr := testutiltx.GenerateAddress() - nonExistingValAddr := sdk.ValAddress(nonExistingAddr.Bytes()) - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - delegator.Addr, valAddr.String(), nonExistingValAddr.String(), big.NewInt(1e18), - } - - logCheckArgs := defaultLogCheck.WithErrContains("redelegation destination validator not found") - - _, _, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - }) - }) - - Context("on behalf of another account", func() { - It("should not redelegate if delegator address is not the msg.sender", func() { - differentAddr := testutiltx.GenerateAddress() - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - differentAddr, valAddr.String(), valAddr2.String(), big.NewInt(1e18), - } - - logCheckArgs := defaultLogCheck.WithErrContains( - fmt.Sprintf(cmn.ErrRequesterIsNotMsgSender, delegator.Addr, differentAddr), - ) - - _, _, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - }) - }) - }) - - Describe("to cancel an unbonding delegation", func() { - BeforeEach(func() { - callArgs.MethodName = staking.CancelUnbondingDelegationMethod - delegator := s.keyring.GetKey(0) - - // Set up an unbonding delegation - undelegateArgs := factory.CallArgs{ - ContractABI: s.precompile.ABI, - MethodName: staking.UndelegateMethod, - Args: []interface{}{ - delegator.Addr, valAddr.String(), big.NewInt(1e18), - }, - } - - logCheckArgs := passCheck. - WithExpEvents(staking.EventTypeUnbond) - - _, _, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, - undelegateArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while setting up an unbonding delegation: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - creationHeight := s.network.GetContext().BlockHeight() - - // Check that the unbonding delegation was created - res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(delegator.AccAddr.String()) - Expect(err).To(BeNil()) - Expect(res.UnbondingResponses).To(HaveLen(1), "expected one unbonding delegation to be found") - Expect(res.UnbondingResponses[0].DelegatorAddress).To(Equal(delegator.AccAddr.String()), "expected delegator address to be %s", delegator.Addr) - Expect(res.UnbondingResponses[0].ValidatorAddress).To(Equal(valAddr.String()), "expected validator address to be %s", valAddr) - Expect(res.UnbondingResponses[0].Entries).To(HaveLen(1), "expected one unbonding delegation entry to be found") - Expect(res.UnbondingResponses[0].Entries[0].CreationHeight).To(Equal(creationHeight), "expected different creation height") - Expect(res.UnbondingResponses[0].Entries[0].Balance).To(Equal(math.NewInt(1e18)), "expected different balance") - }) - - Context("as the token owner", func() { - It("should cancel unbonding delegation", func() { - delegator := s.keyring.GetKey(0) - - valDelRes, err := s.grpcHandler.GetValidatorDelegations(s.network.GetValidators()[0].GetOperator()) - Expect(err).To(BeNil()) - Expect(valDelRes.DelegationResponses).To(HaveLen(0)) - - creationHeight := s.network.GetContext().BlockHeight() - callArgs.Args = []interface{}{ - delegator.Addr, valAddr.String(), big.NewInt(1e18), big.NewInt(creationHeight), - } - - logCheckArgs := passCheck. - WithExpEvents(staking.EventTypeCancelUnbondingDelegation) - - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, - callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(delegator.AccAddr.String()) - Expect(err).To(BeNil()) - Expect(res.UnbondingResponses).To(HaveLen(0), "expected unbonding delegation to be canceled") - - valDelRes, err = s.grpcHandler.GetValidatorDelegations(s.network.GetValidators()[0].GetOperator()) - Expect(err).To(BeNil()) - Expect(valDelRes.DelegationResponses).To(HaveLen(1), "expected one delegation to be found") - }) - - It("should not cancel an unbonding delegation if the amount is not correct", func() { - delegator := s.keyring.GetKey(0) - - creationHeight := s.network.GetContext().BlockHeight() - callArgs.Args = []interface{}{ - delegator.Addr, valAddr.String(), big.NewInt(2e18), big.NewInt(creationHeight), - } - - logCheckArgs := defaultLogCheck.WithErrContains("amount is greater than the unbonding delegation entry balance") - - _, _, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(delegator.AccAddr.String()) - Expect(err).To(BeNil()) - Expect(res.UnbondingResponses).To(HaveLen(1), "expected unbonding delegation not to have been canceled") - }) - - It("should not cancel an unbonding delegation if the creation height is not correct", func() { - delegator := s.keyring.GetKey(0) - - creationHeight := s.network.GetContext().BlockHeight() - callArgs.Args = []interface{}{ - delegator.Addr, valAddr.String(), big.NewInt(1e18), big.NewInt(creationHeight + 1), - } - - logCheckArgs := defaultLogCheck.WithErrContains("unbonding delegation entry is not found at block height") - - _, _, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(delegator.AccAddr.String()) - Expect(err).To(BeNil()) - Expect(res.UnbondingResponses).To(HaveLen(1), "expected unbonding delegation not to have been canceled") - }) - }) - }) - - Describe("Validator queries", func() { - BeforeEach(func() { - callArgs.MethodName = staking.ValidatorMethod - }) - - It("should return validator", func() { - delegator := s.keyring.GetKey(0) - - varHexAddr := common.BytesToAddress(valAddr.Bytes()) - callArgs.Args = []interface{}{varHexAddr} - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var valOut staking.ValidatorOutput - err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) - Expect(valOut.Validator.OperatorAddress).To(Equal(varHexAddr.String()), "expected validator address to match") - Expect(valOut.Validator.DelegatorShares).To(Equal(big.NewInt(1e18)), "expected different delegator shares") - }) - - It("should return an empty validator if the validator is not found", func() { - delegator := s.keyring.GetKey(0) - - newValHexAddr := testutiltx.GenerateAddress() - callArgs.Args = []interface{}{newValHexAddr} - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var valOut staking.ValidatorOutput - err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) - Expect(valOut.Validator.OperatorAddress).To(Equal(""), "expected validator address to be empty") - Expect(valOut.Validator.Status).To(BeZero(), "expected unspecified bonding status") - }) - }) - - Describe("Validators queries", func() { - BeforeEach(func() { - callArgs.MethodName = staking.ValidatorsMethod - }) - - It("should return validators (default pagination)", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - stakingtypes.Bonded.String(), - query.PageRequest{}, - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var valOut staking.ValidatorsOutput - err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorsMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) - - Expect(valOut.PageResponse.NextKey).To(BeEmpty()) - Expect(valOut.PageResponse.Total).To(Equal(uint64(len(s.network.GetValidators())))) - - Expect(valOut.Validators).To(HaveLen(len(s.network.GetValidators())), "expected two validators to be returned") - // return order can change, that's why each validator is checked individually - for _, val := range valOut.Validators { - s.CheckValidatorOutput(val) - } - }) - - //nolint:dupl // this is a duplicate of the test for smart contract calls to the precompile - It("should return validators w/pagination limit = 1", func() { - const limit uint64 = 1 - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - stakingtypes.Bonded.String(), - query.PageRequest{ - Limit: limit, - CountTotal: true, - }, - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var valOut staking.ValidatorsOutput - err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorsMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) - - // no pagination, should return default values - Expect(valOut.PageResponse.NextKey).NotTo(BeEmpty()) - Expect(valOut.PageResponse.Total).To(Equal(uint64(len(s.network.GetValidators())))) - - Expect(valOut.Validators).To(HaveLen(int(limit)), "expected one validator to be returned") - - // return order can change, that's why each validator is checked individually - for _, val := range valOut.Validators { - s.CheckValidatorOutput(val) - } - }) - - It("should return an error if the bonding type is not known", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - "15", // invalid bonding type - query.PageRequest{}, - } - - invalidStatusCheck := defaultLogCheck.WithErrContains("invalid validator status 15") - - _, _, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, - callArgs, - invalidStatusCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - }) - - It("should return an empty array if there are no validators with the given bonding type", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - stakingtypes.Unbonded.String(), - query.PageRequest{}, - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var valOut staking.ValidatorsOutput - err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorsMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) - - Expect(valOut.PageResponse.NextKey).To(BeEmpty()) - Expect(valOut.PageResponse.Total).To(Equal(uint64(0))) - Expect(valOut.Validators).To(HaveLen(0), "expected no validators to be returned") - }) - }) - - Describe("Delegation queries", func() { - BeforeEach(func() { - callArgs.MethodName = staking.DelegationMethod - }) - - It("should return a delegation if it is found", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - delegator.Addr, - valAddr.String(), - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var delOut staking.DelegationOutput - err = s.precompile.UnpackIntoInterface(&delOut, staking.DelegationMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the delegation output: %v", err) - Expect(delOut.Shares).To(Equal(big.NewInt(1e18)), "expected different shares") - Expect(delOut.Balance).To(Equal(cmn.Coin{Denom: s.bondDenom, Amount: big.NewInt(1e18)}), "expected different shares") - }) - - It("should return an empty delegation if it is not found", func() { - delegator := s.keyring.GetKey(0) - - newValAddr := sdk.ValAddress(testutiltx.GenerateAddress().Bytes()) - callArgs.Args = []interface{}{ - delegator.Addr, - newValAddr.String(), - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var delOut staking.DelegationOutput - err = s.precompile.UnpackIntoInterface(&delOut, staking.DelegationMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the delegation output: %v", err) - Expect(delOut.Shares.Int64()).To(BeZero(), "expected no shares") - Expect(delOut.Balance.Denom).To(Equal(s.bondDenom), "expected different denomination") - Expect(delOut.Balance.Amount.Int64()).To(BeZero(), "expected a zero amount") - }) - }) - - Describe("UnbondingDelegation queries", func() { - // undelAmount is the amount of tokens to be unbonded - undelAmount := big.NewInt(1e17) - - BeforeEach(func() { - callArgs.MethodName = staking.UnbondingDelegationMethod - - delegator := s.keyring.GetKey(0) - - undelegateArgs := factory.CallArgs{ - ContractABI: s.precompile.ABI, - MethodName: staking.UndelegateMethod, - Args: []interface{}{ - delegator.Addr, valAddr.String(), undelAmount, - }, - } - - unbondCheck := passCheck.WithExpEvents(staking.EventTypeUnbond) - _, _, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, undelegateArgs, - unbondCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - // check that the unbonding delegation exists - res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(delegator.AccAddr.String()) - Expect(err).To(BeNil()) - Expect(res.UnbondingResponses).To(HaveLen(1), "expected one unbonding delegation") - }) - - It("should return an unbonding delegation if it is found", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - delegator.Addr, - valAddr.String(), - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var unbondingDelegationOutput staking.UnbondingDelegationOutput - err = s.precompile.UnpackIntoInterface(&unbondingDelegationOutput, staking.UnbondingDelegationMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the unbonding delegation output: %v", err) - Expect(unbondingDelegationOutput.UnbondingDelegation.Entries).To(HaveLen(1), "expected one unbonding delegation entry") - // TODO: why are initial balance and balance the same always? - Expect(unbondingDelegationOutput.UnbondingDelegation.Entries[0].InitialBalance).To(Equal(undelAmount), "expected different initial balance") - Expect(unbondingDelegationOutput.UnbondingDelegation.Entries[0].Balance).To(Equal(undelAmount), "expected different balance") - }) - - It("should return an empty slice if the unbonding delegation is not found", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - delegator.Addr, - valAddr2.String(), - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var unbondingDelegationOutput staking.UnbondingDelegationOutput - err = s.precompile.UnpackIntoInterface(&unbondingDelegationOutput, staking.UnbondingDelegationMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the unbonding delegation output: %v", err) - Expect(unbondingDelegationOutput.UnbondingDelegation.Entries).To(HaveLen(0), "expected one unbonding delegation entry") - }) - }) - - Describe("to query a redelegation", func() { - BeforeEach(func() { - callArgs.MethodName = staking.RedelegationMethod - }) - - It("should return the redelegation if it exists", func() { - delegator := s.keyring.GetKey(0) - - // create a redelegation - redelegateArgs := factory.CallArgs{ - ContractABI: s.precompile.ABI, - MethodName: staking.RedelegateMethod, - Args: []interface{}{ - delegator.Addr, valAddr.String(), valAddr2.String(), big.NewInt(1e17), - }, - } - - redelegateCheck := passCheck.WithExpEvents(staking.EventTypeRedelegate) - - _, _, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, redelegateArgs, - redelegateCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - // query the redelegation - callArgs.Args = []interface{}{ - delegator.Addr, - valAddr.String(), - valAddr2.String(), - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var redelegationOutput staking.RedelegationOutput - err = s.precompile.UnpackIntoInterface(&redelegationOutput, staking.RedelegationMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the redelegation output: %v", err) - Expect(redelegationOutput.Redelegation.Entries).To(HaveLen(1), "expected one redelegation entry") - Expect(redelegationOutput.Redelegation.Entries[0].InitialBalance).To(Equal(big.NewInt(1e17)), "expected different initial balance") - Expect(redelegationOutput.Redelegation.Entries[0].SharesDst).To(Equal(big.NewInt(1e17)), "expected different balance") - }) - - It("should return an empty output if the redelegation is not found", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - delegator.Addr, - valAddr.String(), - valAddr2.String(), - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var redelegationOutput staking.RedelegationOutput - err = s.precompile.UnpackIntoInterface(&redelegationOutput, staking.RedelegationMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the redelegation output: %v", err) - Expect(redelegationOutput.Redelegation.Entries).To(HaveLen(0), "expected no redelegation entries") - }) - }) - - Describe("Redelegations queries", func() { - var ( - // delAmt is the amount of tokens to be delegated - delAmt = big.NewInt(3e17) - // redelTotalCount is the total number of redelegations - redelTotalCount uint64 = 1 - ) - - BeforeEach(func() { - delegator := s.keyring.GetKey(0) - - callArgs.MethodName = staking.RedelegationsMethod - // create some redelegations - redelegationsArgs := []factory.CallArgs{ - { - ContractABI: s.precompile.ABI, - MethodName: staking.RedelegateMethod, - Args: []interface{}{ - delegator.Addr, valAddr.String(), valAddr2.String(), delAmt, - }, - }, - { - ContractABI: s.precompile.ABI, - MethodName: staking.RedelegateMethod, - Args: []interface{}{ - delegator.Addr, valAddr.String(), valAddr2.String(), delAmt, - }, - }, - } - - logCheckArgs := passCheck. - WithExpEvents(staking.EventTypeRedelegate) - - txArgs.GasLimit = 500_000 - for _, args := range redelegationsArgs { - _, _, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, args, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while creating redelegation: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - } - }) - - It("should return all redelegations for delegator (default pagination)", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - delegator.Addr, - "", - "", - query.PageRequest{}, - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var redelOut staking.RedelegationsOutput - err = s.precompile.UnpackIntoInterface(&redelOut, staking.RedelegationsMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) - - Expect(redelOut.PageResponse.NextKey).To(BeEmpty()) - Expect(redelOut.PageResponse.Total).To(Equal(redelTotalCount)) - - Expect(redelOut.Response).To(HaveLen(int(redelTotalCount)), "expected two redelegations to be returned") - // return order can change - redOrder := []int{0, 1} - if len(redelOut.Response[0].Entries) == 2 { - redOrder = []int{1, 0} - } - - for i, r := range redelOut.Response { - Expect(r.Entries).To(HaveLen(redOrder[i] + 1)) - } - }) - - It("should return all redelegations for delegator w/pagination", func() { - delegator := s.keyring.GetKey(0) - - // make 2 queries - // 1st one with pagination limit = 1 - // 2nd using the next page key - var nextPageKey []byte - for i := 0; i < 2; i++ { - var pagination query.PageRequest - if nextPageKey == nil { - pagination.Limit = 1 - pagination.CountTotal = true - } else { - pagination.Key = nextPageKey - } - callArgs.Args = []interface{}{ - delegator.Addr, - "", - "", - pagination, - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - var redelOut staking.RedelegationsOutput - err = s.precompile.UnpackIntoInterface(&redelOut, staking.RedelegationsMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) - - if nextPageKey == nil { - nextPageKey = redelOut.PageResponse.NextKey - Expect(redelOut.PageResponse.Total).To(Equal(redelTotalCount)) - } else { - Expect(redelOut.PageResponse.NextKey).To(BeEmpty()) - Expect(redelOut.PageResponse.Total).To(Equal(uint64(1))) - } - - Expect(redelOut.Response).To(HaveLen(1), "expected two redelegations to be returned") - // return order can change - redOrder := []int{0, 1} - if len(redelOut.Response[0].Entries) == 2 { - redOrder = []int{1, 0} - } - - for i, r := range redelOut.Response { - Expect(r.Entries).To(HaveLen(redOrder[i] + 1)) - } - } - }) - - It("should return an empty array if no redelegation is found for the given source validator", func() { - // NOTE: the way that the functionality is implemented in the Cosmos SDK, the following combinations are - // possible (see https://github.com/evmos/cosmos-sdk/blob/e773cf768844c87245d0c737cda1893a2819dd89/x/staking/keeper/querier.go#L361-L373): - // - // - delegator is NOT empty, source validator is empty, destination validator is empty - // --> filtering for all redelegations of the given delegator - // - delegator is empty, source validator is NOT empty, destination validator is empty - // --> filtering for all redelegations with the given source validator - // - delegator is NOT empty, source validator is NOT empty, destination validator is NOT empty - // --> filtering for all redelegations with the given combination of delegator, source and destination validator - callArgs.Args = []interface{}{ - common.Address{}, // passing in an empty address to filter for all redelegations from valAddr2 - valAddr2.String(), - "", - query.PageRequest{}, - } - - sender := s.keyring.GetKey(0) - _, ethRes, err := s.factory.CallContractAndCheckLogs( - sender.Priv, - txArgs, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "expected error while calling the smart contract") - - var redelOut staking.RedelegationsOutput - err = s.precompile.UnpackIntoInterface(&redelOut, staking.RedelegationsMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) - - Expect(redelOut.PageResponse.NextKey).To(BeEmpty()) - Expect(redelOut.PageResponse.Total).To(BeZero(), "expected no redelegations to be returned") - - Expect(redelOut.Response).To(HaveLen(0), "expected no redelegations to be returned") - }) - }) - - It("Should refund leftover gas", func() { - delegator := s.keyring.GetKey(0) - - resBal, err := s.grpcHandler.GetBalanceFromBank(delegator.AccAddr, s.bondDenom) - Expect(err).To(BeNil(), "error while getting balance") - balancePre := resBal.Balance - gasPrice := big.NewInt(1e9) - delAmt := big.NewInt(1e18) - - // Call the precompile with a lot of gas - callArgs.MethodName = staking.DelegateMethod - callArgs.Args = []interface{}{ - delegator.Addr, - valAddr.String(), - delAmt, - } - - txArgs.GasPrice = gasPrice - - logCheckArgs := passCheck. - WithExpEvents(staking.EventTypeDelegate) - - res, _, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - resBal, err = s.grpcHandler.GetBalanceFromBank(delegator.AccAddr, s.bondDenom) - Expect(err).To(BeNil(), "error while getting balance") - balancePost := resBal.Balance - difference := balancePre.Sub(*balancePost) - - // NOTE: the expected difference is the delegate amount plus the gas price multiplied by the gas used, because the rest should be refunded - expDifference := delAmt.Int64() + gasPrice.Int64()*res.GasUsed - Expect(difference.Amount.Int64()).To(Equal(expDifference), "expected different total transaction cost") - }) -}) - -var _ = Describe("Calling staking precompile via Solidity", Ordered, func() { - var ( - // s is the precompile test suite to use for the tests - s *PrecompileTestSuite - // contractAddr is the address of the smart contract that will be deployed - contractAddr common.Address - contractTwoAddr common.Address - stkReverterAddr common.Address - - // stakingCallerContract is the contract instance calling into the staking precompile - stakingCallerContract evmtypes.CompiledContract - stakingCallerTwoContract evmtypes.CompiledContract - stakingReverterContract evmtypes.CompiledContract - - // execRevertedCheck defines the default log checking arguments which include the - // standard revert message - execRevertedCheck testutil.LogCheckArgs - // err is a basic error type - err error - - // nonExistingAddr is an address that does not exist in the state of the test suite - nonExistingAddr = testutiltx.GenerateAddress() - // nonExistingVal is a validator address that does not exist in the state of the test suite - nonExistingVal = sdk.ValAddress(nonExistingAddr.Bytes()) - testContractInitialBalance = math.NewInt(1e18) - ) - - BeforeAll(func() { - stakingCallerContract, err = testdata.LoadStakingCallerContract() - Expect(err).To(BeNil()) - stakingCallerTwoContract, err = testdata.LoadStakingCallerTwoContract() - Expect(err).To(BeNil(), "error while loading the StakingCallerTwo contract") - stakingReverterContract, err = contracts.LoadStakingReverterContract() - Expect(err).To(BeNil(), "error while loading the StakingReverter contract") - }) - - BeforeEach(func() { - s = new(PrecompileTestSuite) - s.SetupTest() - delegator := s.keyring.GetKey(0) - - contractAddr, err = s.factory.DeployContract( - delegator.Priv, - evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values - factory.ContractDeploymentData{ - Contract: stakingCallerContract, - }, - ) - Expect(err).To(BeNil(), "error while deploying the smart contract: %v", err) - valAddr, err = sdk.ValAddressFromBech32(s.network.GetValidators()[0].GetOperator()) - Expect(err).To(BeNil()) - valAddr2, err = sdk.ValAddressFromBech32(s.network.GetValidators()[1].GetOperator()) - Expect(err).To(BeNil()) - - Expect(s.network.NextBlock()).To(BeNil()) - - // Deploy StakingCallerTwo contract - contractTwoAddr, err = s.factory.DeployContract( - delegator.Priv, - evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values - factory.ContractDeploymentData{ - Contract: stakingCallerTwoContract, - }, - ) - Expect(err).To(BeNil(), "error while deploying the StakingCallerTwo contract") - Expect(s.network.NextBlock()).To(BeNil()) - - // Deploy StakingReverter contract - stkReverterAddr, err = s.factory.DeployContract( - delegator.Priv, - evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values - factory.ContractDeploymentData{ - Contract: stakingReverterContract, - }, - ) - Expect(err).To(BeNil(), "error while deploying the StakingReverter contract") - Expect(s.network.NextBlock()).To(BeNil()) - - // send some funds to the StakingCallerTwo & StakingReverter contracts to transfer to the - // delegator during the tx - err := testutils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), contractTwoAddr.Bytes(), testContractInitialBalance) - Expect(err).To(BeNil(), "error while funding the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - err = testutils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), stkReverterAddr.Bytes(), testContractInitialBalance) - Expect(err).To(BeNil(), "error while funding the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - // check contract was correctly deployed - cAcc := s.network.App.EVMKeeper.GetAccount(s.network.GetContext(), contractAddr) - Expect(cAcc).ToNot(BeNil(), "contract account should exist") - Expect(cAcc.IsContract()).To(BeTrue(), "account should be a contract") - - // populate default TxArgs - txArgs.To = &contractAddr - // populate default call args - callArgs = factory.CallArgs{ - ContractABI: stakingCallerContract.ABI, - } - // populate default log check args - defaultLogCheck = testutil.LogCheckArgs{ - ABIEvents: s.precompile.Events, - } - execRevertedCheck = defaultLogCheck.WithErrContains(vm.ErrExecutionReverted.Error()) - passCheck = defaultLogCheck.WithExpPass(true) - }) - - Describe("when the precompile is not enabled in the EVM params", func() { - It("should return an error", func() { - delegator := s.keyring.GetKey(0) - - // disable the precompile - res, err := s.grpcHandler.GetEvmParams() - Expect(err).To(BeNil(), "error while setting params") - params := res.Params - var activePrecompiles []string - for _, precompile := range params.ActiveStaticPrecompiles { - if precompile != s.precompile.Address().String() { - activePrecompiles = append(activePrecompiles, precompile) - } - } - params.ActiveStaticPrecompiles = activePrecompiles - - err = testutils.UpdateEvmParams(testutils.UpdateParamsInput{ - Tf: s.factory, - Network: s.network, - Pk: delegator.Priv, - Params: params, - }) - Expect(err).To(BeNil(), "error while setting params") - - // try to call the precompile - callArgs.MethodName = "testDelegate" - callArgs.Args = []interface{}{ - valAddr.String(), - } - - txArgs.Amount = big.NewInt(1e9) - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - execRevertedCheck, - ) - Expect(err).To(BeNil(), "fails for other reason, I think general message like ") - }) - }) - - Context("create a validator", func() { - var ( - valPriv *ethsecp256k1.PrivKey - valAddr sdk.AccAddress - valHexAddr common.Address - - defaultDescription = staking.Description{ - Moniker: "new node", - Identity: "", - Website: "", - SecurityContact: "", - Details: "", - } - defaultCommission = staking.Commission{ - Rate: big.NewInt(100000000000000000), - MaxRate: big.NewInt(100000000000000000), - MaxChangeRate: big.NewInt(100000000000000000), - } - defaultMinSelfDelegation = big.NewInt(1) - defaultPubkeyBase64Str = GenerateBase64PubKey() - defaultValue = big.NewInt(1e8) - ) - - BeforeEach(func() { - callArgs.MethodName = "testCreateValidator" - valAddr, valPriv = testutiltx.NewAccAddressAndKey() - valHexAddr = common.BytesToAddress(valAddr.Bytes()) - err = testutils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), valAddr.Bytes(), math.NewInt(1e18)) - Expect(err).To(BeNil(), "error while funding account: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - }) - - It("tx from validator operator - should NOT create a validator", func() { - callArgs.Args = []interface{}{ - defaultDescription, defaultCommission, defaultMinSelfDelegation, valHexAddr, defaultPubkeyBase64Str, defaultValue, - } - - _, _, err = s.factory.CallContractAndCheckLogs( - valPriv, - txArgs, callArgs, - execRevertedCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract") - Expect(s.network.NextBlock()).To(BeNil()) - - qc := s.network.GetStakingClient() - _, err := qc.Validator(s.network.GetContext(), &stakingtypes.QueryValidatorRequest{ValidatorAddr: sdk.ValAddress(valAddr).String()}) - Expect(err).NotTo(BeNil(), "expected validator NOT to be found") - Expect(err.Error()).To(ContainSubstring("not found"), "expected validator NOT to be found") - }) - - It("tx from another EOA - should create a validator fail", func() { - callArgs.Args = []interface{}{ - defaultDescription, defaultCommission, defaultMinSelfDelegation, valHexAddr, defaultPubkeyBase64Str, defaultValue, - } - - _, _, err = s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, callArgs, - execRevertedCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract") - Expect(s.network.NextBlock()).To(BeNil()) - - qc := s.network.GetStakingClient() - _, err := qc.Validator(s.network.GetContext(), &stakingtypes.QueryValidatorRequest{ValidatorAddr: sdk.ValAddress(valAddr).String()}) - Expect(err).NotTo(BeNil(), "expected validator NOT to be found") - Expect(err.Error()).To(ContainSubstring("not found"), "expected validator NOT to be found") - }) - }) - - Context("to edit a validator", func() { - var ( - valPriv *ethsecp256k1.PrivKey - valAddr sdk.AccAddress - valHexAddr common.Address - - defaultDescription = staking.Description{ - Moniker: "edit node", - Identity: "[do-not-modify]", - Website: "[do-not-modify]", - SecurityContact: "[do-not-modify]", - Details: "[do-not-modify]", - } - defaultCommissionRate = big.NewInt(staking.DoNotModifyCommissionRate) - defaultMinSelfDelegation = big.NewInt(staking.DoNotModifyMinSelfDelegation) - - minSelfDelegation = big.NewInt(1) - - description = staking.Description{} - commission = staking.Commission{} - ) - - BeforeEach(func() { - callArgs.MethodName = "testEditValidator" - - // create a new validator - valAddr, valPriv = testutiltx.NewAccAddressAndKey() - valHexAddr = common.BytesToAddress(valAddr.Bytes()) - err = testutils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), valAddr.Bytes(), math.NewInt(2e18)) - Expect(err).To(BeNil(), "error while funding account: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - description = staking.Description{ - Moniker: "original moniker", - Identity: "", - Website: "", - SecurityContact: "", - Details: "", - } - commission = staking.Commission{ - Rate: big.NewInt(100000000000000000), - MaxRate: big.NewInt(100000000000000000), - MaxChangeRate: big.NewInt(100000000000000000), - } - pubkeyBase64Str := "UuhHQmkUh2cPBA6Rg4ei0M2B04cVYGNn/F8SAUsYIb4=" - value := big.NewInt(1e18) - - createValidatorArgs := factory.CallArgs{ - ContractABI: s.precompile.ABI, - MethodName: staking.CreateValidatorMethod, - Args: []interface{}{description, commission, minSelfDelegation, valHexAddr, pubkeyBase64Str, value}, - } - - logCheckArgs := passCheck.WithExpEvents(staking.EventTypeCreateValidator) - - toAddr := s.precompile.Address() - _, _, err = s.factory.CallContractAndCheckLogs( - valPriv, - evmtypes.EvmTxArgs{ - To: &toAddr, - }, - createValidatorArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract") - Expect(s.network.NextBlock()).To(BeNil()) - }) - - It("with tx from validator operator - should NOT edit a validator", func() { - callArgs.Args = []interface{}{ - defaultDescription, valHexAddr, - defaultCommissionRate, defaultMinSelfDelegation, - } - - _, _, err = s.factory.CallContractAndCheckLogs( - valPriv, - txArgs, - callArgs, - execRevertedCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract") - Expect(s.network.NextBlock()).To(BeNil()) - - qc := s.network.GetStakingClient() - qRes, err := qc.Validator(s.network.GetContext(), &stakingtypes.QueryValidatorRequest{ValidatorAddr: sdk.ValAddress(valAddr).String()}) - Expect(err).To(BeNil()) - Expect(qRes).NotTo(BeNil()) - validator := qRes.Validator - Expect(validator.Description.Moniker).NotTo(Equal(defaultDescription.Moniker), "expected validator moniker NOT to be updated") - }) - - It("with tx from another EOA - should fail", func() { - callArgs.Args = []interface{}{ - defaultDescription, valHexAddr, - defaultCommissionRate, defaultMinSelfDelegation, - } - - _, _, err = s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - callArgs, - execRevertedCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract") - Expect(s.network.NextBlock()).To(BeNil()) - - // validator should remain unchanged - qc := s.network.GetStakingClient() - qRes, err := qc.Validator(s.network.GetContext(), &stakingtypes.QueryValidatorRequest{ValidatorAddr: sdk.ValAddress(valAddr).String()}) - Expect(err).To(BeNil()) - Expect(qRes).NotTo(BeNil()) - - validator := qRes.Validator - Expect(validator.Description.Moniker).To(Equal("original moniker"), "expected validator moniker is updated") - Expect(validator.Commission.Rate.BigInt().String()).To(Equal("100000000000000000"), "expected validator commission rate remain unchanged") - }) - }) - - Context("delegating", func() { - // prevDelegation is the delegation that is available prior to the test (an initial delegation is - // added in the test suite setup). - var prevDelegation stakingtypes.Delegation - - BeforeEach(func() { - delegator := s.keyring.GetKey(0) - - txArgs.Amount = big.NewInt(1e18) - txArgs.GasLimit = 500_000 - - // initial delegation via contract - callArgs.MethodName = "testDelegate" - callArgs.Args = []interface{}{ - valAddr.String(), - } - - logCheckArgs := passCheck. - WithExpEvents(staking.EventTypeDelegate) - - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, - callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract") - Expect(s.network.NextBlock()).To(BeNil()) - - // get the delegation that is available prior to the test - contractAccAddr := sdk.AccAddress(contractAddr.Bytes()) - Expect(err).To(BeNil()) - res, err := s.grpcHandler.GetDelegation(contractAccAddr.String(), valAddr.String()) - Expect(err).To(BeNil()) - Expect(res.DelegationResponse).NotTo(BeNil()) - - prevDelegation = res.DelegationResponse.Delegation - }) - - Context("with native coin transfer", func() { - It("should delegate", func() { - delegator := s.keyring.GetKey(0) - - txArgs.Amount = big.NewInt(1e18) - - callArgs.Args = []interface{}{ - valAddr.String(), - } - - logCheckArgs := passCheck. - WithExpEvents(staking.EventTypeDelegate) - - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - contractAccAddr := sdk.AccAddress(contractAddr.Bytes()) - res, err := s.grpcHandler.GetDelegation(contractAccAddr.String(), valAddr.String()) - Expect(err).To(BeNil()) - Expect(res.DelegationResponse).NotTo(BeNil()) - delegation := res.DelegationResponse.Delegation - - expShares := prevDelegation.GetShares().Add(math.LegacyNewDec(1)) - Expect(delegation.GetShares()).To(Equal(expShares), "expected delegation shares to be 2") - }) - - Context("Calling the precompile from the StakingReverter contract", func() { - var ( - txSenderInitialBal *sdk.Coin - contractInitialBalance *sdk.Coin - gasPrice = math.NewInt(1e9) - ) - - BeforeEach(func() { - balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - txSenderInitialBal = balRes.Balance - balRes, err = s.grpcHandler.GetBalanceFromBank(stkReverterAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - contractInitialBalance = balRes.Balance - }) - - It("should revert the changes and NOT delegate - successful tx", func() { - callArgs := factory.CallArgs{ - ContractABI: stakingReverterContract.ABI, - MethodName: "run", - Args: []interface{}{ - big.NewInt(5), s.network.GetValidators()[0].OperatorAddress, - }, - } - - // Tx should be successful, but no state changes happened - res, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - evmtypes.EvmTxArgs{ - To: &stkReverterAddr, - GasPrice: gasPrice.BigInt(), - }, - callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - fees := gasPrice.MulRaw(res.GasUsed) - - // contract balance should remain unchanged - balRes, err := s.grpcHandler.GetBalanceFromBank(stkReverterAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - contractFinalBalance := balRes.Balance - Expect(contractFinalBalance.Amount).To(Equal(contractInitialBalance.Amount)) - - // No delegation should be created - _, err = s.grpcHandler.GetDelegation(sdk.AccAddress(stkReverterAddr.Bytes()).String(), s.network.GetValidators()[0].OperatorAddress) - Expect(err).NotTo(BeNil()) - Expect(err.Error()).To(ContainSubstring("not found"), "expected NO delegation created") - - // Only fees deducted on tx sender - balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - txSenderFinalBal := balRes.Balance - Expect(txSenderFinalBal.Amount).To(Equal(txSenderInitialBal.Amount.Sub(fees))) - }) - - It("should revert the changes and NOT delegate - failed tx - max precompile calls reached", func() { - callArgs := factory.CallArgs{ - ContractABI: stakingReverterContract.ABI, - MethodName: "multipleDelegations", - Args: []interface{}{ - big.NewInt(int64(evmtypes.MaxPrecompileCalls + 2)), s.network.GetValidators()[0].OperatorAddress, - }, - } - - // Tx should fail due to MaxPrecompileCalls - _, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - evmtypes.EvmTxArgs{ - To: &stkReverterAddr, - GasPrice: gasPrice.BigInt(), - }, - callArgs, - execRevertedCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - // contract balance should remain unchanged - balRes, err := s.grpcHandler.GetBalanceFromBank(stkReverterAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - contractFinalBalance := balRes.Balance - Expect(contractFinalBalance.Amount).To(Equal(contractInitialBalance.Amount)) - - // No delegation should be created - _, err = s.grpcHandler.GetDelegation(sdk.AccAddress(stkReverterAddr.Bytes()).String(), s.network.GetValidators()[0].OperatorAddress) - Expect(err).NotTo(BeNil()) - Expect(err.Error()).To(ContainSubstring("not found"), "expected NO delegation created") - }) - }) - - Context("Table-driven tests for Delegate method", func() { - // testCase is a struct used for cases of contracts calls that have some operation - // performed before and/or after the precompile call - type testCase struct { - before bool - after bool - } - - var ( - args factory.CallArgs - delegatorInitialBal *sdk.Coin - contractInitialBalance *sdk.Coin - bondedTokensPoolInitialBalance *sdk.Coin - delAmt = math.NewInt(1e18) - gasPrice = math.NewInt(1e9) - bondedTokensPoolAccAddr = authtypes.NewModuleAddress("bonded_tokens_pool") - ) - - BeforeEach(func() { - balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - delegatorInitialBal = balRes.Balance - balRes, err = s.grpcHandler.GetBalanceFromBank(contractTwoAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - contractInitialBalance = balRes.Balance - balRes, err = s.grpcHandler.GetBalanceFromBank(bondedTokensPoolAccAddr, s.bondDenom) - Expect(err).To(BeNil()) - bondedTokensPoolInitialBalance = balRes.Balance - - args.ContractABI = stakingCallerTwoContract.ABI - args.MethodName = "testDelegateWithCounterAndTransfer" - }) - - DescribeTable("should delegate and update balances accordingly", func(tc testCase) { - args.Args = []interface{}{ - valAddr.String(), tc.before, tc.after, - } - - // This is the amount of tokens transferred from the contract to the delegator - // during the contract call - transferToDelAmt := math.ZeroInt() - for _, transferred := range []bool{tc.before, tc.after} { - if transferred { - transferToDelAmt = transferToDelAmt.AddRaw(15) - } - } - - logCheckArgs := passCheck. - WithExpEvents(staking.EventTypeDelegate) - - txArgs := evmtypes.EvmTxArgs{ - To: &contractTwoAddr, - GasPrice: gasPrice.BigInt(), - GasLimit: 500_000, - Amount: delAmt.BigInt(), - } - - res, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - args, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - fees := gasPrice.MulRaw(res.GasUsed) - - // check the contract's balance was deducted to fund the vesting account - balRes, err := s.grpcHandler.GetBalanceFromBank(contractTwoAddr.Bytes(), s.bondDenom) - contractFinalBal := balRes.Balance - Expect(err).To(BeNil()) - Expect(contractFinalBal.Amount).To(Equal(contractInitialBalance.Amount.Sub(transferToDelAmt))) - - contractTwoAccAddr := sdk.AccAddress(contractTwoAddr.Bytes()) - qRes, err := s.grpcHandler.GetDelegation(contractTwoAccAddr.String(), valAddr.String()) - Expect(err).To(BeNil()) - Expect(qRes).NotTo(BeNil(), "expected delegation to be found") - delegation := qRes.DelegationResponse.Delegation - expShares := math.LegacyZeroDec().Add(math.LegacyNewDec(1)) - Expect(delegation.GetShares()).To(Equal(expShares), "expected delegation shares to be 2") - - balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) - Expect(err).To(BeNil()) - delegatorFinalBal := balRes.Balance - Expect(delegatorFinalBal.Amount).To(Equal(delegatorInitialBal.Amount.Sub(fees).Sub(delAmt).Add(transferToDelAmt))) - - // check the bondedTokenPool is updated with the delegated tokens - balRes, err = s.grpcHandler.GetBalanceFromBank(bondedTokensPoolAccAddr, s.bondDenom) - bondedTokensPoolFinalBalance := balRes.Balance - Expect(err).To(BeNil()) - Expect(bondedTokensPoolFinalBalance.Amount).To(Equal(bondedTokensPoolInitialBalance.Amount.Add(delAmt))) - }, - Entry("contract tx with transfer to delegator before and after precompile call ", testCase{ - before: true, - after: true, - }), - Entry("contract tx with transfer to delegator before precompile call ", testCase{ - before: true, - after: false, - }), - Entry("contract tx with transfer to delegator after precompile call ", testCase{ - before: false, - after: true, - }), - ) - - It("should NOT delegate and update balances accordingly - internal transfer to tokens pool", func() { - args.MethodName = "testDelegateWithTransfer" - args.Args = []interface{}{ - common.BytesToAddress(bondedTokensPoolAccAddr), - s.keyring.GetAddr(0), valAddr.String(), true, true, - } - - txArgs.Amount = delAmt.BigInt() - _, _, err := s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - txArgs, - args, - execRevertedCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - // contract balance should remain unchanged - balRes, err := s.grpcHandler.GetBalanceFromBank(contractTwoAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil()) - contractFinalBal := balRes.Balance - Expect(contractFinalBal.Amount).To(Equal(contractInitialBalance.Amount)) - - // check the bondedTokenPool should remain unchanged - balRes, err = s.grpcHandler.GetBalanceFromBank(bondedTokensPoolAccAddr, s.bondDenom) - Expect(err).To(BeNil()) - bondedTokensPoolFinalBalance := balRes.Balance - Expect(bondedTokensPoolFinalBalance.Amount).To(Equal(bondedTokensPoolInitialBalance.Amount)) - }) - }) - - It("should not delegate when validator does not exist", func() { - delegator := s.keyring.GetKey(0) - - txArgs.Amount = big.NewInt(1e18) - - callArgs.Args = []interface{}{ - nonExistingVal.String(), - } - - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - execRevertedCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - contractAccAddr := sdk.AccAddress(contractAddr.Bytes()) - res, err := s.grpcHandler.GetDelegation(contractAccAddr.String(), nonExistingVal.String()) - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("delegation with delegator %s not found for validator %s", contractAccAddr.String(), nonExistingVal.String()))) - Expect(res).To(BeNil()) - }) - }) - }) - - Context("unbonding", func() { - var contractAccAddr sdk.AccAddress - - BeforeEach(func() { - contractAccAddr = sdk.AccAddress(contractAddr.Bytes()) - - callArgs.MethodName = "testUndelegate" - - // delegate to undelegate - _, _, err = s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - evmtypes.EvmTxArgs{ - To: &contractAddr, - Amount: big.NewInt(1e18), - GasPrice: big.NewInt(1e9), - GasLimit: 500_000, - }, - factory.CallArgs{ - ContractABI: stakingCallerContract.ABI, - MethodName: "testDelegate", - Args: []interface{}{ - valAddr.String(), - }, - }, - passCheck.WithExpEvents(staking.EventTypeDelegate), - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - txArgs.GasLimit = 500_000 - txArgs.Amount = big.NewInt(0) - }) - - It("should undelegate", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - valAddr.String(), big.NewInt(1e18), - } - - logCheckArgs := defaultLogCheck. - WithExpEvents(staking.EventTypeUnbond). - WithExpPass(true) - - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - logCheckArgs) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(contractAccAddr.String()) - Expect(err).To(BeNil()) - Expect(res.UnbondingResponses).To(HaveLen(1), "expected one undelegation") - Expect(res.UnbondingResponses[0].ValidatorAddress).To(Equal(valAddr.String()), "expected validator address to be %s", valAddr) - }) - - It("should not undelegate if the delegation does not exist", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - nonExistingVal.String(), big.NewInt(1e18), - } - - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - execRevertedCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(contractAccAddr.String()) - Expect(err).To(BeNil()) - Expect(res.UnbondingResponses).To(BeEmpty()) - }) - - It("should not undelegate when called from a different address", func() { - delegator := s.keyring.GetKey(0) - differentSender := s.keyring.GetKey(1) - - callArgs.Args = []interface{}{ - valAddr.String(), big.NewInt(1e18), - } - - _, _, err = s.factory.CallContractAndCheckLogs( - differentSender.Priv, - txArgs, callArgs, - execRevertedCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(delegator.AccAddr.String()) - Expect(err).To(BeNil()) - Expect(res.UnbondingResponses).To(BeEmpty()) - }) - }) - - Context("redelegating", func() { - var contractAccAddr sdk.AccAddress - - BeforeEach(func() { - contractAccAddr = sdk.AccAddress(contractAddr.Bytes()) - - callArgs.MethodName = "testRedelegate" - - // delegate to redelegate - _, _, err = s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - evmtypes.EvmTxArgs{ - To: &contractAddr, - Amount: big.NewInt(1e18), - GasPrice: big.NewInt(1e9), - GasLimit: 500_000, - }, - factory.CallArgs{ - ContractABI: stakingCallerContract.ABI, - MethodName: "testDelegate", - Args: []interface{}{ - valAddr.String(), - }, - }, - passCheck.WithExpEvents(staking.EventTypeDelegate), - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - txArgs.GasLimit = 500_000 - txArgs.Amount = big.NewInt(0) - }) - - It("should redelegate", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - valAddr.String(), valAddr2.String(), big.NewInt(1e18), - } - - logCheckArgs := defaultLogCheck. - WithExpEvents(staking.EventTypeRedelegate). - WithExpPass(true) - - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - res, err := s.grpcHandler.GetRedelegations(contractAccAddr.String(), valAddr.String(), valAddr2.String()) - Expect(err).To(BeNil()) - Expect(res.RedelegationResponses).To(HaveLen(1), "expected one redelegation to be found") - Expect(res.RedelegationResponses[0].Redelegation.DelegatorAddress).To(Equal(contractAccAddr.String()), "expected delegator address to be %s", contractAccAddr) - Expect(res.RedelegationResponses[0].Redelegation.ValidatorSrcAddress).To(Equal(valAddr.String()), "expected source validator address to be %s", valAddr) - Expect(res.RedelegationResponses[0].Redelegation.ValidatorDstAddress).To(Equal(valAddr2.String()), "expected destination validator address to be %s", valAddr2) - }) - - It("should not redelegate if the delegation does not exist", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - nonExistingVal.String(), valAddr2.String(), big.NewInt(1e18), - } - - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - execRevertedCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - res, err := s.grpcHandler.GetRedelegations(contractAccAddr.String(), nonExistingVal.String(), valAddr2.String()) - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("redelegation not found for delegator address %s from validator address %s", contractAccAddr, nonExistingVal))) - Expect(res).To(BeNil(), "expected no redelegations to be found") - }) - - It("should not redelegate when calling from a different address", func() { - differentSender := s.keyring.GetKey(1) - - callArgs.Args = []interface{}{ - valAddr.String(), valAddr2.String(), big.NewInt(1e18), - } - - _, _, err = s.factory.CallContractAndCheckLogs( - differentSender.Priv, - txArgs, callArgs, - execRevertedCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - res, err := s.grpcHandler.GetRedelegations(contractAccAddr.String(), valAddr.String(), valAddr2.String()) - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("redelegation not found for delegator address %s from validator address %s", contractAccAddr, valAddr))) - Expect(res).To(BeNil(), "expected no redelegations to be found") - }) - - It("should not redelegate when the validator does not exist", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - valAddr.String(), nonExistingVal.String(), big.NewInt(1e18), - } - - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - execRevertedCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - res, err := s.grpcHandler.GetRedelegations(contractAccAddr.String(), valAddr.String(), nonExistingVal.String()) - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("redelegation not found for delegator address %s from validator address %s", contractAccAddr, valAddr))) - Expect(res).To(BeNil()) - }) - }) - - Context("canceling unbonding delegations", func() { - // expCreationHeight is the expected creation height of the unbonding delegation - var expCreationHeight int64 - var contractAccAddr sdk.AccAddress - - BeforeEach(func() { - contractAccAddr = sdk.AccAddress(contractAddr.Bytes()) - - callArgs.MethodName = "testCancelUnbonding" - - // delegate to undelegate - _, _, err = s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - evmtypes.EvmTxArgs{ - To: &contractAddr, - Amount: big.NewInt(1e18), - GasPrice: big.NewInt(1e9), - GasLimit: 500_000, - }, - factory.CallArgs{ - ContractABI: stakingCallerContract.ABI, - MethodName: "testDelegate", - Args: []interface{}{ - valAddr.String(), - }, - }, - passCheck.WithExpEvents(staking.EventTypeDelegate), - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil(), "failed to advance block") - - // undelegate to cancel unbonding - delegator := s.keyring.GetKey(0) - txArgs.Amount = big.NewInt(0) - undelegateArgs := factory.CallArgs{ - ContractABI: stakingCallerContract.ABI, - MethodName: "testUndelegate", - Args: []interface{}{valAddr.String(), big.NewInt(1e18)}, - } - - logCheckArgs := defaultLogCheck. - WithExpEvents(staking.EventTypeUnbond). - WithExpPass(true) - - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, undelegateArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while setting up an unbonding delegation: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - expCreationHeight = s.network.GetContext().BlockHeight() - // Check that the unbonding delegation was created - res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(contractAccAddr.String()) - Expect(err).To(BeNil()) - Expect(res.UnbondingResponses).To(HaveLen(1), "expected one unbonding delegation to be found") - Expect(res.UnbondingResponses[0].DelegatorAddress).To(Equal(contractAccAddr.String()), "expected delegator address to be %s", contractAccAddr) - Expect(res.UnbondingResponses[0].ValidatorAddress).To(Equal(valAddr.String()), "expected validator address to be %s", valAddr) - Expect(res.UnbondingResponses[0].Entries).To(HaveLen(1), "expected one unbonding delegation entry to be found") - Expect(res.UnbondingResponses[0].Entries[0].CreationHeight).To(Equal(expCreationHeight), "expected different creation height") - Expect(res.UnbondingResponses[0].Entries[0].Balance).To(Equal(math.NewInt(1e18)), "expected different balance") - }) - - It("should cancel unbonding delegations", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - valAddr.String(), big.NewInt(1e18), big.NewInt(expCreationHeight), - } - - txArgs.GasLimit = 1e9 - - logCheckArgs := passCheck. - WithExpEvents(staking.EventTypeCancelUnbondingDelegation) - - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - logCheckArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(contractAccAddr.String()) - Expect(err).To(BeNil()) - Expect(res.UnbondingResponses).To(BeEmpty(), "expected unbonding delegation to be canceled") - }) - - It("should not cancel unbonding any delegations when unbonding delegation does not exist", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - nonExistingVal.String(), - big.NewInt(1e18), - big.NewInt(expCreationHeight), - } - - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, - callArgs, - execRevertedCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(contractAccAddr.String()) - Expect(err).To(BeNil()) - Expect(res.UnbondingResponses).To(HaveLen(1), "expected unbonding delegation to not be canceled") - }) - }) - - Context("querying validator", func() { - BeforeEach(func() { - callArgs.MethodName = "getValidator" - }) - It("with non-existing address should return an empty validator", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - nonExistingAddr, - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var valOut staking.ValidatorOutput - err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) - Expect(valOut.Validator.OperatorAddress).To(Equal(""), "expected empty validator address") - Expect(valOut.Validator.Status).To(Equal(uint8(0)), "expected validator status to be 0 (unspecified)") - }) - - It("with existing address should return the validator", func() { - delegator := s.keyring.GetKey(0) - - valHexAddr := common.BytesToAddress(valAddr.Bytes()) - callArgs.Args = []interface{}{valHexAddr} - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var valOut staking.ValidatorOutput - err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) - Expect(valOut.Validator.OperatorAddress).To(Equal(valHexAddr.String()), "expected validator address to match") - Expect(valOut.Validator.DelegatorShares).To(Equal(big.NewInt(1e18)), "expected different delegator shares") - }) - - It("with status bonded and pagination", func() { - delegator := s.keyring.GetKey(0) - - callArgs.MethodName = "getValidators" - callArgs.Args = []interface{}{ - stakingtypes.Bonded.String(), - query.PageRequest{ - Limit: 1, - CountTotal: true, - }, - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var valOut staking.ValidatorsOutput - err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorsMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) - Expect(valOut.PageResponse.Total).To(Equal(uint64(len(s.network.GetValidators())))) - Expect(valOut.PageResponse.NextKey).NotTo(BeEmpty()) - Expect(valOut.Validators[0].DelegatorShares).To(Equal(big.NewInt(1e18)), "expected different delegator shares") - }) - }) - - Context("querying validators", func() { - BeforeEach(func() { - callArgs.MethodName = "getValidators" - }) - It("should return validators (default pagination)", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - stakingtypes.Bonded.String(), - query.PageRequest{}, - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var valOut staking.ValidatorsOutput - err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorsMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) - Expect(valOut.PageResponse.Total).To(Equal(uint64(len(s.network.GetValidators())))) - Expect(valOut.PageResponse.NextKey).To(BeEmpty()) - Expect(valOut.Validators).To(HaveLen(len(s.network.GetValidators())), "expected all validators to be returned") - // return order can change, that's why each validator is checked individually - for _, val := range valOut.Validators { - s.CheckValidatorOutput(val) - } - }) - - //nolint:dupl // this is a duplicate of the test for EOA calls to the precompile - It("should return validators with pagination limit = 1", func() { - const limit uint64 = 1 - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - stakingtypes.Bonded.String(), - query.PageRequest{ - Limit: limit, - CountTotal: true, - }, - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var valOut staking.ValidatorsOutput - err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorsMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) - - // no pagination, should return default values - Expect(valOut.PageResponse.NextKey).NotTo(BeEmpty()) - Expect(valOut.PageResponse.Total).To(Equal(uint64(len(s.network.GetValidators())))) - - Expect(valOut.Validators).To(HaveLen(int(limit)), "expected one validator to be returned") - - // return order can change, that's why each validator is checked individually - for _, val := range valOut.Validators { - s.CheckValidatorOutput(val) - } - }) - - It("should revert the execution if the bonding type is not known", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - "15", // invalid bonding type - query.PageRequest{}, - } - - _, _, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - execRevertedCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - }) - - It("should return an empty array if there are no validators with the given bonding type", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - stakingtypes.Unbonded.String(), - query.PageRequest{}, - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var valOut staking.ValidatorsOutput - err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorsMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) - - Expect(valOut.PageResponse.NextKey).To(BeEmpty()) - Expect(valOut.PageResponse.Total).To(Equal(uint64(0))) - Expect(valOut.Validators).To(HaveLen(0), "expected no validators to be returned") - }) - }) - - Context("querying delegation", func() { - BeforeEach(func() { - callArgs.MethodName = "getDelegation" - }) - It("which does not exist should return an empty delegation", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - nonExistingAddr, valAddr.String(), - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var delOut staking.DelegationOutput - err = s.precompile.UnpackIntoInterface(&delOut, staking.DelegationMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the delegation output: %v", err) - Expect(delOut.Balance.Amount.Int64()).To(Equal(int64(0)), "expected a different delegation balance") - Expect(delOut.Balance.Denom).To(Equal(cosmosevmutil.ExampleAttoDenom), "expected a different delegation balance") - }) - - It("which exists should return the delegation", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - delegator.Addr, valAddr.String(), - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var delOut staking.DelegationOutput - err = s.precompile.UnpackIntoInterface(&delOut, staking.DelegationMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the delegation output: %v", err) - Expect(delOut.Balance).To(Equal( - cmn.Coin{Denom: cosmosevmutil.ExampleAttoDenom, Amount: big.NewInt(1e18)}), - "expected a different delegation balance", - ) - }) - }) - - Context("querying redelegation", func() { - var contractAccAddr sdk.AccAddress - - BeforeEach(func() { - callArgs.MethodName = "getRedelegation" - contractAccAddr = sdk.AccAddress(contractAddr.Bytes()) - - // delegate to redelegate - _, _, err = s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - evmtypes.EvmTxArgs{ - To: &contractAddr, - Amount: big.NewInt(1e18), - GasPrice: big.NewInt(1e9), - GasLimit: 500_000, - }, - factory.CallArgs{ - ContractABI: stakingCallerContract.ABI, - MethodName: "testDelegate", - Args: []interface{}{ - valAddr.String(), - }, - }, - passCheck.WithExpEvents(staking.EventTypeDelegate), - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil(), "failed to advance block") - }) - - It("which does not exist should return an empty redelegation", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - delegator.Addr, valAddr.String(), nonExistingVal.String(), - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var redOut staking.RedelegationOutput - err = s.precompile.UnpackIntoInterface(&redOut, staking.RedelegationMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the redelegation output: %v", err) - Expect(redOut.Redelegation.Entries).To(HaveLen(0), "expected no redelegation entries") - }) - - It("which exists should return the redelegation", func() { - delegator := s.keyring.GetKey(0) - - // set up redelegation - redelegateArgs := factory.CallArgs{ - ContractABI: stakingCallerContract.ABI, - MethodName: "testRedelegate", - Args: []interface{}{valAddr.String(), valAddr2.String(), big.NewInt(1)}, - } - - redelegateCheck := passCheck. - WithExpEvents(staking.EventTypeRedelegate) - - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, redelegateArgs, - redelegateCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - // check that the redelegation was created - res, err := s.grpcHandler.GetRedelegations(contractAccAddr.String(), valAddr.String(), valAddr2.String()) - Expect(err).To(BeNil()) - Expect(res.RedelegationResponses).To(HaveLen(1), "expected one redelegation to be found") - bech32Addr := contractAccAddr - Expect(res.RedelegationResponses[0].Redelegation.DelegatorAddress).To(Equal(bech32Addr.String()), "expected delegator address to be %s", contractAddr) - Expect(res.RedelegationResponses[0].Redelegation.ValidatorSrcAddress).To(Equal(valAddr.String()), "expected source validator address to be %s", valAddr) - Expect(res.RedelegationResponses[0].Redelegation.ValidatorDstAddress).To(Equal(valAddr2.String()), "expected destination validator address to be %s", valAddr2) - - // query redelegation - callArgs.Args = []interface{}{ - contractAddr, valAddr.String(), valAddr2.String(), - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var redOut staking.RedelegationOutput - err = s.precompile.UnpackIntoInterface(&redOut, staking.RedelegationMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the redelegation output: %v", err) - Expect(redOut.Redelegation.Entries).To(HaveLen(1), "expected one redelegation entry to be returned") - }) - }) - - Describe("query redelegations", func() { - var contractAccAddr sdk.AccAddress - - BeforeEach(func() { - contractAccAddr = sdk.AccAddress(contractAddr.Bytes()) - - callArgs.MethodName = "getRedelegations" - - // delegate to redelegate - _, _, err = s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - evmtypes.EvmTxArgs{ - To: &contractAddr, - Amount: big.NewInt(1e18), - GasPrice: big.NewInt(1e9), - GasLimit: 500_000, - }, - factory.CallArgs{ - ContractABI: stakingCallerContract.ABI, - MethodName: "testDelegate", - Args: []interface{}{ - valAddr.String(), - }, - }, - passCheck.WithExpEvents(staking.EventTypeDelegate), - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil(), "failed to advance block") - }) - - It("which exists should return all the existing redelegations w/pagination", func() { - delegator := s.keyring.GetKey(0) - - // set up redelegation - redelegateArgs := factory.CallArgs{ - ContractABI: stakingCallerContract.ABI, - MethodName: "testRedelegate", - Args: []interface{}{valAddr.String(), valAddr2.String(), big.NewInt(1)}, - } - - redelegateCheck := passCheck. - WithExpEvents(staking.EventTypeRedelegate) - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, redelegateArgs, - redelegateCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - // check that the redelegation was created - res, err := s.grpcHandler.GetRedelegations(contractAccAddr.String(), valAddr.String(), valAddr2.String()) - Expect(err).To(BeNil()) - Expect(res.RedelegationResponses).To(HaveLen(1), "expected one redelegation to be found") - bech32Addr := contractAccAddr - Expect(res.RedelegationResponses[0].Redelegation.DelegatorAddress).To(Equal(bech32Addr.String()), "expected delegator address to be %s", contractAccAddr) - Expect(res.RedelegationResponses[0].Redelegation.ValidatorSrcAddress).To(Equal(valAddr.String()), "expected source validator address to be %s", valAddr) - Expect(res.RedelegationResponses[0].Redelegation.ValidatorDstAddress).To(Equal(valAddr2.String()), "expected destination validator address to be %s", valAddr2) - - // query redelegations by delegator address - callArgs.Args = []interface{}{ - contractAddr, "", "", query.PageRequest{Limit: 1, CountTotal: true}, - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - passCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - var redOut staking.RedelegationsOutput - err = s.precompile.UnpackIntoInterface(&redOut, staking.RedelegationsMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the redelegation output: %v", err) - Expect(redOut.Response).To(HaveLen(1), "expected one redelegation entry to be returned") - Expect(redOut.Response[0].Entries).To(HaveLen(1), "expected one redelegation entry to be returned") - Expect(redOut.PageResponse.Total).To(Equal(uint64(1))) - Expect(redOut.PageResponse.NextKey).To(BeEmpty()) - }) - }) - - Context("querying unbonding delegation", func() { - var contractAccAddr sdk.AccAddress - - BeforeEach(func() { - delegator := s.keyring.GetKey(0) - contractAccAddr = sdk.AccAddress(contractAddr.Bytes()) - - callArgs.MethodName = "getUnbondingDelegation" - - // delegate to redelegate - _, _, err = s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - evmtypes.EvmTxArgs{ - To: &contractAddr, - Amount: big.NewInt(1e18), - GasPrice: big.NewInt(1e9), - GasLimit: 500_000, - }, - factory.CallArgs{ - ContractABI: stakingCallerContract.ABI, - MethodName: "testDelegate", - Args: []interface{}{ - valAddr.String(), - }, - }, - passCheck.WithExpEvents(staking.EventTypeDelegate), - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil(), "failed to advance block") - - // undelegate - undelegateArgs := factory.CallArgs{ - ContractABI: stakingCallerContract.ABI, - MethodName: "testUndelegate", - Args: []interface{}{valAddr.String(), big.NewInt(1e18)}, - } - - logCheckArgs := passCheck. - WithExpEvents(staking.EventTypeUnbond) - - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, undelegateArgs, logCheckArgs) - Expect(err).To(BeNil(), "error while setting up an unbonding delegation: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - // Check that the unbonding delegation was created - res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(contractAccAddr.String()) - Expect(err).To(BeNil()) - Expect(res.UnbondingResponses).To(HaveLen(1), "expected one unbonding delegation to be found") - Expect(res.UnbondingResponses[0].DelegatorAddress).To(Equal(contractAccAddr.String()), "expected delegator address to be %s", contractAddr) - Expect(res.UnbondingResponses[0].ValidatorAddress).To(Equal(valAddr.String()), "expected validator address to be %s", valAddr) - Expect(res.UnbondingResponses[0].Entries).To(HaveLen(1), "expected one unbonding delegation entry to be found") - Expect(res.UnbondingResponses[0].Entries[0].CreationHeight).To(Equal(s.network.GetContext().BlockHeight()), "expected different creation height") - Expect(res.UnbondingResponses[0].Entries[0].Balance).To(Equal(math.NewInt(1e18)), "expected different balance") - }) - - It("which does not exist should return an empty unbonding delegation", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - delegator.Addr, valAddr2.String(), - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, passCheck) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var unbondingDelegationOutput staking.UnbondingDelegationOutput - err = s.precompile.UnpackIntoInterface(&unbondingDelegationOutput, staking.UnbondingDelegationMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the unbonding delegation output: %v", err) - Expect(unbondingDelegationOutput.UnbondingDelegation.Entries).To(HaveLen(0), "expected one unbonding delegation entry") - }) - - It("which exists should return the unbonding delegation", func() { - delegator := s.keyring.GetKey(0) - - callArgs.Args = []interface{}{ - contractAddr, valAddr.String(), - } - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, passCheck) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - - var unbondOut staking.UnbondingDelegationOutput - err = s.precompile.UnpackIntoInterface(&unbondOut, staking.UnbondingDelegationMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the unbonding delegation output: %v", err) - Expect(unbondOut.UnbondingDelegation.Entries).To(HaveLen(1), "expected one unbonding delegation entry to be returned") - Expect(unbondOut.UnbondingDelegation.Entries[0].Balance).To(Equal(big.NewInt(1e18)), "expected different balance") - }) - }) - - Context("when using special call opcodes", func() { - var contractAccAddr sdk.AccAddress - - BeforeEach(func() { - contractAccAddr = sdk.AccAddress(contractAddr.Bytes()) - - // delegate to undelegate - _, _, err = s.factory.CallContractAndCheckLogs( - s.keyring.GetPrivKey(0), - evmtypes.EvmTxArgs{ - To: &contractAddr, - Amount: big.NewInt(1e18), - GasPrice: big.NewInt(1e9), - GasLimit: 500_000, - }, - factory.CallArgs{ - ContractABI: stakingCallerContract.ABI, - MethodName: "testDelegate", - Args: []interface{}{ - valAddr2.String(), - }, - }, - passCheck.WithExpEvents(staking.EventTypeDelegate), - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil(), "failed to advance block") - }) - - testcases := []struct { - // calltype is the opcode to use - calltype string - // expTxPass defines if executing transactions should be possible with the given opcode. - // Queries should work for all options. - expTxPass bool - }{ - {"call", true}, - // {"callcode", false}, //todo: fix this - stops working after bech32 prefix changes off of evmos - the validator being sent in as arg contains a wrong checksum - {"staticcall", false}, - {"delegatecall", false}, - } - - for _, tc := range testcases { - // NOTE: this is necessary because of Ginkgo behavior -- if not done, the value of tc - // inside the It block will always be the last entry in the testcases slice - testcase := tc - - It(fmt.Sprintf("should not execute transactions for calltype %q", testcase.calltype), func() { - delegator := s.keyring.GetKey(0) - - callArgs.MethodName = "testCallUndelegate" - callArgs.Args = []interface{}{ - valAddr2.String(), big.NewInt(1e18), testcase.calltype, - } - - checkArgs := execRevertedCheck - if testcase.expTxPass { - checkArgs = passCheck.WithExpEvents(staking.EventTypeUnbond) - } - - _, _, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - checkArgs, - ) - Expect(err).To(BeNil(), "error while calling the smart contract for calltype %s: %v", testcase.calltype, err) - Expect(s.network.NextBlock()).To(BeNil()) - - // check no delegations are unbonding - res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(contractAccAddr.String()) - Expect(err).To(BeNil()) - - if testcase.expTxPass { - Expect(res.UnbondingResponses).To(HaveLen(1), "expected an unbonding delegation") - Expect(res.UnbondingResponses[0].ValidatorAddress).To(Equal(valAddr2.String()), "expected different validator address") - Expect(res.UnbondingResponses[0].DelegatorAddress).To(Equal(contractAccAddr.String()), "expected different delegator address") - } else { - Expect(res.UnbondingResponses).To(HaveLen(0), "expected no unbonding delegations for calltype %s", testcase.calltype) - } - }) - - It(fmt.Sprintf("should execute queries for calltype %q", testcase.calltype), func() { - delegator := s.keyring.GetKey(0) - - callArgs.MethodName = "testCallDelegation" - callArgs.Args = []interface{}{contractAddr, valAddr2.String(), testcase.calltype} - - _, ethRes, err := s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, passCheck) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - var delOut staking.DelegationOutput - err = s.precompile.UnpackIntoInterface(&delOut, staking.DelegationMethod, ethRes.Ret) - Expect(err).To(BeNil(), "error while unpacking the delegation output: %v", err) - Expect(delOut.Shares).To(Equal(math.LegacyNewDec(1).BigInt()), "expected different delegation shares") - Expect(delOut.Balance.Amount).To(Equal(big.NewInt(1e18)), "expected different delegation balance") - if testcase.calltype != "callcode" { // having some trouble with returning the denom from inline assembly but that's a very special edge case which might never be used - Expect(delOut.Balance.Denom).To(Equal(s.bondDenom), "expected different denomination") - } - }) - } - }) - - // NOTE: These tests were added to replicate a problematic behavior, that occurred when a contract - // adjusted the state in multiple subsequent function calls, which adjusted the EVM state as well as - // things from the Cosmos SDK state (e.g. a bank balance). - // The result was, that changes made to the Cosmos SDK state have been overwritten during the next function - // call, because the EVM state was not updated in between. - // - // This behavior was fixed by updating the EVM state after each function call. - Context("when triggering multiple state changes in one function", func() { - // delegationAmount is the amount to be delegated - delegationAmount := big.NewInt(1e18) - - BeforeEach(func() { - // Set up funding for the contract address. - // NOTE: we are first asserting that no balance exists and then check successful - // funding afterwards. - resBal, err := s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil(), "error while getting balance") - - balanceBefore := resBal.Balance - Expect(balanceBefore.Amount.Int64()).To(BeZero(), "expected contract balance to be 0 before funding") - - // Check no delegation exists from the contract to the validator - res, err := s.grpcHandler.GetDelegation(sdk.AccAddress(contractAddr.Bytes()).String(), valAddr.String()) - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("delegation with delegator %s not found for validator %s", sdk.AccAddress(contractAddr.Bytes()), valAddr))) - Expect(res).To(BeNil()) - }) - - It("delegating and increasing counter should change the bank balance accordingly", func() { - delegator := s.keyring.GetKey(0) - - callArgs.MethodName = "testDelegateIncrementCounter" - callArgs.Args = []interface{}{valAddr.String()} - txArgs.GasLimit = 1e9 - txArgs.Amount = delegationAmount - - delegationCheck := passCheck.WithExpEvents( - staking.EventTypeDelegate, - ) - - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - delegationCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - res, err := s.grpcHandler.GetDelegation(sdk.AccAddress(contractAddr.Bytes()).String(), valAddr.String()) - Expect(err).To(BeNil()) - Expect(res.DelegationResponse).NotTo(BeNil()) - Expect(res.DelegationResponse.Delegation.GetShares().BigInt()).To(Equal(delegationAmount), "expected different delegation shares") - - resBal, err := s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil(), "error while getting balance") - - postBalance := resBal.Balance - Expect(postBalance.Amount.Int64()).To(BeZero(), "expected balance to be 0 after contract call") - }) - }) - - Context("when updating the stateDB prior to calling the precompile", func() { - It("should utilize the same contract balance to delegate", func() { - delegator := s.keyring.GetKey(0) - fundAmount := big.NewInt(1e18) - delegationAmount := big.NewInt(1e18) - - // fund the contract before calling the precompile - err = testutils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), contractAddr.Bytes(), math.NewIntFromBigInt(fundAmount)) - Expect(err).To(BeNil(), "error while funding account") - Expect(s.network.NextBlock()).To(BeNil()) - - resBal, err := s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil(), "error while getting balance") - - balanceAfterFunding := resBal.Balance - Expect(balanceAfterFunding.Amount.BigInt()).To(Equal(fundAmount), "expected different contract balance after funding") - - // delegate - callArgs.MethodName = "testDelegateAndFailCustomLogic" - callArgs.Args = []interface{}{valAddr.String()} - - txArgs.Amount = delegationAmount - txArgs.GasLimit = 1e9 - - delegationCheck := passCheck.WithExpEvents( - staking.EventTypeDelegate, - ) - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - delegationCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - resBal, err = s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil(), "error while getting balance") - balance := resBal.Balance - - Expect(balance.Amount.Int64()).To(BeZero(), "expected different contract balance after funding") - res, err := s.grpcHandler.GetDelegatorDelegations(sdk.AccAddress(contractAddr.Bytes()).String()) - Expect(err).To(BeNil()) - Expect(res.DelegationResponses).To(HaveLen(1), "expected one delegation") - Expect(res.DelegationResponses[0].Delegation.GetShares().BigInt()).To(Equal(big.NewInt(1e18)), "expected different delegation shares") - }) - - //nolint:dupl - It("should revert the contract balance to the original value when the custom logic after the precompile fails ", func() { - delegator := s.keyring.GetKey(0) - - callArgs.MethodName = "testDelegateAndFailCustomLogic" - callArgs.Args = []interface{}{valAddr.String()} - - txArgs.Amount = big.NewInt(2e18) - txArgs.GasLimit = 1e9 - - delegationCheck := defaultLogCheck.WithErrContains(vm.ErrExecutionReverted.Error()) - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - delegationCheck, - ) - Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) - Expect(s.network.NextBlock()).To(BeNil()) - - resBal, err := s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) - Expect(err).To(BeNil(), "error while getting balance") - - balance := resBal.Balance - Expect(balance.Amount.Int64()).To(BeZero(), "expected different contract balance after funding") - res, err := s.grpcHandler.GetDelegatorDelegations(sdk.AccAddress(contractAddr.Bytes()).String()) - Expect(err).To(BeNil()) - Expect(res.DelegationResponses).To(HaveLen(0), "expected no delegations") - }) - }) -}) - -// These tests are used to check that when batching multiple state changing transactions -// in one block, both states (Cosmos and EVM) are updated or reverted correctly. -// -// For this purpose, we are deploying an ERC20 contract and updating StakingCaller.sol -// to include a method where an ERC20 balance is sent between accounts as well as -// an interaction with the staking precompile is made. -// -// There are ERC20 tokens minted to the address of the deployed StakingCaller contract, -// which will transfer these to the message sender when successfully executed. -var _ = Describe("Batching cosmos and eth interactions", func() { - const ( - erc20Name = "Test" - erc20Token = "TTT" - erc20Decimals = uint8(18) - ) - - var ( - // s is the precompile test suite to use for the tests - s *PrecompileTestSuite - // contractAddr is the address of the deployed StakingCaller contract - contractAddr common.Address - // contractAccAddr is the bech32 encoded account address of the deployed StakingCaller contract - contractAccAddr sdk.AccAddress - // stakingCallerContract is the contract instance calling into the staking precompile - stakingCallerContract evmtypes.CompiledContract - // erc20ContractAddr is the address of the deployed ERC20 contract - erc20ContractAddr common.Address - // erc20Contract is the compiled ERC20 contract - erc20Contract = compiledcontracts.ERC20MinterBurnerDecimalsContract - - // err is a standard error - err error - // execRevertedCheck is a standard log check for a reverted transaction - execRevertedCheck = defaultLogCheck.WithErrContains(vm.ErrExecutionReverted.Error()) - - // mintAmount is the amount of ERC20 tokens minted to the StakingCaller contract - mintAmount = big.NewInt(1e18) - // transferredAmount is the amount of ERC20 tokens to transfer during the tests - transferredAmount = big.NewInt(1234e9) - ) - - BeforeEach(func() { - s = new(PrecompileTestSuite) - s.SetupTest() - delegator := s.keyring.GetKey(0) - - stakingCallerContract, err = testdata.LoadStakingCallerContract() - Expect(err).To(BeNil(), "error while loading the StakingCaller contract") - - // Deploy StakingCaller contract - contractAddr, err = s.factory.DeployContract( - delegator.Priv, - evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values - factory.ContractDeploymentData{ - Contract: stakingCallerContract, - }, - ) - Expect(err).To(BeNil(), "error while deploying the StakingCaller contract") - Expect(s.network.NextBlock()).To(BeNil()) - - contractAccAddr = sdk.AccAddress(contractAddr.Bytes()) - Expect(err).To(BeNil()) - - // Deploy ERC20 contract - erc20ContractAddr, err = s.factory.DeployContract( - delegator.Priv, - evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values - factory.ContractDeploymentData{ - Contract: erc20Contract, - ConstructorArgs: []interface{}{erc20Name, erc20Token, erc20Decimals}, - }, - ) - Expect(err).To(BeNil(), "error while deploying the ERC20 contract") - Expect(s.network.NextBlock()).To(BeNil()) - - // Mint tokens to the StakingCaller contract - mintArgs := factory.CallArgs{ - ContractABI: erc20Contract.ABI, - MethodName: "mint", - Args: []interface{}{contractAddr, mintAmount}, - } - - txArgs = evmtypes.EvmTxArgs{ - To: &erc20ContractAddr, - } - - mintCheck := testutil.LogCheckArgs{ - ABIEvents: erc20Contract.ABI.Events, - ExpEvents: []string{"Transfer"}, // minting produces a Transfer event - ExpPass: true, - } - - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, mintArgs, mintCheck) - Expect(err).To(BeNil(), "error while minting tokens to the StakingCaller contract") - Expect(s.network.NextBlock()).To(BeNil()) - - // Check that the StakingCaller contract has the correct balance - erc20Balance := s.network.App.Erc20Keeper.BalanceOf(s.network.GetContext(), erc20Contract.ABI, erc20ContractAddr, contractAddr) - Expect(erc20Balance).To(Equal(mintAmount), "expected different ERC20 balance for the StakingCaller contract") - - // populate default call args - callArgs = factory.CallArgs{ - ContractABI: stakingCallerContract.ABI, - MethodName: "callERC20AndDelegate", - } - - txArgs.To = &contractAddr - - // populate default log check args - defaultLogCheck = testutil.LogCheckArgs{ - ABIEvents: s.precompile.Events, - } - execRevertedCheck = defaultLogCheck.WithErrContains(vm.ErrExecutionReverted.Error()) - passCheck = defaultLogCheck.WithExpPass(true) - }) - - Describe("when batching multiple transactions", func() { - // validator is the validator address used for testing - var validator sdk.ValAddress - - BeforeEach(func() { - delegator := s.keyring.GetKey(0) - - res, err := s.grpcHandler.GetDelegatorDelegations(delegator.AccAddr.String()) - Expect(err).To(BeNil()) - Expect(res.DelegationResponses).ToNot(HaveLen(0), "expected address to have delegations") - - validator, err = sdk.ValAddressFromBech32(res.DelegationResponses[0].Delegation.ValidatorAddress) - Expect(err).To(BeNil()) - - _ = erc20ContractAddr - - // delegate - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - evmtypes.EvmTxArgs{ - To: &contractAddr, - Amount: big.NewInt(1e18), - GasPrice: big.NewInt(1e9), - GasLimit: 500_000, - }, - factory.CallArgs{ - ContractABI: stakingCallerContract.ABI, - MethodName: "testDelegate", - Args: []interface{}{ - validator.String(), - }, - }, - passCheck.WithExpEvents(staking.EventTypeDelegate), - ) - Expect(err).To(BeNil(), "error while calling the StakingCaller contract") - Expect(s.network.NextBlock()).To(BeNil()) - }) - - It("should revert both states if a staking transaction fails", func() { - delegator := s.keyring.GetKey(0) - - res, err := s.grpcHandler.GetDelegation(contractAccAddr.String(), validator.String()) - Expect(err).To(BeNil()) - Expect(res.DelegationResponse).NotTo(BeNil()) - - delegationPre := res.DelegationResponse.Delegation - sharesPre := delegationPre.GetShares() - - // NOTE: passing an invalid validator address here should fail AFTER the erc20 transfer was made in the smart contract. - // Therefore this can be used to check that both EVM and Cosmos states are reverted correctly. - callArgs.Args = []interface{}{erc20ContractAddr, "invalid validator", transferredAmount} - - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - execRevertedCheck) - Expect(err).To(BeNil(), "expected error while calling the smart contract") - Expect(s.network.NextBlock()).To(BeNil()) - - res, err = s.grpcHandler.GetDelegation(contractAccAddr.String(), validator.String()) - Expect(err).To(BeNil()) - Expect(res.DelegationResponse).NotTo(BeNil()) - delegationPost := res.DelegationResponse.Delegation - sharesPost := delegationPost.GetShares() - erc20BalancePost := s.network.App.Erc20Keeper.BalanceOf(s.network.GetContext(), erc20Contract.ABI, erc20ContractAddr, delegator.Addr) - - Expect(sharesPost).To(Equal(sharesPre), "expected shares to be equal when reverting state") - Expect(erc20BalancePost.Int64()).To(BeZero(), "expected erc20 balance of target address to be zero when reverting state") - }) - - It("should revert both states if an ERC20 transaction fails", func() { - delegator := s.keyring.GetKey(0) - - res, err := s.grpcHandler.GetDelegation(contractAccAddr.String(), validator.String()) - Expect(err).To(BeNil()) - Expect(res.DelegationResponse).NotTo(BeNil()) - - delegationPre := res.DelegationResponse.Delegation - sharesPre := delegationPre.GetShares() - - // NOTE: trying to transfer more than the balance of the contract should fail in the smart contract. - // Therefore this can be used to check that both EVM and Cosmos states are reverted correctly. - moreThanMintedAmount := new(big.Int).Add(mintAmount, big.NewInt(1)) - callArgs.Args = []interface{}{erc20ContractAddr, s.network.GetValidators()[0].OperatorAddress, moreThanMintedAmount} - - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - execRevertedCheck) - Expect(err).To(BeNil(), "expected error while calling the smart contract") - Expect(s.network.NextBlock()).To(BeNil()) - - res, err = s.grpcHandler.GetDelegation(contractAccAddr.String(), validator.String()) - Expect(err).To(BeNil()) - Expect(res.DelegationResponse).NotTo(BeNil()) - delegationPost := res.DelegationResponse.Delegation - sharesPost := delegationPost.GetShares() - erc20BalancePost := s.network.App.Erc20Keeper.BalanceOf(s.network.GetContext(), erc20Contract.ABI, erc20ContractAddr, delegator.Addr) - - Expect(sharesPost).To(Equal(sharesPre), "expected shares to be equal when reverting state") - Expect(erc20BalancePost.Int64()).To(BeZero(), "expected erc20 balance of target address to be zero when reverting state") - }) - - It("should persist changes in both the cosmos and eth states", func() { - delegator := s.keyring.GetKey(0) - - res, err := s.grpcHandler.GetDelegation(contractAccAddr.String(), validator.String()) - Expect(err).To(BeNil()) - Expect(res.DelegationResponse).NotTo(BeNil()) - - delegationPre := res.DelegationResponse.Delegation - sharesPre := delegationPre.GetShares() - - // NOTE: trying to transfer more than the balance of the contract should fail in the smart contract. - // Therefore this can be used to check that both EVM and Cosmos states are reverted correctly. - callArgs.Args = []interface{}{erc20ContractAddr, s.network.GetValidators()[0].OperatorAddress, transferredAmount} - - // Build combined map of ABI events to check for both ERC20 Transfer event as well as precompile events - combinedABIEvents := s.precompile.Events - combinedABIEvents["Transfer"] = erc20Contract.ABI.Events["Transfer"] - - successCheck := passCheck. - WithABIEvents(combinedABIEvents). - WithExpEvents( - "Transfer", staking.EventTypeDelegate, - ) - - txArgs.Amount = big.NewInt(1e18) - txArgs.GasPrice = big.NewInt(1e9) - txArgs.GasLimit = 500_000 - _, _, err = s.factory.CallContractAndCheckLogs( - delegator.Priv, - txArgs, callArgs, - successCheck) - Expect(err).ToNot(HaveOccurred(), "error while calling the smart contract") - Expect(s.network.NextBlock()).To(BeNil()) - - res, err = s.grpcHandler.GetDelegation(contractAccAddr.String(), validator.String()) - Expect(err).To(BeNil()) - Expect(res.DelegationResponse).NotTo(BeNil(), - "expected delegation from %s to validator %s to be found after calling the smart contract", - delegator.AccAddr.String(), validator.String(), - ) - delegationPost := res.DelegationResponse.Delegation - sharesPost := delegationPost.GetShares() - erc20BalancePost := s.network.App.Erc20Keeper.BalanceOf(s.network.GetContext(), erc20Contract.ABI, erc20ContractAddr, delegator.Addr) - - Expect(sharesPost.GT(sharesPre)).To(BeTrue(), "expected shares to be more than before") - Expect(erc20BalancePost).To(Equal(transferredAmount), "expected different erc20 balance of target address") - }) - }) -}) diff --git a/precompiles/testutil/contracts/contracts.go b/precompiles/testutil/contracts/contracts.go index 7982c4daa..e039c9b69 100644 --- a/precompiles/testutil/contracts/contracts.go +++ b/precompiles/testutil/contracts/contracts.go @@ -9,17 +9,16 @@ import ( abci "github.com/cometbft/cometbft/abci/types" + "github.com/cosmos/evm" "github.com/cosmos/evm/crypto/ethsecp256k1" - exampleapp "github.com/cosmos/evm/evmd" - chainutil "github.com/cosmos/evm/evmd/testutil" - precompiletestutil "github.com/cosmos/evm/precompiles/testutil" + "github.com/cosmos/evm/testutil/integration" evmtypes "github.com/cosmos/evm/x/vm/types" sdk "github.com/cosmos/cosmos-sdk/types" ) // Call is a helper function to call any arbitrary smart contract. -func Call(ctx sdk.Context, app *exampleapp.EVMD, args CallArgs) (res abci.ExecTxResult, ethRes *evmtypes.MsgEthereumTxResponse, err error) { +func Call(ctx sdk.Context, app evm.EvmApp, args CallArgs) (res abci.ExecTxResult, ethRes *evmtypes.MsgEthereumTxResponse, err error) { var ( nonce uint64 gasLimit = args.GasLimit @@ -42,7 +41,7 @@ func Call(ctx sdk.Context, app *exampleapp.EVMD, args CallArgs) (res abci.ExecTx addr := crypto.PubkeyToAddress(key.PublicKey) if args.Nonce == nil { - nonce = app.EVMKeeper.GetNonce(ctx, addr) + nonce = app.GetEVMKeeper().GetNonce(ctx, addr) } else { nonce = args.Nonce.Uint64() } @@ -56,7 +55,7 @@ func Call(ctx sdk.Context, app *exampleapp.EVMD, args CallArgs) (res abci.ExecTx // if gas price not provided var gasPrice *big.Int if args.GasPrice == nil { - baseFeeRes, err := app.EVMKeeper.BaseFee(ctx, &evmtypes.QueryBaseFeeRequest{}) + baseFeeRes, err := app.GetEVMKeeper().BaseFee(ctx, &evmtypes.QueryBaseFeeRequest{}) if err != nil { return abci.ExecTxResult{}, nil, err } @@ -64,13 +63,13 @@ func Call(ctx sdk.Context, app *exampleapp.EVMD, args CallArgs) (res abci.ExecTx } else { gasPrice = args.GasPrice } - // Create MsgEthereumTx that calls the contract + // create MsgEthereumTx that calls the contract input, err := args.ContractABI.Pack(args.MethodName, args.Args...) if err != nil { return abci.ExecTxResult{}, nil, fmt.Errorf("error while packing the input: %v", err) } - // Create MsgEthereumTx that calls the contract + // create MsgEthereumTx that calls the contract msg := evmtypes.NewTx(&evmtypes.EvmTxArgs{ ChainID: evmtypes.GetEthChainConfig().ChainID, Nonce: nonce, @@ -85,7 +84,7 @@ func Call(ctx sdk.Context, app *exampleapp.EVMD, args CallArgs) (res abci.ExecTx }) msg.From = addr.Hex() - res, err = chainutil.DeliverEthTx(app, args.PrivKey, msg) + res, err = integration.DeliverEthTx(app, args.PrivKey, msg) if err != nil { return res, nil, fmt.Errorf("error during deliver tx: %s", err) } @@ -100,15 +99,3 @@ func Call(ctx sdk.Context, app *exampleapp.EVMD, args CallArgs) (res abci.ExecTx return res, ethRes, nil } - -// CallContractAndCheckLogs is a helper function to call any arbitrary smart contract and check that the logs -// contain the expected events. -func CallContractAndCheckLogs(ctx sdk.Context, app *exampleapp.EVMD, cArgs CallArgs, logCheckArgs precompiletestutil.LogCheckArgs) (abci.ExecTxResult, *evmtypes.MsgEthereumTxResponse, error) { - res, ethRes, err := Call(ctx, app, cArgs) - if err != nil { - return res, nil, err - } - - logCheckArgs.Res = res - return res, ethRes, precompiletestutil.CheckLogs(logCheckArgs) -} diff --git a/precompiles/werc20/integration_test.go b/precompiles/werc20/integration_test.go deleted file mode 100644 index cdc3db7c8..000000000 --- a/precompiles/werc20/integration_test.go +++ /dev/null @@ -1,605 +0,0 @@ -package werc20_test - -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" - - "github.com/cosmos/evm/precompiles/erc20" - "github.com/cosmos/evm/precompiles/testutil" - "github.com/cosmos/evm/precompiles/werc20" - "github.com/cosmos/evm/precompiles/werc20/testdata" - testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" - utiltx "github.com/cosmos/evm/testutil/tx" - erc20types "github.com/cosmos/evm/x/erc20/types" - feemarkettypes "github.com/cosmos/evm/x/feemarket/types" - evmtypes "github.com/cosmos/evm/x/vm/types" - - "cosmossdk.io/math" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// ------------------------------------------------------------------------------------------------- -// Integration test suite -// ------------------------------------------------------------------------------------------------- - -type PrecompileIntegrationTestSuite struct { - network *network.UnitTestNetwork - factory factory.TxFactory - grpcHandler grpc.Handler - keyring keyring.Keyring - - wrappedCoinDenom string - - // WEVMOS related fields - precompile *werc20.Precompile - precompileAddrHex string -} - -func TestPrecompileIntegrationTestSuite(t *testing.T) { - // Run Ginkgo integration tests - RegisterFailHandler(Fail) - RunSpecs(t, "WEVMOS precompile test suite") -} - -// checkAndReturnBalance check that the balance of the address is the same in -// the smart contract and in the balance and returns the amount. -func (is *PrecompileIntegrationTestSuite) checkAndReturnBalance( - balanceCheck testutil.LogCheckArgs, - callsData CallsData, - address common.Address, -) *big.Int { - txArgs, balancesArgs := callsData.getTxAndCallArgs(directCall, erc20.BalanceOfMethod, address) - txArgs.GasLimit = 1_000_000_000_000 - - _, ethRes, err := is.factory.CallContractAndCheckLogs(callsData.sender.Priv, txArgs, balancesArgs, balanceCheck) - Expect(err).ToNot(HaveOccurred(), "failed to execute balanceOf") - var erc20Balance *big.Int - err = is.precompile.UnpackIntoInterface(&erc20Balance, erc20.BalanceOfMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack result") - - addressAcc := sdk.AccAddress(address.Bytes()) - balanceAfter, err := is.grpcHandler.GetBalanceFromBank(addressAcc, is.wrappedCoinDenom) - Expect(err).ToNot(HaveOccurred(), "expected no error getting balance") - - Expect(erc20Balance.String()).To(Equal(balanceAfter.Balance.Amount.BigInt().String()), "expected return balance from contract equal to bank") - return erc20Balance -} - -// ------------------------------------------------------------------------------------------------- -// Integration tests -// ------------------------------------------------------------------------------------------------- - -var _ = When("a user interact with the WEVMOS precompiled contract", func() { - var ( - is *PrecompileIntegrationTestSuite - passCheck, failCheck testutil.LogCheckArgs - transferCheck, depositCheck, withdrawCheck testutil.LogCheckArgs - - callsData CallsData - - txSender, user keyring.Key - - revertContractAddr common.Address - ) - - depositAmount := big.NewInt(1e18) - withdrawAmount := depositAmount - transferAmount := depositAmount - - BeforeEach(func() { - is = new(PrecompileIntegrationTestSuite) - keyring := keyring.New(2) - - txSender = keyring.GetKey(0) - user = keyring.GetKey(1) - - // Set the base fee to zero to allow for zero cost tx. The final gas cost is - // not part of the logic tested here so this makes testing more easy. - customGenesis := network.CustomGenesisState{} - feemarketGenesis := feemarkettypes.DefaultGenesisState() - feemarketGenesis.Params.NoBaseFee = true - customGenesis[feemarkettypes.ModuleName] = feemarketGenesis - - // Reset evm config here for the standard case - configurator := evmtypes.NewEVMConfigurator() - configurator.ResetTestConfig() - Expect(configurator. - WithEVMCoinInfo(testconstants.ExampleChainCoinInfo[testconstants.ExampleChainID]). - Configure()).To(BeNil(), "expected no error setting the evm configurator") - - integrationNetwork := network.NewUnitTestNetwork( - network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), - network.WithCustomGenesis(customGenesis), - ) - grpcHandler := grpc.NewIntegrationHandler(integrationNetwork) - txFactory := factory.New(integrationNetwork, grpcHandler) - - is.network = integrationNetwork - is.factory = txFactory - is.grpcHandler = grpcHandler - is.keyring = keyring - - is.wrappedCoinDenom = evmtypes.GetEVMCoinDenom() - is.precompileAddrHex = network.GetWEVMOSContractHex(testconstants.ChainID{ - ChainID: is.network.GetChainID(), - EVMChainID: is.network.GetEIP155ChainID().Uint64(), - }) - - ctx := integrationNetwork.GetContext() - - // Perform some check before adding the precompile to the suite. - - // Check that WEVMOS is part of the native precompiles. - erc20Params := is.network.App.Erc20Keeper.GetParams(ctx) - Expect(erc20Params.NativePrecompiles).To( - ContainElement(is.precompileAddrHex), - "expected wevmos to be in the native precompiles", - ) - _, found := is.network.App.BankKeeper.GetDenomMetaData(ctx, evmtypes.GetEVMCoinDenom()) - Expect(found).To(BeTrue(), "expected native token metadata to be registered") - - // Check that WEVMOS is registered in the token pairs map. - tokenPairID := is.network.App.Erc20Keeper.GetTokenPairID(ctx, is.wrappedCoinDenom) - tokenPair, found := is.network.App.Erc20Keeper.GetTokenPair(ctx, tokenPairID) - Expect(found).To(BeTrue(), "expected wevmos precompile to be registered in the tokens map") - Expect(tokenPair.Erc20Address).To(Equal(is.precompileAddrHex)) - - precompileAddr := common.HexToAddress(is.precompileAddrHex) - tokenPair = erc20types.NewTokenPair( - precompileAddr, - evmtypes.GetEVMCoinDenom(), - erc20types.OWNER_MODULE, - ) - precompile, err := werc20.NewPrecompile( - tokenPair, - is.network.App.BankKeeper, - is.network.App.Erc20Keeper, - is.network.App.TransferKeeper, - ) - Expect(err).ToNot(HaveOccurred(), "failed to instantiate the werc20 precompile") - is.precompile = precompile - - // Setup of the contract calling into the precompile to tests revert - // edge cases and proper handling of snapshots. - revertCallerContract, err := testdata.LoadWEVMOS9TestCaller() - Expect(err).ToNot(HaveOccurred(), "failed to load werc20 reverter caller contract") - - txArgs := evmtypes.EvmTxArgs{} - txArgs.GasTipCap = new(big.Int).SetInt64(0) - txArgs.GasLimit = 1_000_000_000_000 - revertContractAddr, err = is.factory.DeployContract( - txSender.Priv, - txArgs, - factory.ContractDeploymentData{ - Contract: revertCallerContract, - ConstructorArgs: []interface{}{ - common.HexToAddress(is.precompileAddrHex), - }, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to deploy werc20 reverter contract") - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - // Support struct used to simplify transactions creation. - callsData = CallsData{ - sender: txSender, - - precompileAddr: precompileAddr, - precompileABI: precompile.ABI, - - precompileReverterAddr: revertContractAddr, - precompileReverterABI: revertCallerContract.ABI, - } - - // Utility types used to check the different events emitted. - failCheck = testutil.LogCheckArgs{ABIEvents: is.precompile.Events} - passCheck = failCheck.WithExpPass(true) - withdrawCheck = passCheck.WithExpEvents(werc20.EventTypeWithdrawal) - depositCheck = passCheck.WithExpEvents(werc20.EventTypeDeposit) - transferCheck = passCheck.WithExpEvents(erc20.EventTypeTransfer) - }) - Context("calling a specific wrapped coin method", func() { - Context("and funds are part of the transaction", func() { - When("the method is deposit", func() { - It("it should return funds to sender and emit the event", func() { - // Store initial balance to verify that sender - // balance remains the same after the contract call. - initBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - txArgs, callArgs := callsData.getTxAndCallArgs(directCall, werc20.DepositMethod) - txArgs.Amount = depositAmount - - _, _, err := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected error calling the precompile") - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - finalBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) - Expect(finalBalance.String()).To(Equal(initBalance.String())) - }) - It("it should consume at least the deposit requested gas", func() { - txArgs, callArgs := callsData.getTxAndCallArgs(directCall, werc20.DepositMethod) - txArgs.Amount = depositAmount - - _, ethRes, _ := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - Expect(ethRes.GasUsed).To(BeNumerically(">=", werc20.DepositRequiredGas), "expected different gas used for deposit") - }) - }) - //nolint:dupl - When("no calldata is provided", func() { - It("it should call the receive which behave like deposit", func() { - initBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - txArgs, callArgs := callsData.getTxAndCallArgs(directCall, "") - txArgs.Amount = depositAmount - - _, _, err := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected error calling the precompile") - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - finalBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) - Expect(finalBalance).To(Equal(initBalance)) - }) - It("it should consume at least the deposit requested gas", func() { - txArgs, callArgs := callsData.getTxAndCallArgs(directCall, werc20.DepositMethod) - txArgs.Amount = depositAmount - - _, ethRes, _ := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - Expect(ethRes.GasUsed).To(BeNumerically(">=", werc20.DepositRequiredGas), "expected different gas used for receive") - }) - }) - When("the specified method is too short", func() { - It("it should call the fallback which behave like deposit", func() { - initBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - txArgs, callArgs := callsData.getTxAndCallArgs(directCall, "") - txArgs.Amount = depositAmount - // Short method is directly set in the input to skip ABI validation - txArgs.Input = []byte{1, 2, 3} - - _, _, err := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected error calling the precompile") - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - finalBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) - Expect(finalBalance).To(Equal(initBalance)) - }) - It("it should consume at least the deposit requested gas", func() { - txArgs, callArgs := callsData.getTxAndCallArgs(directCall, "") - txArgs.Amount = depositAmount - // Short method is directly set in the input to skip ABI validation - txArgs.Input = []byte{1, 2, 3} - - _, ethRes, _ := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - Expect(ethRes.GasUsed).To(BeNumerically(">=", werc20.DepositRequiredGas), "expected different gas used for fallback") - }) - }) - When("the specified method does not exist", func() { - It("it should call the fallback which behave like deposit", func() { - initBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - txArgs, callArgs := callsData.getTxAndCallArgs(directCall, "") - txArgs.Amount = depositAmount - // Wrong method is directly set in the input to skip ABI validation - txArgs.Input = []byte("nonExistingMethod") - - _, _, err := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected error calling the precompile") - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - finalBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) - Expect(finalBalance).To(Equal(initBalance)) - }) - It("it should consume at least the deposit requested gas", func() { - txArgs, callArgs := callsData.getTxAndCallArgs(directCall, "") - txArgs.Amount = depositAmount - // Wrong method is directly set in the input to skip ABI validation - txArgs.Input = []byte("nonExistingMethod") - - _, ethRes, _ := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - Expect(ethRes.GasUsed).To(BeNumerically(">=", werc20.DepositRequiredGas), "expected different gas used for fallback") - }) - }) - }) - Context("and funds are NOT part of the transaction", func() { - When("the method is withdraw", func() { - It("it should fail if user doesn't have enough funds", func() { - // Store initial balance to verify withdraw is a no-op and sender - // balance remains the same after the contract call. - initBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - newUserAcc, newUserPriv := utiltx.NewAccAddressAndKey() - newUserBalance := sdk.Coins{sdk.Coin{ - Denom: evmtypes.GetEVMCoinDenom(), - Amount: math.NewIntFromBigInt(withdrawAmount).SubRaw(1), - }} - err := is.network.App.BankKeeper.SendCoins(is.network.GetContext(), user.AccAddr, newUserAcc, newUserBalance) - Expect(err).ToNot(HaveOccurred(), "expected no error sending tokens") - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - txArgs, callArgs := callsData.getTxAndCallArgs(directCall, werc20.WithdrawMethod, withdrawAmount) - - _, _, err = is.factory.CallContractAndCheckLogs(newUserPriv, txArgs, callArgs, withdrawCheck) - Expect(err).To(HaveOccurred(), "expected an error because not enough funds") - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - finalBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) - Expect(finalBalance).To(Equal(initBalance)) - }) - It("it should be a no-op and emit the event", func() { - initBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - txArgs, callArgs := callsData.getTxAndCallArgs(directCall, werc20.WithdrawMethod, withdrawAmount) - - _, _, err := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, withdrawCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected error calling the precompile") - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - finalBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) - Expect(finalBalance).To(Equal(initBalance)) - }) - It("it should consume at least the withdraw requested gas", func() { - txArgs, callArgs := callsData.getTxAndCallArgs(directCall, werc20.WithdrawMethod, withdrawAmount) - - _, ethRes, _ := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, withdrawCheck) - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - Expect(ethRes.GasUsed).To(BeNumerically(">=", werc20.WithdrawRequiredGas), "expected different gas used for withdraw") - }) - }) - //nolint:dupl - When("no calldata is provided", func() { - It("it should call the fallback which behave like deposit", func() { - initBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - txArgs, callArgs := callsData.getTxAndCallArgs(directCall, "") - txArgs.Amount = depositAmount - - _, _, err := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected error calling the precompile") - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - finalBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) - Expect(finalBalance).To(Equal(initBalance)) - }) - It("it should consume at least the deposit requested gas", func() { - txArgs, callArgs := callsData.getTxAndCallArgs(directCall, werc20.DepositMethod) - txArgs.Amount = depositAmount - - _, ethRes, _ := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - Expect(ethRes.GasUsed).To(BeNumerically(">=", werc20.DepositRequiredGas), "expected different gas used for receive") - }) - }) - When("the specified method is too short", func() { - It("it should call the fallback which behave like deposit", func() { - initBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - txArgs, callArgs := callsData.getTxAndCallArgs(directCall, "") - txArgs.Amount = depositAmount - // Short method is directly set in the input to skip ABI validation - txArgs.Input = []byte{1, 2, 3} - - _, _, err := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected error calling the precompile") - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - finalBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) - Expect(finalBalance).To(Equal(initBalance)) - }) - It("it should consume at least the deposit requested gas", func() { - txArgs, callArgs := callsData.getTxAndCallArgs(directCall, "") - txArgs.Amount = depositAmount - // Short method is directly set in the input to skip ABI validation - txArgs.Input = []byte{1, 2, 3} - - _, ethRes, _ := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - Expect(ethRes.GasUsed).To(BeNumerically(">=", werc20.DepositRequiredGas), "expected different gas used for fallback") - }) - }) - When("the specified method does not exist", func() { - It("it should call the fallback which behave like deposit", func() { - initBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - txArgs, callArgs := callsData.getTxAndCallArgs(directCall, "") - txArgs.Amount = depositAmount - // Wrong method is directly set in the input to skip ABI validation - txArgs.Input = []byte("nonExistingMethod") - - _, _, err := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected error calling the precompile") - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - finalBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) - Expect(finalBalance).To(Equal(initBalance)) - }) - It("it should consume at least the deposit requested gas", func() { - txArgs, callArgs := callsData.getTxAndCallArgs(directCall, "") - txArgs.Amount = depositAmount - // Wrong method is directly set in the input to skip ABI validation - txArgs.Input = []byte("nonExistingMethod") - - _, ethRes, _ := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - Expect(ethRes.GasUsed).To(BeNumerically(">=", werc20.DepositRequiredGas), "expected different gas used for fallback") - }) - }) - }) - }) - Context("calling a reverter contract", func() { - When("to call the deposit", func() { - It("it should return funds to the last sender and emit the event", func() { - ctx := is.network.GetContext() - - txArgs, callArgs := callsData.getTxAndCallArgs(contractCall, "depositWithRevert", false, false) - txArgs.Amount = depositAmount - - _, _, err := is.factory.CallContractAndCheckLogs(txSender.Priv, txArgs, callArgs, depositCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected error calling the precompile") - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - finalBalance := is.network.App.BankKeeper.GetAllBalances(ctx, revertContractAddr.Bytes()) - Expect(finalBalance.AmountOf(evmtypes.GetEVMCoinDenom()).String()).To(Equal(depositAmount.String()), "expected final balance equal to deposit") - }) - }) - DescribeTable("to call the deposit", func(before, after bool) { - ctx := is.network.GetContext() - - initBalance := is.network.App.BankKeeper.GetAllBalances(ctx, txSender.AccAddr) - - txArgs, callArgs := callsData.getTxAndCallArgs(contractCall, "depositWithRevert", before, after) - txArgs.Amount = depositAmount - - _, _, err := is.factory.CallContractAndCheckLogs(txSender.Priv, txArgs, callArgs, depositCheck) - Expect(err).To(HaveOccurred(), "execution should have reverted") - Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") - - finalBalance := is.network.App.BankKeeper.GetAllBalances(ctx, txSender.AccAddr) - Expect(finalBalance.String()).To(Equal(initBalance.String()), "expected final balance equal to initial") - }, - Entry("it should not move funds and dont emit the event reverting before changing state", true, false), - Entry("it should not move funds and dont emit the event reverting after changing state", false, true), - ) - }) - Context("calling an erc20 method", func() { - When("transferring tokens", func() { - It("it should transfer tokens to a receiver using `transfer`", func() { - ctx := is.network.GetContext() - - senderBalance := is.network.App.BankKeeper.GetAllBalances(ctx, txSender.AccAddr) - receiverBalance := is.network.App.BankKeeper.GetAllBalances(ctx, user.AccAddr) - - txArgs, transferArgs := callsData.getTxAndCallArgs(directCall, erc20.TransferMethod, user.Addr, transferAmount) - transferCoins := sdk.Coins{sdk.NewInt64Coin(is.wrappedCoinDenom, transferAmount.Int64())} - - _, _, err := is.factory.CallContractAndCheckLogs(txSender.Priv, txArgs, transferArgs, transferCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - senderBalanceAfter := is.network.App.BankKeeper.GetAllBalances(ctx, txSender.AccAddr) - receiverBalanceAfter := is.network.App.BankKeeper.GetAllBalances(ctx, user.AccAddr) - Expect(senderBalanceAfter).To(Equal(senderBalance.Sub(transferCoins...))) - Expect(receiverBalanceAfter).To(Equal(receiverBalance.Add(transferCoins...))) - }) - It("it should fail to transfer tokens to a receiver using `transferFrom`", func() { - ctx := is.network.GetContext() - - senderBalance := is.network.App.BankKeeper.GetAllBalances(ctx, txSender.AccAddr) - receiverBalance := is.network.App.BankKeeper.GetAllBalances(ctx, user.AccAddr) - - txArgs, transferArgs := callsData.getTxAndCallArgs(directCall, erc20.TransferFromMethod, txSender.Addr, user.Addr, transferAmount) - - insufficientAllowanceCheck := failCheck.WithErrContains(erc20.ErrInsufficientAllowance.Error()) - _, _, err := is.factory.CallContractAndCheckLogs(txSender.Priv, txArgs, transferArgs, insufficientAllowanceCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - senderBalanceAfter := is.network.App.BankKeeper.GetAllBalances(ctx, txSender.AccAddr) - receiverBalanceAfter := is.network.App.BankKeeper.GetAllBalances(ctx, user.AccAddr) - Expect(senderBalanceAfter).To(Equal(senderBalance)) - Expect(receiverBalanceAfter).To(Equal(receiverBalance)) - }) - }) - When("querying information", func() { - Context("to retrieve a balance", func() { - It("should return the correct balance for an existing account", func() { - // Query the balance - txArgs, balancesArgs := callsData.getTxAndCallArgs(directCall, erc20.BalanceOfMethod, txSender.Addr) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(txSender.Priv, txArgs, balancesArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - expBalance := is.network.App.BankKeeper.GetBalance(is.network.GetContext(), txSender.AccAddr, is.wrappedCoinDenom) - - var balance *big.Int - err = is.precompile.UnpackIntoInterface(&balance, erc20.BalanceOfMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack result") - Expect(balance).To(Equal(expBalance.Amount.BigInt()), "expected different balance") - }) - It("should return 0 for a new account", func() { - // Query the balance - txArgs, balancesArgs := callsData.getTxAndCallArgs(directCall, erc20.BalanceOfMethod, utiltx.GenerateAddress()) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(txSender.Priv, txArgs, balancesArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - var balance *big.Int - err = is.precompile.UnpackIntoInterface(&balance, erc20.BalanceOfMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack result") - Expect(balance.Int64()).To(Equal(int64(0)), "expected different balance") - }) - }) - It("should return the correct name", func() { - txArgs, nameArgs := callsData.getTxAndCallArgs(directCall, erc20.NameMethod) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(txSender.Priv, txArgs, nameArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - var name string - err = is.precompile.UnpackIntoInterface(&name, erc20.NameMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack result") - Expect(name).To(ContainSubstring("Cosmos EVM"), "expected different name") - }) - - It("should return the correct symbol", func() { - txArgs, symbolArgs := callsData.getTxAndCallArgs(directCall, erc20.SymbolMethod) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(txSender.Priv, txArgs, symbolArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - var symbol string - err = is.precompile.UnpackIntoInterface(&symbol, erc20.SymbolMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack result") - Expect(symbol).To(ContainSubstring("ATOM"), "expected different symbol") - }) - - It("should return the decimals", func() { - txArgs, decimalsArgs := callsData.getTxAndCallArgs(directCall, erc20.DecimalsMethod) - - _, ethRes, err := is.factory.CallContractAndCheckLogs(txSender.Priv, txArgs, decimalsArgs, passCheck) - Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") - - var decimals uint8 - err = is.precompile.UnpackIntoInterface(&decimals, erc20.DecimalsMethod, ethRes.Ret) - Expect(err).ToNot(HaveOccurred(), "failed to unpack result") - - coinInfo := testconstants.ExampleChainCoinInfo[testconstants.ChainID{ - ChainID: is.network.GetChainID(), - EVMChainID: is.network.GetEIP155ChainID().Uint64(), - }] - Expect(decimals).To(Equal(uint8(coinInfo.Decimals)), "expected different decimals") - }, - ) - }) - }) -}) diff --git a/rpc/backend/account_info.go b/rpc/backend/account_info.go index f1edb06d1..c8d5118ad 100644 --- a/rpc/backend/account_info.go +++ b/rpc/backend/account_info.go @@ -33,7 +33,7 @@ func (b *Backend) GetCode(address common.Address, blockNrOrHash rpctypes.BlockNu Address: address.String(), } - res, err := b.queryClient.Code(rpctypes.ContextWithHeight(blockNum.Int64()), req) + res, err := b.QueryClient.Code(rpctypes.ContextWithHeight(blockNum.Int64()), req) if err != nil { return nil, err } @@ -71,14 +71,14 @@ func (b *Backend) GetProof(address common.Address, storageKeys []string, blockNr height = int64(bn) //#nosec G115 -- checked for int overflow already } - clientCtx := b.clientCtx.WithHeight(height) + clientCtx := b.ClientCtx.WithHeight(height) // query storage proofs storageProofs := make([]rpctypes.StorageResult, len(storageKeys)) for i, key := range storageKeys { hexKey := common.HexToHash(key) - valueBz, proof, err := b.queryClient.GetProof(clientCtx, evmtypes.StoreKey, evmtypes.StateKey(address, hexKey.Bytes())) + valueBz, proof, err := b.QueryClient.GetProof(clientCtx, evmtypes.StoreKey, evmtypes.StateKey(address, hexKey.Bytes())) if err != nil { return nil, err } @@ -95,14 +95,14 @@ func (b *Backend) GetProof(address common.Address, storageKeys []string, blockNr Address: address.String(), } - res, err := b.queryClient.Account(ctx, req) + res, err := b.QueryClient.Account(ctx, req) if err != nil { return nil, err } // query account proofs accountKey := bytes.HexBytes(append(authtypes.AddressStoreKeyPrefix, address.Bytes()...)) - _, proof, err := b.queryClient.GetProof(clientCtx, authtypes.StoreKey, accountKey) + _, proof, err := b.QueryClient.GetProof(clientCtx, authtypes.StoreKey, accountKey) if err != nil { return nil, err } @@ -135,7 +135,7 @@ func (b *Backend) GetStorageAt(address common.Address, key string, blockNrOrHash Key: key, } - res, err := b.queryClient.Storage(rpctypes.ContextWithHeight(blockNum.Int64()), req) + res, err := b.QueryClient.Storage(rpctypes.ContextWithHeight(blockNum.Int64()), req) if err != nil { return nil, err } @@ -160,7 +160,7 @@ func (b *Backend) GetBalance(address common.Address, blockNrOrHash rpctypes.Bloc return nil, err } - res, err := b.queryClient.Balance(rpctypes.ContextWithHeight(blockNum.Int64()), req) + res, err := b.QueryClient.Balance(rpctypes.ContextWithHeight(blockNum.Int64()), req) if err != nil { return nil, err } @@ -197,16 +197,16 @@ func (b *Backend) GetTransactionCount(address common.Address, blockNum rpctypes. } // Get nonce (sequence) from account from := sdk.AccAddress(address.Bytes()) - accRet := b.clientCtx.AccountRetriever + accRet := b.ClientCtx.AccountRetriever - err = accRet.EnsureExists(b.clientCtx, from) + err = accRet.EnsureExists(b.ClientCtx, from) if err != nil { // account doesn't exist yet, return 0 return &n, nil } includePending := blockNum == rpctypes.EthPendingBlockNumber - nonce, err := b.getAccountNonce(address, includePending, blockNum.Int64(), b.logger) + nonce, err := b.getAccountNonce(address, includePending, blockNum.Int64(), b.Logger) if err != nil { return nil, err } diff --git a/rpc/backend/backend.go b/rpc/backend/backend.go index 320388d53..98fe07eb0 100644 --- a/rpc/backend/backend.go +++ b/rpc/backend/backend.go @@ -126,15 +126,15 @@ var _ BackendI = (*Backend)(nil) // Backend implements the BackendI interface type Backend struct { - ctx context.Context - clientCtx client.Context - rpcClient tmrpcclient.SignClient - queryClient *rpctypes.QueryClient // gRPC query client - logger log.Logger - chainID *big.Int - cfg config.Config - allowUnprotectedTxs bool - indexer cosmosevmtypes.EVMTxIndexer + Ctx context.Context + ClientCtx client.Context + RpcClient tmrpcclient.SignClient + QueryClient *rpctypes.QueryClient // gRPC query client + Logger log.Logger + EvmChainID *big.Int + Cfg config.Config + AllowUnprotectedTxs bool + Indexer cosmosevmtypes.EVMTxIndexer } // NewBackend creates a new Backend instance for cosmos and ethereum namespaces @@ -156,14 +156,14 @@ func NewBackend( } return &Backend{ - ctx: context.Background(), - clientCtx: clientCtx, - rpcClient: rpcClient, - queryClient: rpctypes.NewQueryClient(clientCtx), - logger: logger.With("module", "backend"), - chainID: big.NewInt(int64(appConf.EVM.EVMChainID)), //nolint:gosec // G115 // won't exceed uint64 - cfg: appConf, - allowUnprotectedTxs: allowUnprotectedTxs, - indexer: indexer, + Ctx: context.Background(), + ClientCtx: clientCtx, + RpcClient: rpcClient, + QueryClient: rpctypes.NewQueryClient(clientCtx), + Logger: logger.With("module", "backend"), + EvmChainID: big.NewInt(int64(appConf.EVM.EVMChainID)), //nolint:gosec // G115 // won't exceed uint64 + Cfg: appConf, + AllowUnprotectedTxs: allowUnprotectedTxs, + Indexer: indexer, } } diff --git a/rpc/backend/blocks.go b/rpc/backend/blocks.go index bc32ae915..3c72681cd 100644 --- a/rpc/backend/blocks.go +++ b/rpc/backend/blocks.go @@ -31,7 +31,7 @@ import ( func (b *Backend) BlockNumber() (hexutil.Uint64, error) { // do any grpc query, ignore the response and use the returned block height var header metadata.MD - _, err := b.queryClient.Params(b.ctx, &evmtypes.QueryParamsRequest{}, grpc.Header(&header)) + _, err := b.QueryClient.Params(b.Ctx, &evmtypes.QueryParamsRequest{}, grpc.Header(&header)) if err != nil { return hexutil.Uint64(0), err } @@ -67,15 +67,15 @@ func (b *Backend) GetBlockByNumber(blockNum rpctypes.BlockNumber, fullTx bool) ( return nil, nil } - blockRes, err := b.rpcClient.BlockResults(b.ctx, &resBlock.Block.Height) + blockRes, err := b.RpcClient.BlockResults(b.Ctx, &resBlock.Block.Height) if err != nil { - b.logger.Debug("failed to fetch block result from Tendermint", "height", blockNum, "error", err.Error()) + b.Logger.Debug("failed to fetch block result from Tendermint", "height", blockNum, "error", err.Error()) return nil, nil } res, err := b.RPCBlockFromTendermintBlock(resBlock, blockRes, fullTx) if err != nil { - b.logger.Debug("GetEthBlockFromTendermint failed", "height", blockNum, "error", err.Error()) + b.Logger.Debug("GetEthBlockFromTendermint failed", "height", blockNum, "error", err.Error()) return nil, err } @@ -95,15 +95,15 @@ func (b *Backend) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]inte return nil, nil } - blockRes, err := b.rpcClient.BlockResults(b.ctx, &resBlock.Block.Height) + blockRes, err := b.RpcClient.BlockResults(b.Ctx, &resBlock.Block.Height) if err != nil { - b.logger.Debug("failed to fetch block result from Tendermint", "block-hash", hash.String(), "error", err.Error()) + b.Logger.Debug("failed to fetch block result from Tendermint", "block-hash", hash.String(), "error", err.Error()) return nil, nil } res, err := b.RPCBlockFromTendermintBlock(resBlock, blockRes, fullTx) if err != nil { - b.logger.Debug("GetEthBlockFromTendermint failed", "hash", hash, "error", err.Error()) + b.Logger.Debug("GetEthBlockFromTendermint failed", "hash", hash, "error", err.Error()) return nil, err } @@ -113,14 +113,14 @@ func (b *Backend) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]inte // GetBlockTransactionCountByHash returns the number of Ethereum transactions in // the block identified by hash. func (b *Backend) GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Uint { - block, err := b.rpcClient.BlockByHash(b.ctx, hash.Bytes()) + block, err := b.RpcClient.BlockByHash(b.Ctx, hash.Bytes()) if err != nil { - b.logger.Debug("block not found", "hash", hash.Hex(), "error", err.Error()) + b.Logger.Debug("block not found", "hash", hash.Hex(), "error", err.Error()) return nil } if block.Block == nil { - b.logger.Debug("block not found", "hash", hash.Hex()) + b.Logger.Debug("block not found", "hash", hash.Hex()) return nil } @@ -132,12 +132,12 @@ func (b *Backend) GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Uint func (b *Backend) GetBlockTransactionCountByNumber(blockNum rpctypes.BlockNumber) *hexutil.Uint { block, err := b.TendermintBlockByNumber(blockNum) if err != nil { - b.logger.Debug("block not found", "height", blockNum.Int64(), "error", err.Error()) + b.Logger.Debug("block not found", "height", blockNum.Int64(), "error", err.Error()) return nil } if block.Block == nil { - b.logger.Debug("block not found", "height", blockNum.Int64()) + b.Logger.Debug("block not found", "height", blockNum.Int64()) return nil } @@ -147,7 +147,7 @@ func (b *Backend) GetBlockTransactionCountByNumber(blockNum rpctypes.BlockNumber // GetBlockTransactionCount returns the number of Ethereum transactions in a // given block. func (b *Backend) GetBlockTransactionCount(block *tmrpctypes.ResultBlock) *hexutil.Uint { - blockRes, err := b.rpcClient.BlockResults(b.ctx, &block.Block.Height) + blockRes, err := b.RpcClient.BlockResults(b.Ctx, &block.Block.Height) if err != nil { return nil } @@ -169,14 +169,14 @@ func (b *Backend) TendermintBlockByNumber(blockNum rpctypes.BlockNumber) (*tmrpc } height = int64(n) //#nosec G115 -- checked for int overflow already } - resBlock, err := b.rpcClient.Block(b.ctx, &height) + resBlock, err := b.RpcClient.Block(b.Ctx, &height) if err != nil { - b.logger.Debug("tendermint client failed to get block", "height", height, "error", err.Error()) + b.Logger.Debug("tendermint client failed to get block", "height", height, "error", err.Error()) return nil, err } if resBlock.Block == nil { - b.logger.Debug("TendermintBlockByNumber block not found", "height", height) + b.Logger.Debug("TendermintBlockByNumber block not found", "height", height) return nil, nil } @@ -186,19 +186,19 @@ func (b *Backend) TendermintBlockByNumber(blockNum rpctypes.BlockNumber) (*tmrpc // TendermintBlockResultByNumber returns a Tendermint-formatted block result // by block number func (b *Backend) TendermintBlockResultByNumber(height *int64) (*tmrpctypes.ResultBlockResults, error) { - return b.rpcClient.BlockResults(b.ctx, height) + return b.RpcClient.BlockResults(b.Ctx, height) } // TendermintBlockByHash returns a Tendermint-formatted block by block number func (b *Backend) TendermintBlockByHash(blockHash common.Hash) (*tmrpctypes.ResultBlock, error) { - resBlock, err := b.rpcClient.BlockByHash(b.ctx, blockHash.Bytes()) + resBlock, err := b.RpcClient.BlockByHash(b.Ctx, blockHash.Bytes()) if err != nil { - b.logger.Debug("tendermint client failed to get block", "blockHash", blockHash.Hex(), "error", err.Error()) + b.Logger.Debug("tendermint client failed to get block", "blockHash", blockHash.Hex(), "error", err.Error()) return nil, err } if resBlock == nil || resBlock.Block == nil { - b.logger.Debug("TendermintBlockByHash block not found", "blockHash", blockHash.Hex()) + b.Logger.Debug("TendermintBlockByHash block not found", "blockHash", blockHash.Hex()) return nil, nil } @@ -225,7 +225,7 @@ func (b *Backend) BlockNumberFromTendermint(blockNrOrHash rpctypes.BlockNumberOr // BlockNumberFromTendermintByHash returns the block height of given block hash func (b *Backend) BlockNumberFromTendermintByHash(blockHash common.Hash) (*big.Int, error) { - resBlock, err := b.rpcClient.HeaderByHash(b.ctx, blockHash.Bytes()) + resBlock, err := b.RpcClient.HeaderByHash(b.Ctx, blockHash.Bytes()) if err != nil { return nil, err } @@ -255,13 +255,13 @@ func (b *Backend) EthMsgsFromTendermintBlock( // - Include unsuccessful tx that failed when committing changes to stateDB // - Exclude unsuccessful tx with any other error but ExceedBlockGasLimit if !rpctypes.TxSucessOrExpectedFailure(txResults[i]) { - b.logger.Debug("invalid tx result code", "cosmos-hash", hexutil.Encode(tx.Hash())) + b.Logger.Debug("invalid tx result code", "cosmos-hash", hexutil.Encode(tx.Hash())) continue } - tx, err := b.clientCtx.TxConfig.TxDecoder()(tx) + tx, err := b.ClientCtx.TxConfig.TxDecoder()(tx) if err != nil { - b.logger.Debug("failed to decode transaction in block", "height", block.Height, "error", err.Error()) + b.Logger.Debug("failed to decode transaction in block", "height", block.Height, "error", err.Error()) continue } @@ -290,20 +290,20 @@ func (b *Backend) HeaderByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Heade return nil, errors.Errorf("block not found for height %d", blockNum) } - blockRes, err := b.rpcClient.BlockResults(b.ctx, &resBlock.Block.Height) + blockRes, err := b.RpcClient.BlockResults(b.Ctx, &resBlock.Block.Height) if err != nil { return nil, errors.Errorf("block result not found for height %d", resBlock.Block.Height) } bloom, err := b.BlockBloom(blockRes) if err != nil { - b.logger.Debug("HeaderByNumber BlockBloom failed", "height", resBlock.Block.Height) + b.Logger.Debug("HeaderByNumber BlockBloom failed", "height", resBlock.Block.Height) } baseFee, err := b.BaseFee(blockRes) if err != nil { // handle the error for pruned node. - b.logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", resBlock.Block.Height, "error", err) + b.Logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", resBlock.Block.Height, "error", err) } ethHeader := rpctypes.EthHeaderFromTendermint(resBlock.Block.Header, bloom, baseFee) @@ -312,7 +312,7 @@ func (b *Backend) HeaderByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Heade // HeaderByHash returns the block header identified by hash. func (b *Backend) HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) { - resHeader, err := b.rpcClient.HeaderByHash(b.ctx, blockHash.Bytes()) + resHeader, err := b.RpcClient.HeaderByHash(b.Ctx, blockHash.Bytes()) if err != nil { return nil, err } @@ -323,20 +323,20 @@ func (b *Backend) HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) height := resHeader.Header.Height - blockRes, err := b.rpcClient.BlockResults(b.ctx, &resHeader.Header.Height) + blockRes, err := b.RpcClient.BlockResults(b.Ctx, &resHeader.Header.Height) if err != nil { return nil, errors.Errorf("block result not found for height %d", height) } bloom, err := b.BlockBloom(blockRes) if err != nil { - b.logger.Debug("HeaderByHash BlockBloom failed", "height", height) + b.Logger.Debug("HeaderByHash BlockBloom failed", "height", height) } baseFee, err := b.BaseFee(blockRes) if err != nil { // handle the error for pruned node. - b.logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", height, "error", err) + b.Logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", height, "error", err) } ethHeader := rpctypes.EthHeaderFromTendermint(*resHeader.Header, bloom, baseFee) @@ -372,7 +372,7 @@ func (b *Backend) RPCBlockFromTendermintBlock( baseFee, err := b.BaseFee(blockRes) if err != nil { // handle the error for pruned node. - b.logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", block.Height, "error", err) + b.Logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", block.Height, "error", err) } msgs := b.EthMsgsFromTendermintBlock(resBlock, blockRes) @@ -392,10 +392,10 @@ func (b *Backend) RPCBlockFromTendermintBlock( height, index, baseFee, - b.chainID, + b.EvmChainID, ) if err != nil { - b.logger.Debug("NewTransactionFromData for receipt failed", "hash", tx.Hash().Hex(), "error", err.Error()) + b.Logger.Debug("NewTransactionFromData for receipt failed", "hash", tx.Hash().Hex(), "error", err.Error()) continue } ethRPCTxs = append(ethRPCTxs, rpcTx) @@ -403,7 +403,7 @@ func (b *Backend) RPCBlockFromTendermintBlock( bloom, err := b.BlockBloom(blockRes) if err != nil { - b.logger.Debug("failed to query BlockBloom", "height", block.Height, "error", err.Error()) + b.Logger.Debug("failed to query BlockBloom", "height", block.Height, "error", err.Error()) } req := &evmtypes.QueryValidatorAccountRequest{ @@ -413,9 +413,9 @@ func (b *Backend) RPCBlockFromTendermintBlock( var validatorAccAddr sdk.AccAddress ctx := rpctypes.ContextWithHeight(block.Height) - res, err := b.queryClient.ValidatorAccount(ctx, req) + res, err := b.QueryClient.ValidatorAccount(ctx, req) if err != nil { - b.logger.Debug( + b.Logger.Debug( "failed to query validator operator address", "height", block.Height, "cons-address", req.ConsAddress, @@ -432,9 +432,9 @@ func (b *Backend) RPCBlockFromTendermintBlock( validatorAddr := common.BytesToAddress(validatorAccAddr) - gasLimit, err := rpctypes.BlockMaxGasFromConsensusParams(ctx, b.clientCtx, block.Height) + gasLimit, err := rpctypes.BlockMaxGasFromConsensusParams(ctx, b.ClientCtx, block.Height) if err != nil { - b.logger.Error("failed to query consensus params", "error", err.Error()) + b.Logger.Error("failed to query consensus params", "error", err.Error()) } gasUsed := uint64(0) @@ -468,7 +468,7 @@ func (b *Backend) EthBlockByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Blo return nil, fmt.Errorf("block not found for height %d", blockNum) } - blockRes, err := b.rpcClient.BlockResults(b.ctx, &resBlock.Block.Height) + blockRes, err := b.RpcClient.BlockResults(b.Ctx, &resBlock.Block.Height) if err != nil { return nil, fmt.Errorf("block result not found for height %d", resBlock.Block.Height) } @@ -486,13 +486,13 @@ func (b *Backend) EthBlockFromTendermintBlock( height := block.Height bloom, err := b.BlockBloom(blockRes) if err != nil { - b.logger.Debug("HeaderByNumber BlockBloom failed", "height", height) + b.Logger.Debug("HeaderByNumber BlockBloom failed", "height", height) } baseFee, err := b.BaseFee(blockRes) if err != nil { // handle error for pruned node and log - b.logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", height, "error", err) + b.Logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", height, "error", err) } ethHeader := rpctypes.EthHeaderFromTendermint(block.Header, bloom, baseFee) @@ -530,7 +530,7 @@ func (b *Backend) GetBlockReceipts( return nil, fmt.Errorf("block not found for height %d", *blockNum.TmHeight()) } - blockRes, err := b.rpcClient.BlockResults(b.ctx, blockNum.TmHeight()) + blockRes, err := b.RpcClient.BlockResults(b.Ctx, blockNum.TmHeight()) if err != nil { return nil, fmt.Errorf("block result not found for height %d", resBlock.Block.Height) } @@ -592,7 +592,7 @@ func (b *Backend) formatTxReceipt(ethMsg *evmtypes.MsgEthereumTx, blockMsgs []*e msgIndex := int(txResult.MsgIndex) // #nosec G115 -- checked for int overflow already logs, err := TxLogsFromEvents(blockRes.TxsResults[txResult.TxIndex].Events, msgIndex) if err != nil { - b.logger.Debug("failed to parse logs", "hash", ethMsg.Hash, "error", err.Error()) + b.Logger.Debug("failed to parse logs", "hash", ethMsg.Hash, "error", err.Error()) } if txResult.EthTxIndex == -1 { @@ -650,7 +650,7 @@ func (b *Backend) formatTxReceipt(ethMsg *evmtypes.MsgEthereumTx, blockMsgs []*e baseFee, err := b.BaseFee(blockRes) if err != nil { // tolerate the error for pruned node. - b.logger.Error("fetch basefee failed, node is pruned?", "height", txResult.Height, "error", err) + b.Logger.Error("fetch basefee failed, node is pruned?", "height", txResult.Height, "error", err) } else { receipt["effectiveGasPrice"] = hexutil.Big(*dynamicTx.EffectiveGasPrice(baseFee)) } diff --git a/rpc/backend/call_tx.go b/rpc/backend/call_tx.go index cb37232f4..edd4084ab 100644 --- a/rpc/backend/call_tx.go +++ b/rpc/backend/call_tx.go @@ -40,7 +40,7 @@ func (b *Backend) Resend(args evmtypes.TransactionArgs, gasPrice *hexutil.Big, g // signers to be backwards-compatible with old transactions. cfg := b.ChainConfig() if cfg == nil { - cfg = evmtypes.DefaultChainConfig(b.chainID.Uint64()).EthereumConfig(nil) + cfg = evmtypes.DefaultChainConfig(b.EvmChainID.Uint64()).EthereumConfig(nil) } signer := ethtypes.LatestSigner(cfg) @@ -102,7 +102,7 @@ func (b *Backend) SendRawTransaction(data hexutil.Bytes) (common.Hash, error) { // RLP decode raw transaction bytes tx := ðtypes.Transaction{} if err := tx.UnmarshalBinary(data); err != nil { - b.logger.Error("transaction decoding failed", "error", err.Error()) + b.Logger.Error("transaction decoding failed", "error", err.Error()) return common.Hash{}, err } @@ -112,46 +112,46 @@ func (b *Backend) SendRawTransaction(data hexutil.Bytes) (common.Hash, error) { // Ensure only eip155 signed transactions are submitted if EIP155Required is set. return common.Hash{}, errors.New("only replay-protected (EIP-155) transactions allowed over RPC") } - if tx.ChainId().Uint64() != b.chainID.Uint64() { - return common.Hash{}, fmt.Errorf("incorrect chain-id; expected %d, got %d", b.chainID, tx.ChainId()) + if tx.ChainId().Uint64() != b.EvmChainID.Uint64() { + return common.Hash{}, fmt.Errorf("incorrect chain-id; expected %d, got %d", b.EvmChainID, tx.ChainId()) } } ethereumTx := &evmtypes.MsgEthereumTx{} if err := ethereumTx.FromEthereumTx(tx); err != nil { - b.logger.Error("transaction converting failed", "error", err.Error()) + b.Logger.Error("transaction converting failed", "error", err.Error()) return common.Hash{}, err } if err := ethereumTx.ValidateBasic(); err != nil { - b.logger.Debug("tx failed basic validation", "error", err.Error()) + b.Logger.Debug("tx failed basic validation", "error", err.Error()) return common.Hash{}, err } baseDenom := evmtypes.GetEVMCoinDenom() - cosmosTx, err := ethereumTx.BuildTx(b.clientCtx.TxConfig.NewTxBuilder(), baseDenom) + cosmosTx, err := ethereumTx.BuildTx(b.ClientCtx.TxConfig.NewTxBuilder(), baseDenom) if err != nil { - b.logger.Error("failed to build cosmos tx", "error", err.Error()) + b.Logger.Error("failed to build cosmos tx", "error", err.Error()) return common.Hash{}, err } // Encode transaction by default Tx encoder - txBytes, err := b.clientCtx.TxConfig.TxEncoder()(cosmosTx) + txBytes, err := b.ClientCtx.TxConfig.TxEncoder()(cosmosTx) if err != nil { - b.logger.Error("failed to encode eth tx using default encoder", "error", err.Error()) + b.Logger.Error("failed to encode eth tx using default encoder", "error", err.Error()) return common.Hash{}, err } txHash := ethereumTx.AsTransaction().Hash() - syncCtx := b.clientCtx.WithBroadcastMode(flags.BroadcastSync) + syncCtx := b.ClientCtx.WithBroadcastMode(flags.BroadcastSync) rsp, err := syncCtx.BroadcastTx(txBytes) if rsp != nil && rsp.Code != 0 { err = errorsmod.ABCIError(rsp.Codespace, rsp.Code, rsp.RawLog) } if err != nil { - b.logger.Error("failed to broadcast tx", "error", err.Error()) + b.Logger.Error("failed to broadcast tx", "error", err.Error()) return txHash, err } @@ -226,7 +226,7 @@ func (b *Backend) SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.Transac if args.Nonce == nil { // get the nonce from the account retriever // ignore error in case tge account doesn't exist yet - nonce, _ := b.getAccountNonce(*args.From, true, 0, b.logger) // #nosec G703s + nonce, _ := b.getAccountNonce(*args.From, true, 0, b.Logger) // #nosec G703s args.Nonce = (*hexutil.Uint64)(&nonce) } @@ -276,11 +276,11 @@ func (b *Backend) SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.Transac return args, err } args.Gas = &estimated - b.logger.Debug("estimate gas usage automatically", "gas", args.Gas) + b.Logger.Debug("estimate gas usage automatically", "gas", args.Gas) } if args.ChainID == nil { - args.ChainID = (*hexutil.Big)(b.chainID) + args.ChainID = (*hexutil.Big)(b.EvmChainID) } return args, nil @@ -308,13 +308,13 @@ func (b *Backend) EstimateGas(args evmtypes.TransactionArgs, blockNrOptional *rp Args: bz, GasCap: b.RPCGasCap(), ProposerAddress: sdk.ConsAddress(header.Block.ProposerAddress), - ChainId: b.chainID.Int64(), + ChainId: b.EvmChainID.Int64(), } // From ContextWithHeight: if the provided height is 0, // it will return an empty context and the gRPC query will use // the latest block height for querying. - res, err := b.queryClient.EstimateGas(rpctypes.ContextWithHeight(blockNr.Int64()), &req) + res, err := b.QueryClient.EstimateGas(rpctypes.ContextWithHeight(blockNr.Int64()), &req) if err != nil { return 0, err } @@ -343,7 +343,7 @@ func (b *Backend) DoCall( Args: bz, GasCap: b.RPCGasCap(), ProposerAddress: sdk.ConsAddress(header.Block.ProposerAddress), - ChainId: b.chainID.Int64(), + ChainId: b.EvmChainID.Int64(), } // From ContextWithHeight: if the provided height is 0, @@ -365,7 +365,7 @@ func (b *Backend) DoCall( // this makes sure resources are cleaned up. defer cancel() - res, err := b.queryClient.EthCall(ctx, &req) + res, err := b.QueryClient.EthCall(ctx, &req) if err != nil { return nil, err } diff --git a/rpc/backend/chain_info.go b/rpc/backend/chain_info.go index 5058b030a..87d662bbf 100644 --- a/rpc/backend/chain_info.go +++ b/rpc/backend/chain_info.go @@ -24,11 +24,11 @@ import ( // ChainID is the EIP-155 replay-protection chain id for the current ethereum chain config. func (b *Backend) ChainID() (*hexutil.Big, error) { - // if current block is at or past the EIP-155 replay-protection fork block, return chainID from config + // if current block is at or past the EIP-155 replay-protection fork block, return EvmChainID from config bn, err := b.BlockNumber() if err != nil { - b.logger.Debug("failed to fetch latest block number", "error", err.Error()) - return (*hexutil.Big)(b.chainID), nil + b.Logger.Debug("failed to fetch latest block number", "error", err.Error()) + return (*hexutil.Big)(b.EvmChainID), nil } if config := b.ChainConfig(); config.IsEIP155(new(big.Int).SetUint64(uint64(bn))) { @@ -45,7 +45,7 @@ func (b *Backend) ChainConfig() *params.ChainConfig { // GlobalMinGasPrice returns MinGasPrice param from FeeMarket func (b *Backend) GlobalMinGasPrice() (*big.Int, error) { - res, err := b.queryClient.GlobalMinGasPrice(b.ctx, &evmtypes.QueryGlobalMinGasPriceRequest{}) + res, err := b.QueryClient.GlobalMinGasPrice(b.Ctx, &evmtypes.QueryGlobalMinGasPriceRequest{}) if err != nil { return nil, err } @@ -61,7 +61,7 @@ func (b *Backend) GlobalMinGasPrice() (*big.Int, error) { // return nil. func (b *Backend) BaseFee(blockRes *cmtrpctypes.ResultBlockResults) (*big.Int, error) { // return BaseFee if London hard fork is activated and feemarket is enabled - res, err := b.queryClient.BaseFee(rpctypes.ContextWithHeight(blockRes.Height), &evmtypes.QueryBaseFeeRequest{}) + res, err := b.QueryClient.BaseFee(rpctypes.ContextWithHeight(blockRes.Height), &evmtypes.QueryBaseFeeRequest{}) if err != nil || res.BaseFee == nil { // we can't tell if it's london HF not enabled or the state is pruned, // in either case, we'll fallback to parsing from begin blocker event, @@ -96,19 +96,19 @@ func (b *Backend) CurrentHeader() (*ethtypes.Header, error) { // PendingTransactions returns the transactions that are in the transaction pool // and have a from address that is one of the accounts this node manages. func (b *Backend) PendingTransactions() ([]*sdk.Tx, error) { - mc, ok := b.clientCtx.Client.(cmtrpcclient.MempoolClient) + mc, ok := b.ClientCtx.Client.(cmtrpcclient.MempoolClient) if !ok { return nil, errors.New("invalid rpc client") } - res, err := mc.UnconfirmedTxs(b.ctx, nil) + res, err := mc.UnconfirmedTxs(b.Ctx, nil) if err != nil { return nil, err } result := make([]*sdk.Tx, 0, len(res.Txs)) for _, txBz := range res.Txs { - tx, err := b.clientCtx.TxConfig.TxDecoder()(txBz) + tx, err := b.ClientCtx.TxConfig.TxDecoder()(txBz) if err != nil { return nil, err } @@ -120,12 +120,12 @@ func (b *Backend) PendingTransactions() ([]*sdk.Tx, error) { // GetCoinbase is the address that staking rewards will be send to (alias for Etherbase). func (b *Backend) GetCoinbase() (sdk.AccAddress, error) { - node, err := b.clientCtx.GetNode() + node, err := b.ClientCtx.GetNode() if err != nil { return nil, err } - status, err := node.Status(b.ctx) + status, err := node.Status(b.Ctx) if err != nil { return nil, err } @@ -134,7 +134,7 @@ func (b *Backend) GetCoinbase() (sdk.AccAddress, error) { ConsAddress: sdk.ConsAddress(status.ValidatorInfo.Address).String(), } - res, err := b.queryClient.ValidatorAccount(b.ctx, req) + res, err := b.QueryClient.ValidatorAccount(b.Ctx, req) if err != nil { return nil, err } @@ -160,7 +160,7 @@ func (b *Backend) FeeHistory( } blocks := int64(userBlockCount) // #nosec G115 -- checked for int overflow already - maxBlockCount := int64(b.cfg.JSONRPC.FeeHistoryCap) // #nosec G115 -- checked for int overflow already + maxBlockCount := int64(b.Cfg.JSONRPC.FeeHistoryCap) // #nosec G115 -- checked for int overflow already if blocks > maxBlockCount { return nil, fmt.Errorf("FeeHistory user block count %d higher than %d", blocks, maxBlockCount) } @@ -201,9 +201,9 @@ func (b *Backend) FeeHistory( } // tendermint block result - tendermintBlockResult, err := b.rpcClient.BlockResults(b.ctx, &tendermintblock.Block.Height) + tendermintBlockResult, err := b.RpcClient.BlockResults(b.Ctx, &tendermintblock.Block.Height) if tendermintBlockResult == nil { - b.logger.Debug("block result not found", "height", tendermintblock.Block.Height, "error", err.Error()) + b.Logger.Debug("block result not found", "height", tendermintblock.Block.Height, "error", err.Error()) return nil, err } @@ -249,7 +249,7 @@ func (b *Backend) SuggestGasTipCap(baseFee *big.Int) (*big.Int, error) { return big.NewInt(0), nil } - params, err := b.queryClient.FeeMarket.Params(b.ctx, &feemarkettypes.QueryParamsRequest{}) + params, err := b.QueryClient.FeeMarket.Params(b.Ctx, &feemarkettypes.QueryParamsRequest{}) if err != nil { return nil, err } diff --git a/rpc/backend/filters.go b/rpc/backend/filters.go index 4d4ed5005..d5cdc0b2c 100644 --- a/rpc/backend/filters.go +++ b/rpc/backend/filters.go @@ -21,7 +21,7 @@ func (b *Backend) GetLogs(hash common.Hash) ([][]*ethtypes.Log, error) { // GetLogsByHeight returns all the logs from all the ethereum transactions in a block. func (b *Backend) GetLogsByHeight(height *int64) ([][]*ethtypes.Log, error) { // NOTE: we query the state in case the tx result logs are not persisted after an upgrade. - blockRes, err := b.rpcClient.BlockResults(b.ctx, height) + blockRes, err := b.RpcClient.BlockResults(b.Ctx, height) if err != nil { return nil, err } diff --git a/rpc/backend/node_info.go b/rpc/backend/node_info.go index 2d594a7dd..60e204351 100644 --- a/rpc/backend/node_info.go +++ b/rpc/backend/node_info.go @@ -34,12 +34,12 @@ import ( func (b *Backend) Accounts() ([]common.Address, error) { addresses := make([]common.Address, 0) // return [] instead of nil if empty - if !b.cfg.JSONRPC.AllowInsecureUnlock { - b.logger.Debug("account unlock with HTTP access is forbidden") + if !b.Cfg.JSONRPC.AllowInsecureUnlock { + b.Logger.Debug("account unlock with HTTP access is forbidden") return addresses, fmt.Errorf("account unlock with HTTP access is forbidden") } - infos, err := b.clientCtx.Keyring.List() + infos, err := b.ClientCtx.Keyring.List() if err != nil { return addresses, err } @@ -64,7 +64,7 @@ func (b *Backend) Accounts() ([]common.Address, error) { // - pulledStates: number of state entries processed until now // - knownStates: number of known state entries that still need to be pulled func (b *Backend) Syncing() (interface{}, error) { - status, err := b.clientCtx.Client.Status(b.ctx) + status, err := b.ClientCtx.Client.Status(b.Ctx) if err != nil { return false, err } @@ -84,14 +84,14 @@ func (b *Backend) Syncing() (interface{}, error) { // SetEtherbase sets the etherbase of the miner func (b *Backend) SetEtherbase(etherbase common.Address) bool { - if !b.cfg.JSONRPC.AllowInsecureUnlock { - b.logger.Debug("account unlock with HTTP access is forbidden") + if !b.Cfg.JSONRPC.AllowInsecureUnlock { + b.Logger.Debug("account unlock with HTTP access is forbidden") return false } delAddr, err := b.GetCoinbase() if err != nil { - b.logger.Debug("failed to get coinbase address", "error", err.Error()) + b.Logger.Debug("failed to get coinbase address", "error", err.Error()) return false } @@ -99,22 +99,22 @@ func (b *Backend) SetEtherbase(etherbase common.Address) bool { msg := distributiontypes.NewMsgSetWithdrawAddress(delAddr, withdrawAddr) // Assemble transaction from fields - builder, ok := b.clientCtx.TxConfig.NewTxBuilder().(authtx.ExtensionOptionsTxBuilder) + builder, ok := b.ClientCtx.TxConfig.NewTxBuilder().(authtx.ExtensionOptionsTxBuilder) if !ok { - b.logger.Debug("clientCtx.TxConfig.NewTxBuilder returns unsupported builder", "error", err.Error()) + b.Logger.Debug("clientCtx.TxConfig.NewTxBuilder returns unsupported builder", "error", err.Error()) return false } err = builder.SetMsgs(msg) if err != nil { - b.logger.Error("builder.SetMsgs failed", "error", err.Error()) + b.Logger.Error("builder.SetMsgs failed", "error", err.Error()) return false } // Fetch minimum gas price to calculate fees using the configuration. - minGasPrices := b.cfg.GetMinGasPrices() + minGasPrices := b.Cfg.GetMinGasPrices() if len(minGasPrices) == 0 || minGasPrices.Empty() { - b.logger.Debug("the minimum fee is not set") + b.Logger.Debug("the minimum fee is not set") return false } minGasPriceValue := minGasPrices[0].Amount @@ -123,21 +123,21 @@ func (b *Backend) SetEtherbase(etherbase common.Address) bool { delCommonAddr := common.BytesToAddress(delAddr.Bytes()) nonce, err := b.GetTransactionCount(delCommonAddr, rpctypes.EthPendingBlockNumber) if err != nil { - b.logger.Debug("failed to get nonce", "error", err.Error()) + b.Logger.Debug("failed to get nonce", "error", err.Error()) return false } txFactory := tx.Factory{} txFactory = txFactory. - WithChainID(b.clientCtx.ChainID). - WithKeybase(b.clientCtx.Keyring). - WithTxConfig(b.clientCtx.TxConfig). + WithChainID(b.ClientCtx.ChainID). + WithKeybase(b.ClientCtx.Keyring). + WithTxConfig(b.ClientCtx.TxConfig). WithSequence(uint64(*nonce)). WithGasAdjustment(1.25) - _, gas, err := tx.CalculateGas(b.clientCtx, txFactory, msg) + _, gas, err := tx.CalculateGas(b.ClientCtx, txFactory, msg) if err != nil { - b.logger.Debug("failed to calculate gas", "error", err.Error()) + b.Logger.Debug("failed to calculate gas", "error", err.Error()) return false } @@ -148,22 +148,22 @@ func (b *Backend) SetEtherbase(etherbase common.Address) bool { builder.SetFeeAmount(fees) builder.SetGasLimit(gas) - keyInfo, err := b.clientCtx.Keyring.KeyByAddress(delAddr) + keyInfo, err := b.ClientCtx.Keyring.KeyByAddress(delAddr) if err != nil { - b.logger.Debug("failed to get the wallet address using the keyring", "error", err.Error()) + b.Logger.Debug("failed to get the wallet address using the keyring", "error", err.Error()) return false } - if err := tx.Sign(b.clientCtx.CmdContext, txFactory, keyInfo.Name, builder, false); err != nil { - b.logger.Debug("failed to sign tx", "error", err.Error()) + if err := tx.Sign(b.ClientCtx.CmdContext, txFactory, keyInfo.Name, builder, false); err != nil { + b.Logger.Debug("failed to sign tx", "error", err.Error()) return false } // Encode transaction by default Tx encoder - txEncoder := b.clientCtx.TxConfig.TxEncoder() + txEncoder := b.ClientCtx.TxConfig.TxEncoder() txBytes, err := txEncoder(builder.GetTx()) if err != nil { - b.logger.Debug("failed to encode eth tx using default encoder", "error", err.Error()) + b.Logger.Debug("failed to encode eth tx using default encoder", "error", err.Error()) return false } @@ -171,17 +171,17 @@ func (b *Backend) SetEtherbase(etherbase common.Address) bool { // Broadcast transaction in sync mode (default) // NOTE: If error is encountered on the node, the broadcast will not return an error - syncCtx := b.clientCtx.WithBroadcastMode(flags.BroadcastSync) + syncCtx := b.ClientCtx.WithBroadcastMode(flags.BroadcastSync) rsp, err := syncCtx.BroadcastTx(txBytes) if rsp != nil && rsp.Code != 0 { err = errorsmod.ABCIError(rsp.Codespace, rsp.Code, rsp.RawLog) } if err != nil { - b.logger.Debug("failed to broadcast tx", "error", err.Error()) + b.Logger.Debug("failed to broadcast tx", "error", err.Error()) return false } - b.logger.Debug("broadcasted tx to set miner withdraw address (etherbase)", "hash", tmHash.String()) + b.Logger.Debug("broadcasted tx to set miner withdraw address (etherbase)", "hash", tmHash.String()) return true } @@ -202,21 +202,21 @@ func (b *Backend) ImportRawKey(privkey, password string) (common.Address, error) ethereumAddr := common.BytesToAddress(addr) // return if the key has already been imported - if _, err := b.clientCtx.Keyring.KeyByAddress(addr); err == nil { + if _, err := b.ClientCtx.Keyring.KeyByAddress(addr); err == nil { return ethereumAddr, nil } // ignore error as we only care about the length of the list - list, _ := b.clientCtx.Keyring.List() // #nosec G703 + list, _ := b.ClientCtx.Keyring.List() // #nosec G703 privKeyName := fmt.Sprintf("personal_%d", len(list)) armor := sdkcrypto.EncryptArmorPrivKey(privKey, password, ethsecp256k1.KeyType) - if err := b.clientCtx.Keyring.ImportPrivKey(privKeyName, armor, password); err != nil { + if err := b.ClientCtx.Keyring.ImportPrivKey(privKeyName, armor, password); err != nil { return common.Address{}, err } - b.logger.Info("key successfully imported", "name", privKeyName, "address", ethereumAddr.String()) + b.Logger.Info("key successfully imported", "name", privKeyName, "address", ethereumAddr.String()) return ethereumAddr, nil } @@ -225,12 +225,12 @@ func (b *Backend) ImportRawKey(privkey, password string) (common.Address, error) func (b *Backend) ListAccounts() ([]common.Address, error) { addrs := []common.Address{} - if !b.cfg.JSONRPC.AllowInsecureUnlock { - b.logger.Debug("account unlock with HTTP access is forbidden") + if !b.Cfg.JSONRPC.AllowInsecureUnlock { + b.Logger.Debug("account unlock with HTTP access is forbidden") return addrs, fmt.Errorf("account unlock with HTTP access is forbidden") } - list, err := b.clientCtx.Keyring.List() + list, err := b.ClientCtx.Keyring.List() if err != nil { return nil, err } @@ -253,7 +253,7 @@ func (b *Backend) NewMnemonic(uid string, bip39Passphrase string, algo keyring.SignatureAlgo, ) (*keyring.Record, error) { - info, _, err := b.clientCtx.Keyring.NewMnemonic(uid, keyring.English, hdPath, bip39Passphrase, algo) + info, _, err := b.ClientCtx.Keyring.NewMnemonic(uid, keyring.English, hdPath, bip39Passphrase, algo) if err != nil { return nil, err } @@ -264,16 +264,16 @@ func (b *Backend) NewMnemonic(uid string, // NOTE: this function accepts only integers to have the same interface than go-eth // to use float values, the gas prices must be configured using the configuration file func (b *Backend) SetGasPrice(gasPrice hexutil.Big) bool { - appConf, err := config.GetConfig(b.clientCtx.Viper) + appConf, err := config.GetConfig(b.ClientCtx.Viper) if err != nil { - b.logger.Debug("could not get the server config", "error", err.Error()) + b.Logger.Debug("could not get the server config", "error", err.Error()) return false } c := b.GenerateMinGasCoin(gasPrice, appConf) appConf.SetMinGasPrices(sdk.DecCoins{c}) - sdkconfig.WriteConfigFile(b.clientCtx.Viper.ConfigFileUsed(), appConf) - b.logger.Info("Your configuration file was modified. Please RESTART your node.", "gas-price", c.String()) + sdkconfig.WriteConfigFile(b.ClientCtx.Viper.ConfigFileUsed(), appConf) + b.Logger.Info("Your configuration file was modified. Please RESTART your node.", "gas-price", c.String()) return true } @@ -299,42 +299,42 @@ func (b *Backend) GenerateMinGasCoin(gasPrice hexutil.Big, appConf config.Config // UnprotectedAllowed returns the node configuration value for allowing // unprotected transactions (i.e not replay-protected) func (b Backend) UnprotectedAllowed() bool { - return b.allowUnprotectedTxs + return b.AllowUnprotectedTxs } // RPCGasCap is the global gas cap for eth-call variants. func (b *Backend) RPCGasCap() uint64 { - return b.cfg.JSONRPC.GasCap + return b.Cfg.JSONRPC.GasCap } // RPCEVMTimeout is the global evm timeout for eth-call variants. func (b *Backend) RPCEVMTimeout() time.Duration { - return b.cfg.JSONRPC.EVMTimeout + return b.Cfg.JSONRPC.EVMTimeout } // RPCGasCap is the global gas cap for eth-call variants. func (b *Backend) RPCTxFeeCap() float64 { - return b.cfg.JSONRPC.TxFeeCap + return b.Cfg.JSONRPC.TxFeeCap } // RPCFilterCap is the limit for total number of filters that can be created func (b *Backend) RPCFilterCap() int32 { - return b.cfg.JSONRPC.FilterCap + return b.Cfg.JSONRPC.FilterCap } // RPCFeeHistoryCap is the limit for total number of blocks that can be fetched func (b *Backend) RPCFeeHistoryCap() int32 { - return b.cfg.JSONRPC.FeeHistoryCap + return b.Cfg.JSONRPC.FeeHistoryCap } // RPCLogsCap defines the max number of results can be returned from single `eth_getLogs` query. func (b *Backend) RPCLogsCap() int32 { - return b.cfg.JSONRPC.LogsCap + return b.Cfg.JSONRPC.LogsCap } // RPCBlockRangeCap defines the max block range allowed for `eth_getLogs` query. func (b *Backend) RPCBlockRangeCap() int32 { - return b.cfg.JSONRPC.BlockRangeCap + return b.Cfg.JSONRPC.BlockRangeCap } // RPCMinGasPrice returns the minimum gas price for a transaction obtained from @@ -342,7 +342,7 @@ func (b *Backend) RPCBlockRangeCap() int32 { func (b *Backend) RPCMinGasPrice() *big.Int { baseDenom := evmtypes.GetEVMCoinDenom() - minGasPrice := b.cfg.GetMinGasPrices() + minGasPrice := b.Cfg.GetMinGasPrices() amt := minGasPrice.AmountOf(baseDenom) if amt.IsNil() || amt.IsZero() { return big.NewInt(constants.DefaultGasPrice) diff --git a/rpc/backend/sign_tx.go b/rpc/backend/sign_tx.go index bdd52851c..b1c6bbbdc 100644 --- a/rpc/backend/sign_tx.go +++ b/rpc/backend/sign_tx.go @@ -24,19 +24,19 @@ import ( // SendTransaction sends transaction based on received args using Node's key to sign it func (b *Backend) SendTransaction(args evmtypes.TransactionArgs) (common.Hash, error) { // Look up the wallet containing the requested signer - if !b.cfg.JSONRPC.AllowInsecureUnlock { - b.logger.Debug("account unlock with HTTP access is forbidden") + if !b.Cfg.JSONRPC.AllowInsecureUnlock { + b.Logger.Debug("account unlock with HTTP access is forbidden") return common.Hash{}, fmt.Errorf("account unlock with HTTP access is forbidden") } - _, err := b.clientCtx.Keyring.KeyByAddress(sdk.AccAddress(args.GetFrom().Bytes())) + _, err := b.ClientCtx.Keyring.KeyByAddress(sdk.AccAddress(args.GetFrom().Bytes())) if err != nil { - b.logger.Error("failed to find key in keyring", "address", args.GetFrom(), "error", err.Error()) + b.Logger.Error("failed to find key in keyring", "address", args.GetFrom(), "error", err.Error()) return common.Hash{}, fmt.Errorf("failed to find key in the node's keyring; %s; %s", keystore.ErrNoMatch, err.Error()) } - if args.ChainID != nil && (b.chainID).Cmp((*big.Int)(args.ChainID)) != 0 { - return common.Hash{}, fmt.Errorf("chainId does not match node's (have=%v, want=%v)", args.ChainID, (*hexutil.Big)(b.chainID)) + if args.ChainID != nil && (b.EvmChainID).Cmp((*big.Int)(args.ChainID)) != 0 { + return common.Hash{}, fmt.Errorf("chainId does not match node's (have=%v, want=%v)", args.ChainID, (*hexutil.Big)(b.EvmChainID)) } args, err = b.SetTxDefaults(args) @@ -46,7 +46,7 @@ func (b *Backend) SendTransaction(args evmtypes.TransactionArgs) (common.Hash, e bn, err := b.BlockNumber() if err != nil { - b.logger.Debug("failed to fetch latest block number", "error", err.Error()) + b.Logger.Debug("failed to fetch latest block number", "error", err.Error()) return common.Hash{}, err } @@ -57,35 +57,35 @@ func (b *Backend) SendTransaction(args evmtypes.TransactionArgs) (common.Hash, e signer := ethtypes.MakeSigner(b.ChainConfig(), new(big.Int).SetUint64(uint64(bn)), header.Time) - // LegacyTx derives chainID from the signature. To make sure the msg.ValidateBasic makes - // the corresponding chainID validation, we need to sign the transaction before calling it + // LegacyTx derives EvmChainID from the signature. To make sure the msg.ValidateBasic makes + // the corresponding EvmChainID validation, we need to sign the transaction before calling it // Sign transaction msg := args.ToTransaction() - if err := msg.Sign(signer, b.clientCtx.Keyring); err != nil { - b.logger.Debug("failed to sign tx", "error", err.Error()) + if err := msg.Sign(signer, b.ClientCtx.Keyring); err != nil { + b.Logger.Debug("failed to sign tx", "error", err.Error()) return common.Hash{}, err } if err := msg.ValidateBasic(); err != nil { - b.logger.Debug("tx failed basic validation", "error", err.Error()) + b.Logger.Debug("tx failed basic validation", "error", err.Error()) return common.Hash{}, err } baseDenom := evmtypes.GetEVMCoinDenom() // Assemble transaction from fields - tx, err := msg.BuildTx(b.clientCtx.TxConfig.NewTxBuilder(), baseDenom) + tx, err := msg.BuildTx(b.ClientCtx.TxConfig.NewTxBuilder(), baseDenom) if err != nil { - b.logger.Error("build cosmos tx failed", "error", err.Error()) + b.Logger.Error("build cosmos tx failed", "error", err.Error()) return common.Hash{}, err } // Encode transaction by default Tx encoder - txEncoder := b.clientCtx.TxConfig.TxEncoder() + txEncoder := b.ClientCtx.TxConfig.TxEncoder() txBytes, err := txEncoder(tx) if err != nil { - b.logger.Error("failed to encode eth tx using default encoder", "error", err.Error()) + b.Logger.Error("failed to encode eth tx using default encoder", "error", err.Error()) return common.Hash{}, err } @@ -101,13 +101,13 @@ func (b *Backend) SendTransaction(args evmtypes.TransactionArgs) (common.Hash, e // Broadcast transaction in sync mode (default) // NOTE: If error is encountered on the node, the broadcast will not return an error - syncCtx := b.clientCtx.WithBroadcastMode(flags.BroadcastSync) + syncCtx := b.ClientCtx.WithBroadcastMode(flags.BroadcastSync) rsp, err := syncCtx.BroadcastTx(txBytes) if rsp != nil && rsp.Code != 0 { err = errorsmod.ABCIError(rsp.Codespace, rsp.Code, rsp.RawLog) } if err != nil { - b.logger.Error("failed to broadcast tx", "error", err.Error()) + b.Logger.Error("failed to broadcast tx", "error", err.Error()) return txHash, err } @@ -119,16 +119,16 @@ func (b *Backend) SendTransaction(args evmtypes.TransactionArgs) (common.Hash, e func (b *Backend) Sign(address common.Address, data hexutil.Bytes) (hexutil.Bytes, error) { from := sdk.AccAddress(address.Bytes()) - _, err := b.clientCtx.Keyring.KeyByAddress(from) + _, err := b.ClientCtx.Keyring.KeyByAddress(from) if err != nil { - b.logger.Error("failed to find key in keyring", "address", address.String()) + b.Logger.Error("failed to find key in keyring", "address", address.String()) return nil, fmt.Errorf("%s; %s", keystore.ErrNoMatch, err.Error()) } // Sign the requested hash with the wallet - signature, _, err := b.clientCtx.Keyring.SignByAddress(from, data, signingtypes.SignMode_SIGN_MODE_TEXTUAL) + signature, _, err := b.ClientCtx.Keyring.SignByAddress(from, data, signingtypes.SignMode_SIGN_MODE_TEXTUAL) if err != nil { - b.logger.Error("keyring.SignByAddress failed", "address", address.Hex()) + b.Logger.Error("keyring.SignByAddress failed", "address", address.Hex()) return nil, err } @@ -140,9 +140,9 @@ func (b *Backend) Sign(address common.Address, data hexutil.Bytes) (hexutil.Byte func (b *Backend) SignTypedData(address common.Address, typedData apitypes.TypedData) (hexutil.Bytes, error) { from := sdk.AccAddress(address.Bytes()) - _, err := b.clientCtx.Keyring.KeyByAddress(from) + _, err := b.ClientCtx.Keyring.KeyByAddress(from) if err != nil { - b.logger.Error("failed to find key in keyring", "address", address.String()) + b.Logger.Error("failed to find key in keyring", "address", address.String()) return nil, fmt.Errorf("%s; %s", keystore.ErrNoMatch, err.Error()) } @@ -152,9 +152,9 @@ func (b *Backend) SignTypedData(address common.Address, typedData apitypes.Typed } // Sign the requested hash with the wallet - signature, _, err := b.clientCtx.Keyring.SignByAddress(from, sigHash, signingtypes.SignMode_SIGN_MODE_TEXTUAL) + signature, _, err := b.ClientCtx.Keyring.SignByAddress(from, sigHash, signingtypes.SignMode_SIGN_MODE_TEXTUAL) if err != nil { - b.logger.Error("keyring.SignByAddress failed", "address", address.Hex()) + b.Logger.Error("keyring.SignByAddress failed", "address", address.Hex()) return nil, err } diff --git a/rpc/backend/tracing.go b/rpc/backend/tracing.go index 788ecf5d9..5959721d1 100644 --- a/rpc/backend/tracing.go +++ b/rpc/backend/tracing.go @@ -23,7 +23,7 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi // Get transaction by hash transaction, err := b.GetTxByEthHash(hash) if err != nil { - b.logger.Debug("tx not found", "hash", hash) + b.Logger.Debug("tx not found", "hash", hash) return nil, err } @@ -34,7 +34,7 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi blk, err := b.TendermintBlockByNumber(rpctypes.BlockNumber(transaction.Height)) if err != nil { - b.logger.Debug("block not found", "height", transaction.Height) + b.Logger.Debug("block not found", "height", transaction.Height) return nil, err } @@ -44,15 +44,15 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi } txsLen := uint32(len(blk.Block.Txs)) // #nosec G115 -- checked for int overflow already if txsLen < transaction.TxIndex { - b.logger.Debug("tx index out of bounds", "index", transaction.TxIndex, "hash", hash.String(), "height", blk.Block.Height) + b.Logger.Debug("tx index out of bounds", "index", transaction.TxIndex, "hash", hash.String(), "height", blk.Block.Height) return nil, fmt.Errorf("transaction not included in block %v", blk.Block.Height) } var predecessors []*evmtypes.MsgEthereumTx for _, txBz := range blk.Block.Txs[:transaction.TxIndex] { - tx, err := b.clientCtx.TxConfig.TxDecoder()(txBz) + tx, err := b.ClientCtx.TxConfig.TxDecoder()(txBz) if err != nil { - b.logger.Debug("failed to decode transaction in block", "height", blk.Block.Height, "error", err.Error()) + b.Logger.Debug("failed to decode transaction in block", "height", blk.Block.Height, "error", err.Error()) continue } for _, msg := range tx.GetMsgs() { @@ -65,9 +65,9 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi } } - tx, err := b.clientCtx.TxConfig.TxDecoder()(blk.Block.Txs[transaction.TxIndex]) + tx, err := b.ClientCtx.TxConfig.TxDecoder()(blk.Block.Txs[transaction.TxIndex]) if err != nil { - b.logger.Debug("tx not found", "hash", hash) + b.Logger.Debug("tx not found", "hash", hash) return nil, err } @@ -83,16 +83,16 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi ethMessage, ok := tx.GetMsgs()[transaction.MsgIndex].(*evmtypes.MsgEthereumTx) if !ok { - b.logger.Debug("invalid transaction type", "type", fmt.Sprintf("%T", tx)) + b.Logger.Debug("invalid transaction type", "type", fmt.Sprintf("%T", tx)) return nil, fmt.Errorf("invalid transaction type %T", tx) } - nc, ok := b.clientCtx.Client.(tmrpcclient.NetworkClient) + nc, ok := b.ClientCtx.Client.(tmrpcclient.NetworkClient) if !ok { return nil, errors.New("invalid rpc client") } - cp, err := nc.ConsensusParams(b.ctx, &blk.Block.Height) + cp, err := nc.ConsensusParams(b.Ctx, &blk.Block.Height) if err != nil { return nil, err } @@ -104,7 +104,7 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi BlockTime: blk.Block.Time, BlockHash: common.Bytes2Hex(blk.BlockID.Hash), ProposerAddress: sdk.ConsAddress(blk.Block.ProposerAddress), - ChainId: b.chainID.Int64(), + ChainId: b.EvmChainID.Int64(), BlockMaxGas: cp.ConsensusParams.Block.MaxGas, } @@ -118,7 +118,7 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi // 0 is a special value in `ContextWithHeight` contextHeight = 1 } - traceResult, err := b.queryClient.TraceTx(rpctypes.ContextWithHeight(contextHeight), &traceTxRequest) + traceResult, err := b.QueryClient.TraceTx(rpctypes.ContextWithHeight(contextHeight), &traceTxRequest) if err != nil { return nil, err } @@ -149,13 +149,13 @@ func (b *Backend) TraceBlock(height rpctypes.BlockNumber, return []*evmtypes.TxTraceResult{}, nil } - txDecoder := b.clientCtx.TxConfig.TxDecoder() + txDecoder := b.ClientCtx.TxConfig.TxDecoder() var txsMessages []*evmtypes.MsgEthereumTx for i, tx := range txs { decodedTx, err := txDecoder(tx) if err != nil { - b.logger.Error("failed to decode transaction", "hash", txs[i].Hash(), "error", err.Error()) + b.Logger.Error("failed to decode transaction", "hash", txs[i].Hash(), "error", err.Error()) continue } @@ -177,12 +177,12 @@ func (b *Backend) TraceBlock(height rpctypes.BlockNumber, } ctxWithHeight := rpctypes.ContextWithHeight(int64(contextHeight)) - nc, ok := b.clientCtx.Client.(tmrpcclient.NetworkClient) + nc, ok := b.ClientCtx.Client.(tmrpcclient.NetworkClient) if !ok { return nil, errors.New("invalid rpc client") } - cp, err := nc.ConsensusParams(b.ctx, &block.Block.Height) + cp, err := nc.ConsensusParams(b.Ctx, &block.Block.Height) if err != nil { return nil, err } @@ -194,11 +194,11 @@ func (b *Backend) TraceBlock(height rpctypes.BlockNumber, BlockTime: block.Block.Time, BlockHash: common.Bytes2Hex(block.BlockID.Hash), ProposerAddress: sdk.ConsAddress(block.Block.ProposerAddress), - ChainId: b.chainID.Int64(), + ChainId: b.EvmChainID.Int64(), BlockMaxGas: cp.ConsensusParams.Block.MaxGas, } - res, err := b.queryClient.TraceBlock(ctxWithHeight, traceBlockRequest) + res, err := b.QueryClient.TraceBlock(ctxWithHeight, traceBlockRequest) if err != nil { return nil, err } diff --git a/rpc/backend/tx_info.go b/rpc/backend/tx_info.go index 928dd8151..dfa770802 100644 --- a/rpc/backend/tx_info.go +++ b/rpc/backend/tx_info.go @@ -29,7 +29,7 @@ func (b *Backend) GetTransactionByHash(txHash common.Hash) (*rpctypes.RPCTransac hexTx := txHash.Hex() if err != nil { - return b.getTransactionByHashPending(txHash) + return b.GetTransactionByHashPending(txHash) } block, err := b.TendermintBlockByNumber(rpctypes.BlockNumber(res.Height)) @@ -37,7 +37,7 @@ func (b *Backend) GetTransactionByHash(txHash common.Hash) (*rpctypes.RPCTransac return nil, err } - tx, err := b.clientCtx.TxConfig.TxDecoder()(block.Block.Txs[res.TxIndex]) + tx, err := b.ClientCtx.TxConfig.TxDecoder()(block.Block.Txs[res.TxIndex]) if err != nil { return nil, err } @@ -48,9 +48,9 @@ func (b *Backend) GetTransactionByHash(txHash common.Hash) (*rpctypes.RPCTransac return nil, errors.New("invalid ethereum tx") } - blockRes, err := b.rpcClient.BlockResults(b.ctx, &block.Block.Height) + blockRes, err := b.RpcClient.BlockResults(b.Ctx, &block.Block.Height) if err != nil { - b.logger.Debug("block result not found", "height", block.Block.Height, "error", err.Error()) + b.Logger.Debug("block result not found", "height", block.Block.Height, "error", err.Error()) return nil, nil } @@ -75,7 +75,7 @@ func (b *Backend) GetTransactionByHash(txHash common.Hash) (*rpctypes.RPCTransac baseFee, err := b.BaseFee(blockRes) if err != nil { // handle the error for pruned node. - b.logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", blockRes.Height, "error", err) + b.Logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", blockRes.Height, "error", err) } height := uint64(res.Height) //#nosec G115 -- checked for int overflow already @@ -86,17 +86,17 @@ func (b *Backend) GetTransactionByHash(txHash common.Hash) (*rpctypes.RPCTransac height, index, baseFee, - b.chainID, + b.EvmChainID, ) } -// getTransactionByHashPending find pending tx from mempool -func (b *Backend) getTransactionByHashPending(txHash common.Hash) (*rpctypes.RPCTransaction, error) { +// GetTransactionByHashPending find pending tx from mempool +func (b *Backend) GetTransactionByHashPending(txHash common.Hash) (*rpctypes.RPCTransaction, error) { hexTx := txHash.Hex() // try to find tx in mempool txs, err := b.PendingTransactions() if err != nil { - b.logger.Debug("tx not found", "hash", hexTx, "error", err.Error()) + b.Logger.Debug("tx not found", "hash", hexTx, "error", err.Error()) return nil, nil } @@ -115,7 +115,7 @@ func (b *Backend) getTransactionByHashPending(txHash common.Hash) (*rpctypes.RPC uint64(0), uint64(0), nil, - b.chainID, + b.EvmChainID, ) if err != nil { return nil, err @@ -124,7 +124,7 @@ func (b *Backend) getTransactionByHashPending(txHash common.Hash) (*rpctypes.RPC } } - b.logger.Debug("tx not found", "hash", hexTx) + b.Logger.Debug("tx not found", "hash", hexTx) return nil, nil } @@ -133,7 +133,7 @@ func (b *Backend) GetGasUsed(res *types.TxResult, price *big.Int, gas uint64) ui // patch gasUsed if tx is reverted and happened before height on which fixed was introduced // to return real gas charged // more info at https://github.com/evmos/ethermint/pull/1557 - if res.Failed && res.Height < b.cfg.JSONRPC.FixRevertGasRefundHeight { + if res.Failed && res.Height < b.Cfg.JSONRPC.FixRevertGasRefundHeight { return new(big.Int).Mul(price, new(big.Int).SetUint64(gas)).Uint64() } return res.GasUsed @@ -142,23 +142,23 @@ func (b *Backend) GetGasUsed(res *types.TxResult, price *big.Int, gas uint64) ui // GetTransactionReceipt returns the transaction receipt identified by hash. func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{}, error) { hexTx := hash.Hex() - b.logger.Debug("eth_getTransactionReceipt", "hash", hexTx) + b.Logger.Debug("eth_getTransactionReceipt", "hash", hexTx) res, err := b.GetTxByEthHash(hash) if err != nil { - b.logger.Debug("tx not found", "hash", hexTx, "error", err.Error()) + b.Logger.Debug("tx not found", "hash", hexTx, "error", err.Error()) return nil, nil } resBlock, err := b.TendermintBlockByNumber(rpctypes.BlockNumber(res.Height)) if err != nil { - b.logger.Debug("block not found", "height", res.Height, "error", err.Error()) + b.Logger.Debug("block not found", "height", res.Height, "error", err.Error()) return nil, nil } - tx, err := b.clientCtx.TxConfig.TxDecoder()(resBlock.Block.Txs[res.TxIndex]) + tx, err := b.ClientCtx.TxConfig.TxDecoder()(resBlock.Block.Txs[res.TxIndex]) if err != nil { - b.logger.Debug("decoding failed", "error", err.Error()) + b.Logger.Debug("decoding failed", "error", err.Error()) return nil, fmt.Errorf("failed to decode tx: %w", err) } @@ -166,14 +166,14 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{ txData, err := evmtypes.UnpackTxData(ethMsg.Data) if err != nil { - b.logger.Error("failed to unpack tx data", "error", err.Error()) + b.Logger.Error("failed to unpack tx data", "error", err.Error()) return nil, err } cumulativeGasUsed := uint64(0) - blockRes, err := b.rpcClient.BlockResults(b.ctx, &res.Height) + blockRes, err := b.RpcClient.BlockResults(b.Ctx, &res.Height) if err != nil { - b.logger.Debug("failed to retrieve block results", "height", res.Height, "error", err.Error()) + b.Logger.Debug("failed to retrieve block results", "height", res.Height, "error", err.Error()) return nil, nil } @@ -204,7 +204,7 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{ msgIndex := int(res.MsgIndex) // #nosec G115 -- checked for int overflow already logs, err := TxLogsFromEvents(blockRes.TxsResults[res.TxIndex].Events, msgIndex) if err != nil { - b.logger.Debug("failed to parse logs", "hash", hexTx, "error", err.Error()) + b.Logger.Debug("failed to parse logs", "hash", hexTx, "error", err.Error()) } if res.EthTxIndex == -1 { @@ -272,7 +272,7 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{ baseFee, err := b.BaseFee(blockRes) if err != nil { // tolerate the error for pruned node. - b.logger.Error("fetch basefee failed, node is pruned?", "height", res.Height, "error", err) + b.Logger.Error("fetch basefee failed, node is pruned?", "height", res.Height, "error", err) } else { receipt["effectiveGasPrice"] = hexutil.Big(*dynamicTx.EffectiveGasPrice(baseFee)) } @@ -287,7 +287,7 @@ func (b *Backend) GetTransactionLogs(hash common.Hash) ([]*ethtypes.Log, error) res, err := b.GetTxByEthHash(hash) if err != nil { - b.logger.Debug("tx not found", "hash", hexTx, "error", err.Error()) + b.Logger.Debug("tx not found", "hash", hexTx, "error", err.Error()) return nil, nil } @@ -296,9 +296,9 @@ func (b *Backend) GetTransactionLogs(hash common.Hash) ([]*ethtypes.Log, error) return nil, nil } - resBlockResult, err := b.rpcClient.BlockResults(b.ctx, &res.Height) + resBlockResult, err := b.RpcClient.BlockResults(b.Ctx, &res.Height) if err != nil { - b.logger.Debug("block result not found", "number", res.Height, "error", err.Error()) + b.Logger.Debug("block result not found", "number", res.Height, "error", err.Error()) return nil, nil } @@ -309,20 +309,20 @@ func (b *Backend) GetTransactionLogs(hash common.Hash) ([]*ethtypes.Log, error) // GetTransactionByBlockHashAndIndex returns the transaction identified by hash and index. func (b *Backend) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) { - b.logger.Debug("eth_getTransactionByBlockHashAndIndex", "hash", hash.Hex(), "index", idx) - sc, ok := b.clientCtx.Client.(tmrpcclient.SignClient) + b.Logger.Debug("eth_getTransactionByBlockHashAndIndex", "hash", hash.Hex(), "index", idx) + sc, ok := b.ClientCtx.Client.(tmrpcclient.SignClient) if !ok { return nil, errors.New("invalid rpc client") } - block, err := sc.BlockByHash(b.ctx, hash.Bytes()) + block, err := sc.BlockByHash(b.Ctx, hash.Bytes()) if err != nil { - b.logger.Debug("block not found", "hash", hash.Hex(), "error", err.Error()) + b.Logger.Debug("block not found", "hash", hash.Hex(), "error", err.Error()) return nil, nil } if block.Block == nil { - b.logger.Debug("block not found", "hash", hash.Hex()) + b.Logger.Debug("block not found", "hash", hash.Hex()) return nil, nil } @@ -331,16 +331,16 @@ func (b *Backend) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexuti // GetTransactionByBlockNumberAndIndex returns the transaction identified by number and index. func (b *Backend) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNumber, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) { - b.logger.Debug("eth_getTransactionByBlockNumberAndIndex", "number", blockNum, "index", idx) + b.Logger.Debug("eth_getTransactionByBlockNumberAndIndex", "number", blockNum, "index", idx) block, err := b.TendermintBlockByNumber(blockNum) if err != nil { - b.logger.Debug("block not found", "height", blockNum.Int64(), "error", err.Error()) + b.Logger.Debug("block not found", "height", blockNum.Int64(), "error", err.Error()) return nil, nil } if block.Block == nil { - b.logger.Debug("block not found", "height", blockNum.Int64()) + b.Logger.Debug("block not found", "height", blockNum.Int64()) return nil, nil } @@ -351,13 +351,13 @@ func (b *Backend) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNum // TODO: Don't need to convert once hashing is fixed on Tendermint // https://github.com/cometbft/cometbft/issues/6539 func (b *Backend) GetTxByEthHash(hash common.Hash) (*types.TxResult, error) { - if b.indexer != nil { - return b.indexer.GetByTxHash(hash) + if b.Indexer != nil { + return b.Indexer.GetByTxHash(hash) } // fallback to tendermint tx indexer query := fmt.Sprintf("%s.%s='%s'", evmtypes.TypeMsgEthereumTx, evmtypes.AttributeKeyEthereumTxHash, hash.Hex()) - txResult, err := b.queryTendermintTxIndexer(query, func(txs *rpctypes.ParsedTxs) *rpctypes.ParsedTx { + txResult, err := b.QueryTendermintTxIndexer(query, func(txs *rpctypes.ParsedTxs) *rpctypes.ParsedTx { return txs.GetTxByHash(hash) }) if err != nil { @@ -369,8 +369,8 @@ func (b *Backend) GetTxByEthHash(hash common.Hash) (*types.TxResult, error) { // GetTxByTxIndex uses `/tx_query` to find transaction by tx index of valid ethereum txs func (b *Backend) GetTxByTxIndex(height int64, index uint) (*types.TxResult, error) { int32Index := int32(index) //#nosec G115 -- checked for int overflow already - if b.indexer != nil { - return b.indexer.GetByBlockAndIndex(height, int32Index) + if b.Indexer != nil { + return b.Indexer.GetByBlockAndIndex(height, int32Index) } // fallback to tendermint tx indexer @@ -378,7 +378,7 @@ func (b *Backend) GetTxByTxIndex(height int64, index uint) (*types.TxResult, err height, evmtypes.TypeMsgEthereumTx, evmtypes.AttributeKeyTxIndex, index, ) - txResult, err := b.queryTendermintTxIndexer(query, func(txs *rpctypes.ParsedTxs) *rpctypes.ParsedTx { + txResult, err := b.QueryTendermintTxIndexer(query, func(txs *rpctypes.ParsedTxs) *rpctypes.ParsedTx { return txs.GetTxByTxIndex(int(index)) // #nosec G115 -- checked for int overflow already }) if err != nil { @@ -387,9 +387,9 @@ func (b *Backend) GetTxByTxIndex(height int64, index uint) (*types.TxResult, err return txResult, nil } -// queryTendermintTxIndexer query tx in tendermint tx indexer -func (b *Backend) queryTendermintTxIndexer(query string, txGetter func(*rpctypes.ParsedTxs) *rpctypes.ParsedTx) (*types.TxResult, error) { - resTxs, err := b.clientCtx.Client.TxSearch(b.ctx, query, false, nil, nil, "") +// QueryTendermintTxIndexer query tx in tendermint tx indexer +func (b *Backend) QueryTendermintTxIndexer(query string, txGetter func(*rpctypes.ParsedTxs) *rpctypes.ParsedTx) (*types.TxResult, error) { + resTxs, err := b.ClientCtx.Client.TxSearch(b.Ctx, query, false, nil, nil, "") if err != nil { return nil, err } @@ -404,7 +404,7 @@ func (b *Backend) queryTendermintTxIndexer(query string, txGetter func(*rpctypes var tx sdk.Tx if txResult.TxResult.Code != 0 { // it's only needed when the tx exceeds block gas limit - tx, err = b.clientCtx.TxConfig.TxDecoder()(txResult.Tx) + tx, err = b.ClientCtx.TxConfig.TxDecoder()(txResult.Tx) if err != nil { return nil, fmt.Errorf("invalid ethereum tx") } @@ -415,7 +415,7 @@ func (b *Backend) queryTendermintTxIndexer(query string, txGetter func(*rpctypes // GetTransactionByBlockAndIndex is the common code shared by `GetTransactionByBlockNumberAndIndex` and `GetTransactionByBlockHashAndIndex`. func (b *Backend) GetTransactionByBlockAndIndex(block *tmrpctypes.ResultBlock, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) { - blockRes, err := b.rpcClient.BlockResults(b.ctx, &block.Block.Height) + blockRes, err := b.RpcClient.BlockResults(b.Ctx, &block.Block.Height) if err != nil { return nil, nil } @@ -424,9 +424,9 @@ func (b *Backend) GetTransactionByBlockAndIndex(block *tmrpctypes.ResultBlock, i // find in tx indexer res, err := b.GetTxByTxIndex(block.Block.Height, uint(idx)) if err == nil { - tx, err := b.clientCtx.TxConfig.TxDecoder()(block.Block.Txs[res.TxIndex]) + tx, err := b.ClientCtx.TxConfig.TxDecoder()(block.Block.Txs[res.TxIndex]) if err != nil { - b.logger.Debug("invalid ethereum tx", "height", block.Block.Header, "index", idx) + b.Logger.Debug("invalid ethereum tx", "height", block.Block.Header, "index", idx) return nil, nil } @@ -434,14 +434,14 @@ func (b *Backend) GetTransactionByBlockAndIndex(block *tmrpctypes.ResultBlock, i // msgIndex is inferred from tx events, should be within bound. msg, ok = tx.GetMsgs()[res.MsgIndex].(*evmtypes.MsgEthereumTx) if !ok { - b.logger.Debug("invalid ethereum tx", "height", block.Block.Header, "index", idx) + b.Logger.Debug("invalid ethereum tx", "height", block.Block.Header, "index", idx) return nil, nil } } else { i := int(idx) // #nosec G115 ethMsgs := b.EthMsgsFromTendermintBlock(block, blockRes) if i >= len(ethMsgs) { - b.logger.Debug("block txs index out of bound", "index", i) + b.Logger.Debug("block txs index out of bound", "index", i) return nil, nil } @@ -451,7 +451,7 @@ func (b *Backend) GetTransactionByBlockAndIndex(block *tmrpctypes.ResultBlock, i baseFee, err := b.BaseFee(blockRes) if err != nil { // handle the error for pruned node. - b.logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", block.Block.Height, "error", err) + b.Logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", block.Block.Height, "error", err) } height := uint64(block.Block.Height) // #nosec G115 -- checked for int overflow already @@ -462,6 +462,6 @@ func (b *Backend) GetTransactionByBlockAndIndex(block *tmrpctypes.ResultBlock, i height, index, baseFee, - b.chainID, + b.EvmChainID, ) } diff --git a/rpc/backend/utils.go b/rpc/backend/utils.go index 33c92e0d4..7d579a607 100644 --- a/rpc/backend/utils.go +++ b/rpc/backend/utils.go @@ -48,7 +48,7 @@ func (s sortGasAndReward) Less(i, j int) bool { // txs in order to compute and return the pending tx sequence. // Todo: include the ability to specify a blockNumber func (b *Backend) getAccountNonce(accAddr common.Address, pending bool, height int64, logger log.Logger) (uint64, error) { - queryClient := authtypes.NewQueryClient(b.clientCtx) + queryClient := authtypes.NewQueryClient(b.ClientCtx) adr := sdk.AccAddress(accAddr.Bytes()).String() ctx := types.ContextWithHeight(height) res, err := queryClient.Account(ctx, &authtypes.QueryAccountRequest{Address: adr}) @@ -61,7 +61,7 @@ func (b *Backend) getAccountNonce(accAddr common.Address, pending bool, height i return 0, err } var acc sdk.AccountI - if err := b.clientCtx.InterfaceRegistry.UnpackAny(res.Account, &acc); err != nil { + if err := b.ClientCtx.InterfaceRegistry.UnpackAny(res.Account, &acc); err != nil { return 0, err } @@ -89,7 +89,7 @@ func (b *Backend) getAccountNonce(accAddr common.Address, pending bool, height i break } - sender, err := ethMsg.GetSender(b.chainID) + sender, err := ethMsg.GetSender(b.EvmChainID) if err != nil { continue } @@ -166,9 +166,9 @@ func (b *Backend) processBlock( eachTendermintTx := tendermintTxs[i] eachTendermintTxResult := tendermintTxResults[i] - tx, err := b.clientCtx.TxConfig.TxDecoder()(eachTendermintTx) + tx, err := b.ClientCtx.TxConfig.TxDecoder()(eachTendermintTx) if err != nil { - b.logger.Debug("failed to decode transaction in block", "height", blockHeight, "error", err.Error()) + b.Logger.Debug("failed to decode transaction in block", "height", blockHeight, "error", err.Error()) continue } txGasUsed := uint64(eachTendermintTxResult.GasUsed) // #nosec G115 diff --git a/tests/integration/README.md b/tests/integration/README.md new file mode 100644 index 000000000..0b1eca323 --- /dev/null +++ b/tests/integration/README.md @@ -0,0 +1,16 @@ +# Integration Test Suite + +## Test File Naming Convention +To support external integration testing, all test-related helper files in this module are named using the `test_*.go` prefix instead of the conventional `*_test.go`. + +This change is intentional: +In Go, files ending with `*_test.go` are excluded from regular build contexts and only compiled during go test execution. +As a result, such files are not included when **the package is imported by other modules** — for example, when downstream chains want to reuse our EVM test harness. + +To work around this, we rename those files to `test_*.go`, which: +- Keeps them recognizable as test helpers, +- Ensures they are compiled as part of the package during regular builds, +- Allows external chains to import and invoke testing utilities like `NewKeeperTestSuite()` or `NewUnitTestNetwork(...)`. + +> Note: These files are still test-focused and should not be used in production builds. + diff --git a/tests/integration/ante/ante_test_suite.go b/tests/integration/ante/ante_test_suite.go new file mode 100644 index 000000000..911f797ea --- /dev/null +++ b/tests/integration/ante/ante_test_suite.go @@ -0,0 +1,192 @@ +package ante + +import ( + "math" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/testutil/integration" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/keyring" + feemarkettypes "github.com/cosmos/evm/x/feemarket/types" + evmtypes "github.com/cosmos/evm/x/vm/types" + + sdkmath "cosmossdk.io/math" + + "github.com/cosmos/cosmos-sdk/client" + sdk "github.com/cosmos/cosmos-sdk/types" + consensustypes "github.com/cosmos/cosmos-sdk/x/consensus/types" +) + +const TestGasLimit uint64 = 100000 + +type AnteTestSuite struct { + suite.Suite + + create network.CreateEvmApp + options []network.ConfigOption + network *network.UnitTestNetwork + handler grpc.Handler + keyring keyring.Keyring + factory factory.TxFactory + clientCtx client.Context + anteHandler sdk.AnteHandler + + enableFeemarket bool + baseFee *sdkmath.LegacyDec + enableLondonHF bool + evmParamsOption func(*evmtypes.Params) +} + +func NewAnteTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *AnteTestSuite { + suite := &AnteTestSuite{ + create: create, + options: options, + } + return suite +} + +func (s *AnteTestSuite) SetupTest() { + keys := keyring.New(2) + + customGenesis := network.CustomGenesisState{} + feemarketGenesis := feemarkettypes.DefaultGenesisState() + if s.enableFeemarket { + feemarketGenesis.Params.EnableHeight = 1 + feemarketGenesis.Params.NoBaseFee = false + } else { + feemarketGenesis.Params.NoBaseFee = true + } + if s.baseFee != nil { + feemarketGenesis.Params.BaseFee = *s.baseFee + } + customGenesis[feemarkettypes.ModuleName] = feemarketGenesis + + evmGenesis := evmtypes.DefaultGenesisState() + + if s.evmParamsOption != nil { + s.evmParamsOption(&evmGenesis.Params) + } + customGenesis[evmtypes.ModuleName] = evmGenesis + + // set block max gas to be less than maxUint64 + cp := integration.DefaultConsensusParams + cp.Block.MaxGas = 1000000000000000000 + customGenesis[consensustypes.ModuleName] = cp + + options := []network.ConfigOption{ + network.WithPreFundedAccounts(keys.GetAllAccAddrs()...), + network.WithCustomGenesis(customGenesis), + } + options = append(options, s.options...) + nw := network.NewUnitTestNetwork(s.create, options...) + + gh := grpc.NewIntegrationHandler(nw) + tf := factory.New(nw, gh) + + s.network = nw + s.factory = tf + s.handler = gh + s.keyring = keys + // set antehandler + s.anteHandler = nw.App.GetAnteHandler() + + encodingConfig := nw.GetEncodingConfig() + + s.clientCtx = client.Context{}.WithTxConfig(encodingConfig.TxConfig) + + s.Require().NotNil(s.network.App.AppCodec()) + + chainConfig := evmtypes.DefaultChainConfig(s.network.GetEIP155ChainID().Uint64()) + if !s.enableLondonHF { + maxInt := sdkmath.NewInt(math.MaxInt64) + chainConfig.LondonBlock = &maxInt + chainConfig.ArrowGlacierBlock = &maxInt + chainConfig.GrayGlacierBlock = &maxInt + chainConfig.MergeNetsplitBlock = &maxInt + chainConfig.ShanghaiTime = &maxInt + chainConfig.CancunTime = &maxInt + chainConfig.PragueTime = &maxInt + } + + // get the denom and decimals set when initialized the chain + // to set them again + // when resetting the chain config + denom := evmtypes.GetEVMCoinDenom() //nolint:staticcheck + extendedDenom := evmtypes.GetEVMCoinExtendedDenom() //nolint:staticcheck + decimals := evmtypes.GetEVMCoinDecimals() //nolint:staticcheck + + configurator := evmtypes.NewEVMConfigurator() + configurator.ResetTestConfig() + err := configurator. + WithChainConfig(chainConfig). + WithEVMCoinInfo(evmtypes.EvmCoinInfo{ + Denom: denom, + ExtendedDenom: extendedDenom, + Decimals: decimals, + }). + Configure() + s.Require().NoError(err) +} + +func (s *AnteTestSuite) WithFeemarketEnabled(enabled bool) { + s.enableFeemarket = enabled +} + +func (s *AnteTestSuite) WithLondonHardForkEnabled(enabled bool) { + s.enableLondonHF = enabled +} + +func (s *AnteTestSuite) WithBaseFee(baseFee *sdkmath.LegacyDec) { + s.baseFee = baseFee +} + +func (s *AnteTestSuite) WithEvmParamsOptions(evmParamsOpts func(*evmtypes.Params)) { + s.evmParamsOption = evmParamsOpts +} + +func (s *AnteTestSuite) ResetEvmParamsOptions() { + s.evmParamsOption = nil +} + +func (s *AnteTestSuite) GetKeyring() keyring.Keyring { + return s.keyring +} + +func (s *AnteTestSuite) GetTxFactory() factory.TxFactory { + return s.factory +} + +func (s *AnteTestSuite) GetNetwork() *network.UnitTestNetwork { + return s.network +} + +func (s *AnteTestSuite) GetClientCtx() client.Context { + return s.clientCtx +} + +func (s *AnteTestSuite) GetAnteHandler() sdk.AnteHandler { + return s.anteHandler +} + +func (s *AnteTestSuite) CreateTestCosmosTxBuilder(gasPrice sdkmath.Int, denom string, msgs ...sdk.Msg) client.TxBuilder { + txBuilder := s.GetClientCtx().TxConfig.NewTxBuilder() + + txBuilder.SetGasLimit(TestGasLimit) + fees := &sdk.Coins{{Denom: denom, Amount: gasPrice.MulRaw(int64(TestGasLimit))}} + txBuilder.SetFeeAmount(*fees) + err := txBuilder.SetMsgs(msgs...) + s.Require().NoError(err) + return txBuilder +} + +func (s *AnteTestSuite) CreateTestCosmosTxBuilderWithFees(fees sdk.Coins, msgs ...sdk.Msg) client.TxBuilder { + txBuilder := s.GetClientCtx().TxConfig.NewTxBuilder() + txBuilder.SetGasLimit(TestGasLimit) + txBuilder.SetFeeAmount(fees) + err := txBuilder.SetMsgs(msgs...) + s.Require().NoError(err) + return txBuilder +} diff --git a/evmd/ante/evm_benchmark_test.go b/tests/integration/ante/benchmark_evm_antehandler.go similarity index 76% rename from evmd/ante/evm_benchmark_test.go rename to tests/integration/ante/benchmark_evm_antehandler.go index 4dc965b66..e30f8cea8 100644 --- a/evmd/ante/evm_benchmark_test.go +++ b/tests/integration/ante/benchmark_evm_antehandler.go @@ -1,18 +1,19 @@ -package ante_test +package ante import ( "fmt" "math/big" "testing" + chainante "cosmosevm.io/evmd/ante" + "github.com/cosmos/evm/ante" ethante "github.com/cosmos/evm/ante/evm" - chainante "github.com/cosmos/evm/evmd/ante" - cmmnfactory "github.com/cosmos/evm/testutil/integration/common/factory" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" + basefactory "github.com/cosmos/evm/testutil/integration/base/factory" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + testkeyring "github.com/cosmos/evm/testutil/keyring" cosmosevmtypes "github.com/cosmos/evm/types" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -58,16 +59,18 @@ var table = []struct { }, } -func BenchmarkAnteHandler(b *testing.B) { +func RunBenchmarkAnteHandler(b *testing.B, create network.CreateEvmApp, options ...network.ConfigOption) { keyring := testkeyring.New(2) for _, v := range table { // Reset chain on every tx type to have a clean state // and a fair benchmark b.StopTimer() - unitNetwork := network.NewUnitTestNetwork( + opts := []network.ConfigOption{ network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), - ) + } + opts = append(opts, options...) + unitNetwork := network.NewUnitTestNetwork(create, opts...) grpcHandler := grpc.NewIntegrationHandler(unitNetwork) txFactory := factory.New(unitNetwork, grpcHandler) suite := benchmarkSuite{ @@ -131,7 +134,7 @@ func (s *benchmarkSuite) generateTxType(txType string) (sdktypes.Tx, error) { ), ), ) - txArgs := cmmnfactory.CosmosTxArgs{Msgs: []sdktypes.Msg{bankmsg}} + txArgs := basefactory.CosmosTxArgs{Msgs: []sdktypes.Msg{bankmsg}} return s.txFactory.BuildCosmosTx(sender.Priv, txArgs) default: return nil, fmt.Errorf("invalid tx type") @@ -142,16 +145,16 @@ func (s *benchmarkSuite) generateHandlerOptions() chainante.HandlerOptions { encCfg := s.network.GetEncodingConfig() return chainante.HandlerOptions{ Cdc: s.network.App.AppCodec(), - AccountKeeper: s.network.App.AccountKeeper, - BankKeeper: s.network.App.BankKeeper, + AccountKeeper: s.network.App.GetAccountKeeper(), + BankKeeper: s.network.App.GetBankKeeper(), ExtensionOptionChecker: cosmosevmtypes.HasDynamicFeeExtensionOption, - EvmKeeper: s.network.App.EVMKeeper, - FeegrantKeeper: s.network.App.FeeGrantKeeper, - IBCKeeper: s.network.App.IBCKeeper, - FeeMarketKeeper: s.network.App.FeeMarketKeeper, + EvmKeeper: s.network.App.GetEVMKeeper(), + FeegrantKeeper: s.network.App.GetFeeGrantKeeper(), + IBCKeeper: s.network.App.GetIBCKeeper(), + FeeMarketKeeper: s.network.App.GetFeeMarketKeeper(), SignModeHandler: encCfg.TxConfig.SignModeHandler(), SigGasConsumer: ante.SigVerificationGasConsumer, MaxTxGasWanted: 1_000_000_000, - TxFeeChecker: ethante.NewDynamicFeeChecker(s.network.App.FeeMarketKeeper), + TxFeeChecker: ethante.NewDynamicFeeChecker(s.network.App.GetFeeMarketKeeper()), } } diff --git a/tests/integration/ante/evm_ante_test_suite.go b/tests/integration/ante/evm_ante_test_suite.go new file mode 100644 index 000000000..58efd7aea --- /dev/null +++ b/tests/integration/ante/evm_ante_test_suite.go @@ -0,0 +1,707 @@ +package ante + +import ( + "encoding/json" + "fmt" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/holiman/uint256" + "github.com/stretchr/testify/require" + + "github.com/cosmos/evm" + "github.com/cosmos/evm/crypto/ethsecp256k1" + "github.com/cosmos/evm/ethereum/eip712" + "github.com/cosmos/evm/testutil" + "github.com/cosmos/evm/testutil/constants" + "github.com/cosmos/evm/testutil/integration/evm/network" + utiltx "github.com/cosmos/evm/testutil/tx" + evmtypes "github.com/cosmos/evm/x/vm/types" + ibctypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" + ibcclienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" + + sdkmath "cosmossdk.io/math" + storetypes "cosmossdk.io/store/types" + evtypes "cosmossdk.io/x/evidence/types" + "cosmossdk.io/x/feegrant" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/crypto/types/multisig" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/tx/signing" + sdkante "github.com/cosmos/cosmos-sdk/x/auth/ante" + "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" + authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" + authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" + "github.com/cosmos/cosmos-sdk/x/authz" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + govtypesv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + teststaking "github.com/cosmos/cosmos-sdk/x/staking/testutil" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +type EvmAnteTestSuite struct { + *AnteTestSuite + UseLegacyEIP712TypedData bool +} + +func NewEvmAnteTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *EvmAnteTestSuite { + return &EvmAnteTestSuite{ + AnteTestSuite: NewAnteTestSuite(create), + } +} + +func (s *EvmAnteTestSuite) CreateTxBuilder(privKey cryptotypes.PrivKey, txArgs evmtypes.EvmTxArgs, unsetExtensionOptions ...bool) client.TxBuilder { + var option *codectypes.Any + var err error + if len(unsetExtensionOptions) == 0 { + option, err = codectypes.NewAnyWithValue(&evmtypes.ExtensionOptionsEthereumTx{}) + s.Require().NoError(err) + } + msgEthTx, err := s.GetTxFactory().GenerateMsgEthereumTx(privKey, txArgs) + s.Require().NoError(err) + + signedMsg, err := s.GetTxFactory().SignMsgEthereumTx(privKey, msgEthTx) + s.Require().NoError(err) + s.Require().NoError(signedMsg.ValidateBasic()) + + tb := s.GetClientCtx().TxConfig.NewTxBuilder() + builder, ok := tb.(authtx.ExtensionOptionsTxBuilder) + s.Require().True(ok) + + if len(unsetExtensionOptions) == 0 { + builder.SetExtensionOptions(option) + } + + err = builder.SetMsgs(&signedMsg) + s.Require().NoError(err) + + txData, err := evmtypes.UnpackTxData(signedMsg.Data) + s.Require().NoError(err) + + fees := sdk.NewCoins(sdk.NewCoin(s.GetNetwork().GetBaseDenom(), sdkmath.NewIntFromBigInt(txData.Fee()))) + builder.SetFeeAmount(fees) + builder.SetGasLimit(signedMsg.GetGas()) + return builder +} + +func (s *EvmAnteTestSuite) RequireErrorForLegacyTypedData(err error) { + if s.UseLegacyEIP712TypedData { + s.Require().Error(err) + } else { + s.Require().NoError(err) + } +} + +func (s *EvmAnteTestSuite) TxForLegacyTypedData(txBuilder client.TxBuilder) sdk.Tx { + if s.UseLegacyEIP712TypedData { + // Since the TxBuilder will be nil on failure, + // we return an empty Tx to avoid panics. + emptyTxBuilder := s.GetClientCtx().TxConfig.NewTxBuilder() + return emptyTxBuilder.GetTx() + } + + return txBuilder.GetTx() +} + +func (s *EvmAnteTestSuite) CreateTestCosmosTxBuilder(gasPrice sdkmath.Int, denom string, msgs ...sdk.Msg) client.TxBuilder { + txBuilder := s.GetClientCtx().TxConfig.NewTxBuilder() + + txBuilder.SetGasLimit(TestGasLimit) + fees := &sdk.Coins{{Denom: denom, Amount: gasPrice.MulRaw(int64(TestGasLimit))}} + txBuilder.SetFeeAmount(*fees) + err := txBuilder.SetMsgs(msgs...) + s.Require().NoError(err) + return txBuilder +} + +func (s *EvmAnteTestSuite) CreateTestEIP712TxBuilderMsgSend(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { + // Build MsgSend + recipient := sdk.AccAddress(common.Address{}.Bytes()) + msgSend := banktypes.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(s.GetNetwork().GetBaseDenom(), sdkmath.NewInt(1)))) + return s.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, msgSend) +} + +func (s *EvmAnteTestSuite) CreateTestEIP712TxBuilderMsgDelegate(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { + // Build MsgDelegate + val := s.GetNetwork().GetValidators()[0] + msgDelegate := stakingtypes.NewMsgDelegate(from.String(), val.OperatorAddress, sdk.NewCoin(s.GetNetwork().GetBaseDenom(), sdkmath.NewInt(20))) + return s.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, msgDelegate) +} + +func (s *EvmAnteTestSuite) CreateTestEIP712MsgCreateValidator(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { + // Build MsgCreateValidator + valAddr := sdk.ValAddress(from.Bytes()) + privEd := ed25519.GenPrivKey() + evmDenom := evmtypes.GetEVMCoinDenom() + msgCreate, err := stakingtypes.NewMsgCreateValidator( + valAddr.String(), + privEd.PubKey(), + sdk.NewCoin(evmDenom, sdkmath.NewInt(20)), + stakingtypes.NewDescription("moniker", "identity", "website", "security_contract", "details"), + stakingtypes.NewCommissionRates(sdkmath.LegacyOneDec(), sdkmath.LegacyOneDec(), sdkmath.LegacyOneDec()), + sdkmath.OneInt(), + ) + s.Require().NoError(err) + return s.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, msgCreate) +} + +func (s *EvmAnteTestSuite) CreateTestEIP712MsgCreateValidator2(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { + // Build MsgCreateValidator + valAddr := sdk.ValAddress(from.Bytes()) + privEd := ed25519.GenPrivKey() + msgCreate, err := stakingtypes.NewMsgCreateValidator( + valAddr.String(), + privEd.PubKey(), + sdk.NewCoin(s.GetNetwork().GetBaseDenom(), sdkmath.NewInt(20)), + // Ensure optional fields can be left blank + stakingtypes.NewDescription("moniker", "identity", "", "", ""), + stakingtypes.NewCommissionRates(sdkmath.LegacyOneDec(), sdkmath.LegacyOneDec(), sdkmath.LegacyOneDec()), + sdkmath.OneInt(), + ) + s.Require().NoError(err) + return s.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, msgCreate) +} + +func (s *EvmAnteTestSuite) CreateTestEIP712SubmitProposal(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins, deposit sdk.Coins) (client.TxBuilder, error) { + proposal, ok := govtypes.ContentFromProposalType("My proposal", "My description", govtypes.ProposalTypeText) + s.Require().True(ok) + msgSubmit, err := govtypes.NewMsgSubmitProposal(proposal, deposit, from) + s.Require().NoError(err) + return s.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, msgSubmit) +} + +func (s *EvmAnteTestSuite) CreateTestEIP712GrantAllowance(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { + spendLimit := sdk.NewCoins(sdk.NewInt64Coin(s.GetNetwork().GetBaseDenom(), 10)) + threeHours := time.Now().Add(3 * time.Hour) + basic := &feegrant.BasicAllowance{ + SpendLimit: spendLimit, + Expiration: &threeHours, + } + granted := utiltx.GenerateAddress() + grantedAddr := s.GetNetwork().App.GetAccountKeeper().NewAccountWithAddress(s.GetNetwork().GetContext(), granted.Bytes()) + msgGrant, err := feegrant.NewMsgGrantAllowance(basic, from, grantedAddr.GetAddress()) + s.Require().NoError(err) + return s.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, msgGrant) +} + +func (s *EvmAnteTestSuite) CreateTestEIP712MsgEditValidator(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { + valAddr := sdk.ValAddress(from.Bytes()) + msgEdit := stakingtypes.NewMsgEditValidator( + valAddr.String(), + stakingtypes.NewDescription("moniker", "identity", "website", "security_contract", "details"), + nil, + nil, + ) + return s.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, msgEdit) +} + +func (s *EvmAnteTestSuite) CreateTestEIP712MsgSubmitEvidence(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { + pk := ed25519.GenPrivKey() + msgEvidence, err := evtypes.NewMsgSubmitEvidence(from, &evtypes.Equivocation{ + Height: 11, + Time: time.Now().UTC(), + Power: 100, + ConsensusAddress: pk.PubKey().Address().String(), + }) + s.Require().NoError(err) + + return s.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, msgEvidence) +} + +func (s *EvmAnteTestSuite) CreateTestEIP712MsgVoteV1(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { + msgVote := govtypesv1.NewMsgVote(from, 1, govtypesv1.VoteOption_VOTE_OPTION_YES, "") + return s.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, msgVote) +} + +func (s *EvmAnteTestSuite) CreateTestEIP712SubmitProposalV1(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { + // Build V1 proposal messages. Must all be same-type, since EIP-712 + // does not support arrays of variable type. + authAcc := s.GetNetwork().App.GetGovKeeper().GetGovernanceAccount(s.GetNetwork().GetContext()) + + proposal1, ok := govtypes.ContentFromProposalType("My proposal 1", "My description 1", govtypes.ProposalTypeText) + s.Require().True(ok) + content1, err := govtypesv1.NewLegacyContent( + proposal1, + sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), authAcc.GetAddress().Bytes()), + ) + s.Require().NoError(err) + + proposal2, ok := govtypes.ContentFromProposalType("My proposal 2", "My description 2", govtypes.ProposalTypeText) + s.Require().True(ok) + content2, err := govtypesv1.NewLegacyContent( + proposal2, + sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), authAcc.GetAddress().Bytes()), + ) + s.Require().NoError(err) + + proposalMsgs := []sdk.Msg{ + content1, + content2, + } + + // Build V1 proposal + msgProposal, err := govtypesv1.NewMsgSubmitProposal( + proposalMsgs, + sdk.NewCoins(sdk.NewCoin(s.GetNetwork().GetBaseDenom(), sdkmath.NewInt(100))), + sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), from.Bytes()), + "Metadata", "title", "summary", + false, + ) + + s.Require().NoError(err) + + return s.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, msgProposal) +} + +func (s *EvmAnteTestSuite) CreateTestEIP712MsgExec(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { + recipient := sdk.AccAddress(common.Address{}.Bytes()) + msgSend := banktypes.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(s.GetNetwork().GetBaseDenom(), sdkmath.NewInt(1)))) + msgExec := authz.NewMsgExec(from, []sdk.Msg{msgSend}) + return s.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, &msgExec) +} + +func (s *EvmAnteTestSuite) CreateTestEIP712MultipleMsgSend(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { + recipient := sdk.AccAddress(common.Address{}.Bytes()) + msgSend := banktypes.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(s.GetNetwork().GetBaseDenom(), sdkmath.NewInt(1)))) + return s.CreateTestEIP712CosmosTxBuilder(priv, chainID, evmChainID, gas, gasAmount, []sdk.Msg{msgSend, msgSend, msgSend}) +} + +func (s *EvmAnteTestSuite) CreateTestEIP712MultipleDifferentMsgs(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { + recipient := sdk.AccAddress(common.Address{}.Bytes()) + msgSend := banktypes.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(s.GetNetwork().GetBaseDenom(), sdkmath.NewInt(1)))) + + msgVote := govtypesv1.NewMsgVote(from, 1, govtypesv1.VoteOption_VOTE_OPTION_YES, "") + + valEthAddr := utiltx.GenerateAddress() + valAddr := sdk.ValAddress(valEthAddr.Bytes()) + msgDelegate := stakingtypes.NewMsgDelegate(from.String(), valAddr.String(), sdk.NewCoin(s.GetNetwork().GetBaseDenom(), sdkmath.NewInt(20))) + + return s.CreateTestEIP712CosmosTxBuilder(priv, chainID, evmChainID, gas, gasAmount, []sdk.Msg{msgSend, msgVote, msgDelegate}) +} + +func (s *EvmAnteTestSuite) CreateTestEIP712SameMsgDifferentSchemas(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { + msgVote1 := govtypesv1.NewMsgVote(from, 1, govtypesv1.VoteOption_VOTE_OPTION_YES, "") + msgVote2 := govtypesv1.NewMsgVote(from, 5, govtypesv1.VoteOption_VOTE_OPTION_ABSTAIN, "With Metadata") + + return s.CreateTestEIP712CosmosTxBuilder(priv, chainID, evmChainID, gas, gasAmount, []sdk.Msg{msgVote1, msgVote2}) +} + +func (s *EvmAnteTestSuite) CreateTestEIP712ZeroValueArray(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { + recipient := sdk.AccAddress(common.Address{}.Bytes()) + msgSend := banktypes.NewMsgSend(from, recipient, sdk.NewCoins()) + return s.CreateTestEIP712CosmosTxBuilder(priv, chainID, evmChainID, gas, gasAmount, []sdk.Msg{msgSend}) +} + +func (s *EvmAnteTestSuite) CreateTestEIP712ZeroValueNumber(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { + msgVote := govtypesv1.NewMsgVote(from, 0, govtypesv1.VoteOption_VOTE_OPTION_NO, "") + + return s.CreateTestEIP712CosmosTxBuilder(priv, chainID, evmChainID, gas, gasAmount, []sdk.Msg{msgVote}) +} + +func (s *EvmAnteTestSuite) CreateTestEIP712MsgTransfer(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { + msgTransfer := s.createMsgTransfer(from, "With Memo") + return s.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, msgTransfer) +} + +func (s *EvmAnteTestSuite) CreateTestEIP712MsgTransferWithoutMemo(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { + msgTransfer := s.createMsgTransfer(from, "") + return s.CreateTestEIP712SingleMessageTxBuilder(priv, chainID, evmChainID, gas, gasAmount, msgTransfer) +} + +func (s *EvmAnteTestSuite) createMsgTransfer(from sdk.AccAddress, memo string) *ibctypes.MsgTransfer { + recipient := sdk.AccAddress(common.Address{}.Bytes()) + msgTransfer := ibctypes.NewMsgTransfer("transfer", "channel-25", sdk.NewCoin(s.GetNetwork().GetBaseDenom(), sdkmath.NewInt(100000)), from.String(), recipient.String(), ibcclienttypes.NewHeight(1000, 1000), 1000, memo) + return msgTransfer +} + +func (s *EvmAnteTestSuite) CreateTestEIP712MultipleSignerMsgs(from sdk.AccAddress, priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins) (client.TxBuilder, error) { + recipient := sdk.AccAddress(common.Address{}.Bytes()) + msgSend1 := banktypes.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(s.GetNetwork().GetBaseDenom(), sdkmath.NewInt(1)))) + msgSend2 := banktypes.NewMsgSend(recipient, from, sdk.NewCoins(sdk.NewCoin(s.GetNetwork().GetBaseDenom(), sdkmath.NewInt(1)))) + return s.CreateTestEIP712CosmosTxBuilder(priv, chainID, evmChainID, gas, gasAmount, []sdk.Msg{msgSend1, msgSend2}) +} + +// StdSignBytes returns the bytes to sign for a transaction. +func StdSignBytes(cdc *codec.LegacyAmino, chainID string, accnum uint64, sequence uint64, timeout uint64, fee legacytx.StdFee, msgs []sdk.Msg, memo string) []byte { + msgsBytes := make([]json.RawMessage, 0, len(msgs)) + for _, msg := range msgs { + legacyMsg, ok := msg.(legacytx.LegacyMsg) + if !ok { + panic(fmt.Errorf("expected %T when using amino JSON", (*legacytx.LegacyMsg)(nil))) + } + + msgsBytes = append(msgsBytes, json.RawMessage(legacyMsg.GetSignBytes())) + } + + bz, err := cdc.MarshalJSON(legacytx.StdSignDoc{ + AccountNumber: accnum, + ChainID: chainID, + Fee: json.RawMessage(fee.Bytes()), + Memo: memo, + Msgs: msgsBytes, + Sequence: sequence, + TimeoutHeight: timeout, + }) + if err != nil { + panic(err) + } + + return sdk.MustSortJSON(bz) +} + +func (s *EvmAnteTestSuite) CreateTestEIP712SingleMessageTxBuilder( + priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins, msg sdk.Msg, +) (client.TxBuilder, error) { + msgs := []sdk.Msg{msg} + return s.CreateTestEIP712CosmosTxBuilder( + priv, + chainID, + evmChainID, + gas, + gasAmount, + msgs, + ) +} + +func (s *EvmAnteTestSuite) CreateTestEIP712CosmosTxBuilder( + priv cryptotypes.PrivKey, chainID string, evmChainID, gas uint64, gasAmount sdk.Coins, msgs []sdk.Msg, +) (client.TxBuilder, error) { + txConf := s.GetClientCtx().TxConfig + cosmosTxArgs := utiltx.CosmosTxArgs{ + TxCfg: txConf, + Priv: priv, + ChainID: chainID, + Gas: gas, + Fees: gasAmount, + Msgs: msgs, + } + + return utiltx.PrepareEIP712CosmosTx( + s.GetNetwork().GetContext(), + s.GetNetwork().App, + utiltx.EIP712TxArgs{ + CosmosTxArgs: cosmosTxArgs, + UseLegacyTypedData: s.UseLegacyEIP712TypedData, + EVMChainID: evmChainID, + }, + ) +} + +// Generate a set of pub/priv keys to be used in creating multi-keys +func (s *EvmAnteTestSuite) GenerateMultipleKeys(n int) ([]cryptotypes.PrivKey, []cryptotypes.PubKey) { + privKeys := make([]cryptotypes.PrivKey, n) + pubKeys := make([]cryptotypes.PubKey, n) + for i := 0; i < n; i++ { + privKey, err := ethsecp256k1.GenerateKey() + s.Require().NoError(err) + privKeys[i] = privKey + pubKeys[i] = privKey.PubKey() + } + return privKeys, pubKeys +} + +// generateSingleSignature signs the given sign doc bytes using the given signType (EIP-712 or Standard) +func (s *EvmAnteTestSuite) generateSingleSignature(signMode signing.SignMode, privKey cryptotypes.PrivKey, signDocBytes []byte, signType string) (signature signing.SignatureV2) { + var ( + msg []byte + err error + ) + + msg = signDocBytes + + if signType == "EIP-712" { + msg, err = eip712.GetEIP712BytesForMsg(signDocBytes) + s.Require().NoError(err) + } + + sigBytes, _ := privKey.Sign(msg) + sigData := &signing.SingleSignatureData{ + SignMode: signMode, + Signature: sigBytes, + } + + return signing.SignatureV2{ + PubKey: privKey.PubKey(), + Data: sigData, + } +} + +// generateMultikeySignatures signs a set of messages using each private key within a given multi-key +func (s *EvmAnteTestSuite) generateMultikeySignatures(signMode signing.SignMode, privKeys []cryptotypes.PrivKey, signDocBytes []byte, signType string) (signatures []signing.SignatureV2) { + n := len(privKeys) + signatures = make([]signing.SignatureV2, n) + + for i := 0; i < n; i++ { + privKey := privKeys[i] + currentType := signType + + // If mixed type, alternate signing type on each iteration + if signType == "mixed" { + if i%2 == 0 { + currentType = "EIP-712" + } else { + currentType = "Standard" + } + } + + signatures[i] = s.generateSingleSignature( + signMode, + privKey, + signDocBytes, + currentType, + ) + } + + return signatures +} + +// RegisterAccount creates an account with the keeper and populates the initial balance +func (s *EvmAnteTestSuite) RegisterAccount(pubKey cryptotypes.PubKey, balance *uint256.Int) { + ctx := s.GetNetwork().GetContext() + + acc := s.GetNetwork().App.GetAccountKeeper().NewAccountWithAddress(ctx, sdk.AccAddress(pubKey.Address())) + s.GetNetwork().App.GetAccountKeeper().SetAccount(ctx, acc) + + err := s.GetNetwork().App.GetEVMKeeper().SetBalance(ctx, common.BytesToAddress(pubKey.Address()), balance) + s.Require().NoError(err) +} + +// createSignerBytes generates sign doc bytes using the given parameters +func (s *EvmAnteTestSuite) createSignerBytes(chainID string, signMode signing.SignMode, pubKey cryptotypes.PubKey, txBuilder client.TxBuilder) []byte { + ctx := s.GetNetwork().GetContext() + acc, err := sdkante.GetSignerAcc(ctx, s.GetNetwork().App.GetAccountKeeper(), sdk.AccAddress(pubKey.Address())) + s.Require().NoError(err) + signerInfo := authsigning.SignerData{ + Address: sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), acc.GetAddress().Bytes()), + ChainID: chainID, + AccountNumber: acc.GetAccountNumber(), + Sequence: acc.GetSequence(), + PubKey: pubKey, + } + + signerBytes, err := authsigning.GetSignBytesAdapter( + ctx, + s.GetClientCtx().TxConfig.SignModeHandler(), + signMode, + signerInfo, + txBuilder.GetTx(), + ) + + s.Require().NoError(err) + + return signerBytes +} + +// createBaseTxBuilder creates a TxBuilder to be used for Single- or Multi-signing +func (s *EvmAnteTestSuite) createBaseTxBuilder(msg sdk.Msg, gas uint64) client.TxBuilder { + txBuilder := s.GetClientCtx().TxConfig.NewTxBuilder() + + txBuilder.SetGasLimit(gas) + txBuilder.SetFeeAmount(sdk.NewCoins( + sdk.NewCoin(s.GetNetwork().GetBaseDenom(), sdkmath.NewInt(10000)), + )) + + err := txBuilder.SetMsgs(msg) + s.Require().NoError(err) + + txBuilder.SetMemo("") + + return txBuilder +} + +// CreateTestSignedMultisigTx creates and sign a multi-signed tx for the given message. `signType` indicates whether to use standard signing ("Standard"), +// EIP-712 signing ("EIP-712"), or a mix of the two ("mixed"). +func (s *EvmAnteTestSuite) CreateTestSignedMultisigTx(privKeys []cryptotypes.PrivKey, signMode signing.SignMode, msg sdk.Msg, chainID string, gas uint64, signType string) client.TxBuilder { + pubKeys := make([]cryptotypes.PubKey, len(privKeys)) + for i, privKey := range privKeys { + pubKeys[i] = privKey.PubKey() + } + + // Re-derive multikey + numKeys := len(privKeys) + multiKey := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys) + + s.RegisterAccount(multiKey, uint256.NewInt(10000000000)) + + txBuilder := s.createBaseTxBuilder(msg, gas) + + // Prepare signature field + sig := multisig.NewMultisig(len(pubKeys)) + err := txBuilder.SetSignatures(signing.SignatureV2{ + PubKey: multiKey, + Data: sig, + }) + s.Require().NoError(err) + + signerBytes := s.createSignerBytes(chainID, signMode, multiKey, txBuilder) + + // Sign for each key and update signature field + sigs := s.generateMultikeySignatures(signMode, privKeys, signerBytes, signType) + for _, pkSig := range sigs { + err := multisig.AddSignatureV2(sig, pkSig, pubKeys) + s.Require().NoError(err) + } + + err = txBuilder.SetSignatures(signing.SignatureV2{ + PubKey: multiKey, + Data: sig, + }) + s.Require().NoError(err) + + return txBuilder +} + +func (s *EvmAnteTestSuite) CreateTestSingleSignedTx(privKey cryptotypes.PrivKey, signMode signing.SignMode, msg sdk.Msg, chainID string, gas uint64, signType string) client.TxBuilder { + pubKey := privKey.PubKey() + + s.RegisterAccount(pubKey, uint256.NewInt(10_000_000_000)) + + txBuilder := s.createBaseTxBuilder(msg, gas) + + // Prepare signature field + sig := signing.SingleSignatureData{} + err := txBuilder.SetSignatures(signing.SignatureV2{ + PubKey: pubKey, + Data: &sig, + }) + s.Require().NoError(err) + + signerBytes := s.createSignerBytes(chainID, signMode, pubKey, txBuilder) + + sigData := s.generateSingleSignature(signMode, privKey, signerBytes, signType) + err = txBuilder.SetSignatures(sigData) + s.Require().NoError(err) + + return txBuilder +} + +// prepareAccount is a helper function that assigns the corresponding +// balance and rewards to the provided account +func (s *EvmAnteTestSuite) prepareAccount(ctx sdk.Context, addr sdk.AccAddress, balance, rewards sdkmath.Int) sdk.Context { + ctx, err := PrepareAccountsForDelegationRewards( + s.T(), ctx, s.GetNetwork().App, addr, balance, rewards, + ) + s.Require().NoError(err, "error while preparing accounts for delegation rewards") + return ctx. + WithBlockGasMeter(storetypes.NewGasMeter(1e19)). + WithBlockHeight(ctx.BlockHeight() + 1) +} + +// PrepareAccountsForDelegationRewards prepares the test suite for testing to withdraw delegation rewards. +// +// Balance is the amount of tokens that will be left in the account after the setup is done. +// For each defined reward, a validator is created and tokens are allocated to it using the distribution keeper, +// such that the given amount of tokens is outstanding as a staking reward for the account. +// +// The setup is done in the following way: +// - Fund the account with the given address with the given balance. +// - If the given balance is zero, the account will be created with zero balance. +// +// For every reward defined in the rewards argument, the following steps are executed: +// - Set up a validator with zero commission and delegate to it -> the account delegation will be 50% of the total delegation. +// - Allocate rewards to the validator. +// +// The function returns the updated context along with a potential error. +func PrepareAccountsForDelegationRewards(t *testing.T, ctx sdk.Context, app evm.EvmApp, addr sdk.AccAddress, balance sdkmath.Int, rewards ...sdkmath.Int) (sdk.Context, error) { + t.Helper() + // Calculate the necessary amount of tokens to fund the account in order for the desired residual balance to + // be left after creating validators and delegating to them. + totalRewards := sdkmath.ZeroInt() + for _, reward := range rewards { + totalRewards = totalRewards.Add(reward) + } + totalNeededBalance := balance.Add(totalRewards) + + accountKeeper := app.GetAccountKeeper() + bankKeeper := app.GetBankKeeper() + distrKeeper := app.GetDistrKeeper() + stakingKeeper := app.GetStakingKeeper() + if totalNeededBalance.IsZero() { + accountKeeper.SetAccount(ctx, accountKeeper.NewAccountWithAddress(ctx, addr)) + } else { + // Fund account with enough tokens to stake them + err := testutil.FundAccountWithBaseDenom(ctx, bankKeeper, addr, totalNeededBalance.Int64()) + if err != nil { + return sdk.Context{}, fmt.Errorf("failed to fund account: %s", err.Error()) + } + } + + if totalRewards.IsZero() { + return ctx, nil + } + + // reset historical count in distribution keeper which is necessary + // for the delegation rewards to be calculated correctly + distrKeeper.DeleteAllValidatorHistoricalRewards(ctx) + + // set distribution module account balance which pays out the rewards + distrAcc := distrKeeper.GetDistributionAccount(ctx) + err := testutil.FundModuleAccount(ctx, bankKeeper, distrAcc.GetName(), sdk.NewCoins(sdk.NewCoin(constants.ExampleAttoDenom, totalRewards))) + if err != nil { + return sdk.Context{}, fmt.Errorf("failed to fund distribution module account: %s", err.Error()) + } + accountKeeper.SetModuleAccount(ctx, distrAcc) + + for _, reward := range rewards { + if reward.IsZero() { + continue + } + + // Set up validator and delegate to it + privKey := ed25519.GenPrivKey() + addr2, _ := utiltx.NewAccAddressAndKey() + err := testutil.FundAccountWithBaseDenom(ctx, bankKeeper, addr2, reward.Int64()) + if err != nil { + return sdk.Context{}, fmt.Errorf("failed to fund validator account: %s", err.Error()) + } + + zeroDec := sdkmath.LegacyZeroDec() + stakingParams, err := stakingKeeper.GetParams(ctx) + if err != nil { + return sdk.Context{}, fmt.Errorf("failed to get staking params: %s", err.Error()) + } + stakingParams.BondDenom = constants.ExampleAttoDenom + stakingParams.MinCommissionRate = zeroDec + err = stakingKeeper.SetParams(ctx, stakingParams) + require.NoError(t, err) + + stakingHelper := teststaking.NewHelper(t, ctx, stakingKeeper) + stakingHelper.Commission = stakingtypes.NewCommissionRates(zeroDec, zeroDec, zeroDec) + stakingHelper.Denom = constants.ExampleAttoDenom + + valAddr := sdk.ValAddress(addr2.Bytes()) + // self-delegate the same amount of tokens as the delegate address also stakes + // this ensures, that the delegation rewards are 50% of the total rewards + stakingHelper.CreateValidator(valAddr, privKey.PubKey(), reward, true) + stakingHelper.Delegate(addr, valAddr, reward) + + // end block to bond validator and increase block height + // Not using Commit() here because code panics due to invalid block height + _, err = stakingKeeper.EndBlocker(ctx) + require.NoError(t, err) + + // allocate rewards to validator (of these 50% will be paid out to the delegator) + validator, err := stakingKeeper.Validator(ctx, valAddr) + if err != nil { + return sdk.Context{}, fmt.Errorf("failed to get validator: %s", err.Error()) + } + allocatedRewards := sdk.NewDecCoins(sdk.NewDecCoin(constants.ExampleAttoDenom, reward.Mul(sdkmath.NewInt(2)))) + if err = distrKeeper.AllocateTokensToValidator(ctx, validator, allocatedRewards); err != nil { + return sdk.Context{}, fmt.Errorf("failed to allocate tokens to validator: %s", err.Error()) + } + } + + // Increase block height in ctx for the rewards calculation + // NOTE: this will only work for unit tests that use the context + // returned by this function + currentHeight := ctx.BlockHeight() + return ctx.WithBlockHeight(currentHeight + 1), nil +} diff --git a/tests/integration/ante/evm_unit_ante_test_suite.go b/tests/integration/ante/evm_unit_ante_test_suite.go new file mode 100644 index 000000000..a02f6f240 --- /dev/null +++ b/tests/integration/ante/evm_unit_ante_test_suite.go @@ -0,0 +1,29 @@ +package ante + +import ( + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/testutil/integration/evm/network" +) + +// EvmUniAnteTestSuite aims to test all EVM ante handler unit functions. +// NOTE: the suite only holds properties related to global execution parameters +// (what type of tx to run the tests with) not independent tests values. +type EvmUnitAnteTestSuite struct { + suite.Suite + + create network.CreateEvmApp + + // To make sure that every tests is run with all the tx types + EthTxType int + ChainID string + EvmChainID uint64 +} + +func NewEvmUnitAnteTestSuite( + create network.CreateEvmApp, +) *EvmUnitAnteTestSuite { + return &EvmUnitAnteTestSuite{ + create: create, + } +} diff --git a/ante/evm/eth_benchmark_test.go b/tests/integration/ante/test_bench_evm_ante.go similarity index 77% rename from ante/evm/eth_benchmark_test.go rename to tests/integration/ante/test_bench_evm_ante.go index a7031d4c2..1d19b3e06 100644 --- a/ante/evm/eth_benchmark_test.go +++ b/tests/integration/ante/test_bench_evm_ante.go @@ -1,4 +1,4 @@ -package evm_test +package ante import ( "fmt" @@ -7,9 +7,9 @@ import ( ethtypes "github.com/ethereum/go-ethereum/core/types" - ethante "github.com/cosmos/evm/ante/evm" - "github.com/cosmos/evm/ante/testutils" + evmante "github.com/cosmos/evm/ante/evm" "github.com/cosmos/evm/testutil" + "github.com/cosmos/evm/testutil/integration/evm/network" testutiltx "github.com/cosmos/evm/testutil/tx" "github.com/cosmos/evm/x/vm/statedb" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -20,16 +20,11 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -func BenchmarkEthGasConsumeDecorator(b *testing.B) { - baseSuite := new(testutils.AnteTestSuite) - s := &AnteTestSuite{ - AnteTestSuite: baseSuite, - } - +func RunBenchmarkEthGasConsumeDecorator(b *testing.B, create network.CreateEvmApp, options ...network.ConfigOption) { + s := NewEvmAnteTestSuite(create, options...) s.SetT(&testing.T{}) s.SetupTest() - ctx := s.GetNetwork().GetContext() - + ctx := s.network.GetContext() args := &evmtypes.EvmTxArgs{ ChainID: evmtypes.GetEthChainConfig().ChainID, Nonce: 1, @@ -65,11 +60,11 @@ func BenchmarkEthGasConsumeDecorator(b *testing.B) { cacheCtx, _ := ctx.CacheContext() // Create new stateDB for each test case from the cached context - vmdb = testutil.NewStateDB(cacheCtx, s.GetNetwork().App.EVMKeeper) + vmdb = testutil.NewStateDB(cacheCtx, s.GetNetwork().App.GetEVMKeeper()) cacheCtx = s.prepareAccount(cacheCtx, addr.Bytes(), tc.balance, tc.rewards) s.Require().NoError(vmdb.Commit()) - baseFee := s.GetNetwork().App.FeeMarketKeeper.GetParams(ctx).BaseFee + baseFee := s.GetNetwork().App.GetFeeMarketKeeper().GetParams(ctx).BaseFee fee := tx.GetEffectiveFee(baseFee.BigInt()) denom := evmtypes.GetEVMCoinDenom() fees := sdk.NewCoins(sdk.NewCoin(denom, sdkmath.NewIntFromBigInt(fee))) @@ -78,9 +73,9 @@ func BenchmarkEthGasConsumeDecorator(b *testing.B) { // Benchmark only the ante handler logic - start the timer b.StartTimer() - err := ethante.ConsumeFeesAndEmitEvent( + err := evmante.ConsumeFeesAndEmitEvent( cacheCtx.WithIsCheckTx(true).WithGasMeter(storetypes.NewInfiniteGasMeter()), - s.GetNetwork().App.EVMKeeper, + s.GetNetwork().App.GetEVMKeeper(), fees, bechAddr, ) diff --git a/ante/evm/01_setup_ctx_test.go b/tests/integration/ante/test_evm_01_setup_ctx.go similarity index 64% rename from ante/evm/01_setup_ctx_test.go rename to tests/integration/ante/test_evm_01_setup_ctx.go index a243ed504..259e601f5 100644 --- a/ante/evm/01_setup_ctx_test.go +++ b/tests/integration/ante/test_evm_01_setup_ctx.go @@ -1,4 +1,4 @@ -package evm_test +package ante import ( "math/big" @@ -13,8 +13,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -func (suite *AnteTestSuite) TestEthSetupContextDecorator() { - dec := evmante.NewEthSetUpContextDecorator(suite.GetNetwork().App.EVMKeeper) +func (s *EvmAnteTestSuite) TestEthSetupContextDecorator() { + dec := evmante.NewEthSetUpContextDecorator(s.GetNetwork().App.GetEVMKeeper()) ethContractCreationTxParams := &evmtypes.EvmTxArgs{ ChainID: evmtypes.GetEthChainConfig().ChainID, Nonce: 1, @@ -38,15 +38,15 @@ func (suite *AnteTestSuite) TestEthSetupContextDecorator() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - ctx, err := dec.AnteHandle(suite.GetNetwork().GetContext(), tc.tx, false, testutil.NoOpNextFn) + s.Run(tc.name, func() { + ctx, err := dec.AnteHandle(s.GetNetwork().GetContext(), tc.tx, false, testutil.NoOpNextFn) if tc.expPass { - suite.Require().NoError(err) - suite.Equal(storetypes.GasConfig{}, ctx.KVGasConfig()) - suite.Equal(storetypes.GasConfig{}, ctx.TransientKVGasConfig()) + s.Require().NoError(err) + s.Equal(storetypes.GasConfig{}, ctx.KVGasConfig()) + s.Equal(storetypes.GasConfig{}, ctx.TransientKVGasConfig()) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } diff --git a/ante/evm/ante_test.go b/tests/integration/ante/test_evm_ante.go similarity index 61% rename from ante/evm/ante_test.go rename to tests/integration/ante/test_evm_ante.go index 2c4d25674..3e63b5092 100644 --- a/ante/evm/ante_test.go +++ b/tests/integration/ante/test_evm_ante.go @@ -1,4 +1,4 @@ -package evm_test +package ante import ( "errors" @@ -11,6 +11,8 @@ import ( ethparams "github.com/ethereum/go-ethereum/params" "github.com/holiman/uint256" + ethante "github.com/cosmos/evm/ante/evm" + "github.com/cosmos/evm/testutil" testconstants "github.com/cosmos/evm/testutil/constants" utiltx "github.com/cosmos/evm/testutil/tx" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -26,7 +28,7 @@ import ( govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" ) -func (suite *AnteTestSuite) TestAnteHandler() { +func (s *EvmAnteTestSuite) TestAnteHandler() { var ( ctx sdk.Context addr common.Address @@ -35,15 +37,15 @@ func (suite *AnteTestSuite) TestAnteHandler() { to := utiltx.GenerateAddress() setup := func() { - suite.WithFeemarketEnabled(false) + s.WithFeemarketEnabled(false) baseFee := sdkmath.LegacyNewDec(100) - suite.WithBaseFee(&baseFee) - suite.SetupTest() // reset + s.WithBaseFee(&baseFee) + s.SetupTest() // reset - fromKey := suite.GetKeyring().GetKey(0) + fromKey := s.GetKeyring().GetKey(0) addr = fromKey.Addr privKey = fromKey.Priv - ctx = suite.GetNetwork().GetContext() + ctx = s.GetNetwork().GetContext() } ethCfg := evmtypes.GetEthChainConfig() @@ -76,8 +78,8 @@ func (suite *AnteTestSuite) TestAnteHandler() { { "success - DeliverTx (contract)", func() sdk.Tx { - tx, err := suite.GetTxFactory().GenerateSignedEthTx(privKey, ethContractCreationTxParams) - suite.Require().NoError(err) + tx, err := s.GetTxFactory().GenerateSignedEthTx(privKey, ethContractCreationTxParams) + s.Require().NoError(err) return tx }, false, false, true, @@ -85,8 +87,8 @@ func (suite *AnteTestSuite) TestAnteHandler() { { "success - CheckTx (contract)", func() sdk.Tx { - tx, err := suite.GetTxFactory().GenerateSignedEthTx(privKey, ethContractCreationTxParams) - suite.Require().NoError(err) + tx, err := s.GetTxFactory().GenerateSignedEthTx(privKey, ethContractCreationTxParams) + s.Require().NoError(err) return tx }, true, false, true, @@ -94,8 +96,8 @@ func (suite *AnteTestSuite) TestAnteHandler() { { "success - ReCheckTx (contract)", func() sdk.Tx { - tx, err := suite.GetTxFactory().GenerateSignedEthTx(privKey, ethContractCreationTxParams) - suite.Require().NoError(err) + tx, err := s.GetTxFactory().GenerateSignedEthTx(privKey, ethContractCreationTxParams) + s.Require().NoError(err) return tx }, false, true, true, @@ -103,8 +105,8 @@ func (suite *AnteTestSuite) TestAnteHandler() { { "success - DeliverTx", func() sdk.Tx { - tx, err := suite.GetTxFactory().GenerateSignedEthTx(privKey, ethTxParams) - suite.Require().NoError(err) + tx, err := s.GetTxFactory().GenerateSignedEthTx(privKey, ethTxParams) + s.Require().NoError(err) return tx }, false, false, true, @@ -112,8 +114,8 @@ func (suite *AnteTestSuite) TestAnteHandler() { { "success - CheckTx", func() sdk.Tx { - tx, err := suite.GetTxFactory().GenerateSignedEthTx(privKey, ethTxParams) - suite.Require().NoError(err) + tx, err := s.GetTxFactory().GenerateSignedEthTx(privKey, ethTxParams) + s.Require().NoError(err) return tx }, true, false, true, @@ -121,23 +123,23 @@ func (suite *AnteTestSuite) TestAnteHandler() { { "success - ReCheckTx", func() sdk.Tx { - tx, err := suite.GetTxFactory().GenerateSignedEthTx(privKey, ethTxParams) - suite.Require().NoError(err) + tx, err := s.GetTxFactory().GenerateSignedEthTx(privKey, ethTxParams) + s.Require().NoError(err) return tx }, false, true, true, }, { "success - CheckTx (cosmos tx not signed)", func() sdk.Tx { - tx, err := suite.GetTxFactory().GenerateSignedEthTx(privKey, ethTxParams) - suite.Require().NoError(err) + tx, err := s.GetTxFactory().GenerateSignedEthTx(privKey, ethTxParams) + s.Require().NoError(err) return tx }, false, true, true, }, { "fail - CheckTx (cosmos tx is not valid)", func() sdk.Tx { - txBuilder := suite.CreateTxBuilder(privKey, ethTxParams) + txBuilder := s.CreateTxBuilder(privKey, ethTxParams) // bigger than MaxGasWanted txBuilder.SetGasLimit(uint64(1 << 63)) @@ -147,7 +149,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { { "fail - CheckTx (memo too long)", func() sdk.Tx { - txBuilder := suite.CreateTxBuilder(privKey, ethTxParams) + txBuilder := s.CreateTxBuilder(privKey, ethTxParams) txBuilder.SetMemo(strings.Repeat("*", 257)) return txBuilder.GetTx() @@ -156,7 +158,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { { "fail - CheckTx (ExtensionOptionsEthereumTx not set)", func() sdk.Tx { - txBuilder := suite.CreateTxBuilder(privKey, ethTxParams, true) + txBuilder := s.CreateTxBuilder(privKey, ethTxParams, true) return txBuilder.GetTx() }, true, false, false, }, @@ -176,8 +178,8 @@ func (suite *AnteTestSuite) TestAnteHandler() { To: ethTxParams.To, Accesses: ethTxParams.Accesses, } - tx, err := suite.GetTxFactory().GenerateSignedEthTxWithChainID(privKey, txParamsCopy, chainID) - suite.Require().NoError(err) + tx, err := s.GetTxFactory().GenerateSignedEthTxWithChainID(privKey, txParamsCopy, chainID) + s.Require().NoError(err) return tx }, true, false, false, @@ -187,8 +189,8 @@ func (suite *AnteTestSuite) TestAnteHandler() { { "fail - DeliverTx (cosmos tx signed)", func() sdk.Tx { - nonce, err := suite.GetNetwork().App.AccountKeeper.GetSequence(ctx, suite.GetKeyring().GetAccAddr(0)) - suite.Require().NoError(err) + nonce, err := s.GetNetwork().App.GetAccountKeeper().GetSequence(ctx, s.GetKeyring().GetAccAddr(0)) + s.Require().NoError(err) ethTxParams := evmtypes.EvmTxArgs{ ChainID: ethCfg.ChainID, To: &to, @@ -198,16 +200,16 @@ func (suite *AnteTestSuite) TestAnteHandler() { GasPrice: big.NewInt(1), } - txBuilder := suite.CreateTxBuilder(privKey, ethTxParams, true) - suite.Require().NoError(suite.GetTxFactory().SignCosmosTx(privKey, txBuilder)) + txBuilder := s.CreateTxBuilder(privKey, ethTxParams, true) + s.Require().NoError(s.GetTxFactory().SignCosmosTx(privKey, txBuilder)) return txBuilder.GetTx() }, false, false, false, }, { "fail - DeliverTx (cosmos tx with memo)", func() sdk.Tx { - nonce, err := suite.GetNetwork().App.AccountKeeper.GetSequence(ctx, suite.GetKeyring().GetAccAddr(0)) - suite.Require().NoError(err) + nonce, err := s.GetNetwork().App.GetAccountKeeper().GetSequence(ctx, s.GetKeyring().GetAccAddr(0)) + s.Require().NoError(err) ethTxParams := evmtypes.EvmTxArgs{ ChainID: ethCfg.ChainID, To: &to, @@ -216,7 +218,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { GasLimit: 100000, GasPrice: big.NewInt(1), } - txBuilder := suite.CreateTxBuilder(privKey, ethTxParams) + txBuilder := s.CreateTxBuilder(privKey, ethTxParams) txBuilder.SetMemo("memo for cosmos tx not allowed") return txBuilder.GetTx() }, false, false, false, @@ -224,8 +226,8 @@ func (suite *AnteTestSuite) TestAnteHandler() { { "fail - DeliverTx (cosmos tx with timeoutheight)", func() sdk.Tx { - nonce, err := suite.GetNetwork().App.AccountKeeper.GetSequence(ctx, suite.GetKeyring().GetAccAddr(0)) - suite.Require().NoError(err) + nonce, err := s.GetNetwork().App.GetAccountKeeper().GetSequence(ctx, s.GetKeyring().GetAccAddr(0)) + s.Require().NoError(err) ethTxParams := evmtypes.EvmTxArgs{ ChainID: ethCfg.ChainID, To: &to, @@ -234,7 +236,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { GasLimit: 100000, GasPrice: big.NewInt(1), } - txBuilder := suite.CreateTxBuilder(privKey, ethTxParams) + txBuilder := s.CreateTxBuilder(privKey, ethTxParams) txBuilder.SetTimeoutHeight(10) return txBuilder.GetTx() }, false, false, false, @@ -242,8 +244,8 @@ func (suite *AnteTestSuite) TestAnteHandler() { { "fail - DeliverTx (invalid fee amount)", func() sdk.Tx { - nonce, err := suite.GetNetwork().App.AccountKeeper.GetSequence(ctx, suite.GetKeyring().GetAccAddr(0)) - suite.Require().NoError(err) + nonce, err := s.GetNetwork().App.GetAccountKeeper().GetSequence(ctx, s.GetKeyring().GetAccAddr(0)) + s.Require().NoError(err) ethTxParams := evmtypes.EvmTxArgs{ ChainID: ethCfg.ChainID, To: &to, @@ -252,10 +254,10 @@ func (suite *AnteTestSuite) TestAnteHandler() { GasLimit: 100000, GasPrice: big.NewInt(1), } - txBuilder := suite.CreateTxBuilder(privKey, ethTxParams) + txBuilder := s.CreateTxBuilder(privKey, ethTxParams) expFee := txBuilder.GetTx().GetFee() - oneCoin := sdk.NewCoin(suite.GetNetwork().GetBaseDenom(), sdkmath.NewInt(1)) + oneCoin := sdk.NewCoin(s.GetNetwork().GetBaseDenom(), sdkmath.NewInt(1)) invalidFee := expFee.Add(oneCoin) txBuilder.SetFeeAmount(invalidFee) return txBuilder.GetTx() @@ -264,8 +266,8 @@ func (suite *AnteTestSuite) TestAnteHandler() { { "fail - DeliverTx (invalid fee gaslimit)", func() sdk.Tx { - nonce, err := suite.GetNetwork().App.AccountKeeper.GetSequence(ctx, suite.GetKeyring().GetAccAddr(0)) - suite.Require().NoError(err) + nonce, err := s.GetNetwork().App.GetAccountKeeper().GetSequence(ctx, s.GetKeyring().GetAccAddr(0)) + s.Require().NoError(err) ethTxParams := evmtypes.EvmTxArgs{ ChainID: ethCfg.ChainID, To: &to, @@ -274,7 +276,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { GasLimit: 100000, GasPrice: big.NewInt(1), } - txBuilder := suite.CreateTxBuilder(privKey, ethTxParams) + txBuilder := s.CreateTxBuilder(privKey, ethTxParams) expGasLimit := txBuilder.GetTx().GetGas() invalidGasLimit := expGasLimit + 1 @@ -285,68 +287,68 @@ func (suite *AnteTestSuite) TestAnteHandler() { { "success - DeliverTx EIP712 signed Cosmos Tx with MsgSend", func() sdk.Tx { - from := suite.GetKeyring().GetAccAddr(0) + from := s.GetKeyring().GetAccAddr(0) gas := uint64(200000) amount := sdk.NewCoins(sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(100*int64(gas)))) //#nosec G115 - txBuilder, err := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) - suite.Require().NoError(err) + txBuilder, err := s.CreateTestEIP712TxBuilderMsgSend(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) + s.Require().NoError(err) return txBuilder.GetTx() }, false, false, true, }, { "success - DeliverTx EIP712 signed Cosmos Tx with DelegateMsg", func() sdk.Tx { - from := suite.GetKeyring().GetAccAddr(0) + from := s.GetKeyring().GetAccAddr(0) gas := uint64(200000) coinAmount := sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(100*int64(gas))) //#nosec G115 amount := sdk.NewCoins(coinAmount) - txBuilder, err := suite.CreateTestEIP712TxBuilderMsgDelegate(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) - suite.Require().NoError(err) + txBuilder, err := s.CreateTestEIP712TxBuilderMsgDelegate(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) + s.Require().NoError(err) return txBuilder.GetTx() }, false, false, true, }, { "success- DeliverTx EIP712 create validator", func() sdk.Tx { - from := suite.GetKeyring().GetAccAddr(0) + from := s.GetKeyring().GetAccAddr(0) coinAmount := sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(20)) amount := sdk.NewCoins(coinAmount) gas := uint64(200000) - txBuilder, err := suite.CreateTestEIP712MsgCreateValidator(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) - suite.Require().NoError(err) + txBuilder, err := s.CreateTestEIP712MsgCreateValidator(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) + s.Require().NoError(err) return txBuilder.GetTx() }, false, false, true, }, { "success- DeliverTx EIP712 create validator (with blank fields)", func() sdk.Tx { - from := suite.GetKeyring().GetAccAddr(0) + from := s.GetKeyring().GetAccAddr(0) coinAmount := sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(20)) amount := sdk.NewCoins(coinAmount) gas := uint64(200000) - txBuilder, err := suite.CreateTestEIP712MsgCreateValidator2(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) - suite.Require().NoError(err) + txBuilder, err := s.CreateTestEIP712MsgCreateValidator2(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) + s.Require().NoError(err) return txBuilder.GetTx() }, false, false, true, }, { "success- DeliverTx EIP712 MsgSubmitProposal", func() sdk.Tx { - from := suite.GetKeyring().GetAccAddr(0) + from := s.GetKeyring().GetAccAddr(0) coinAmount := sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(20)) gasAmount := sdk.NewCoins(coinAmount) gas := uint64(200000) // reusing the gasAmount for deposit deposit := sdk.NewCoins(coinAmount) - txBuilder, err := suite.CreateTestEIP712SubmitProposal(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, gasAmount, deposit) - suite.Require().NoError(err) + txBuilder, err := s.CreateTestEIP712SubmitProposal(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, gasAmount, deposit) + s.Require().NoError(err) return txBuilder.GetTx() }, false, false, true, }, { "success- DeliverTx EIP712 MsgGrant", func() sdk.Tx { - from := suite.GetKeyring().GetAccAddr(0) + from := s.GetKeyring().GetAccAddr(0) grantee := sdk.AccAddress("_______grantee______") coinAmount := sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(20)) gasAmount := sdk.NewCoins(coinAmount) @@ -356,9 +358,9 @@ func (suite *AnteTestSuite) TestAnteHandler() { msg, err := authz.NewMsgGrant( from, grantee, &banktypes.SendAuthorization{SpendLimit: gasAmount}, &expiresAt, ) - suite.Require().NoError(err) - builder, err := suite.CreateTestEIP712SingleMessageTxBuilder(privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, gasAmount, msg) - suite.Require().NoError(err) + s.Require().NoError(err) + builder, err := s.CreateTestEIP712SingleMessageTxBuilder(privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, gasAmount, msg) + s.Require().NoError(err) return builder.GetTx() }, false, false, true, @@ -367,12 +369,12 @@ func (suite *AnteTestSuite) TestAnteHandler() { { "success- DeliverTx EIP712 MsgGrantAllowance", func() sdk.Tx { - from := suite.GetKeyring().GetAccAddr(0) + from := s.GetKeyring().GetAccAddr(0) coinAmount := sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(20)) gasAmount := sdk.NewCoins(coinAmount) gas := uint64(200000) - txBuilder, err := suite.CreateTestEIP712GrantAllowance(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, gasAmount) - suite.Require().NoError(err) + txBuilder, err := s.CreateTestEIP712GrantAllowance(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, gasAmount) + s.Require().NoError(err) return txBuilder.GetTx() }, false, false, true, @@ -380,178 +382,178 @@ func (suite *AnteTestSuite) TestAnteHandler() { { "success- DeliverTx EIP712 edit validator", func() sdk.Tx { - from := suite.GetKeyring().GetAccAddr(0) + from := s.GetKeyring().GetAccAddr(0) coinAmount := sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(20)) amount := sdk.NewCoins(coinAmount) gas := uint64(200000) - txBuilder, err := suite.CreateTestEIP712MsgEditValidator(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) - suite.Require().NoError(err) + txBuilder, err := s.CreateTestEIP712MsgEditValidator(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) + s.Require().NoError(err) return txBuilder.GetTx() }, false, false, true, }, { "success- DeliverTx EIP712 submit evidence", func() sdk.Tx { - from := suite.GetKeyring().GetAccAddr(0) + from := s.GetKeyring().GetAccAddr(0) coinAmount := sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(20)) amount := sdk.NewCoins(coinAmount) gas := uint64(200000) - txBuilder, err := suite.CreateTestEIP712MsgSubmitEvidence(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) - suite.Require().NoError(err) + txBuilder, err := s.CreateTestEIP712MsgSubmitEvidence(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) + s.Require().NoError(err) return txBuilder.GetTx() }, false, false, true, }, { "success- DeliverTx EIP712 submit proposal v1", func() sdk.Tx { - from := suite.GetKeyring().GetAccAddr(0) + from := s.GetKeyring().GetAccAddr(0) coinAmount := sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(20)) amount := sdk.NewCoins(coinAmount) gas := uint64(200000) - txBuilder, err := suite.CreateTestEIP712SubmitProposalV1(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) - suite.Require().NoError(err) + txBuilder, err := s.CreateTestEIP712SubmitProposalV1(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) + s.Require().NoError(err) return txBuilder.GetTx() }, false, false, true, }, { "success- DeliverTx EIP712 MsgExec", func() sdk.Tx { - from := suite.GetKeyring().GetAccAddr(0) + from := s.GetKeyring().GetAccAddr(0) coinAmount := sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(20)) amount := sdk.NewCoins(coinAmount) gas := uint64(200000) - txBuilder, err := suite.CreateTestEIP712MsgExec(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) - suite.Require().NoError(err) + txBuilder, err := s.CreateTestEIP712MsgExec(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) + s.Require().NoError(err) return txBuilder.GetTx() }, false, false, true, }, { "success- DeliverTx EIP712 MsgVoteV1", func() sdk.Tx { - from := suite.GetKeyring().GetAccAddr(0) + from := s.GetKeyring().GetAccAddr(0) coinAmount := sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(20)) amount := sdk.NewCoins(coinAmount) gas := uint64(200000) - txBuilder, err := suite.CreateTestEIP712MsgVoteV1(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) - suite.Require().NoError(err) + txBuilder, err := s.CreateTestEIP712MsgVoteV1(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) + s.Require().NoError(err) return txBuilder.GetTx() }, false, false, true, }, { "success- DeliverTx EIP712 Multiple MsgSend", func() sdk.Tx { - from := suite.GetKeyring().GetAccAddr(0) + from := s.GetKeyring().GetAccAddr(0) coinAmount := sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(20)) amount := sdk.NewCoins(coinAmount) gas := uint64(200000) - txBuilder, err := suite.CreateTestEIP712MultipleMsgSend(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) - suite.Require().NoError(err) + txBuilder, err := s.CreateTestEIP712MultipleMsgSend(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) + s.Require().NoError(err) return txBuilder.GetTx() }, false, false, true, }, { "success- DeliverTx EIP712 Multiple Different Msgs", func() sdk.Tx { - from := suite.GetKeyring().GetAccAddr(0) + from := s.GetKeyring().GetAccAddr(0) coinAmount := sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(20)) amount := sdk.NewCoins(coinAmount) gas := uint64(200000) - txBuilder, err := suite.CreateTestEIP712MultipleDifferentMsgs(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) - suite.RequireErrorForLegacyTypedData(err) - return suite.TxForLegacyTypedData(txBuilder) - }, false, false, !suite.useLegacyEIP712TypedData, + txBuilder, err := s.CreateTestEIP712MultipleDifferentMsgs(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) + s.RequireErrorForLegacyTypedData(err) + return s.TxForLegacyTypedData(txBuilder) + }, false, false, !s.UseLegacyEIP712TypedData, }, { "success- DeliverTx EIP712 Same Msgs, Different Schemas", func() sdk.Tx { - from := suite.GetKeyring().GetAccAddr(0) + from := s.GetKeyring().GetAccAddr(0) coinAmount := sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(20)) amount := sdk.NewCoins(coinAmount) gas := uint64(200000) - txBuilder, err := suite.CreateTestEIP712SameMsgDifferentSchemas(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) - suite.RequireErrorForLegacyTypedData(err) - return suite.TxForLegacyTypedData(txBuilder) - }, false, false, !suite.useLegacyEIP712TypedData, + txBuilder, err := s.CreateTestEIP712SameMsgDifferentSchemas(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) + s.RequireErrorForLegacyTypedData(err) + return s.TxForLegacyTypedData(txBuilder) + }, false, false, !s.UseLegacyEIP712TypedData, }, { "success- DeliverTx EIP712 Zero Value Array (Should Not Omit Field)", func() sdk.Tx { - from := suite.GetKeyring().GetAccAddr(0) + from := s.GetKeyring().GetAccAddr(0) coinAmount := sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(20)) amount := sdk.NewCoins(coinAmount) gas := uint64(200000) - txBuilder, err := suite.CreateTestEIP712ZeroValueArray(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) - suite.RequireErrorForLegacyTypedData(err) - return suite.TxForLegacyTypedData(txBuilder) - }, false, false, !suite.useLegacyEIP712TypedData, + txBuilder, err := s.CreateTestEIP712ZeroValueArray(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) + s.RequireErrorForLegacyTypedData(err) + return s.TxForLegacyTypedData(txBuilder) + }, false, false, !s.UseLegacyEIP712TypedData, }, { "success- DeliverTx EIP712 Zero Value Number (Should Not Omit Field)", func() sdk.Tx { - from := suite.GetKeyring().GetAccAddr(0) + from := s.GetKeyring().GetAccAddr(0) coinAmount := sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(20)) amount := sdk.NewCoins(coinAmount) gas := uint64(200000) - txBuilder, err := suite.CreateTestEIP712ZeroValueNumber(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) - suite.RequireErrorForLegacyTypedData(err) - return suite.TxForLegacyTypedData(txBuilder) - }, false, false, !suite.useLegacyEIP712TypedData, + txBuilder, err := s.CreateTestEIP712ZeroValueNumber(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) + s.RequireErrorForLegacyTypedData(err) + return s.TxForLegacyTypedData(txBuilder) + }, false, false, !s.UseLegacyEIP712TypedData, }, { "success- DeliverTx EIP712 MsgTransfer", func() sdk.Tx { - from := suite.GetKeyring().GetAccAddr(0) + from := s.GetKeyring().GetAccAddr(0) coinAmount := sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(20)) amount := sdk.NewCoins(coinAmount) gas := uint64(200000) - txBuilder, err := suite.CreateTestEIP712MsgTransfer(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) - suite.Require().NoError(err) + txBuilder, err := s.CreateTestEIP712MsgTransfer(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) + s.Require().NoError(err) return txBuilder.GetTx() }, false, false, true, }, { "success- DeliverTx EIP712 MsgTransfer Without Memo", func() sdk.Tx { - from := suite.GetKeyring().GetAccAddr(0) + from := s.GetKeyring().GetAccAddr(0) coinAmount := sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(20)) amount := sdk.NewCoins(coinAmount) gas := uint64(200000) - txBuilder, err := suite.CreateTestEIP712MsgTransferWithoutMemo(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) - suite.Require().NoError(err) + txBuilder, err := s.CreateTestEIP712MsgTransferWithoutMemo(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) + s.Require().NoError(err) return txBuilder.GetTx() }, false, false, true, }, { "fails - DeliverTx EIP712 Multiple Signers", func() sdk.Tx { - from := suite.GetKeyring().GetAccAddr(0) + from := s.GetKeyring().GetAccAddr(0) coinAmount := sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(20)) amount := sdk.NewCoins(coinAmount) gas := uint64(200000) - txBuilder, err := suite.CreateTestEIP712MultipleSignerMsgs(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) - suite.Require().NoError(err) + txBuilder, err := s.CreateTestEIP712MultipleSignerMsgs(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) + s.Require().NoError(err) return txBuilder.GetTx() }, false, false, false, }, { "fails - DeliverTx EIP712 signed Cosmos Tx with wrong Chain ID", func() sdk.Tx { - from := suite.GetKeyring().GetAccAddr(0) + from := s.GetKeyring().GetAccAddr(0) gas := uint64(200000) amount := sdk.NewCoins(sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(100*int64(gas)))) //#nosec G115 - txBuilder, err := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, "cosmos-1", 9002, gas, amount) - suite.Require().NoError(err) + txBuilder, err := s.CreateTestEIP712TxBuilderMsgSend(from, privKey, "cosmos-1", 9002, gas, amount) + s.Require().NoError(err) return txBuilder.GetTx() }, false, false, false, }, { "fails - DeliverTx EIP712 signed Cosmos Tx with different gas fees", func() sdk.Tx { - from := suite.GetKeyring().GetAccAddr(0) + from := s.GetKeyring().GetAccAddr(0) gas := uint64(200000) amount := sdk.NewCoins(sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(100*int64(gas)))) //#nosec G115 - txBuilder, err := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) - suite.Require().NoError(err) + txBuilder, err := s.CreateTestEIP712TxBuilderMsgSend(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) + s.Require().NoError(err) txBuilder.SetGasLimit(uint64(300000)) txBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(30)))) return txBuilder.GetTx() @@ -560,24 +562,24 @@ func (suite *AnteTestSuite) TestAnteHandler() { { "fails - DeliverTx EIP712 signed Cosmos Tx with invalid chain id", func() sdk.Tx { - from := suite.GetKeyring().GetAccAddr(0) + from := s.GetKeyring().GetAccAddr(0) gas := uint64(200000) amount := sdk.NewCoins(sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(100*int64(gas)))) //#nosec G115 - txBuilder, err := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, "cosmos-1", 9005, gas, amount) - suite.Require().NoError(err) + txBuilder, err := s.CreateTestEIP712TxBuilderMsgSend(from, privKey, "cosmos-1", 9005, gas, amount) + s.Require().NoError(err) return txBuilder.GetTx() }, false, false, false, }, { "fails - DeliverTx EIP712 signed Cosmos Tx with invalid sequence", func() sdk.Tx { - from := suite.GetKeyring().GetAccAddr(0) + from := s.GetKeyring().GetAccAddr(0) gas := uint64(200000) amount := sdk.NewCoins(sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(100*int64(gas)))) //#nosec G115 - txBuilder, err := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) - suite.Require().NoError(err) - nonce, err := suite.GetNetwork().App.AccountKeeper.GetSequence(ctx, suite.GetKeyring().GetAccAddr(0)) - suite.Require().NoError(err) + txBuilder, err := s.CreateTestEIP712TxBuilderMsgSend(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) + s.Require().NoError(err) + nonce, err := s.GetNetwork().App.GetAccountKeeper().GetSequence(ctx, s.GetKeyring().GetAccAddr(0)) + s.Require().NoError(err) sigsV2 := signing.SignatureV2{ PubKey: privKey.PubKey(), Data: &signing.SingleSignatureData{ @@ -587,20 +589,20 @@ func (suite *AnteTestSuite) TestAnteHandler() { } err = txBuilder.SetSignatures(sigsV2) - suite.Require().NoError(err) + s.Require().NoError(err) return txBuilder.GetTx() }, false, false, false, }, { "fails - DeliverTx EIP712 signed Cosmos Tx with invalid signMode", func() sdk.Tx { - from := suite.GetKeyring().GetAccAddr(0) + from := s.GetKeyring().GetAccAddr(0) gas := uint64(200000) amount := sdk.NewCoins(sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(100*int64(gas)))) //#nosec G115 - txBuilder, err := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) - suite.Require().NoError(err) - nonce, err := suite.GetNetwork().App.AccountKeeper.GetSequence(ctx, suite.GetKeyring().GetAccAddr(0)) - suite.Require().NoError(err) + txBuilder, err := s.CreateTestEIP712TxBuilderMsgSend(from, privKey, ctx.ChainID(), ethCfg.ChainID.Uint64(), gas, amount) + s.Require().NoError(err) + nonce, err := s.GetNetwork().App.GetAccountKeeper().GetSequence(ctx, s.GetKeyring().GetAccAddr(0)) + s.Require().NoError(err) sigsV2 := signing.SignatureV2{ PubKey: privKey.PubKey(), Data: &signing.SingleSignatureData{ @@ -609,15 +611,15 @@ func (suite *AnteTestSuite) TestAnteHandler() { Sequence: nonce, } err = txBuilder.SetSignatures(sigsV2) - suite.Require().NoError(err) + s.Require().NoError(err) return txBuilder.GetTx() }, false, false, false, }, { "fails - invalid from", func() sdk.Tx { - tx, err := suite.GetTxFactory().GenerateSignedEthTx(privKey, ethContractCreationTxParams) - suite.Require().NoError(err) + tx, err := s.GetTxFactory().GenerateSignedEthTx(privKey, ethContractCreationTxParams) + s.Require().NoError(err) msg := tx.GetMsgs()[0].(*evmtypes.MsgEthereumTx) msg.From = addr.Hex() return tx @@ -638,7 +640,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { ), ) - txBuilder := suite.CreateTestSingleSignedTx( + txBuilder := s.CreateTestSingleSignedTx( privKey, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, msg, @@ -654,7 +656,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { "passes - EIP-712 multi-key", func() sdk.Tx { numKeys := 5 - privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys) + privKeys, pubKeys := s.GenerateMultipleKeys(numKeys) pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys) msg := banktypes.NewMsgSend( @@ -668,7 +670,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { ), ) - txBuilder := suite.CreateTestSignedMultisigTx( + txBuilder := s.CreateTestSignedMultisigTx( privKeys, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, msg, @@ -684,7 +686,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { "passes - Mixed multi-key", func() sdk.Tx { numKeys := 5 - privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys) + privKeys, pubKeys := s.GenerateMultipleKeys(numKeys) pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys) msg := banktypes.NewMsgSend( @@ -698,7 +700,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { ), ) - txBuilder := suite.CreateTestSignedMultisigTx( + txBuilder := s.CreateTestSignedMultisigTx( privKeys, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, msg, @@ -714,7 +716,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { "passes - Mixed multi-key with MsgVote", func() sdk.Tx { numKeys := 5 - privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys) + privKeys, pubKeys := s.GenerateMultipleKeys(numKeys) pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys) msg := govtypes.NewMsgVote( @@ -723,7 +725,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { govtypes.OptionYes, ) - txBuilder := suite.CreateTestSignedMultisigTx( + txBuilder := s.CreateTestSignedMultisigTx( privKeys, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, msg, @@ -739,7 +741,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { "Fails - Multi-Key with incorrect Chain ID", func() sdk.Tx { numKeys := 5 - privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys) + privKeys, pubKeys := s.GenerateMultipleKeys(numKeys) pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys) msg := banktypes.NewMsgSend( @@ -753,7 +755,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { ), ) - txBuilder := suite.CreateTestSignedMultisigTx( + txBuilder := s.CreateTestSignedMultisigTx( privKeys, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, msg, @@ -769,7 +771,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { "Fails - Multi-Key with incorrect sign mode", func() sdk.Tx { numKeys := 5 - privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys) + privKeys, pubKeys := s.GenerateMultipleKeys(numKeys) pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys) msg := banktypes.NewMsgSend( @@ -783,7 +785,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { ), ) - txBuilder := suite.CreateTestSignedMultisigTx( + txBuilder := s.CreateTestSignedMultisigTx( privKeys, signing.SignMode_SIGN_MODE_DIRECT, msg, @@ -799,7 +801,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { "Fails - Multi-Key with too little gas", func() sdk.Tx { numKeys := 5 - privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys) + privKeys, pubKeys := s.GenerateMultipleKeys(numKeys) pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys) msg := banktypes.NewMsgSend( @@ -813,7 +815,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { ), ) - txBuilder := suite.CreateTestSignedMultisigTx( + txBuilder := s.CreateTestSignedMultisigTx( privKeys, signing.SignMode_SIGN_MODE_DIRECT, msg, @@ -829,7 +831,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { "Fails - Multi-Key with different payload than one signed", func() sdk.Tx { numKeys := 1 - privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys) + privKeys, pubKeys := s.GenerateMultipleKeys(numKeys) pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys) msg := banktypes.NewMsgSend( @@ -843,7 +845,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { ), ) - txBuilder := suite.CreateTestSignedMultisigTx( + txBuilder := s.CreateTestSignedMultisigTx( privKeys, signing.SignMode_SIGN_MODE_DIRECT, msg, @@ -854,7 +856,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { msg.Amount[0].Amount = sdkmath.NewInt(5) err := txBuilder.SetMsgs(msg) - suite.Require().NoError(err) + s.Require().NoError(err) return txBuilder.GetTx() }, false, false, false, @@ -863,7 +865,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { "Fails - Multi-Key with messages added after signing", func() sdk.Tx { numKeys := 1 - privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys) + privKeys, pubKeys := s.GenerateMultipleKeys(numKeys) pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys) msg := banktypes.NewMsgSend( @@ -877,7 +879,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { ), ) - txBuilder := suite.CreateTestSignedMultisigTx( + txBuilder := s.CreateTestSignedMultisigTx( privKeys, signing.SignMode_SIGN_MODE_DIRECT, msg, @@ -888,7 +890,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { // Duplicate err := txBuilder.SetMsgs(msg, msg) - suite.Require().NoError(err) + s.Require().NoError(err) return txBuilder.GetTx() }, false, false, false, @@ -907,7 +909,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { ), ) - txBuilder := suite.CreateTestSingleSignedTx( + txBuilder := s.CreateTestSingleSignedTx( privKey, signing.SignMode_SIGN_MODE_DIRECT, msg, @@ -917,7 +919,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { ) err := txBuilder.SetMsgs(msg, msg) - suite.Require().NoError(err) + s.Require().NoError(err) return txBuilder.GetTx() }, false, false, false, @@ -925,23 +927,23 @@ func (suite *AnteTestSuite) TestAnteHandler() { } for _, tc := range testCases { - suite.Run(tc.name, func() { + s.Run(tc.name, func() { setup() ctx = ctx.WithIsCheckTx(tc.checkTx).WithIsReCheckTx(tc.reCheckTx) - anteHandler := suite.GetAnteHandler() + anteHandler := s.GetAnteHandler() _, err := anteHandler(ctx, tc.txFn(), false) if tc.expPass { - suite.Require().NoError(err) + s.Require().NoError(err) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *AnteTestSuite) TestAnteHandlerWithDynamicTxFee() { +func (s *EvmAnteTestSuite) TestAnteHandlerWithDynamicTxFee() { addr, privKey := utiltx.NewAddrKey() to := utiltx.GenerateAddress() @@ -979,8 +981,8 @@ func (suite *AnteTestSuite) TestAnteHandlerWithDynamicTxFee() { { "success - DeliverTx (contract)", func() sdk.Tx { - tx, err := suite.GetTxFactory().GenerateSignedEthTx(privKey, ethContractCreationTxParams) - suite.Require().NoError(err) + tx, err := s.GetTxFactory().GenerateSignedEthTx(privKey, ethContractCreationTxParams) + s.Require().NoError(err) return tx }, true, @@ -989,8 +991,8 @@ func (suite *AnteTestSuite) TestAnteHandlerWithDynamicTxFee() { { "success - CheckTx (contract)", func() sdk.Tx { - tx, err := suite.GetTxFactory().GenerateSignedEthTx(privKey, ethContractCreationTxParams) - suite.Require().NoError(err) + tx, err := s.GetTxFactory().GenerateSignedEthTx(privKey, ethContractCreationTxParams) + s.Require().NoError(err) return tx }, true, @@ -999,8 +1001,8 @@ func (suite *AnteTestSuite) TestAnteHandlerWithDynamicTxFee() { { "success - ReCheckTx (contract)", func() sdk.Tx { - tx, err := suite.GetTxFactory().GenerateSignedEthTx(privKey, ethContractCreationTxParams) - suite.Require().NoError(err) + tx, err := s.GetTxFactory().GenerateSignedEthTx(privKey, ethContractCreationTxParams) + s.Require().NoError(err) return tx }, true, @@ -1009,8 +1011,8 @@ func (suite *AnteTestSuite) TestAnteHandlerWithDynamicTxFee() { { "success - DeliverTx", func() sdk.Tx { - tx, err := suite.GetTxFactory().GenerateSignedEthTx(privKey, ethTxParams) - suite.Require().NoError(err) + tx, err := s.GetTxFactory().GenerateSignedEthTx(privKey, ethTxParams) + s.Require().NoError(err) return tx }, true, @@ -1019,8 +1021,8 @@ func (suite *AnteTestSuite) TestAnteHandlerWithDynamicTxFee() { { "success - CheckTx", func() sdk.Tx { - tx, err := suite.GetTxFactory().GenerateSignedEthTx(privKey, ethTxParams) - suite.Require().NoError(err) + tx, err := s.GetTxFactory().GenerateSignedEthTx(privKey, ethTxParams) + s.Require().NoError(err) return tx }, true, @@ -1029,8 +1031,8 @@ func (suite *AnteTestSuite) TestAnteHandlerWithDynamicTxFee() { { "success - ReCheckTx", func() sdk.Tx { - tx, err := suite.GetTxFactory().GenerateSignedEthTx(privKey, ethTxParams) - suite.Require().NoError(err) + tx, err := s.GetTxFactory().GenerateSignedEthTx(privKey, ethTxParams) + s.Require().NoError(err) return tx }, true, @@ -1039,8 +1041,8 @@ func (suite *AnteTestSuite) TestAnteHandlerWithDynamicTxFee() { { "success - CheckTx (cosmos tx not signed)", func() sdk.Tx { - tx, err := suite.GetTxFactory().GenerateSignedEthTx(privKey, ethTxParams) - suite.Require().NoError(err) + tx, err := s.GetTxFactory().GenerateSignedEthTx(privKey, ethTxParams) + s.Require().NoError(err) return tx }, true, @@ -1049,7 +1051,7 @@ func (suite *AnteTestSuite) TestAnteHandlerWithDynamicTxFee() { { "fail - CheckTx (cosmos tx is not valid)", func() sdk.Tx { - txBuilder := suite.CreateTxBuilder(privKey, ethTxParams) + txBuilder := s.CreateTxBuilder(privKey, ethTxParams) // bigger than MaxGasWanted txBuilder.SetGasLimit(uint64(1 << 63)) return txBuilder.GetTx() @@ -1060,7 +1062,7 @@ func (suite *AnteTestSuite) TestAnteHandlerWithDynamicTxFee() { { "fail - CheckTx (memo too long)", func() sdk.Tx { - txBuilder := suite.CreateTxBuilder(privKey, ethTxParams) + txBuilder := s.CreateTxBuilder(privKey, ethTxParams) txBuilder.SetMemo(strings.Repeat("*", 257)) return txBuilder.GetTx() }, @@ -1070,8 +1072,8 @@ func (suite *AnteTestSuite) TestAnteHandlerWithDynamicTxFee() { { "fail - DynamicFeeTx without london hark fork", func() sdk.Tx { - tx, err := suite.GetTxFactory().GenerateSignedEthTx(privKey, ethContractCreationTxParams) - suite.Require().NoError(err) + tx, err := s.GetTxFactory().GenerateSignedEthTx(privKey, ethContractCreationTxParams) + s.Require().NoError(err) return tx }, false, @@ -1080,33 +1082,33 @@ func (suite *AnteTestSuite) TestAnteHandlerWithDynamicTxFee() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.WithFeemarketEnabled(true) - suite.WithLondonHardForkEnabled(tc.enableLondonHF) - suite.SetupTest() // reset - ctx := suite.GetNetwork().GetContext() - acc := suite.GetNetwork().App.AccountKeeper.NewAccountWithAddress(ctx, addr.Bytes()) - suite.Require().NoError(acc.SetSequence(1)) - suite.GetNetwork().App.AccountKeeper.SetAccount(ctx, acc) + s.Run(tc.name, func() { + s.WithFeemarketEnabled(true) + s.WithLondonHardForkEnabled(tc.enableLondonHF) + s.SetupTest() // reset + ctx := s.GetNetwork().GetContext() + acc := s.GetNetwork().App.GetAccountKeeper().NewAccountWithAddress(ctx, addr.Bytes()) + s.Require().NoError(acc.SetSequence(1)) + s.GetNetwork().App.GetAccountKeeper().SetAccount(ctx, acc) ctx = ctx.WithIsCheckTx(tc.checkTx).WithIsReCheckTx(tc.reCheckTx) - err := suite.GetNetwork().App.EVMKeeper.SetBalance(ctx, addr, uint256.NewInt((ethparams.InitialBaseFee+10)*100000)) - suite.Require().NoError(err) + err := s.GetNetwork().App.GetEVMKeeper().SetBalance(ctx, addr, uint256.NewInt((ethparams.InitialBaseFee+10)*100000)) + s.Require().NoError(err) - anteHandler := suite.GetAnteHandler() + anteHandler := s.GetAnteHandler() _, err = anteHandler(ctx, tc.txFn(), false) if tc.expPass { - suite.Require().NoError(err) + s.Require().NoError(err) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } - suite.WithFeemarketEnabled(false) - suite.WithLondonHardForkEnabled(true) + s.WithFeemarketEnabled(false) + s.WithLondonHardForkEnabled(true) } -func (suite *AnteTestSuite) TestAnteHandlerWithParams() { +func (s *EvmAnteTestSuite) TestAnteHandlerWithParams() { addr, privKey := utiltx.NewAddrKey() to := utiltx.GenerateAddress() @@ -1144,8 +1146,8 @@ func (suite *AnteTestSuite) TestAnteHandlerWithParams() { { "fail - Contract Creation Disabled", func() sdk.Tx { - tx, err := suite.GetTxFactory().GenerateSignedEthTx(privKey, ethContractCreationTxParams) - suite.Require().NoError(err) + tx, err := s.GetTxFactory().GenerateSignedEthTx(privKey, ethContractCreationTxParams) + s.Require().NoError(err) return tx }, evmtypes.AccessControl{ @@ -1163,8 +1165,8 @@ func (suite *AnteTestSuite) TestAnteHandlerWithParams() { { "success - Contract Creation Enabled", func() sdk.Tx { - tx, err := suite.GetTxFactory().GenerateSignedEthTx(privKey, ethContractCreationTxParams) - suite.Require().NoError(err) + tx, err := s.GetTxFactory().GenerateSignedEthTx(privKey, ethContractCreationTxParams) + s.Require().NoError(err) return tx }, evmtypes.DefaultAccessControl, @@ -1173,8 +1175,8 @@ func (suite *AnteTestSuite) TestAnteHandlerWithParams() { { "fail - EVM Call Disabled", func() sdk.Tx { - tx, err := suite.GetTxFactory().GenerateSignedEthTx(privKey, ethTxParams) - suite.Require().NoError(err) + tx, err := s.GetTxFactory().GenerateSignedEthTx(privKey, ethTxParams) + s.Require().NoError(err) return tx }, evmtypes.AccessControl{ @@ -1192,8 +1194,8 @@ func (suite *AnteTestSuite) TestAnteHandlerWithParams() { { "success - EVM Call Enabled", func() sdk.Tx { - tx, err := suite.GetTxFactory().GenerateSignedEthTx(privKey, ethTxParams) - suite.Require().NoError(err) + tx, err := s.GetTxFactory().GenerateSignedEthTx(privKey, ethTxParams) + s.Require().NoError(err) return tx }, evmtypes.DefaultAccessControl, @@ -1202,33 +1204,148 @@ func (suite *AnteTestSuite) TestAnteHandlerWithParams() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.WithEvmParamsOptions(func(params *evmtypes.Params) { + s.Run(tc.name, func() { + s.WithEvmParamsOptions(func(params *evmtypes.Params) { params.AccessControl = tc.permissions }) // clean up the evmParamsOption - defer suite.ResetEvmParamsOptions() + defer s.ResetEvmParamsOptions() - suite.SetupTest() // reset + s.SetupTest() // reset - ctx := suite.GetNetwork().GetContext() - acc := suite.GetNetwork().App.AccountKeeper.NewAccountWithAddress(ctx, addr.Bytes()) - suite.Require().NoError(acc.SetSequence(1)) - suite.GetNetwork().App.AccountKeeper.SetAccount(ctx, acc) + ctx := s.GetNetwork().GetContext() + acc := s.GetNetwork().App.GetAccountKeeper().NewAccountWithAddress(ctx, addr.Bytes()) + s.Require().NoError(acc.SetSequence(1)) + s.GetNetwork().App.GetAccountKeeper().SetAccount(ctx, acc) ctx = ctx.WithIsCheckTx(true) - err := suite.GetNetwork().App.EVMKeeper.SetBalance(ctx, addr, uint256.NewInt((ethparams.InitialBaseFee+10)*100000)) - suite.Require().NoError(err) + err := s.GetNetwork().App.GetEVMKeeper().SetBalance(ctx, addr, uint256.NewInt((ethparams.InitialBaseFee+10)*100000)) + s.Require().NoError(err) - anteHandler := suite.GetAnteHandler() + anteHandler := s.GetAnteHandler() _, err = anteHandler(ctx, tc.txFn(), false) if tc.expErr == nil { - suite.Require().NoError(err) + s.Require().NoError(err) } else { - suite.Require().Error(err) - suite.Require().True(errors.Is(err, tc.expErr)) + s.Require().Error(err) + s.Require().True(errors.Is(err, tc.expErr)) } }) } - suite.WithEvmParamsOptions(nil) + s.WithEvmParamsOptions(nil) +} + +func (s *EvmAnteTestSuite) TestEthSigVerificationDecorator() { + addr, privKey := utiltx.NewAddrKey() + ethCfg := evmtypes.GetEthChainConfig() + ethSigner := types.LatestSignerForChainID(ethCfg.ChainID) + + ethContractCreationTxParams := &evmtypes.EvmTxArgs{ + ChainID: ethCfg.ChainID, + Nonce: 1, + Amount: big.NewInt(10), + GasLimit: 1000, + GasPrice: big.NewInt(1), + } + signedTx := evmtypes.NewTx(ethContractCreationTxParams) + signedTx.From = addr.Hex() + err := signedTx.Sign(ethSigner, utiltx.NewSigner(privKey)) + s.Require().NoError(err) + + unprotectedEthTxParams := &evmtypes.EvmTxArgs{ + Nonce: 1, + Amount: big.NewInt(10), + GasLimit: 1000, + GasPrice: big.NewInt(1), + } + unprotectedTx := evmtypes.NewTx(unprotectedEthTxParams) + unprotectedTx.From = addr.Hex() + err = unprotectedTx.Sign(types.HomesteadSigner{}, utiltx.NewSigner(privKey)) + s.Require().NoError(err) + + testCases := []struct { + name string + tx sdk.Tx + allowUnprotectedTxs bool + reCheckTx bool + expPass bool + }{ + {"ReCheckTx", &utiltx.InvalidTx{}, false, true, false}, + {"invalid transaction type", &utiltx.InvalidTx{}, false, false, false}, + { + "invalid sender", + evmtypes.NewTx(&evmtypes.EvmTxArgs{ + To: &addr, + Nonce: 1, + Amount: big.NewInt(10), + GasLimit: 1000, + GasPrice: big.NewInt(1), + }), + true, + false, + false, + }, + {"successful signature verification", signedTx, false, false, true}, + {"invalid, reject unprotected txs", unprotectedTx, false, false, false}, + {"successful, allow unprotected txs", unprotectedTx, true, false, true}, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.WithEvmParamsOptions(func(params *evmtypes.Params) { + params.AllowUnprotectedTxs = tc.allowUnprotectedTxs + }) + s.SetupTest() + dec := ethante.NewEthSigVerificationDecorator(s.GetNetwork().App.GetEVMKeeper()) + _, err := dec.AnteHandle(s.GetNetwork().GetContext().WithIsReCheckTx(tc.reCheckTx), tc.tx, false, testutil.NoOpNextFn) + + if tc.expPass { + s.Require().NoError(err) + } else { + s.Require().Error(err) + } + }) + } + s.WithEvmParamsOptions(nil) +} + +func (s *EvmAnteTestSuite) TestSignatures() { + s.WithFeemarketEnabled(false) + s.SetupTest() // reset + + privKey := s.GetKeyring().GetPrivKey(0) + to := utiltx.GenerateAddress() + + txArgs := evmtypes.EvmTxArgs{ + ChainID: evmtypes.GetEthChainConfig().ChainID, + Nonce: 0, + To: &to, + Amount: big.NewInt(10), + GasLimit: 100000, + GasPrice: big.NewInt(1), + } + + // CreateTestTx will sign the msgEthereumTx but not sign the cosmos tx since we have signCosmosTx as false + tx := s.CreateTxBuilder(privKey, txArgs).GetTx() + sigs, err := tx.GetSignaturesV2() + s.Require().NoError(err) + + // signatures of cosmos tx should be empty + s.Require().Equal(len(sigs), 0) + + msg := tx.GetMsgs()[0] + msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx) + s.Require().True(ok) + txData, err := evmtypes.UnpackTxData(msgEthTx.Data) + s.Require().NoError(err) + + msgV, msgR, msgS := txData.GetRawSignatureValues() + + ethTx := msgEthTx.AsTransaction() + ethV, ethR, ethS := ethTx.RawSignatureValues() + + // The signatures of MsgEthereumTx should be the same with the corresponding eth tx + s.Require().Equal(msgV, ethV) + s.Require().Equal(msgR, ethR) + s.Require().Equal(msgS, ethS) } diff --git a/ante/evm/fee_market_test.go b/tests/integration/ante/test_evm_fee_market.go similarity index 84% rename from ante/evm/fee_market_test.go rename to tests/integration/ante/test_evm_fee_market.go index 9395f415d..e610893d7 100644 --- a/ante/evm/fee_market_test.go +++ b/tests/integration/ante/test_evm_fee_market.go @@ -1,4 +1,4 @@ -package evm_test +package ante import ( "math/big" @@ -6,7 +6,6 @@ import ( ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/cosmos/evm/ante/evm" - "github.com/cosmos/evm/ante/testutils" "github.com/cosmos/evm/server/config" "github.com/cosmos/evm/testutil" testconstants "github.com/cosmos/evm/testutil/constants" @@ -20,11 +19,11 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) -func (suite *AnteTestSuite) TestGasWantedDecorator() { +func (suite *EvmAnteTestSuite) TestGasWantedDecorator() { suite.WithFeemarketEnabled(true) suite.SetupTest() ctx := suite.GetNetwork().GetContext() - dec := evm.NewGasWantedDecorator(suite.GetNetwork().App.EVMKeeper, suite.GetNetwork().App.FeeMarketKeeper) + dec := evm.NewGasWantedDecorator(suite.GetNetwork().App.GetEVMKeeper(), suite.GetNetwork().App.GetFeeMarketKeeper()) from, fromPrivKey := utiltx.NewAddrKey() to := utiltx.GenerateAddress() denom := evmtypes.GetEVMCoinDenom() @@ -37,7 +36,7 @@ func (suite *AnteTestSuite) TestGasWantedDecorator() { }{ { "Cosmos Tx", - testutils.TestGasLimit, + TestGasLimit, func() sdk.Tx { testMsg := banktypes.MsgSend{ FromAddress: "cosmos1x8fhpj9nmhqk8z9kpgjt95ck2xwyue0ptzkucp", @@ -51,12 +50,12 @@ func (suite *AnteTestSuite) TestGasWantedDecorator() { }, { "Ethereum Legacy Tx", - testutils.TestGasLimit, + TestGasLimit, func() sdk.Tx { txArgs := evmtypes.EvmTxArgs{ To: &to, GasPrice: big.NewInt(0), - GasLimit: testutils.TestGasLimit, + GasLimit: TestGasLimit, } return suite.CreateTxBuilder(fromPrivKey, txArgs).GetTx() }, @@ -64,13 +63,13 @@ func (suite *AnteTestSuite) TestGasWantedDecorator() { }, { "Ethereum Access List Tx", - testutils.TestGasLimit, + TestGasLimit, func() sdk.Tx { emptyAccessList := ethtypes.AccessList{} txArgs := evmtypes.EvmTxArgs{ To: &to, GasPrice: big.NewInt(0), - GasLimit: testutils.TestGasLimit, + GasLimit: TestGasLimit, Accesses: &emptyAccessList, } return suite.CreateTxBuilder(fromPrivKey, txArgs).GetTx() @@ -79,14 +78,14 @@ func (suite *AnteTestSuite) TestGasWantedDecorator() { }, { "Ethereum Dynamic Fee Tx (EIP1559)", - testutils.TestGasLimit, + TestGasLimit, func() sdk.Tx { emptyAccessList := ethtypes.AccessList{} txArgs := evmtypes.EvmTxArgs{ To: &to, GasPrice: big.NewInt(0), GasFeeCap: big.NewInt(100), - GasLimit: testutils.TestGasLimit, + GasLimit: TestGasLimit, GasTipCap: big.NewInt(50), Accesses: &emptyAccessList, } @@ -100,9 +99,9 @@ func (suite *AnteTestSuite) TestGasWantedDecorator() { func() sdk.Tx { amount := sdk.NewCoins(sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(20))) gas := uint64(200000) - acc := suite.GetNetwork().App.AccountKeeper.NewAccountWithAddress(ctx, from.Bytes()) + acc := suite.GetNetwork().App.GetAccountKeeper().NewAccountWithAddress(ctx, from.Bytes()) suite.Require().NoError(acc.SetSequence(1)) - suite.GetNetwork().App.AccountKeeper.SetAccount(ctx, acc) + suite.GetNetwork().App.GetAccountKeeper().SetAccount(ctx, acc) builder, err := suite.CreateTestEIP712TxBuilderMsgSend(acc.GetAddress(), fromPrivKey, ctx.ChainID(), config.DefaultEVMChainID, gas, amount) suite.Require().NoError(err) return builder.GetTx() @@ -111,7 +110,7 @@ func (suite *AnteTestSuite) TestGasWantedDecorator() { }, { "Cosmos Tx - gasWanted > max block gas", - testutils.TestGasLimit, + TestGasLimit, func() sdk.Tx { denom := testconstants.ExampleAttoDenom testMsg := banktypes.MsgSend{ @@ -137,7 +136,7 @@ func (suite *AnteTestSuite) TestGasWantedDecorator() { if tc.expPass { suite.Require().NoError(err) - gasWanted := suite.GetNetwork().App.FeeMarketKeeper.GetTransientGasWanted(ctx) + gasWanted := suite.GetNetwork().App.GetFeeMarketKeeper().GetTransientGasWanted(ctx) expectedGasWanted += tc.expectedGasWanted suite.Require().Equal(expectedGasWanted, gasWanted) } else { diff --git a/ante/evm/02_mempool_fee_test.go b/tests/integration/ante/test_evm_unit_02_mempool_fee.go similarity index 95% rename from ante/evm/02_mempool_fee_test.go rename to tests/integration/ante/test_evm_unit_02_mempool_fee.go index a681b15b6..b033eecca 100644 --- a/ante/evm/02_mempool_fee_test.go +++ b/tests/integration/ante/test_evm_unit_02_mempool_fee.go @@ -1,4 +1,4 @@ -package evm_test +package ante import ( "github.com/cosmos/evm/ante/evm" @@ -8,7 +8,7 @@ import ( errortypes "github.com/cosmos/cosmos-sdk/types/errors" ) -func (suite *EvmAnteTestSuite) TestMempoolFee() { +func (suite *EvmUnitAnteTestSuite) TestMempoolFee() { testCases := []struct { name string expectedError error diff --git a/ante/evm/03_global_fee_test.go b/tests/integration/ante/test_evm_unit_03_global_fee.go similarity index 95% rename from ante/evm/03_global_fee_test.go rename to tests/integration/ante/test_evm_unit_03_global_fee.go index 0b68f4b19..c7276df4c 100644 --- a/ante/evm/03_global_fee_test.go +++ b/tests/integration/ante/test_evm_unit_03_global_fee.go @@ -1,4 +1,4 @@ -package evm_test +package ante import ( "github.com/cosmos/evm/ante/evm" @@ -8,7 +8,7 @@ import ( errortypes "github.com/cosmos/cosmos-sdk/types/errors" ) -func (suite *EvmAnteTestSuite) TestGlobalFee() { +func (suite *EvmUnitAnteTestSuite) TestGlobalFee() { testCases := []struct { name string expectedError error diff --git a/ante/evm/04_validate_test.go b/tests/integration/ante/test_evm_unit_04_validate.go similarity index 97% rename from ante/evm/04_validate_test.go rename to tests/integration/ante/test_evm_unit_04_validate.go index 1523042c6..b65a35895 100644 --- a/ante/evm/04_validate_test.go +++ b/tests/integration/ante/test_evm_unit_04_validate.go @@ -1,4 +1,4 @@ -package evm_test +package ante import ( "fmt" @@ -8,7 +8,7 @@ import ( "github.com/cosmos/evm/ante/evm" testconstants "github.com/cosmos/evm/testutil/constants" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" + testkeyring "github.com/cosmos/evm/testutil/keyring" evmtypes "github.com/cosmos/evm/x/vm/types" "cosmossdk.io/math" @@ -24,7 +24,7 @@ type validateMsgParams struct { txData evmtypes.TxData } -func (suite *EvmAnteTestSuite) TestValidateMsg() { +func (suite *EvmUnitAnteTestSuite) TestValidateMsg() { keyring := testkeyring.New(2) testCases := []struct { @@ -220,7 +220,7 @@ func getTxByType(typeTx string, recipient common.Address) evmtypes.EvmTxArgs { } } -func (suite *EvmAnteTestSuite) TestCheckTxFee() { +func (suite *EvmUnitAnteTestSuite) TestCheckTxFee() { // amount represents 1 token in the 18 decimals representation. amount := math.NewInt(1e18) gasLimit := uint64(1e6) diff --git a/ante/evm/06_account_verification_test.go b/tests/integration/ante/test_evm_unit_06_account_verification.go similarity index 88% rename from ante/evm/06_account_verification_test.go rename to tests/integration/ante/test_evm_unit_06_account_verification.go index dcbc56644..3c784ec99 100644 --- a/ante/evm/06_account_verification_test.go +++ b/tests/integration/ante/test_evm_unit_06_account_verification.go @@ -1,4 +1,4 @@ -package evm_test +package ante import ( "fmt" @@ -8,10 +8,10 @@ import ( "github.com/cosmos/evm/ante/evm" testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + testkeyring "github.com/cosmos/evm/testutil/keyring" "github.com/cosmos/evm/x/vm/statedb" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -20,14 +20,15 @@ import ( errortypes "github.com/cosmos/cosmos-sdk/types/errors" ) -func (suite *EvmAnteTestSuite) TestVerifyAccountBalance() { +func (suite *EvmUnitAnteTestSuite) TestVerifyAccountBalance() { // Setup keyring := testkeyring.New(2) unitNetwork := network.NewUnitTestNetwork( + suite.create, network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), network.WithChainID(testconstants.ChainID{ - ChainID: suite.chainID, - EVMChainID: suite.evmChainID, + ChainID: suite.ChainID, + EVMChainID: suite.EvmChainID, }), ) grpcHandler := grpc.NewIntegrationHandler(unitNetwork) @@ -44,7 +45,7 @@ func (suite *EvmAnteTestSuite) TestVerifyAccountBalance() { expectedError: errortypes.ErrInvalidType, generateAccountAndArgs: func() (*statedb.Account, evmtypes.EvmTxArgs) { statedbAccount := getDefaultStateDBAccount(unitNetwork, senderKey.Addr) - txArgs, err := txFactory.GenerateDefaultTxTypeArgs(senderKey.Addr, suite.ethTxType) + txArgs, err := txFactory.GenerateDefaultTxTypeArgs(senderKey.Addr, suite.EthTxType) suite.Require().NoError(err) statedbAccount.CodeHash = []byte("test") @@ -57,7 +58,7 @@ func (suite *EvmAnteTestSuite) TestVerifyAccountBalance() { expectedError: errortypes.ErrInsufficientFunds, generateAccountAndArgs: func() (*statedb.Account, evmtypes.EvmTxArgs) { statedbAccount := getDefaultStateDBAccount(unitNetwork, senderKey.Addr) - txArgs, err := txFactory.GenerateDefaultTxTypeArgs(senderKey.Addr, suite.ethTxType) + txArgs, err := txFactory.GenerateDefaultTxTypeArgs(senderKey.Addr, suite.EthTxType) suite.Require().NoError(err) // Make tx cost greater than balance @@ -76,7 +77,7 @@ func (suite *EvmAnteTestSuite) TestVerifyAccountBalance() { expectedError: errortypes.ErrInvalidCoins, generateAccountAndArgs: func() (*statedb.Account, evmtypes.EvmTxArgs) { statedbAccount := getDefaultStateDBAccount(unitNetwork, senderKey.Addr) - txArgs, err := txFactory.GenerateDefaultTxTypeArgs(senderKey.Addr, suite.ethTxType) + txArgs, err := txFactory.GenerateDefaultTxTypeArgs(senderKey.Addr, suite.EthTxType) suite.Require().NoError(err) // Make tx cost negative. This has to be a big value because @@ -90,7 +91,7 @@ func (suite *EvmAnteTestSuite) TestVerifyAccountBalance() { name: "success: tx is successful and account is created if its nil", expectedError: errortypes.ErrInsufficientFunds, generateAccountAndArgs: func() (*statedb.Account, evmtypes.EvmTxArgs) { - txArgs, err := txFactory.GenerateDefaultTxTypeArgs(senderKey.Addr, suite.ethTxType) + txArgs, err := txFactory.GenerateDefaultTxTypeArgs(senderKey.Addr, suite.EthTxType) suite.Require().NoError(err) return nil, txArgs }, @@ -100,7 +101,7 @@ func (suite *EvmAnteTestSuite) TestVerifyAccountBalance() { expectedError: nil, generateAccountAndArgs: func() (*statedb.Account, evmtypes.EvmTxArgs) { statedbAccount := getDefaultStateDBAccount(unitNetwork, senderKey.Addr) - txArgs, err := txFactory.GenerateDefaultTxTypeArgs(senderKey.Addr, suite.ethTxType) + txArgs, err := txFactory.GenerateDefaultTxTypeArgs(senderKey.Addr, suite.EthTxType) suite.Require().NoError(err) return statedbAccount, txArgs }, @@ -108,7 +109,7 @@ func (suite *EvmAnteTestSuite) TestVerifyAccountBalance() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("%v_%v_%v", evmtypes.GetTxTypeName(suite.ethTxType), suite.chainID, tc.name), func() { + suite.Run(fmt.Sprintf("%v_%v_%v", evmtypes.GetTxTypeName(suite.EthTxType), suite.ChainID, tc.name), func() { // Perform test logic statedbAccount, txArgs := tc.generateAccountAndArgs() txData, err := txArgs.ToTxData() @@ -117,7 +118,7 @@ func (suite *EvmAnteTestSuite) TestVerifyAccountBalance() { // Function to be tested err = evm.VerifyAccountBalance( unitNetwork.GetContext(), - unitNetwork.App.AccountKeeper, + unitNetwork.App.GetAccountKeeper(), statedbAccount, senderKey.Addr, txData, diff --git a/ante/evm/07_can_transfer_test.go b/tests/integration/ante/test_evm_unit_07_can_transfer.go similarity index 86% rename from ante/evm/07_can_transfer_test.go rename to tests/integration/ante/test_evm_unit_07_can_transfer.go index bd52cd9e3..5bf3d0fc9 100644 --- a/ante/evm/07_can_transfer_test.go +++ b/tests/integration/ante/test_evm_unit_07_can_transfer.go @@ -1,4 +1,4 @@ -package evm_test +package ante import ( "fmt" @@ -8,10 +8,10 @@ import ( "github.com/cosmos/evm/ante/evm" testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + testkeyring "github.com/cosmos/evm/testutil/keyring" evmtypes "github.com/cosmos/evm/x/vm/types" "cosmossdk.io/math" @@ -19,12 +19,13 @@ import ( errortypes "github.com/cosmos/cosmos-sdk/types/errors" ) -func (suite *EvmAnteTestSuite) TestCanTransfer() { +func (suite *EvmUnitAnteTestSuite) TestCanTransfer() { keyring := testkeyring.New(1) unitNetwork := network.NewUnitTestNetwork( + suite.create, network.WithChainID(testconstants.ChainID{ - ChainID: suite.chainID, - EVMChainID: suite.evmChainID, + ChainID: suite.ChainID, + EVMChainID: suite.EvmChainID, }), network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), ) @@ -70,7 +71,7 @@ func (suite *EvmAnteTestSuite) TestCanTransfer() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("%v_%v_%v", evmtypes.GetTxTypeName(suite.ethTxType), suite.chainID, tc.name), func() { + suite.Run(fmt.Sprintf("%v_%v_%v", evmtypes.GetTxTypeName(suite.EthTxType), suite.ChainID, tc.name), func() { baseFeeResp, err := grpcHandler.GetEvmBaseFee() suite.Require().NoError(err) ethCfg := unitNetwork.GetEVMChainConfig() @@ -78,7 +79,7 @@ func (suite *EvmAnteTestSuite) TestCanTransfer() { suite.Require().NoError(err) ctx := unitNetwork.GetContext() signer := gethtypes.MakeSigner(ethCfg, big.NewInt(ctx.BlockHeight()), uint64(ctx.BlockTime().Unix())) //#nosec G115 -- int overflow is not a concern here - txArgs, err := txFactory.GenerateDefaultTxTypeArgs(senderKey.Addr, suite.ethTxType) + txArgs, err := txFactory.GenerateDefaultTxTypeArgs(senderKey.Addr, suite.EthTxType) suite.Require().NoError(err) txArgs.Amount = big.NewInt(100) @@ -94,7 +95,7 @@ func (suite *EvmAnteTestSuite) TestCanTransfer() { // Function under test err = evm.CanTransfer( unitNetwork.GetContext(), - unitNetwork.App.EVMKeeper, + unitNetwork.App.GetEVMKeeper(), *coreMsg, baseFeeResp.BaseFee.BigInt(), evmParams.Params, diff --git a/ante/evm/08_gas_consume_test.go b/tests/integration/ante/test_evm_unit_08_gas_consume.go similarity index 89% rename from ante/evm/08_gas_consume_test.go rename to tests/integration/ante/test_evm_unit_08_gas_consume.go index 8b88b7144..03f6e2bc2 100644 --- a/ante/evm/08_gas_consume_test.go +++ b/tests/integration/ante/test_evm_unit_08_gas_consume.go @@ -1,15 +1,15 @@ -package evm_test +package ante import ( "fmt" evmante "github.com/cosmos/evm/ante/evm" testconstants "github.com/cosmos/evm/testutil/constants" - commonfactory "github.com/cosmos/evm/testutil/integration/common/factory" - testfactory "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" + commonfactory "github.com/cosmos/evm/testutil/integration/base/factory" + testfactory "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + testkeyring "github.com/cosmos/evm/testutil/keyring" evmtypes "github.com/cosmos/evm/x/vm/types" sdkmath "cosmossdk.io/math" @@ -18,12 +18,13 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) -func (suite *EvmAnteTestSuite) TestUpdateCumulativeGasWanted() { +func (suite *EvmUnitAnteTestSuite) TestUpdateCumulativeGasWanted() { keyring := testkeyring.New(1) unitNetwork := network.NewUnitTestNetwork( + suite.create, network.WithChainID(testconstants.ChainID{ - ChainID: suite.chainID, - EVMChainID: suite.evmChainID, + ChainID: suite.ChainID, + EVMChainID: suite.EvmChainID, }), network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), ) @@ -94,12 +95,13 @@ func (suite *EvmAnteTestSuite) TestUpdateCumulativeGasWanted() { } // NOTE: claim rewards are not tested since there is an independent suite to test just that -func (suite *EvmAnteTestSuite) TestConsumeGasAndEmitEvent() { +func (suite *EvmUnitAnteTestSuite) TestConsumeGasAndEmitEvent() { keyring := testkeyring.New(1) unitNetwork := network.NewUnitTestNetwork( + suite.create, network.WithChainID(testconstants.ChainID{ - ChainID: suite.chainID, - EVMChainID: suite.evmChainID, + ChainID: suite.ChainID, + EVMChainID: suite.EvmChainID, }), network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), ) @@ -153,7 +155,7 @@ func (suite *EvmAnteTestSuite) TestConsumeGasAndEmitEvent() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("%v_%v_%v", evmtypes.GetTxTypeName(suite.ethTxType), suite.chainID, tc.name), func() { + suite.Run(fmt.Sprintf("%v_%v_%v", evmtypes.GetTxTypeName(suite.EthTxType), suite.ChainID, tc.name), func() { sender := tc.getSender() resp, err := grpcHandler.GetBalanceFromEVM(sender) @@ -168,7 +170,7 @@ func (suite *EvmAnteTestSuite) TestConsumeGasAndEmitEvent() { // Function under test err = evmante.ConsumeFeesAndEmitEvent( unitNetwork.GetContext(), - unitNetwork.App.EVMKeeper, + unitNetwork.App.GetEVMKeeper(), fees, sender, ) diff --git a/ante/evm/09_increment_sequence_test.go b/tests/integration/ante/test_evm_unit_09_increment_sequence.go similarity index 82% rename from ante/evm/09_increment_sequence_test.go rename to tests/integration/ante/test_evm_unit_09_increment_sequence.go index dab7e7f69..84909fbc6 100644 --- a/ante/evm/09_increment_sequence_test.go +++ b/tests/integration/ante/test_evm_unit_09_increment_sequence.go @@ -1,22 +1,23 @@ -package evm_test +package ante import ( "github.com/cosmos/evm/ante/evm" testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/os/grpc" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + testkeyring "github.com/cosmos/evm/testutil/keyring" sdktypes "github.com/cosmos/cosmos-sdk/types" errortypes "github.com/cosmos/cosmos-sdk/types/errors" ) -func (suite *EvmAnteTestSuite) TestIncrementSequence() { +func (suite *EvmUnitAnteTestSuite) TestIncrementSequence() { keyring := testkeyring.New(1) unitNetwork := network.NewUnitTestNetwork( + suite.create, network.WithChainID(testconstants.ChainID{ - ChainID: suite.chainID, - EVMChainID: suite.evmChainID, + ChainID: suite.ChainID, + EVMChainID: suite.EvmChainID, }), network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), ) @@ -55,7 +56,7 @@ func (suite *EvmAnteTestSuite) TestIncrementSequence() { // Function under test err = evm.IncrementNonce( unitNetwork.GetContext(), - unitNetwork.App.AccountKeeper, + unitNetwork.App.GetAccountKeeper(), account, nonce, ) diff --git a/ante/evm/10_gas_wanted_test.go b/tests/integration/ante/test_evm_unit_10_gas_wanted.go similarity index 83% rename from ante/evm/10_gas_wanted_test.go rename to tests/integration/ante/test_evm_unit_10_gas_wanted.go index fa5a50af5..04e5e6350 100644 --- a/ante/evm/10_gas_wanted_test.go +++ b/tests/integration/ante/test_evm_unit_10_gas_wanted.go @@ -1,15 +1,15 @@ -package evm_test +package ante import ( "fmt" "github.com/cosmos/evm/ante/evm" testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" - integrationutils "github.com/cosmos/evm/testutil/integration/os/utils" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/integration/evm/utils" + testkeyring "github.com/cosmos/evm/testutil/keyring" evmtypes "github.com/cosmos/evm/x/vm/types" storetypes "cosmossdk.io/store/types" @@ -18,12 +18,13 @@ import ( errortypes "github.com/cosmos/cosmos-sdk/types/errors" ) -func (suite *EvmAnteTestSuite) TestCheckGasWanted() { +func (suite *EvmUnitAnteTestSuite) TestCheckGasWanted() { keyring := testkeyring.New(1) unitNetwork := network.NewUnitTestNetwork( + suite.create, network.WithChainID(testconstants.ChainID{ - ChainID: suite.chainID, - EVMChainID: suite.evmChainID, + ChainID: suite.ChainID, + EVMChainID: suite.EvmChainID, }), network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), ) @@ -78,7 +79,7 @@ func (suite *EvmAnteTestSuite) TestCheckGasWanted() { suite.Require().NoError(err) feeMarketParams.Params.NoBaseFee = true - err = integrationutils.UpdateFeeMarketParams(integrationutils.UpdateParamsInput{ + err = utils.UpdateFeeMarketParams(utils.UpdateParamsInput{ Tf: txFactory, Network: unitNetwork, Pk: keyring.GetPrivKey(0), @@ -95,11 +96,11 @@ func (suite *EvmAnteTestSuite) TestCheckGasWanted() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("%v_%v_%v", evmtypes.GetTxTypeName(suite.ethTxType), suite.chainID, tc.name), func() { + suite.Run(fmt.Sprintf("%v_%v_%v", evmtypes.GetTxTypeName(suite.EthTxType), suite.ChainID, tc.name), func() { sender := keyring.GetKey(0) txArgs, err := txFactory.GenerateDefaultTxTypeArgs( sender.Addr, - suite.ethTxType, + suite.EthTxType, ) suite.Require().NoError(err) txArgs.GasLimit = commonGasLimit @@ -111,7 +112,7 @@ func (suite *EvmAnteTestSuite) TestCheckGasWanted() { // Function under test err = evm.CheckGasWanted( ctx, - unitNetwork.App.FeeMarketKeeper, + unitNetwork.App.GetFeeMarketKeeper(), tx, tc.isLondon, ) @@ -121,7 +122,7 @@ func (suite *EvmAnteTestSuite) TestCheckGasWanted() { suite.Contains(err.Error(), tc.expectedError.Error()) } else { suite.Require().NoError(err) - transientGasWanted := unitNetwork.App.FeeMarketKeeper.GetTransientGasWanted( + transientGasWanted := unitNetwork.App.GetFeeMarketKeeper().GetTransientGasWanted( unitNetwork.GetContext(), ) suite.Require().Equal(tc.expectedTransientGasWanted, transientGasWanted) diff --git a/tests/integration/ante/test_integration.go b/tests/integration/ante/test_integration.go new file mode 100644 index 000000000..adbe1a979 --- /dev/null +++ b/tests/integration/ante/test_integration.go @@ -0,0 +1,237 @@ +package ante + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + //nolint:revive // dot imports are fine for Ginkgo + . "github.com/onsi/ginkgo/v2" + //nolint:revive // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" + + testconstants "github.com/cosmos/evm/testutil/constants" + commonfactory "github.com/cosmos/evm/testutil/integration/base/factory" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/integration/evm/utils" + testkeyring "github.com/cosmos/evm/testutil/keyring" + testutiltx "github.com/cosmos/evm/testutil/tx" + + "cosmossdk.io/math" + + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" +) + +type IntegrationTestSuite struct { + suite.Suite + + create network.CreateEvmApp + options []network.ConfigOption + network network.Network + factory factory.TxFactory + grpcHandler grpc.Handler + keyring testkeyring.Keyring +} + +func NewIntegrationTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *IntegrationTestSuite { + return &IntegrationTestSuite{ + create: create, + options: options, + } +} + +func (s *IntegrationTestSuite) SetupTest() { + keyring := testkeyring.New(2) + validatorsKeys := generateKeys(3) + customGen := network.CustomGenesisState{} + + // set some slashing events for integration test + distrGen := distrtypes.DefaultGenesisState() + customGen[distrtypes.ModuleName] = distrGen + + // set non-zero inflation for rewards to accrue (use defaults from SDK for values) + mintGen := minttypes.DefaultGenesisState() + mintGen.Params.MintDenom = testconstants.ExampleAttoDenom + customGen[minttypes.ModuleName] = mintGen + + operatorsAddr := make([]sdk.AccAddress, 3) + for i, k := range validatorsKeys { + operatorsAddr[i] = k.AccAddr + } + + options := []network.ConfigOption{ + network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), + network.WithCustomGenesis(customGen), + network.WithValidatorOperators(operatorsAddr), + } + options = append(options, s.options...) + nw := network.NewUnitTestNetwork(s.create, options...) + grpcHandler := grpc.NewIntegrationHandler(nw) + txFactory := factory.New(nw, grpcHandler) + + s.factory = txFactory + s.grpcHandler = grpcHandler + s.keyring = keyring + s.network = nw +} + +func TestIntegrationAnteHandler(t *testing.T, create network.CreateEvmApp, options ...network.ConfigOption) { + if create == nil { + panic("create function cannot be nil") + } + + var _ = Describe("when sending a Cosmos transaction", Label("AnteHandler"), Ordered, func() { + var s *IntegrationTestSuite + + BeforeAll(func() { + s = NewIntegrationTestSuite(create, options...) + s.SetupTest() + }) + + Context("and the sender account has enough balance to pay for the transaction cost", Ordered, func() { + var ( + rewards sdk.DecCoins + transferAmt math.Int + addr sdk.AccAddress + receiverAddr sdk.AccAddress + priv cryptotypes.PrivKey + msg sdk.Msg + ) + + BeforeEach(func() { + key := s.keyring.GetKey(0) + addr = key.AccAddr + priv = key.Priv + receiverAddr, _ = testutiltx.NewAccAddressAndKey() + + transferAmt = math.NewInt(1e14) + msg = &banktypes.MsgSend{ + FromAddress: addr.String(), + ToAddress: receiverAddr.String(), + Amount: sdk.Coins{sdk.Coin{Amount: transferAmt, Denom: s.network.GetBaseDenom()}}, + } + + valAddr := s.network.GetValidators()[0].OperatorAddress + delegationCoin := sdk.Coin{Amount: math.NewInt(1e15), Denom: s.network.GetBaseDenom()} + err := s.factory.Delegate(priv, valAddr, delegationCoin) + Expect(err).To(BeNil()) + + minExpRewards := sdk.DecCoins{sdk.DecCoin{Amount: math.LegacyNewDec(1e5), Denom: s.network.GetBaseDenom()}} + + rewards, err = utils.WaitToAccrueRewards(s.network, s.grpcHandler, addr.String(), minExpRewards) + Expect(err).To(BeNil()) + }) + + It("should succeed & not withdraw any staking rewards", func() { + prevBalanceRes, err := s.grpcHandler.GetBalanceFromBank(addr, s.network.GetBaseDenom()) + Expect(err).To(BeNil()) + + baseFeeRes, err := s.grpcHandler.GetEvmBaseFee() + Expect(err).To(BeNil()) + Expect(baseFeeRes).ToNot(BeNil(), "baseFeeRes is nil") + + gasPrice := baseFeeRes.BaseFee.AddRaw(100) + + res, err := s.factory.ExecuteCosmosTx( + priv, + commonfactory.CosmosTxArgs{ + Msgs: []sdk.Msg{msg}, + GasPrice: &gasPrice, + }, + ) + Expect(err).To(BeNil()) + Expect(res.IsOK()).To(BeTrue()) + + // include the tx in a block to update state + err = s.network.NextBlock() + Expect(err).To(BeNil()) + + feesAmt := math.NewInt(res.GasWanted).Mul(gasPrice) + balanceRes, err := s.grpcHandler.GetBalanceFromBank(addr, s.network.GetBaseDenom()) + Expect(err).To(BeNil()) + Expect(balanceRes.Balance.Amount).To(Equal(prevBalanceRes.Balance.Amount.Sub(transferAmt).Sub(feesAmt))) + + rewardsRes, err := s.grpcHandler.GetDelegationTotalRewards(addr.String()) + Expect(err).To(BeNil()) + + // rewards should not be used. Should be more + // than the previous value queried + Expect(rewardsRes.Total.Sub(rewards).IsAllPositive()).To(BeTrue()) + }) + }) + + Context("and the sender account neither has enough balance nor sufficient staking rewards to pay for the transaction cost", func() { + var ( + addr sdk.AccAddress + priv cryptotypes.PrivKey + msg sdk.Msg + ) + + BeforeEach(func() { + addr, priv = testutiltx.NewAccAddressAndKey() + + // this is a new address that does not exist on chain. + // Transfer 1 aatom to this account so it is + // added on chain + err := s.factory.FundAccount( + s.keyring.GetKey(0), + addr, + sdk.Coins{ + sdk.Coin{ + Amount: math.NewInt(1), + Denom: s.network.GetBaseDenom(), + }, + }, + ) + Expect(err).To(BeNil()) + // persist the state changes + Expect(s.network.NextBlock()).To(BeNil()) + + msg = &banktypes.MsgSend{ + FromAddress: addr.String(), + ToAddress: "cosmos1dx67l23hz9l0k9hcher8xz04uj7wf3yu26l2yn", + Amount: sdk.Coins{sdk.Coin{Amount: math.NewInt(1e14), Denom: s.network.GetBaseDenom()}}, + } + }) + + It("should fail", func() { + var gas uint64 = 200_000 // specify gas to avoid failing on simulation tx (internal call in the ExecuteCosmosTx if gas not specified) + res, err := s.factory.ExecuteCosmosTx( + priv, + commonfactory.CosmosTxArgs{ + Msgs: []sdk.Msg{msg}, + Gas: &gas, + }, + ) + Expect(res.IsErr()).To(BeTrue()) + Expect(res.GetLog()).To(ContainSubstring("insufficient funds")) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + }) + + It("should not withdraw any staking rewards", func() { + rewardsRes, err := s.grpcHandler.GetDelegationTotalRewards(addr.String()) + Expect(err).To(BeNil()) + Expect(rewardsRes.Total.Empty()).To(BeTrue()) + }) + }) + }) + + RegisterFailHandler(Fail) + RunSpecs(t, "AnteHandler Integration Test Suite") +} + +func generateKeys(count int) []testkeyring.Key { + accs := make([]testkeyring.Key, 0, count) + for i := 0; i < count; i++ { + acc := testkeyring.NewKey() + accs = append(accs, acc) + } + return accs +} diff --git a/ante/cosmos/min_gas_price_test.go b/tests/integration/ante/test_min_gas_price.go similarity index 59% rename from ante/cosmos/min_gas_price_test.go rename to tests/integration/ante/test_min_gas_price.go index 18e5d085d..2c06894d1 100644 --- a/ante/cosmos/min_gas_price_test.go +++ b/tests/integration/ante/test_min_gas_price.go @@ -1,4 +1,4 @@ -package cosmos_test +package ante import ( "fmt" @@ -23,14 +23,14 @@ var execTypes = []struct { {"deliverTxSimulate", false, true}, } -func (suite *AnteTestSuite) TestMinGasPriceDecorator() { +func (s *AnteTestSuite) TestMinGasPriceDecorator() { denom := constants.ExampleAttoDenom testMsg := banktypes.MsgSend{ FromAddress: "cosmos1x8fhpj9nmhqk8z9kpgjt95ck2xwyue0ptzkucp", ToAddress: "cosmos1dx67l23hz9l0k9hcher8xz04uj7wf3yu26l2yn", Amount: sdk.Coins{sdk.Coin{Amount: math.NewInt(10), Denom: denom}}, } - nw := suite.GetNetwork() + nw := s.GetNetwork() ctx := nw.GetContext() testCases := []struct { @@ -52,12 +52,12 @@ func (suite *AnteTestSuite) TestMinGasPriceDecorator() { { "valid cosmos tx with MinGasPrices = 0, gasPrice = 0", func() sdk.Tx { - params := nw.App.FeeMarketKeeper.GetParams(ctx) + params := nw.App.GetFeeMarketKeeper().GetParams(ctx) params.MinGasPrice = math.LegacyZeroDec() - err := nw.App.FeeMarketKeeper.SetParams(ctx, params) - suite.Require().NoError(err) + err := nw.App.GetFeeMarketKeeper().SetParams(ctx, params) + s.Require().NoError(err) - txBuilder := suite.CreateTestCosmosTxBuilder(math.NewInt(0), denom, &testMsg) + txBuilder := s.CreateTestCosmosTxBuilder(math.NewInt(0), denom, &testMsg) return txBuilder.GetTx() }, true, @@ -67,12 +67,12 @@ func (suite *AnteTestSuite) TestMinGasPriceDecorator() { { "valid cosmos tx with MinGasPrices = 0, gasPrice > 0", func() sdk.Tx { - params := nw.App.FeeMarketKeeper.GetParams(ctx) + params := nw.App.GetFeeMarketKeeper().GetParams(ctx) params.MinGasPrice = math.LegacyZeroDec() - err := nw.App.FeeMarketKeeper.SetParams(ctx, params) - suite.Require().NoError(err) + err := nw.App.GetFeeMarketKeeper().SetParams(ctx, params) + s.Require().NoError(err) - txBuilder := suite.CreateTestCosmosTxBuilder(math.NewInt(10), denom, &testMsg) + txBuilder := s.CreateTestCosmosTxBuilder(math.NewInt(10), denom, &testMsg) return txBuilder.GetTx() }, true, @@ -82,12 +82,12 @@ func (suite *AnteTestSuite) TestMinGasPriceDecorator() { { "valid cosmos tx with MinGasPrices = 10, gasPrice = 10", func() sdk.Tx { - params := nw.App.FeeMarketKeeper.GetParams(ctx) + params := nw.App.GetFeeMarketKeeper().GetParams(ctx) params.MinGasPrice = math.LegacyNewDec(10) - err := nw.App.FeeMarketKeeper.SetParams(ctx, params) - suite.Require().NoError(err) + err := nw.App.GetFeeMarketKeeper().SetParams(ctx, params) + s.Require().NoError(err) - txBuilder := suite.CreateTestCosmosTxBuilder(math.NewInt(10), denom, &testMsg) + txBuilder := s.CreateTestCosmosTxBuilder(math.NewInt(10), denom, &testMsg) return txBuilder.GetTx() }, true, @@ -97,12 +97,12 @@ func (suite *AnteTestSuite) TestMinGasPriceDecorator() { { "invalid cosmos tx with MinGasPrices = 10, gasPrice = 0", func() sdk.Tx { - params := nw.App.FeeMarketKeeper.GetParams(ctx) + params := nw.App.GetFeeMarketKeeper().GetParams(ctx) params.MinGasPrice = math.LegacyNewDec(10) - err := nw.App.FeeMarketKeeper.SetParams(ctx, params) - suite.Require().NoError(err) + err := nw.App.GetFeeMarketKeeper().SetParams(ctx, params) + s.Require().NoError(err) - txBuilder := suite.CreateTestCosmosTxBuilder(math.NewInt(0), denom, &testMsg) + txBuilder := s.CreateTestCosmosTxBuilder(math.NewInt(0), denom, &testMsg) return txBuilder.GetTx() }, false, @@ -112,12 +112,12 @@ func (suite *AnteTestSuite) TestMinGasPriceDecorator() { { "invalid cosmos tx with stake denom", func() sdk.Tx { - params := nw.App.FeeMarketKeeper.GetParams(ctx) + params := nw.App.GetFeeMarketKeeper().GetParams(ctx) params.MinGasPrice = math.LegacyNewDec(10) - err := nw.App.FeeMarketKeeper.SetParams(ctx, params) - suite.Require().NoError(err) + err := nw.App.GetFeeMarketKeeper().SetParams(ctx, params) + s.Require().NoError(err) - txBuilder := suite.CreateTestCosmosTxBuilder(math.NewInt(10), sdk.DefaultBondDenom, &testMsg) + txBuilder := s.CreateTestCosmosTxBuilder(math.NewInt(10), sdk.DefaultBondDenom, &testMsg) return txBuilder.GetTx() }, false, @@ -127,12 +127,12 @@ func (suite *AnteTestSuite) TestMinGasPriceDecorator() { { "valid cosmos tx with MinGasPrices = 0, gasPrice = 0, valid fee", func() sdk.Tx { - params := nw.App.FeeMarketKeeper.GetParams(ctx) + params := nw.App.GetFeeMarketKeeper().GetParams(ctx) params.MinGasPrice = math.LegacyZeroDec() - err := nw.App.FeeMarketKeeper.SetParams(ctx, params) - suite.Require().NoError(err) + err := nw.App.GetFeeMarketKeeper().SetParams(ctx, params) + s.Require().NoError(err) - txBuilder := suite.CreateTestCosmosTxBuilderWithFees(sdk.Coins{sdk.Coin{Amount: math.NewInt(0), Denom: denom}}, &testMsg) + txBuilder := s.CreateTestCosmosTxBuilderWithFees(sdk.Coins{sdk.Coin{Amount: math.NewInt(0), Denom: denom}}, &testMsg) return txBuilder.GetTx() }, true, @@ -142,12 +142,12 @@ func (suite *AnteTestSuite) TestMinGasPriceDecorator() { { "valid cosmos tx with MinGasPrices = 0, gasPrice = 0, nil fees, means len(fees) == 0", func() sdk.Tx { - params := nw.App.FeeMarketKeeper.GetParams(ctx) + params := nw.App.GetFeeMarketKeeper().GetParams(ctx) params.MinGasPrice = math.LegacyZeroDec() - err := nw.App.FeeMarketKeeper.SetParams(ctx, params) - suite.Require().NoError(err) + err := nw.App.GetFeeMarketKeeper().SetParams(ctx, params) + s.Require().NoError(err) - txBuilder := suite.CreateTestCosmosTxBuilderWithFees(nil, &testMsg) + txBuilder := s.CreateTestCosmosTxBuilderWithFees(nil, &testMsg) return txBuilder.GetTx() }, true, @@ -157,12 +157,12 @@ func (suite *AnteTestSuite) TestMinGasPriceDecorator() { { "valid cosmos tx with MinGasPrices = 0, gasPrice = 0, empty fees, means len(fees) == 0", func() sdk.Tx { - params := nw.App.FeeMarketKeeper.GetParams(ctx) + params := nw.App.GetFeeMarketKeeper().GetParams(ctx) params.MinGasPrice = math.LegacyZeroDec() - err := nw.App.FeeMarketKeeper.SetParams(ctx, params) - suite.Require().NoError(err) + err := nw.App.GetFeeMarketKeeper().SetParams(ctx, params) + s.Require().NoError(err) - txBuilder := suite.CreateTestCosmosTxBuilderWithFees(sdk.Coins{}, &testMsg) + txBuilder := s.CreateTestCosmosTxBuilderWithFees(sdk.Coins{}, &testMsg) return txBuilder.GetTx() }, true, @@ -172,13 +172,13 @@ func (suite *AnteTestSuite) TestMinGasPriceDecorator() { { "valid cosmos tx with MinGasPrices = 0, gasPrice = 0, invalid fees", func() sdk.Tx { - params := nw.App.FeeMarketKeeper.GetParams(ctx) + params := nw.App.GetFeeMarketKeeper().GetParams(ctx) params.MinGasPrice = math.LegacyZeroDec() - err := nw.App.FeeMarketKeeper.SetParams(ctx, params) - suite.Require().NoError(err) + err := nw.App.GetFeeMarketKeeper().SetParams(ctx, params) + s.Require().NoError(err) fees := sdk.Coins{sdk.Coin{Amount: math.NewInt(0), Denom: denom}, sdk.Coin{Amount: math.NewInt(10), Denom: "stake"}} - txBuilder := suite.CreateTestCosmosTxBuilderWithFees(fees, &testMsg) + txBuilder := s.CreateTestCosmosTxBuilderWithFees(fees, &testMsg) return txBuilder.GetTx() }, false, @@ -189,16 +189,16 @@ func (suite *AnteTestSuite) TestMinGasPriceDecorator() { for _, et := range execTypes { for _, tc := range testCases { - suite.Run(et.name+"_"+tc.name, func() { + s.Run(et.name+"_"+tc.name, func() { ctx := ctx.WithIsReCheckTx(et.isCheckTx) - dec := cosmosante.NewMinGasPriceDecorator(nw.App.FeeMarketKeeper, nw.App.EVMKeeper) + dec := cosmosante.NewMinGasPriceDecorator(nw.App.GetFeeMarketKeeper(), nw.App.GetEVMKeeper()) _, err := dec.AnteHandle(ctx, tc.malleate(), et.simulate, testutil.NoOpNextFn) if (et.name == "deliverTx" && tc.expPass) || (et.name == "deliverTxSimulate" && et.simulate && tc.allowPassOnSimulate) { - suite.Require().NoError(err, tc.name) + s.Require().NoError(err, tc.name) } else { - suite.Require().Error(err, tc.name) - suite.Require().Contains(err.Error(), tc.errMsg, tc.name) + s.Require().Error(err, tc.name) + s.Require().Contains(err.Error(), tc.errMsg, tc.name) } }) } diff --git a/evmd/ante/handler_options_test.go b/tests/integration/ante/test_validate_handler_options.go similarity index 56% rename from evmd/ante/handler_options_test.go rename to tests/integration/ante/test_validate_handler_options.go index 4607a9282..57d60231c 100644 --- a/evmd/ante/handler_options_test.go +++ b/tests/integration/ante/test_validate_handler_options.go @@ -1,19 +1,19 @@ -package ante_test +package ante import ( "testing" + chainante "cosmosevm.io/evmd/ante" "github.com/stretchr/testify/require" "github.com/cosmos/evm/ante" ethante "github.com/cosmos/evm/ante/evm" - chainante "github.com/cosmos/evm/evmd/ante" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/network" "github.com/cosmos/evm/types" ) -func TestValidateHandlerOptions(t *testing.T) { - nw := network.NewUnitTestNetwork() +func RunValidateHandlerOptionsTest(t *testing.T, create network.CreateEvmApp, options ...network.ConfigOption) { + nw := network.NewUnitTestNetwork(create, options...) cases := []struct { name string options chainante.HandlerOptions @@ -36,7 +36,7 @@ func TestValidateHandlerOptions(t *testing.T) { "fail - empty bank keeper", chainante.HandlerOptions{ Cdc: nw.App.AppCodec(), - AccountKeeper: nw.App.AccountKeeper, + AccountKeeper: nw.App.GetAccountKeeper(), BankKeeper: nil, }, false, @@ -45,8 +45,8 @@ func TestValidateHandlerOptions(t *testing.T) { "fail - empty IBC keeper", chainante.HandlerOptions{ Cdc: nw.App.AppCodec(), - AccountKeeper: nw.App.AccountKeeper, - BankKeeper: nw.App.BankKeeper, + AccountKeeper: nw.App.GetAccountKeeper(), + BankKeeper: nw.App.GetBankKeeper(), IBCKeeper: nil, }, false, @@ -55,9 +55,9 @@ func TestValidateHandlerOptions(t *testing.T) { "fail - empty fee market keeper", chainante.HandlerOptions{ Cdc: nw.App.AppCodec(), - AccountKeeper: nw.App.AccountKeeper, - BankKeeper: nw.App.BankKeeper, - IBCKeeper: nw.App.IBCKeeper, + AccountKeeper: nw.App.GetAccountKeeper(), + BankKeeper: nw.App.GetBankKeeper(), + IBCKeeper: nw.App.GetIBCKeeper(), FeeMarketKeeper: nil, }, false, @@ -66,10 +66,10 @@ func TestValidateHandlerOptions(t *testing.T) { "fail - empty EVM keeper", chainante.HandlerOptions{ Cdc: nw.App.AppCodec(), - AccountKeeper: nw.App.AccountKeeper, - BankKeeper: nw.App.BankKeeper, - IBCKeeper: nw.App.IBCKeeper, - FeeMarketKeeper: nw.App.FeeMarketKeeper, + AccountKeeper: nw.App.GetAccountKeeper(), + BankKeeper: nw.App.GetBankKeeper(), + IBCKeeper: nw.App.GetIBCKeeper(), + FeeMarketKeeper: nw.App.GetFeeMarketKeeper(), EvmKeeper: nil, }, false, @@ -78,11 +78,11 @@ func TestValidateHandlerOptions(t *testing.T) { "fail - empty signature gas consumer", chainante.HandlerOptions{ Cdc: nw.App.AppCodec(), - AccountKeeper: nw.App.AccountKeeper, - BankKeeper: nw.App.BankKeeper, - IBCKeeper: nw.App.IBCKeeper, - FeeMarketKeeper: nw.App.FeeMarketKeeper, - EvmKeeper: nw.App.EVMKeeper, + AccountKeeper: nw.App.GetAccountKeeper(), + BankKeeper: nw.App.GetBankKeeper(), + IBCKeeper: nw.App.GetIBCKeeper(), + FeeMarketKeeper: nw.App.GetFeeMarketKeeper(), + EvmKeeper: nw.App.GetEVMKeeper(), SigGasConsumer: nil, }, false, @@ -91,11 +91,11 @@ func TestValidateHandlerOptions(t *testing.T) { "fail - empty signature mode handler", chainante.HandlerOptions{ Cdc: nw.App.AppCodec(), - AccountKeeper: nw.App.AccountKeeper, - BankKeeper: nw.App.BankKeeper, - IBCKeeper: nw.App.IBCKeeper, - FeeMarketKeeper: nw.App.FeeMarketKeeper, - EvmKeeper: nw.App.EVMKeeper, + AccountKeeper: nw.App.GetAccountKeeper(), + BankKeeper: nw.App.GetBankKeeper(), + IBCKeeper: nw.App.GetIBCKeeper(), + FeeMarketKeeper: nw.App.GetFeeMarketKeeper(), + EvmKeeper: nw.App.GetEVMKeeper(), SigGasConsumer: ante.SigVerificationGasConsumer, SignModeHandler: nil, }, @@ -105,11 +105,11 @@ func TestValidateHandlerOptions(t *testing.T) { "fail - empty tx fee checker", chainante.HandlerOptions{ Cdc: nw.App.AppCodec(), - AccountKeeper: nw.App.AccountKeeper, - BankKeeper: nw.App.BankKeeper, - IBCKeeper: nw.App.IBCKeeper, - FeeMarketKeeper: nw.App.FeeMarketKeeper, - EvmKeeper: nw.App.EVMKeeper, + AccountKeeper: nw.App.GetAccountKeeper(), + BankKeeper: nw.App.GetBankKeeper(), + IBCKeeper: nw.App.GetIBCKeeper(), + FeeMarketKeeper: nw.App.GetFeeMarketKeeper(), + EvmKeeper: nw.App.GetEVMKeeper(), SigGasConsumer: ante.SigVerificationGasConsumer, SignModeHandler: nw.App.GetTxConfig().SignModeHandler(), TxFeeChecker: nil, @@ -120,17 +120,17 @@ func TestValidateHandlerOptions(t *testing.T) { "success - default app options", chainante.HandlerOptions{ Cdc: nw.App.AppCodec(), - AccountKeeper: nw.App.AccountKeeper, - BankKeeper: nw.App.BankKeeper, + AccountKeeper: nw.App.GetAccountKeeper(), + BankKeeper: nw.App.GetBankKeeper(), ExtensionOptionChecker: types.HasDynamicFeeExtensionOption, - EvmKeeper: nw.App.EVMKeeper, - FeegrantKeeper: nw.App.FeeGrantKeeper, - IBCKeeper: nw.App.IBCKeeper, - FeeMarketKeeper: nw.App.FeeMarketKeeper, + EvmKeeper: nw.App.GetEVMKeeper(), + FeegrantKeeper: nw.App.GetFeeGrantKeeper(), + IBCKeeper: nw.App.GetIBCKeeper(), + FeeMarketKeeper: nw.App.GetFeeMarketKeeper(), SignModeHandler: nw.GetEncodingConfig().TxConfig.SignModeHandler(), SigGasConsumer: ante.SigVerificationGasConsumer, MaxTxGasWanted: 40000000, - TxFeeChecker: ethante.NewDynamicFeeChecker(nw.App.FeeMarketKeeper), + TxFeeChecker: ethante.NewDynamicFeeChecker(nw.App.GetFeeMarketKeeper()), }, true, }, diff --git a/ethereum/eip712/eip712_test.go b/tests/integration/eip712/test_eip712.go similarity index 97% rename from ethereum/eip712/eip712_test.go rename to tests/integration/eip712/test_eip712.go index 77627678f..38f4ad41b 100644 --- a/ethereum/eip712/eip712_test.go +++ b/tests/integration/eip712/test_eip712.go @@ -1,9 +1,8 @@ -package eip712_test +package eip712 import ( "bytes" "fmt" - "testing" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/signer/core/apitypes" @@ -15,7 +14,7 @@ import ( "github.com/cosmos/evm/crypto/ethsecp256k1" "github.com/cosmos/evm/ethereum/eip712" "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/network" evmtypes "github.com/cosmos/evm/x/vm/types" "cosmossdk.io/math" @@ -44,12 +43,22 @@ const ( type EIP712TestSuite struct { suite.Suite + create network.CreateEvmApp + options []network.ConfigOption config sdktestutil.TestEncodingConfig clientCtx client.Context useLegacyEIP712TypedData bool denom string } +func NewEIP712TestSuite(create network.CreateEvmApp, useLegacyEIP712TypedData bool, options ...network.ConfigOption) *EIP712TestSuite { + return &EIP712TestSuite{ + create: create, + useLegacyEIP712TypedData: useLegacyEIP712TypedData, + options: options, + } +} + type EIP712TestParams struct { fee txtypes.Fee address sdk.AccAddress @@ -58,17 +67,8 @@ type EIP712TestParams struct { memo string } -func TestEIP712TestSuite(t *testing.T) { - suite.Run(t, &EIP712TestSuite{}) - // Note that we don't test the Legacy EIP-712 Extension, since that case - // is sufficiently covered by the AnteHandler tests. - suite.Run(t, &EIP712TestSuite{ - useLegacyEIP712TypedData: true, - }) -} - func (suite *EIP712TestSuite) SetupTest() { - nw := network.New() + nw := network.New(suite.create, suite.options...) suite.config = nw.GetEncodingConfig() suite.clientCtx = client.Context{}.WithTxConfig(suite.config.TxConfig) suite.denom = evmtypes.GetEVMCoinDenom() diff --git a/tests/integration/eip712/test_eip712_fuzzer.go b/tests/integration/eip712/test_eip712_fuzzer.go new file mode 100644 index 000000000..fbb99b0e2 --- /dev/null +++ b/tests/integration/eip712/test_eip712_fuzzer.go @@ -0,0 +1,194 @@ +package eip712 + +import ( + "fmt" + "strings" + + "github.com/tidwall/gjson" + "github.com/tidwall/sjson" + + "github.com/cometbft/cometbft/libs/rand" + + "github.com/cosmos/evm/ethereum/eip712" +) + +type EIP712FuzzTestParams struct { + numTestObjects int + maxNumFieldsPerObject int + minStringLength int + maxStringLength int + randomFloatRange float64 + maxArrayLength int + maxObjectDepth int +} + +const ( + numPrimitiveJSONTypes = 3 + numJSONTypes = 5 + asciiRangeStart = 65 + asciiRangeEnd = 127 + fuzzTestName = "Flatten" +) + +const ( + jsonBoolType = iota + jsonStringType = iota + jsonFloatType = iota + jsonArrayType = iota + jsonObjectType = iota +) + +var params = EIP712FuzzTestParams{ + numTestObjects: 16, + maxNumFieldsPerObject: 16, + minStringLength: 16, + maxStringLength: 48, + randomFloatRange: 120000000, + maxArrayLength: 8, + maxObjectDepth: 4, +} + +// TestRandomPayloadFlattening generates many random payloads with different JSON values to ensure +// that Flattening works across all inputs. +// Note that this is a fuzz test, although it doesn't use Go's Fuzz testing suite, since there are +// variable input sizes, types, and fields. While it may be possible to translate a single input into +// a JSON object, it would require difficult parsing, and ultimately approximates our randomized unit +// tests as they are. +func (suite *EIP712TestSuite) TestRandomPayloadFlattening() { + // Re-seed rand generator + rand.Seed(rand.Int64()) + + for i := 0; i < params.numTestObjects; i++ { + suite.Run(fmt.Sprintf("%v%d", fuzzTestName, i), func() { + payload := suite.generateRandomPayload(i) + + flattened, numMessages, err := eip712.FlattenPayloadMessages(payload) + + suite.Require().NoError(err) + suite.Require().Equal(numMessages, i) + + suite.verifyPayloadAgainstFlattened(payload, flattened) + }) + } +} + +// generateRandomPayload creates a random payload of the desired format, with random sub-objects. +func (suite *EIP712TestSuite) generateRandomPayload(numMessages int) gjson.Result { + payload := suite.createRandomJSONObject().Raw + msgs := make([]gjson.Result, numMessages) + + for i := 0; i < numMessages; i++ { + msgs[i] = suite.createRandomJSONObject() + } + + payload, err := sjson.Set(payload, msgsFieldName, msgs) + suite.Require().NoError(err) + + return gjson.Parse(payload) +} + +// createRandomJSONObject creates a JSON object with random fields. +func (suite *EIP712TestSuite) createRandomJSONObject() gjson.Result { + var err error + payloadRaw := "" + + numFields := suite.createRandomIntInRange(0, params.maxNumFieldsPerObject) + for i := 0; i < numFields; i++ { + key := suite.createRandomString() + + randField := suite.createRandomJSONField(i, 0) + payloadRaw, err = sjson.Set(payloadRaw, key, randField) + suite.Require().NoError(err) + } + + return gjson.Parse(payloadRaw) +} + +// createRandomJSONField creates a random field with a random JSON type, with the possibility of +// nested fields up to depth objects. +func (suite *EIP712TestSuite) createRandomJSONField(t int, depth int) interface{} { + switch t % numJSONTypes { + case jsonBoolType: + return suite.createRandomBoolean() + case jsonStringType: + return suite.createRandomString() + case jsonFloatType: + return suite.createRandomFloat() + case jsonArrayType: + return suite.createRandomJSONNestedArray(depth) + case jsonObjectType: + return suite.createRandomJSONNestedObject(depth) + default: + return nil + } +} + +// createRandomJSONNestedArray creates an array of random nested JSON fields. +func (suite *EIP712TestSuite) createRandomJSONNestedArray(depth int) []interface{} { + arr := make([]interface{}, rand.Intn(params.maxArrayLength)) + for i := range arr { + arr[i] = suite.createRandomJSONNestedField(depth) + } + + return arr +} + +// createRandomJSONNestedObject creates a key-value set of objects with random nested JSON fields. +func (suite *EIP712TestSuite) createRandomJSONNestedObject(depth int) interface{} { + numFields := rand.Intn(params.maxNumFieldsPerObject) + obj := make(map[string]interface{}) + + for i := 0; i < numFields; i++ { + subField := suite.createRandomJSONNestedField(depth) + + obj[suite.createRandomString()] = subField + } + + return obj +} + +// createRandomJSONNestedField serves as a helper for createRandomJSONField and returns a random +// subfield to populate an array or object type. +func (suite *EIP712TestSuite) createRandomJSONNestedField(depth int) interface{} { + var newFieldType int + + if depth == params.maxObjectDepth { + newFieldType = rand.Intn(numPrimitiveJSONTypes) + } else { + newFieldType = rand.Intn(numJSONTypes) + } + + return suite.createRandomJSONField(newFieldType, depth+1) +} + +func (suite *EIP712TestSuite) createRandomBoolean() bool { + return rand.Intn(2) == 0 +} + +func (suite *EIP712TestSuite) createRandomFloat() float64 { + return (rand.Float64() - 0.5) * params.randomFloatRange +} + +func (suite *EIP712TestSuite) createRandomString() string { + bzLen := suite.createRandomIntInRange(params.minStringLength, params.maxStringLength) + bz := make([]byte, bzLen) + + for i := 0; i < bzLen; i++ { + bz[i] = byte(suite.createRandomIntInRange(asciiRangeStart, asciiRangeEnd)) + } + + str := string(bz) + + // Remove control characters, since they will make JSON invalid + str = strings.ReplaceAll(str, "{", "") + str = strings.ReplaceAll(str, "}", "") + str = strings.ReplaceAll(str, "]", "") + str = strings.ReplaceAll(str, "[", "") + + return str +} + +// createRandomIntInRange provides a random integer between [min, max) +func (suite *EIP712TestSuite) createRandomIntInRange(minInt int, maxInt int) int { + return rand.Intn(maxInt-minInt) + minInt +} diff --git a/tests/integration/eips/test_eips.go b/tests/integration/eips/test_eips.go new file mode 100644 index 000000000..0ad39b11c --- /dev/null +++ b/tests/integration/eips/test_eips.go @@ -0,0 +1,445 @@ +package eips + +import ( + "fmt" + "math/big" + "testing" + + "cosmosevm.io/evmd/eips" + "cosmosevm.io/evmd/eips/testdata" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/params" + + //nolint:revive // dot imports are fine for Ginkgo + . "github.com/onsi/ginkgo/v2" + //nolint:revive // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" + + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/integration/evm/utils" + "github.com/cosmos/evm/testutil/keyring" + testutiltypes "github.com/cosmos/evm/testutil/types" + evmtypes "github.com/cosmos/evm/x/vm/types" + + "github.com/cosmos/cosmos-sdk/crypto/types" +) + +// Below tests are divided in 3 steps: +// 1. Deploy and interact with contracts to compute the gas used BEFORE enabling +// the EIP. +// 2. Activate the EIP under test. +// 3. Deploy and interact with contracts to compute the gas used AFTER enabling +// the EIP. + +func TestEIPs(t *testing.T, create network.CreateEvmApp, options ...network.ConfigOption) { + var _ = Describe("EIP-0000 - ", Ordered, func() { + var ( + in network.Network + tf factory.TxFactory + gh grpc.Handler + k keyring.Keyring + + senderPriv types.PrivKey + senderPriv2 types.PrivKey + senderAddr2 common.Address + + // Gas used before enabling the EIP. + gasUsedPre int64 + ) + + // Multiplier used to modify the opcodes associated with EIP-0. + eipMultiplier := uint64(5) + + // The factory counter is used because it will create a new instance of + // the counter contract, allowing to test the CREATE opcode. + counterFactoryContract, err := testdata.LoadCounterFactoryContract() + Expect(err).ToNot(HaveOccurred(), "failed to load Counter Factory contract") + + deploymentData := testutiltypes.ContractDeploymentData{ + Contract: counterFactoryContract, + ConstructorArgs: []interface{}{}, + } + + BeforeAll(func() { + k = keyring.New(2) + opts := []network.ConfigOption{ + network.WithPreFundedAccounts(k.GetAllAccAddrs()...), + } + opts = append(opts, options...) + in = network.New(create, opts...) + gh = grpc.NewIntegrationHandler(in) + tf = factory.New(in, gh) + + // Account used to deploy the contract before enabling the EIP. + senderPriv = k.GetPrivKey(0) + // Account used to deploy the contract after enabling the EIP. A second + // account is used to avoid possible additional gas costs due to the change + // in the Nonce. + senderPriv2 = k.GetPrivKey(1) + senderAddr2 = k.GetAddr(1) + + // Set extra EIPs to empty to allow testing a single modifier. + defaultParams := evmtypes.DefaultParams() + defaultParams.ExtraEIPs = []int64{} + + err := utils.UpdateEvmParams( + utils.UpdateParamsInput{ + Tf: tf, + Network: in, + Pk: senderPriv, + Params: defaultParams, + }, + ) + Expect(err).To(BeNil(), "failed during update of evm params") + Expect(in.NextBlock()).To(BeNil()) + }) + + It("should deploy the contract before enabling the EIP", func() { + deploymentTxArgs, err := tf.GenerateDeployContractArgs(senderAddr2, evmtypes.EvmTxArgs{}, deploymentData) + Expect(err).To(BeNil(), "failed to create deployment tx args") + + res, err := tf.ExecuteEthTx(senderPriv2, deploymentTxArgs) + Expect(err).To(BeNil(), "failed during contract deployment") + gasUsedPre = res.GasUsed + }) + + It("should enable the new EIP", func() { + eips.Multiplier = eipMultiplier + newEIP := 0o000 + + qRes, err := gh.GetEvmParams() + Expect(err).To(BeNil(), "failed during query to evm params") + qRes.Params.ExtraEIPs = append(qRes.Params.ExtraEIPs, int64(newEIP)) + err = utils.UpdateEvmParams( + utils.UpdateParamsInput{ + Tf: tf, + Network: in, + Pk: senderPriv, + Params: qRes.Params, + }, + ) + Expect(err).To(BeNil(), "failed during update of evm params") + + Expect(in.NextBlock()).To(BeNil()) + + qRes, err = gh.GetEvmParams() + Expect(err).To(BeNil(), "failed during query to evm params") + Expect(qRes.Params.ExtraEIPs).To(ContainElement(int64(newEIP)), "expected to have EIP 0000 in evm params") + }) + + It("should change CREATE opcode constant gas after enabling EIP", func() { + gasCostPre := params.CreateGas + + deploymentTxArgs, err := tf.GenerateDeployContractArgs(senderAddr2, evmtypes.EvmTxArgs{}, deploymentData) + Expect(err).To(BeNil(), "failed to create deployment tx args") + + res, err := tf.ExecuteEthTx(senderPriv2, deploymentTxArgs) + Expect(err).To(BeNil(), "failed during contract deployment") + // commit block to update sender nonce + Expect(in.NextBlock()).To(BeNil()) + + gasUsedPost := res.GasUsed + + // The difference in gas is the new cost of the opcode, minus the cost of the + // opcode before enabling the new eip. + gasUsedDiff := eipMultiplier*gasCostPre - gasCostPre + expectedGas := gasUsedPre + int64(gasUsedDiff) + Expect(gasUsedPost).To(Equal(expectedGas)) + }) + }) + + var _ = Describe("EIP0001 - ", Ordered, func() { + var ( + in network.Network + tf factory.TxFactory + gh grpc.Handler + k keyring.Keyring + + senderPriv types.PrivKey + + // Gas used before enabling the EIP. + gasUsedPre int64 + + // The address of the factory counter. + counterFactoryAddr common.Address + ) + + // Multiplier used to modify the opcodes associated with EIP_0001. + eipMultiplier := uint64(5) + initialCounterValue := 1 + + // The counter factory contract is used to deploy a counter contract and + // perform state transition using the CALL opcode. + counterFactoryContract, err := testdata.LoadCounterFactoryContract() + Expect(err).ToNot(HaveOccurred(), "failed to load Counter Factory contract") + + BeforeAll(func() { + k = keyring.New(1) + opts := []network.ConfigOption{ + network.WithPreFundedAccounts(k.GetAllAccAddrs()...), + } + opts = append(opts, options...) + in = network.New(create, opts...) + gh = grpc.NewIntegrationHandler(in) + tf = factory.New(in, gh) + + senderPriv = k.GetPrivKey(0) + + // Set extra EIPs to empty to allow testing a single modifier. + defaultParams := evmtypes.DefaultParams() + defaultParams.ExtraEIPs = []int64{} + err = utils.UpdateEvmParams( + utils.UpdateParamsInput{ + Tf: tf, + Network: in, + Pk: senderPriv, + Params: defaultParams, + }, + ) + Expect(err).To(BeNil(), "failed during update of evm params") + + Expect(in.NextBlock()).To(BeNil()) + }) + + It("should deploy the contract before enabling the EIP", func() { + counterFactoryAddr, err = tf.DeployContract( + senderPriv, + evmtypes.EvmTxArgs{}, + testutiltypes.ContractDeploymentData{ + Contract: counterFactoryContract, + ConstructorArgs: []interface{}{}, + }, + ) + Expect(err).ToNot(HaveOccurred(), "failed to deploy counter factory contract") + Expect(in.NextBlock()).To(BeNil()) + + res, err := tf.ExecuteContractCall( + senderPriv, + evmtypes.EvmTxArgs{To: &counterFactoryAddr}, + testutiltypes.CallArgs{ + ContractABI: counterFactoryContract.ABI, + MethodName: "incrementCounter", + Args: []interface{}{}, + }, + ) + Expect(err).ToNot(HaveOccurred(), "failed to increment counter value") + gasUsedPre = res.GasUsed + + Expect(in.NextBlock()).To(BeNil()) + + // Query the counter value to check proper state transition later. + res, err = tf.ExecuteContractCall( + senderPriv, + evmtypes.EvmTxArgs{To: &counterFactoryAddr}, + testutiltypes.CallArgs{ + ContractABI: counterFactoryContract.ABI, + MethodName: "getCounterValue", + Args: []interface{}{}, + }, + ) + Expect(err).ToNot(HaveOccurred(), "failed to get counter value") + Expect(in.NextBlock()).To(BeNil()) + + ethRes, err := evmtypes.DecodeTxResponse(res.Data) + Expect(err).ToNot(HaveOccurred(), "failed to decode tx response") + + unpacked, err := counterFactoryContract.ABI.Unpack( + "getCounterValue", + ethRes.Ret, + ) + Expect(err).ToNot(HaveOccurred(), "failed to unpack counter value") + + counter, ok := unpacked[0].(*big.Int) + Expect(ok).To(BeTrue(), "failed to convert counter to big.Int") + Expect(counter.String()).To(Equal(fmt.Sprintf("%d", initialCounterValue+1)), "counter is not correct") + }) + It("should enable the new EIP", func() { + eips.Multiplier = eipMultiplier + newEIP := 0o001 + + qRes, err := gh.GetEvmParams() + Expect(err).To(BeNil(), "failed during query to evm params") + qRes.Params.ExtraEIPs = append(qRes.Params.ExtraEIPs, int64(newEIP)) + + err = utils.UpdateEvmParams( + utils.UpdateParamsInput{ + Tf: tf, + Network: in, + Pk: senderPriv, + Params: qRes.Params, + }, + ) + Expect(err).To(BeNil(), "failed during update of evm params") + + Expect(in.NextBlock()).To(BeNil()) + + qRes, err = gh.GetEvmParams() + Expect(err).To(BeNil(), "failed during query to evm params") + Expect(qRes.Params.ExtraEIPs).To(ContainElement(int64(newEIP)), "expected to have eip 0001 in evm params") + }) + It("should change CALL opcode constant gas after enabling EIP", func() { + // Constant gas cost used before enabling the new EIP. + gasCostPre := params.WarmStorageReadCostEIP2929 + + res, err := tf.ExecuteContractCall( + senderPriv, + evmtypes.EvmTxArgs{To: &counterFactoryAddr}, + testutiltypes.CallArgs{ + ContractABI: counterFactoryContract.ABI, + MethodName: "incrementCounter", + Args: []interface{}{}, + }, + ) + Expect(err).ToNot(HaveOccurred(), "failed to increment counter value") + gasUsedPost := res.GasUsed + Expect(in.NextBlock()).To(BeNil()) + + res, err = tf.ExecuteContractCall( + senderPriv, + evmtypes.EvmTxArgs{To: &counterFactoryAddr}, + testutiltypes.CallArgs{ + ContractABI: counterFactoryContract.ABI, + MethodName: "getCounterValue", + Args: []interface{}{}, + }, + ) + Expect(err).ToNot(HaveOccurred(), "failed to get counter value") + Expect(in.NextBlock()).To(BeNil()) + + ethRes, err := evmtypes.DecodeTxResponse(res.Data) + Expect(err).ToNot(HaveOccurred(), "failed to decode tx response") + + unpacked, err := counterFactoryContract.ABI.Unpack( + "getCounterValue", + ethRes.Ret, + ) + Expect(err).ToNot(HaveOccurred(), "failed to unpack counter value") + + counter, ok := unpacked[0].(*big.Int) + Expect(ok).To(BeTrue(), "failed to convert counter to big.Int") + Expect(counter.String()).To(Equal(fmt.Sprintf("%d", initialCounterValue+2)), "counter is not updated correctly") + + // The difference in gas is the new cost of the opcode, minus the cost of the + // opcode before enabling the new eip. + gasUsedDiff := eipMultiplier*gasCostPre - gasCostPre + expectedGas := gasUsedPre + int64(gasUsedDiff) + Expect(gasUsedPost).To(Equal(expectedGas)) + }) + }) + + var _ = Describe("EIP0002 - ", Ordered, func() { + var ( + in network.Network + tf factory.TxFactory + gh grpc.Handler + k keyring.Keyring + + senderPriv types.PrivKey + senderAddr common.Address + senderPriv2 types.PrivKey + senderAddr2 common.Address + gasUsedPre int64 + ) + // Constant gas used to modify the opcodes associated with EIP_0002. + constantGas := uint64(500) + + counterContract, err := testdata.LoadCounterContract() + Expect(err).ToNot(HaveOccurred(), "failed to load Counter contract") + + deploymentData := testutiltypes.ContractDeploymentData{ + Contract: counterContract, + ConstructorArgs: []interface{}{}, + } + BeforeAll(func() { + k = keyring.New(2) + opts := []network.ConfigOption{ + network.WithPreFundedAccounts(k.GetAllAccAddrs()...), + } + opts = append(opts, options...) + in = network.New(create, opts...) + gh = grpc.NewIntegrationHandler(in) + tf = factory.New(in, gh) + + // Account used to deploy the contract before enabling the EIP. + senderPriv = k.GetPrivKey(0) + senderAddr = k.GetAddr(0) + // Account used to deploy the contract after enabling the EIP. A second + // account is used to avoid possible additional gas costs due to the change + // in the Nonce. + senderPriv2 = k.GetPrivKey(0) + senderAddr2 = k.GetAddr(0) + + // Set extra EIPs to empty to allow testing a single modifier. + defaultParams := evmtypes.DefaultParams() + defaultParams.ExtraEIPs = []int64{} + + err = utils.UpdateEvmParams( + utils.UpdateParamsInput{ + Tf: tf, + Network: in, + Pk: senderPriv, + Params: defaultParams, + }, + ) + Expect(err).To(BeNil(), "failed during update of evm params") + + Expect(in.NextBlock()).To(BeNil()) + }) + + It("should deploy the contract before enabling the EIP", func() { + deploymentTxArgs, err := tf.GenerateDeployContractArgs(senderAddr, evmtypes.EvmTxArgs{}, deploymentData) + Expect(err).To(BeNil(), "failed to create deployment tx args") + + res, err := tf.ExecuteEthTx(senderPriv, deploymentTxArgs) + Expect(err).To(BeNil(), "failed during contract deployment") + Expect(in.NextBlock()).To(BeNil()) + + gasUsedPre = res.GasUsed + }) + + It("should enable the new EIP", func() { + eips.SstoreConstantGas = constantGas + newEIP := 0o002 + + qRes, err := gh.GetEvmParams() + Expect(err).To(BeNil(), "failed during query to evm params") + qRes.Params.ExtraEIPs = append(qRes.Params.ExtraEIPs, int64(newEIP)) + err = utils.UpdateEvmParams( + utils.UpdateParamsInput{ + Tf: tf, + Network: in, + Pk: senderPriv, + Params: qRes.Params, + }, + ) + Expect(err).To(BeNil(), "failed during update of evm params") + + Expect(in.NextBlock()).To(BeNil()) + + qRes, err = gh.GetEvmParams() + Expect(err).To(BeNil(), "failed during query to evm params") + Expect(qRes.Params.ExtraEIPs).To(ContainElement(int64(newEIP)), "expected to have eip 0002 in evm params") + }) + + It("should change SSTORE opcode constant gas after enabling EIP", func() { + deploymentTxArgs, err := tf.GenerateDeployContractArgs(senderAddr2, evmtypes.EvmTxArgs{}, deploymentData) + Expect(err).To(BeNil(), "failed to create deployment tx args") + + res, err := tf.ExecuteEthTx(senderPriv2, deploymentTxArgs) + Expect(err).To(BeNil(), "failed during contract deployment") + Expect(in.NextBlock()).To(BeNil()) + + gasUsedPost := res.GasUsed + + // The expected gas is previous gas plus the constant gas because + // previous this eip, SSTORE was using only the dynamic gas. + expectedGas := gasUsedPre + int64(constantGas) + Expect(gasUsedPost).To(Equal(expectedGas)) + }) + }) + + RegisterFailHandler(Fail) + RunSpecs(t, "EIPs Suite") +} diff --git a/indexer/kv_indexer_test.go b/tests/integration/indexer/test_kv_indexer.go similarity index 96% rename from indexer/kv_indexer_test.go rename to tests/integration/indexer/test_kv_indexer.go index 2e94456fe..860774b51 100644 --- a/indexer/kv_indexer_test.go +++ b/tests/integration/indexer/test_kv_indexer.go @@ -1,4 +1,4 @@ -package indexer_test +package indexer import ( "math/big" @@ -15,7 +15,7 @@ import ( "github.com/cosmos/evm/crypto/ethsecp256k1" "github.com/cosmos/evm/indexer" "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/network" utiltx "github.com/cosmos/evm/testutil/tx" "github.com/cosmos/evm/x/vm/types" @@ -24,7 +24,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" ) -func TestKVIndexer(t *testing.T) { +func TestKVIndexer(t *testing.T, create network.CreateEvmApp, options ...network.ConfigOption) { priv, err := ethsecp256k1.GenerateKey() require.NoError(t, err) from := common.BytesToAddress(priv.PubKey().Address().Bytes()) @@ -43,7 +43,7 @@ func TestKVIndexer(t *testing.T) { require.NoError(t, tx.Sign(ethSigner, signer)) txHash := tx.AsTransaction().Hash() - nw := network.New() + nw := network.New(create, options...) encodingConfig := nw.GetEncodingConfig() clientCtx := client.Context{}.WithTxConfig(encodingConfig.TxConfig).WithCodec(encodingConfig.Codec) diff --git a/tests/integration/ledger/evmosd_suite_test.go b/tests/integration/ledger/evmosd_suite_test.go index 23e6bced1..a69640d52 100644 --- a/tests/integration/ledger/evmosd_suite_test.go +++ b/tests/integration/ledger/evmosd_suite_test.go @@ -8,6 +8,7 @@ import ( "testing" "time" + exampleapp "cosmosevm.io/evmd" "github.com/ethereum/go-ethereum/common" "github.com/spf13/cobra" "github.com/stretchr/testify/suite" @@ -26,7 +27,6 @@ import ( clientkeys "github.com/cosmos/evm/client/keys" "github.com/cosmos/evm/crypto/hd" cosmosevmkeyring "github.com/cosmos/evm/crypto/keyring" - exampleapp "github.com/cosmos/evm/evmd" "github.com/cosmos/evm/tests/integration/ledger/mocks" "github.com/cosmos/evm/testutil/constants" utiltx "github.com/cosmos/evm/testutil/tx" diff --git a/tests/integration/precompiles/bank/test_integration.go b/tests/integration/precompiles/bank/test_integration.go new file mode 100644 index 000000000..84fab9b4c --- /dev/null +++ b/tests/integration/precompiles/bank/test_integration.go @@ -0,0 +1,447 @@ +package bank + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/suite" + + //nolint:revive // dot imports are fine for Ginkgo + . "github.com/onsi/ginkgo/v2" + //nolint:revive // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" + + bank2 "github.com/cosmos/evm/precompiles/bank" + "github.com/cosmos/evm/precompiles/bank/testdata" + "github.com/cosmos/evm/precompiles/testutil" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/integration/evm/utils" + "github.com/cosmos/evm/testutil/keyring" + utiltx "github.com/cosmos/evm/testutil/tx" + testutiltypes "github.com/cosmos/evm/testutil/types" + evmtypes "github.com/cosmos/evm/x/vm/types" + + "cosmossdk.io/math" + + sdk "github.com/cosmos/cosmos-sdk/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" +) + +var is *IntegrationTestSuite + +// IntegrationTestSuite is the implementation of the TestSuite interface for Bank precompile +// unit testis. +type IntegrationTestSuite struct { + suite.Suite + + bondDenom, tokenDenom string + cosmosEVMAddr, xmplAddr common.Address + + create network.CreateEvmApp + options []network.ConfigOption + network *network.UnitTestNetwork + factory factory.TxFactory + grpcHandler grpc.Handler + keyring keyring.Keyring + + precompile *bank2.Precompile +} + +func NewIntegrationTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *IntegrationTestSuite { + return &IntegrationTestSuite{ + create: create, + options: options, + } +} + +func (is *IntegrationTestSuite) SetupTest() { + // Mint and register a second coin for testing purposes + // FIXME the RegisterCoin logic will need to be refactored + // once logic is integrated + // with the protocol via genesis and/or a transaction + is.tokenDenom = xmplDenom + keyring := keyring.New(2) + genesis := utils.CreateGenesisWithTokenPairs(keyring) + + options := []network.ConfigOption{ + network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), + network.WithOtherDenoms([]string{is.tokenDenom}), // set some funds of other denom to the prefunded accounts + network.WithCustomGenesis(genesis), + } + options = append(options, is.options...) + integrationNetwork := network.NewUnitTestNetwork(is.create, options...) + grpcHandler := grpc.NewIntegrationHandler(integrationNetwork) + txFactory := factory.New(integrationNetwork, grpcHandler) + + ctx := integrationNetwork.GetContext() + sk := integrationNetwork.App.GetStakingKeeper() + bondDenom, err := sk.BondDenom(ctx) + Expect(err).ToNot(HaveOccurred()) + Expect(bondDenom).ToNot(BeEmpty(), "bond denom cannot be empty") + + is.bondDenom = bondDenom + is.factory = txFactory + is.grpcHandler = grpcHandler + is.keyring = keyring + is.network = integrationNetwork + + tokenPairID := is.network.App.GetErc20Keeper().GetTokenPairID(is.network.GetContext(), is.bondDenom) + tokenPair, found := is.network.App.GetErc20Keeper().GetTokenPair(is.network.GetContext(), tokenPairID) + Expect(found).To(BeTrue(), "failed to register token erc20 extension") + is.cosmosEVMAddr = common.HexToAddress(tokenPair.Erc20Address) + + // Mint and register a second coin for testing purposes + err = is.network.App.GetBankKeeper().MintCoins(is.network.GetContext(), minttypes.ModuleName, sdk.Coins{{Denom: is.tokenDenom, Amount: math.NewInt(1e18)}}) + Expect(err).ToNot(HaveOccurred(), "failed to mint coin") + + tokenPairID = is.network.App.GetErc20Keeper().GetTokenPairID(is.network.GetContext(), is.tokenDenom) + tokenPair, found = is.network.App.GetErc20Keeper().GetTokenPair(is.network.GetContext(), tokenPairID) + Expect(found).To(BeTrue(), "failed to register token erc20 extension") + is.xmplAddr = common.HexToAddress(tokenPair.Erc20Address) + is.precompile = is.setupBankPrecompile() +} + +func TestIntegrationSuite(t *testing.T, create network.CreateEvmApp, options ...network.ConfigOption) { + var is *IntegrationTestSuite + + var _ = Describe("Bank Extension -", func() { + var ( + bankCallerContractAddr common.Address + bankCallerContract evmtypes.CompiledContract + + err error + sender keyring.Key + amount *big.Int + + // contractData is a helper struct to hold the addresses and ABIs for the + // different contract instances that are subject to testing here. + contractData ContractData + passCheck testutil.LogCheckArgs + + cosmosEVMTotalSupply, _ = new(big.Int).SetString("200003000000000000000000", 10) + xmplTotalSupply, _ = new(big.Int).SetString("200000000000000000000000", 10) + ) + + BeforeEach(func() { + is = NewIntegrationTestSuite(create, options...) + is.SetupTest() + + // Default sender, amount + sender = is.keyring.GetKey(0) + amount = big.NewInt(1e18) + + bankCallerContract, err = testdata.LoadBankCallerContract() + Expect(err).ToNot(HaveOccurred(), "failed to load BankCaller contract") + + bankCallerContractAddr, err = is.factory.DeployContract( + sender.Priv, + evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values + testutiltypes.ContractDeploymentData{ + Contract: bankCallerContract, + }, + ) + Expect(err).ToNot(HaveOccurred(), "failed to deploy ERC20 minter burner contract") + + contractData = ContractData{ + ownerPriv: sender.Priv, + precompileAddr: is.precompile.Address(), + precompileABI: is.precompile.ABI, + contractAddr: bankCallerContractAddr, + contractABI: bankCallerContract.ABI, + } + + passCheck = testutil.LogCheckArgs{}.WithExpPass(true) + + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "failed to advance block") + }) + + Context("Direct precompile queries", func() { + Context("balances query", func() { + It("should return the correct balance", func() { + // New account with 0 balances (does not exist on the chain yet) + receiver := utiltx.GenerateAddress() + + err := is.factory.FundAccount(sender, receiver.Bytes(), sdk.NewCoins(sdk.NewCoin(is.tokenDenom, math.NewIntFromBigInt(amount)))) + Expect(err).ToNot(HaveOccurred(), "error while funding account") + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + queryArgs, balancesArgs := getTxAndCallArgs(directCall, contractData, bank2.BalancesMethod, receiver) + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, balancesArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + var balances []bank2.Balance + err = is.precompile.UnpackIntoInterface(&balances, bank2.BalancesMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") + + balanceAfter, err := is.grpcHandler.GetBalanceFromBank(receiver.Bytes(), is.tokenDenom) + Expect(err).ToNot(HaveOccurred(), "failed to get balance") + + Expect(math.NewInt(balances[0].Amount.Int64())).To(Equal(balanceAfter.Balance.Amount)) + Expect(*balances[0].Amount).To(Equal(*amount)) + }) + + It("should return a single token balance", func() { + // New account with 0 balances (does not exist on the chain yet) + receiver := utiltx.GenerateAddress() + + err := utils.FundAccountWithBaseDenom(is.factory, is.network, sender, receiver.Bytes(), math.NewIntFromBigInt(amount)) + Expect(err).ToNot(HaveOccurred(), "error while funding account") + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + queryArgs, balancesArgs := getTxAndCallArgs(directCall, contractData, bank2.BalancesMethod, receiver) + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, balancesArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + var balances []bank2.Balance + err = is.precompile.UnpackIntoInterface(&balances, bank2.BalancesMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") + + balanceAfter, err := is.grpcHandler.GetBalanceFromBank(receiver.Bytes(), is.network.GetBaseDenom()) + Expect(err).ToNot(HaveOccurred(), "failed to get balance") + + Expect(math.NewInt(balances[0].Amount.Int64())).To(Equal(balanceAfter.Balance.Amount)) + Expect(*balances[0].Amount).To(Equal(*amount)) + }) + + It("should return no balance for new account", func() { + queryArgs, balancesArgs := getTxAndCallArgs(directCall, contractData, bank2.BalancesMethod, utiltx.GenerateAddress()) + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, balancesArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + var balances []bank2.Balance + err = is.precompile.UnpackIntoInterface(&balances, bank2.BalancesMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") + + Expect(balances).To(BeEmpty()) + }) + + It("should consume the correct amount of gas", func() { + queryArgs, balancesArgs := getTxAndCallArgs(directCall, contractData, bank2.BalancesMethod, sender.Addr) + res, err := is.factory.ExecuteContractCall(sender.Priv, queryArgs, balancesArgs) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + ethRes, err := evmtypes.DecodeTxResponse(res.Data) + Expect(err).ToNot(HaveOccurred(), "failed to decode tx response") + + var balances []bank2.Balance + err = is.precompile.UnpackIntoInterface(&balances, bank2.BalancesMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") + + gasUsed := Max(bank2.GasBalances, len(balances)*bank2.GasBalances) + // Here increasing the GasBalanceOf will increase the use of gas so they will never be equal + Expect(gasUsed).To(BeNumerically("<=", ethRes.GasUsed)) + }) + }) + + Context("totalSupply query", func() { + It("should return the correct total supply", func() { + queryArgs, supplyArgs := getTxAndCallArgs(directCall, contractData, bank2.TotalSupplyMethod) + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + var balances []bank2.Balance + err = is.precompile.UnpackIntoInterface(&balances, bank2.TotalSupplyMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") + + Expect(balances[0].Amount.String()).To(Equal(cosmosEVMTotalSupply.String())) + Expect(balances[1].Amount.String()).To(Equal(xmplTotalSupply.String())) + }) + }) + + Context("supplyOf query", func() { + It("should return the supply of Cosmos EVM", func() { + queryArgs, supplyArgs := getTxAndCallArgs(directCall, contractData, bank2.SupplyOfMethod, is.cosmosEVMAddr) + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + out, err := is.precompile.Unpack(bank2.SupplyOfMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") + + Expect(out[0].(*big.Int).String()).To(Equal(cosmosEVMTotalSupply.String())) + }) + + It("should return the supply of XMPL", func() { + queryArgs, supplyArgs := getTxAndCallArgs(directCall, contractData, bank2.SupplyOfMethod, is.xmplAddr) + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + out, err := is.precompile.Unpack(bank2.SupplyOfMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") + + Expect(out[0].(*big.Int).String()).To(Equal(xmplTotalSupply.String())) + }) + + It("should return a supply of 0 for a non existing token", func() { + queryArgs, supplyArgs := getTxAndCallArgs(directCall, contractData, bank2.SupplyOfMethod, utiltx.GenerateAddress()) + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + out, err := is.precompile.Unpack(bank2.SupplyOfMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") + + Expect(out[0].(*big.Int).Int64()).To(Equal(big.NewInt(0).Int64())) + }) + + It("should consume the correct amount of gas", func() { + queryArgs, supplyArgs := getTxAndCallArgs(directCall, contractData, bank2.SupplyOfMethod, is.xmplAddr) + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // Here increasing the GasSupplyOf will increase the use of gas so they will never be equal + Expect(bank2.GasSupplyOf).To(BeNumerically("<=", ethRes.GasUsed)) + }) + }) + }) + + Context("Calls from a contract", func() { + const ( + BalancesFunction = "callBalances" + TotalSupplyOf = "callTotalSupply" + SupplyOfFunction = "callSupplyOf" + ) + + Context("balances query", func() { + It("should return the correct balance", func() { + receiver := utiltx.GenerateAddress() + + err := is.factory.FundAccount(sender, receiver.Bytes(), sdk.NewCoins(sdk.NewCoin(is.tokenDenom, math.NewIntFromBigInt(amount)))) + Expect(err).ToNot(HaveOccurred(), "error while funding account") + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + queryArgs, balancesArgs := getTxAndCallArgs(contractCall, contractData, BalancesFunction, receiver) + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, balancesArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + var balances []bank2.Balance + err = is.precompile.UnpackIntoInterface(&balances, bank2.BalancesMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") + + balanceAfter, err := is.grpcHandler.GetBalanceFromBank(receiver.Bytes(), is.tokenDenom) + Expect(err).ToNot(HaveOccurred(), "failed to get balance") + + Expect(math.NewInt(balances[0].Amount.Int64())).To(Equal(balanceAfter.Balance.Amount)) + Expect(*balances[0].Amount).To(Equal(*amount)) + }) + + It("should return a single token balance", func() { + // New account with 0 balances (does not exist on the chain yet) + receiver := utiltx.GenerateAddress() + + err := utils.FundAccountWithBaseDenom(is.factory, is.network, sender, receiver.Bytes(), math.NewIntFromBigInt(amount)) + Expect(err).ToNot(HaveOccurred(), "error while funding account") + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + queryArgs, balancesArgs := getTxAndCallArgs(contractCall, contractData, BalancesFunction, receiver) + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, balancesArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + var balances []bank2.Balance + err = is.precompile.UnpackIntoInterface(&balances, bank2.BalancesMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") + + balanceAfter, err := is.grpcHandler.GetBalanceFromBank(receiver.Bytes(), is.network.GetBaseDenom()) + Expect(err).ToNot(HaveOccurred(), "failed to get balance") + + Expect(math.NewInt(balances[0].Amount.Int64())).To(Equal(balanceAfter.Balance.Amount)) + Expect(*balances[0].Amount).To(Equal(*amount)) + }) + + It("should return no balance for new account", func() { + queryArgs, balancesArgs := getTxAndCallArgs(contractCall, contractData, BalancesFunction, utiltx.GenerateAddress()) + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, balancesArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + var balances []bank2.Balance + err = is.precompile.UnpackIntoInterface(&balances, bank2.BalancesMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") + + Expect(balances).To(BeEmpty()) + }) + + It("should consume the correct amount of gas", func() { + queryArgs, balancesArgs := getTxAndCallArgs(contractCall, contractData, BalancesFunction, sender.Addr) + res, err := is.factory.ExecuteContractCall(sender.Priv, queryArgs, balancesArgs) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + ethRes, err := evmtypes.DecodeTxResponse(res.Data) + Expect(err).ToNot(HaveOccurred(), "failed to decode tx response") + + var balances []bank2.Balance + err = is.precompile.UnpackIntoInterface(&balances, bank2.BalancesMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") + + gasUsed := Max(bank2.GasBalances, len(balances)*bank2.GasBalances) + // Here increasing the GasBalanceOf will increase the use of gas so they will never be equal + Expect(gasUsed).To(BeNumerically("<=", ethRes.GasUsed)) + }) + }) + + Context("totalSupply query", func() { + It("should return the correct total supply", func() { + queryArgs, supplyArgs := getTxAndCallArgs(contractCall, contractData, TotalSupplyOf) + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + var balances []bank2.Balance + err = is.precompile.UnpackIntoInterface(&balances, bank2.TotalSupplyMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") + + Expect(balances[0].Amount.String()).To(Equal(cosmosEVMTotalSupply.String())) + Expect(balances[1].Amount.String()).To(Equal(xmplTotalSupply.String())) + }) + }) + + Context("supplyOf query", func() { + It("should return the supply of Cosmos EVM", func() { + queryArgs, supplyArgs := getTxAndCallArgs(contractCall, contractData, SupplyOfFunction, is.cosmosEVMAddr) + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + out, err := is.precompile.Unpack(bank2.SupplyOfMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") + + Expect(out[0].(*big.Int).String()).To(Equal(cosmosEVMTotalSupply.String())) + }) + + It("should return the supply of XMPL", func() { + queryArgs, supplyArgs := getTxAndCallArgs(contractCall, contractData, SupplyOfFunction, is.xmplAddr) + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + out, err := is.precompile.Unpack(bank2.SupplyOfMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") + + Expect(out[0].(*big.Int).String()).To(Equal(xmplTotalSupply.String())) + }) + + It("should return a supply of 0 for a non existing token", func() { + queryArgs, supplyArgs := getTxAndCallArgs(contractCall, contractData, SupplyOfFunction, utiltx.GenerateAddress()) + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + out, err := is.precompile.Unpack(bank2.SupplyOfMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack balances") + + Expect(out[0].(*big.Int).Int64()).To(Equal(big.NewInt(0).Int64())) + }) + + It("should consume the correct amount of gas", func() { + queryArgs, supplyArgs := getTxAndCallArgs(contractCall, contractData, SupplyOfFunction, is.xmplAddr) + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, queryArgs, supplyArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // Here increasing the GasSupplyOf will increase the use of gas so they will never be equal + Expect(bank2.GasSupplyOf).To(BeNumerically("<=", ethRes.GasUsed)) + }) + }) + }) + }) + + // Run Ginkgo integration tests + RegisterFailHandler(Fail) + RunSpecs(t, "Bank Extension Suite") +} diff --git a/precompiles/bank/query_test.go b/tests/integration/precompiles/bank/test_query.go similarity index 98% rename from precompiles/bank/query_test.go rename to tests/integration/precompiles/bank/test_query.go index eedf18719..e4f750666 100644 --- a/precompiles/bank/query_test.go +++ b/tests/integration/precompiles/bank/test_query.go @@ -1,4 +1,4 @@ -package bank_test +package bank import ( "math/big" @@ -6,7 +6,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/cosmos/evm/precompiles/bank" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/network" cosmosevmutiltx "github.com/cosmos/evm/testutil/tx" "cosmossdk.io/math" diff --git a/precompiles/bank/setup_test.go b/tests/integration/precompiles/bank/test_setup.go similarity index 61% rename from precompiles/bank/setup_test.go rename to tests/integration/precompiles/bank/test_setup.go index 63a9d3a7d..ab8fc6b6c 100644 --- a/precompiles/bank/setup_test.go +++ b/tests/integration/precompiles/bank/test_setup.go @@ -1,17 +1,15 @@ -package bank_test +package bank import ( - "testing" - "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/suite" - "github.com/cosmos/evm/precompiles/bank" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" - integrationutils "github.com/cosmos/evm/testutil/integration/os/utils" + bank2 "github.com/cosmos/evm/precompiles/bank" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/integration/evm/utils" + testkeyring "github.com/cosmos/evm/testutil/keyring" "cosmossdk.io/math" @@ -26,6 +24,7 @@ var s *PrecompileTestSuite type PrecompileTestSuite struct { suite.Suite + create network.CreateEvmApp bondDenom, tokenDenom string cosmosEVMAddr, xmplAddr common.Address @@ -36,20 +35,22 @@ type PrecompileTestSuite struct { grpcHandler grpc.Handler keyring testkeyring.Keyring - precompile *bank.Precompile + precompile *bank2.Precompile } -func TestPrecompileTestSuite(t *testing.T) { - s = new(PrecompileTestSuite) - suite.Run(t, s) +func NewPrecompileTestSuite(create network.CreateEvmApp) *PrecompileTestSuite { + return &PrecompileTestSuite{ + create: create, + } } func (s *PrecompileTestSuite) SetupTest() sdk.Context { s.tokenDenom = xmplDenom keyring := testkeyring.New(2) - genesis := integrationutils.CreateGenesisWithTokenPairs(keyring) + genesis := utils.CreateGenesisWithTokenPairs(keyring) unitNetwork := network.NewUnitTestNetwork( + s.create, network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), network.WithCustomGenesis(genesis), network.WithOtherDenoms([]string{s.tokenDenom}), @@ -58,7 +59,7 @@ func (s *PrecompileTestSuite) SetupTest() sdk.Context { txFactory := factory.New(unitNetwork, grpcHandler) ctx := unitNetwork.GetContext() - sk := unitNetwork.App.StakingKeeper + sk := unitNetwork.App.GetStakingKeeper() bondDenom, err := sk.BondDenom(ctx) s.Require().NoError(err, "failed to get bond denom") s.Require().NotEmpty(bondDenom, "bond denom cannot be empty") @@ -69,19 +70,19 @@ func (s *PrecompileTestSuite) SetupTest() sdk.Context { s.keyring = keyring s.network = unitNetwork - tokenPairID := s.network.App.Erc20Keeper.GetTokenPairID(s.network.GetContext(), s.bondDenom) - tokenPair, found := s.network.App.Erc20Keeper.GetTokenPair(s.network.GetContext(), tokenPairID) + tokenPairID := s.network.App.GetErc20Keeper().GetTokenPairID(s.network.GetContext(), s.bondDenom) + tokenPair, found := s.network.App.GetErc20Keeper().GetTokenPair(s.network.GetContext(), tokenPairID) s.Require().True(found) s.cosmosEVMAddr = common.HexToAddress(tokenPair.Erc20Address) s.cosmosEVMAddr = tokenPair.GetERC20Contract() // Mint and register a second coin for testing purposes - err = s.network.App.BankKeeper.MintCoins(s.network.GetContext(), minttypes.ModuleName, sdk.Coins{{Denom: "xmpl", Amount: math.NewInt(1e18)}}) + err = s.network.App.GetBankKeeper().MintCoins(s.network.GetContext(), minttypes.ModuleName, sdk.Coins{{Denom: "xmpl", Amount: math.NewInt(1e18)}}) s.Require().NoError(err) - tokenPairID = s.network.App.Erc20Keeper.GetTokenPairID(s.network.GetContext(), s.tokenDenom) - tokenPair, found = s.network.App.Erc20Keeper.GetTokenPair(s.network.GetContext(), tokenPairID) + tokenPairID = s.network.App.GetErc20Keeper().GetTokenPairID(s.network.GetContext(), s.tokenDenom) + tokenPair, found = s.network.App.GetErc20Keeper().GetTokenPair(s.network.GetContext(), tokenPairID) s.Require().True(found) s.xmplAddr = common.HexToAddress(tokenPair.Erc20Address) diff --git a/precompiles/bank/utils_test.go b/tests/integration/precompiles/bank/test_utils.go similarity index 81% rename from precompiles/bank/utils_test.go rename to tests/integration/precompiles/bank/test_utils.go index 9f17bdb82..5856fd70f 100644 --- a/precompiles/bank/utils_test.go +++ b/tests/integration/precompiles/bank/test_utils.go @@ -1,4 +1,4 @@ -package bank_test +package bank import ( "github.com/ethereum/go-ethereum/accounts/abi" @@ -8,7 +8,7 @@ import ( . "github.com/onsi/gomega" "github.com/cosmos/evm/precompiles/bank" - "github.com/cosmos/evm/testutil/integration/os/factory" + testutiltypes "github.com/cosmos/evm/testutil/types" evmtypes "github.com/cosmos/evm/x/vm/types" "cosmossdk.io/math" @@ -22,8 +22,8 @@ import ( // a given token denomination. func (s *PrecompileTestSuite) setupBankPrecompile() *bank.Precompile { precompile, err := bank.NewPrecompile( - s.network.App.BankKeeper, - s.network.App.Erc20Keeper, + s.network.App.GetBankKeeper(), + s.network.App.GetErc20Keeper(), ) s.Require().NoError(err, "failed to create bank precompile") @@ -35,8 +35,8 @@ func (s *PrecompileTestSuite) setupBankPrecompile() *bank.Precompile { // a given token denomination. func (is *IntegrationTestSuite) setupBankPrecompile() *bank.Precompile { precompile, err := bank.NewPrecompile( - is.network.App.BankKeeper, - is.network.App.Erc20Keeper, + is.network.App.GetBankKeeper(), + is.network.App.GetErc20Keeper(), ) Expect(err).ToNot(HaveOccurred(), "failed to create bank precompile") return precompile @@ -45,9 +45,9 @@ func (is *IntegrationTestSuite) setupBankPrecompile() *bank.Precompile { // mintAndSendXMPLCoin is a helper function to mint and send a coin to a given address. func (s *PrecompileTestSuite) mintAndSendXMPLCoin(ctx sdk.Context, addr sdk.AccAddress, amount math.Int) sdk.Context { coins := sdk.NewCoins(sdk.NewCoin(s.tokenDenom, amount)) - err := s.network.App.BankKeeper.MintCoins(ctx, minttypes.ModuleName, coins) + err := s.network.App.GetBankKeeper().MintCoins(ctx, minttypes.ModuleName, coins) s.Require().NoError(err) - err = s.network.App.BankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, coins) + err = s.network.App.GetBankKeeper().SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, coins) s.Require().NoError(err) return ctx } @@ -55,9 +55,9 @@ func (s *PrecompileTestSuite) mintAndSendXMPLCoin(ctx sdk.Context, addr sdk.AccA // mintAndSendXMPLCoin is a helper function to mint and send a coin to a given address. func (is *IntegrationTestSuite) mintAndSendXMPLCoin(addr sdk.AccAddress, amount math.Int) { //nolint:unused coins := sdk.NewCoins(sdk.NewCoin(is.tokenDenom, amount)) - err := is.network.App.BankKeeper.MintCoins(is.network.GetContext(), minttypes.ModuleName, coins) + err := is.network.App.GetBankKeeper().MintCoins(is.network.GetContext(), minttypes.ModuleName, coins) Expect(err).ToNot(HaveOccurred()) - err = is.network.App.BankKeeper.SendCoinsFromModuleToAccount(is.network.GetContext(), minttypes.ModuleName, addr, coins) + err = is.network.App.GetBankKeeper().SendCoinsFromModuleToAccount(is.network.GetContext(), minttypes.ModuleName, addr, coins) Expect(err).ToNot(HaveOccurred()) } @@ -85,9 +85,9 @@ func getTxAndCallArgs( contractData ContractData, methodName string, args ...interface{}, -) (evmtypes.EvmTxArgs, factory.CallArgs) { +) (evmtypes.EvmTxArgs, testutiltypes.CallArgs) { txArgs := evmtypes.EvmTxArgs{} - callArgs := factory.CallArgs{} + callArgs := testutiltypes.CallArgs{} switch callType { case directCall: diff --git a/precompiles/bech32/bech32_test.go b/tests/integration/precompiles/bech32/test_bech32.go similarity index 97% rename from precompiles/bech32/bech32_test.go rename to tests/integration/precompiles/bech32/test_bech32.go index 5c822f5a4..684ad3e8f 100644 --- a/precompiles/bech32/bech32_test.go +++ b/tests/integration/precompiles/bech32/test_bech32.go @@ -1,4 +1,4 @@ -package bech32_test +package bech32 import ( "github.com/ethereum/go-ethereum/common" @@ -131,7 +131,7 @@ func (s *PrecompileTestSuite) TestRun() { { "pass - hex to bech32 validator operator (cosmosvaloper)", func() *vm.Contract { - valAddrCodec := s.network.App.StakingKeeper.ValidatorAddressCodec() + valAddrCodec := s.network.App.GetStakingKeeper().ValidatorAddressCodec() valAddrBz, err := valAddrCodec.StringToBytes(s.network.GetValidators()[0].GetOperator()) s.Require().NoError(err, "failed to convert string to bytes") input, err := s.precompile.Pack( @@ -211,7 +211,7 @@ func (s *PrecompileTestSuite) TestRun() { return contract }, func(data []byte) { - valAddrCodec := s.network.App.StakingKeeper.ValidatorAddressCodec() + valAddrCodec := s.network.App.GetStakingKeeper().ValidatorAddressCodec() valAddrBz, err := valAddrCodec.StringToBytes(s.network.GetValidators()[0].GetOperator()) s.Require().NoError(err, "failed to convert string to bytes") diff --git a/precompiles/bech32/methods_test.go b/tests/integration/precompiles/bech32/test_methods.go similarity index 99% rename from precompiles/bech32/methods_test.go rename to tests/integration/precompiles/bech32/test_methods.go index 5bafc104d..eb4b367d6 100644 --- a/precompiles/bech32/methods_test.go +++ b/tests/integration/precompiles/bech32/test_methods.go @@ -1,4 +1,4 @@ -package bech32_test +package bech32 import ( "fmt" diff --git a/precompiles/bech32/setup_test.go b/tests/integration/precompiles/bech32/test_setup.go similarity index 57% rename from precompiles/bech32/setup_test.go rename to tests/integration/precompiles/bech32/test_setup.go index 09a2aa594..53b47b3b9 100644 --- a/precompiles/bech32/setup_test.go +++ b/tests/integration/precompiles/bech32/test_setup.go @@ -1,13 +1,11 @@ -package bech32_test +package bech32 import ( - "testing" - "github.com/stretchr/testify/suite" "github.com/cosmos/evm/precompiles/bech32" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/network" + testkeyring "github.com/cosmos/evm/testutil/keyring" ) var s *PrecompileTestSuite @@ -17,22 +15,28 @@ var s *PrecompileTestSuite type PrecompileTestSuite struct { suite.Suite + create network.CreateEvmApp + options []network.ConfigOption network *network.UnitTestNetwork keyring testkeyring.Keyring precompile *bech32.Precompile } -func TestPrecompileTestSuite(t *testing.T) { - s = new(PrecompileTestSuite) - suite.Run(t, s) +func NewPrecompileTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *PrecompileTestSuite { + return &PrecompileTestSuite{ + create: create, + options: options, + } } func (s *PrecompileTestSuite) SetupTest() { keyring := testkeyring.New(2) - integrationNetwork := network.NewUnitTestNetwork( + options := []network.ConfigOption{ network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), - ) + } + options = append(options, s.options...) + integrationNetwork := network.NewUnitTestNetwork(s.create, options...) s.keyring = keyring s.network = integrationNetwork diff --git a/precompiles/distribution/distribution_test.go b/tests/integration/precompiles/distribution/test_distribution.go similarity index 89% rename from precompiles/distribution/distribution_test.go rename to tests/integration/precompiles/distribution/test_distribution.go index 64f059ce8..e59ddabfe 100644 --- a/precompiles/distribution/distribution_test.go +++ b/tests/integration/precompiles/distribution/test_distribution.go @@ -1,4 +1,4 @@ -package distribution_test +package distribution import ( "math/big" @@ -9,10 +9,10 @@ import ( "github.com/ethereum/go-ethereum/core/vm" "github.com/holiman/uint256" - chainutil "github.com/cosmos/evm/evmd/testutil" cmn "github.com/cosmos/evm/precompiles/common" "github.com/cosmos/evm/precompiles/distribution" "github.com/cosmos/evm/precompiles/testutil" + chainutil "github.com/cosmos/evm/testutil" "github.com/cosmos/evm/testutil/constants" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -85,9 +85,9 @@ func (s *PrecompileTestSuite) TestRun() { malleate: func() (common.Address, []byte) { valAddr, err := sdk.ValAddressFromBech32(s.network.GetValidators()[0].OperatorAddress) s.Require().NoError(err) - val, _ := s.network.App.StakingKeeper.GetValidator(ctx, valAddr) + val, _ := s.network.App.GetStakingKeeper().GetValidator(ctx, valAddr) coins := sdk.NewCoins(sdk.NewCoin(constants.ExampleAttoDenom, math.NewInt(1e18))) - s.Require().NoError(s.network.App.DistrKeeper.AllocateTokensToValidator(ctx, val, sdk.NewDecCoinsFromCoins(coins...))) + s.Require().NoError(s.network.App.GetDistrKeeper().AllocateTokensToValidator(ctx, val, sdk.NewDecCoinsFromCoins(coins...))) input, err := s.precompile.Pack( distribution.SetWithdrawAddressMethod, @@ -111,9 +111,9 @@ func (s *PrecompileTestSuite) TestRun() { commAmt := math.LegacyNewDecWithPrec(1000000000000000000, 1) valCommission := sdk.DecCoins{sdk.NewDecCoinFromDec(constants.ExampleAttoDenom, commAmt)} // set outstanding rewards - s.Require().NoError(s.network.App.DistrKeeper.SetValidatorOutstandingRewards(ctx, valAddr, types.ValidatorOutstandingRewards{Rewards: valCommission})) + s.Require().NoError(s.network.App.GetDistrKeeper().SetValidatorOutstandingRewards(ctx, valAddr, types.ValidatorOutstandingRewards{Rewards: valCommission})) // set commission - s.Require().NoError(s.network.App.DistrKeeper.SetValidatorAccumulatedCommission(ctx, valAddr, types.ValidatorAccumulatedCommission{Commission: valCommission})) + s.Require().NoError(s.network.App.GetDistrKeeper().SetValidatorAccumulatedCommission(ctx, valAddr, types.ValidatorAccumulatedCommission{Commission: valCommission})) // set distribution module account balance which pays out the rewards coins := sdk.NewCoins(sdk.NewCoin(s.bondDenom, commAmt.RoundInt())) @@ -236,7 +236,7 @@ func (s *PrecompileTestSuite) TestRun() { // setup basic test suite s.SetupTest() ctx = s.network.GetContext() - baseFee := s.network.App.EVMKeeper.GetBaseFee(ctx) + baseFee := s.network.App.GetEVMKeeper().GetBaseFee(ctx) // malleate testcase caller, input := tc.malleate() @@ -265,7 +265,7 @@ func (s *PrecompileTestSuite) TestRun() { // Instantiate config proposerAddress := ctx.BlockHeader().ProposerAddress - cfg, err := s.network.App.EVMKeeper.EVMConfig(ctx, proposerAddress) + cfg, err := s.network.App.GetEVMKeeper().EVMConfig(ctx, proposerAddress) s.Require().NoError(err, "failed to instantiate EVM config") ethChainID := s.network.GetEIP155ChainID() @@ -274,11 +274,11 @@ func (s *PrecompileTestSuite) TestRun() { s.Require().NoError(err, "failed to instantiate Ethereum message") // Instantiate EVM - evm := s.network.App.EVMKeeper.NewEVM( + evm := s.network.App.GetEVMKeeper().NewEVM( ctx, *msg, cfg, nil, s.network.GetStateDB(), ) - precompiles, found, err := s.network.App.EVMKeeper.GetPrecompileInstance(ctx, contractAddr) + precompiles, found, err := s.network.App.GetEVMKeeper().GetPrecompileInstance(ctx, contractAddr) s.Require().NoError(err, "failed to instantiate precompile") s.Require().True(found, "not found precompile") evm.WithPrecompiles(precompiles.Map) @@ -314,9 +314,9 @@ func (s *PrecompileTestSuite) TestCMS() { malleate: func() (common.Address, []byte) { valAddr, err := sdk.ValAddressFromBech32(s.network.GetValidators()[0].OperatorAddress) s.Require().NoError(err) - val, _ := s.network.App.StakingKeeper.GetValidator(ctx, valAddr) + val, _ := s.network.App.GetStakingKeeper().GetValidator(ctx, valAddr) coins := sdk.NewCoins(sdk.NewCoin(constants.ExampleAttoDenom, math.NewInt(1e18))) - s.Require().NoError(s.network.App.DistrKeeper.AllocateTokensToValidator(ctx, val, sdk.NewDecCoinsFromCoins(coins...))) + s.Require().NoError(s.network.App.GetDistrKeeper().AllocateTokensToValidator(ctx, val, sdk.NewDecCoinsFromCoins(coins...))) input, err := s.precompile.Pack( distribution.SetWithdrawAddressMethod, @@ -339,9 +339,9 @@ func (s *PrecompileTestSuite) TestCMS() { commAmt := math.LegacyNewDecWithPrec(1000000000000000000, 1) valCommission := sdk.DecCoins{sdk.NewDecCoinFromDec(constants.ExampleAttoDenom, commAmt)} // set outstanding rewards - s.Require().NoError(s.network.App.DistrKeeper.SetValidatorOutstandingRewards(ctx, valAddr, types.ValidatorOutstandingRewards{Rewards: valCommission})) + s.Require().NoError(s.network.App.GetDistrKeeper().SetValidatorOutstandingRewards(ctx, valAddr, types.ValidatorOutstandingRewards{Rewards: valCommission})) // set commission - s.Require().NoError(s.network.App.DistrKeeper.SetValidatorAccumulatedCommission(ctx, valAddr, types.ValidatorAccumulatedCommission{Commission: valCommission})) + s.Require().NoError(s.network.App.GetDistrKeeper().SetValidatorAccumulatedCommission(ctx, valAddr, types.ValidatorAccumulatedCommission{Commission: valCommission})) // set distribution module account balance which pays out the rewards coins := sdk.NewCoins(sdk.NewCoin(s.bondDenom, commAmt.RoundInt())) @@ -460,12 +460,12 @@ func (s *PrecompileTestSuite) TestCMS() { s.SetupTest() ctx = s.network.GetContext() cms := &testutil.TrackingMultiStore{ - Store: s.network.App.BaseApp.CommitMultiStore().CacheMultiStore(), + Store: s.network.App.GetBaseApp().CommitMultiStore().CacheMultiStore(), Writes: 0, HistoricalStores: nil, } ctx = ctx.WithMultiStore(cms) - baseFee := s.network.App.EVMKeeper.GetBaseFee(ctx) + baseFee := s.network.App.GetEVMKeeper().GetBaseFee(ctx) // malleate testcase caller, input := tc.malleate() @@ -491,7 +491,7 @@ func (s *PrecompileTestSuite) TestCMS() { signedMsg, err := s.factory.SignMsgEthereumTx(s.keyring.GetPrivKey(0), msgEthereumTx) s.Require().NoError(err, "failed to sign Ethereum message") - resp, err := s.network.App.EVMKeeper.EthereumTx(ctx, &signedMsg) + resp, err := s.network.App.GetEVMKeeper().EthereumTx(ctx, &signedMsg) // Check results if tc.expPass { diff --git a/precompiles/distribution/events_test.go b/tests/integration/precompiles/distribution/test_event.go similarity index 98% rename from precompiles/distribution/events_test.go rename to tests/integration/precompiles/distribution/test_event.go index a9c5b012e..d612d870d 100644 --- a/precompiles/distribution/events_test.go +++ b/tests/integration/precompiles/distribution/test_event.go @@ -1,4 +1,4 @@ -package distribution_test +package distribution import ( "math/big" @@ -190,9 +190,9 @@ func (s *PrecompileTestSuite) TestWithdrawValidatorCommissionEvent() { s.Require().NoError(err) valCommission := sdk.DecCoins{sdk.NewDecCoinFromDec(constants.ExampleAttoDenom, math.LegacyNewDecFromInt(amt))} // set outstanding rewards - s.Require().NoError(s.network.App.DistrKeeper.SetValidatorOutstandingRewards(ctx, valAddr, types.ValidatorOutstandingRewards{Rewards: valCommission})) + s.Require().NoError(s.network.App.GetDistrKeeper().SetValidatorOutstandingRewards(ctx, valAddr, types.ValidatorOutstandingRewards{Rewards: valCommission})) // set commission - s.Require().NoError(s.network.App.DistrKeeper.SetValidatorAccumulatedCommission(ctx, valAddr, types.ValidatorAccumulatedCommission{Commission: valCommission})) + s.Require().NoError(s.network.App.GetDistrKeeper().SetValidatorAccumulatedCommission(ctx, valAddr, types.ValidatorAccumulatedCommission{Commission: valCommission})) // set funds to distr mod to pay for commission coins := sdk.NewCoins(sdk.NewCoin(constants.ExampleAttoDenom, amt)) err = s.mintCoinsForDistrMod(ctx, coins) diff --git a/tests/integration/precompiles/distribution/test_integration.go b/tests/integration/precompiles/distribution/test_integration.go new file mode 100644 index 000000000..a19e60035 --- /dev/null +++ b/tests/integration/precompiles/distribution/test_integration.go @@ -0,0 +1,3205 @@ +package distribution + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" + + //nolint:revive // dot imports are fine for Ginkgo + . "github.com/onsi/ginkgo/v2" + //nolint:revive // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" + + cmn "github.com/cosmos/evm/precompiles/common" + "github.com/cosmos/evm/precompiles/distribution" + "github.com/cosmos/evm/precompiles/staking" + "github.com/cosmos/evm/precompiles/testutil" + "github.com/cosmos/evm/precompiles/testutil/contracts" + testconstants "github.com/cosmos/evm/testutil/constants" + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/integration/evm/utils" + testutiltx "github.com/cosmos/evm/testutil/tx" + testutiltypes "github.com/cosmos/evm/testutil/types" + evmtypes "github.com/cosmos/evm/x/vm/types" + + "cosmossdk.io/math" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" +) + +// General variables used for integration tests +var ( + // differentAddr is an address generated for testing purposes that e.g. raises the different requester error (msg.sender != requester) + differentAddr, diffKey = testutiltx.NewAddrKey() + // gasPrice is the gas price used for the transactions + gasPrice = math.NewInt(1e9) + // callArgs are the default arguments for calling the smart contract + // + // NOTE: this has to be populated in a BeforeEach block because the contractAddr would otherwise be a nil address. + callArgs testutiltypes.CallArgs + + // defaultLogCheck instantiates a log check arguments struct with the precompile ABI events populated. + defaultLogCheck testutil.LogCheckArgs + // passCheck defines the arguments to check if the precompile returns no error + passCheck testutil.LogCheckArgs + // outOfGasCheck defines the arguments to check if the precompile returns out of gas error + outOfGasCheck testutil.LogCheckArgs + // txArgs are the EVM transaction arguments to use in the transactions + txArgs evmtypes.EvmTxArgs + // minExpRewardOrCommission is the minimun coins expected for validator's rewards or commission + // required for the tests + minExpRewardOrCommission = sdk.NewDecCoins(sdk.NewDecCoin(testconstants.ExampleAttoDenom, testRewardsAmt)) +) + +func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmApp, options ...network.ConfigOption) { + var _ = Describe("Calling distribution precompile from EOA", func() { + s := NewPrecompileTestSuite(create, options...) + + BeforeEach(func() { + s.SetupTest() + + // set the default call arguments + callArgs = testutiltypes.CallArgs{ + ContractABI: s.precompile.ABI, + } + + defaultLogCheck = testutil.LogCheckArgs{ + ABIEvents: s.precompile.Events, + } + passCheck = defaultLogCheck.WithExpPass(true) + outOfGasCheck = defaultLogCheck.WithErrContains(vm.ErrOutOfGas.Error()) + + // reset tx args each test to avoid keeping custom + // values of previous tests (e.g. gasLimit) + precompileAddr := s.precompile.Address() + txArgs = evmtypes.EvmTxArgs{ + To: &precompileAddr, + } + }) + + // ===================================== + // TRANSACTIONS + // ===================================== + Describe("Execute SetWithdrawAddress transaction", func() { + const method = distribution.SetWithdrawAddressMethod + + BeforeEach(func() { + // set the default call arguments + callArgs.MethodName = method + }) + + It("should return error if the provided gasLimit is too low", func() { + txArgs.GasLimit = 30000 + + callArgs.Args = []interface{}{ + s.keyring.GetAddr(0), + differentAddr.String(), + } + _, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + outOfGasCheck, + ) + Expect(err).To(BeNil(), "error while calling the precompile") + Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock") + + // withdraw address should remain unchanged + delAddr := s.keyring.GetAccAddr(0).String() + res, err := s.grpcHandler.GetDelegatorWithdrawAddr(delAddr) + Expect(err).To(BeNil(), "error while calling the precompile") + Expect(res.WithdrawAddress).To(Equal(delAddr), "expected withdraw address to remain unchanged") + }) + + It("should return error if the msg.sender is different than the delegator", func() { + callArgs.Args = []interface{}{ + differentAddr, + s.keyring.GetAddr(0).String(), + } + + withdrawAddrSetCheck := defaultLogCheck.WithErrContains(cmn.ErrRequesterIsNotMsgSender, s.keyring.GetAddr(0).String(), differentAddr.String()) + + _, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + withdrawAddrSetCheck, + ) + Expect(err).To(BeNil(), "error while calling the precompile") + }) + + It("should set withdraw address", func() { + // initially, withdraw address should be same as address + res, err := s.grpcHandler.GetDelegatorWithdrawAddr(s.keyring.GetAccAddr(0).String()) + Expect(err).To(BeNil(), "error while querying withdraw address") + Expect(res.WithdrawAddress).To(Equal(s.keyring.GetAccAddr(0).String())) + + callArgs.Args = []interface{}{ + s.keyring.GetAddr(0), + differentAddr.String(), + } + + withdrawAddrSetCheck := passCheck. + WithExpEvents(distribution.EventTypeSetWithdrawAddress) + + _, _, err = s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + withdrawAddrSetCheck, + ) + Expect(err).To(BeNil(), "error while calling the precompile") + + // persist state changes + Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock") + + // withdraw should be updated + res, err = s.grpcHandler.GetDelegatorWithdrawAddr(s.keyring.GetAccAddr(0).String()) + Expect(err).To(BeNil(), "error while querying withdraw address") + Expect(res.WithdrawAddress).To(Equal(sdk.AccAddress(differentAddr.Bytes()).String()), "expected different withdraw address") + }) + }) + + Describe("Execute WithdrawDelegatorReward transaction", func() { + var accruedRewards sdk.DecCoins + + BeforeEach(func() { + var err error + // set the default call arguments + callArgs.MethodName = distribution.WithdrawDelegatorRewardMethod + + accruedRewards, err = utils.WaitToAccrueRewards(s.network, s.grpcHandler, s.keyring.GetAccAddr(0).String(), minExpRewardOrCommission) + Expect(err).To(BeNil()) + }) + + It("should return error if the msg.sender is different than the delegator", func() { + callArgs.Args = []interface{}{ + differentAddr, + s.network.GetValidators()[0].OperatorAddress, + } + + withdrawalCheck := defaultLogCheck.WithErrContains( + cmn.ErrRequesterIsNotMsgSender, + s.keyring.GetAddr(0).String(), + differentAddr.String(), + ) + + _, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + withdrawalCheck, + ) + Expect(err).To(BeNil(), "error while calling the precompile") + }) + + It("should withdraw delegation rewards", func() { + // get initial balance + queryRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil(), "error while calling GetBalance") + initialBalance := queryRes.Balance + + txArgs.GasPrice = gasPrice.BigInt() + txArgs.GasLimit = 100_000 + + callArgs.Args = []interface{}{ + s.keyring.GetAddr(0), + s.network.GetValidators()[0].OperatorAddress, + } + + withdrawalCheck := passCheck. + WithExpEvents(distribution.EventTypeWithdrawDelegatorReward) + + res, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + withdrawalCheck, + ) + Expect(err).To(BeNil(), "error while calling the precompile") + Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock") + + var rewards []cmn.Coin + err = s.precompile.UnpackIntoInterface(&rewards, distribution.WithdrawDelegatorRewardMethod, ethRes.Ret) + Expect(err).To(BeNil()) + Expect(len(rewards)).To(Equal(1)) + + // The accrued rewards are based on 3 equal delegations to the existing 3 validators + // The query is from only 1 validator, thus, the expected reward + // for this delegation is totalAccruedRewards / validatorsCount (3) + valCount := len(s.network.GetValidators()) + accruedRewardsAmt := accruedRewards.AmountOf(s.bondDenom) + expRewardPerValidator := accruedRewardsAmt.Quo(math.LegacyNewDec(int64(valCount))) + + Expect(rewards[0].Denom).To(Equal(s.bondDenom)) + Expect(rewards[0].Amount).To(Equal(expRewardPerValidator.TruncateInt().BigInt())) + + // check that the rewards were added to the balance + queryRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil(), "error while calling GetBalance") + fees := gasPrice.Mul(math.NewInt(res.GasUsed)) + expFinal := initialBalance.Amount.Add(expRewardPerValidator.TruncateInt()).Sub(fees) + Expect(queryRes.Balance.Amount).To(Equal(expFinal), "expected final balance to be equal to initial balance + rewards - fees") + }) + + It("should withdraw rewards successfully to the new withdrawer address", func() { + balRes, err := s.grpcHandler.GetBalanceFromBank(differentAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + withdrawerInitialBalance := balRes.Balance + // Set new withdrawer address + err = s.factory.SetWithdrawAddress(s.keyring.GetPrivKey(0), differentAddr.Bytes()) + Expect(err).To(BeNil()) + // persist state change + Expect(s.network.NextBlock()).To(BeNil()) + + // get initial balance + queryRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil(), "error while calling GetBalance") + initialBalance := queryRes.Balance + + // get rewards + rwRes, err := s.grpcHandler.GetDelegationRewards(s.keyring.GetAccAddr(0).String(), s.network.GetValidators()[0].OperatorAddress) + Expect(err).To(BeNil()) + expRewardsAmt := rwRes.Rewards.AmountOf(s.bondDenom).TruncateInt() + + txArgs.GasPrice = gasPrice.BigInt() + callArgs.Args = []interface{}{ + s.keyring.GetAddr(0), + s.network.GetValidators()[0].OperatorAddress, + } + + withdrawalCheck := passCheck. + WithExpEvents(distribution.EventTypeWithdrawDelegatorReward) + + txArgs.GasLimit = 300_000 + res, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + withdrawalCheck, + ) + Expect(err).To(BeNil(), "error while calling the precompile") + Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock") + + var rewards []cmn.Coin + err = s.precompile.UnpackIntoInterface(&rewards, distribution.WithdrawDelegatorRewardMethod, ethRes.Ret) + Expect(err).To(BeNil()) + Expect(len(rewards)).To(Equal(1)) + + Expect(rewards[0].Denom).To(Equal(s.bondDenom)) + Expect(rewards[0].Amount).To(Equal(expRewardsAmt.BigInt())) + + // check that the delegator final balance is initialBalance - fee + queryRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil(), "error while calling GetBalance") + fees := gasPrice.Mul(math.NewInt(res.GasUsed)) + expDelgatorFinal := initialBalance.Amount.Sub(fees) + Expect(queryRes.Balance.Amount).To(Equal(expDelgatorFinal), "expected delegator final balance to be equal to initial balance - fees") + + // check that the rewards were added to the withdrawer balance + queryRes, err = s.grpcHandler.GetBalanceFromBank(differentAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil(), "error while calling GetBalance") + expWithdrawerFinal := withdrawerInitialBalance.Amount.Add(expRewardsAmt) + + Expect(queryRes.Balance.Amount).To(Equal(expWithdrawerFinal), "expected withdrawer final balance to be equal to initial balance + rewards") + }) + + It("should withdraw delegation rewards to a smart contract", func() { + // deploy a smart contract to use as withdrawer + distributionCallerContract, err := contracts.LoadDistributionCallerContract() + Expect(err).To(BeNil(), "error while loading the smart contract: %v", err) + + contractAddr, err := s.factory.DeployContract( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values + testutiltypes.ContractDeploymentData{ + Contract: distributionCallerContract, + }, + ) + Expect(err).To(BeNil(), "error while deploying the smart contract: %v", err) + // persist state change + Expect(s.network.NextBlock()).To(BeNil()) + + balRes, err := s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + initialWithdrawerBalance := balRes.Balance + Expect(initialWithdrawerBalance.Amount).To(Equal(math.ZeroInt())) + + // set contract address as withdrawer address + err = s.factory.SetWithdrawAddress(s.keyring.GetPrivKey(0), contractAddr.Bytes()) + Expect(err).To(BeNil()) + // persist state change + Expect(s.network.NextBlock()).To(BeNil()) + + // get tx sender initial balance + balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil(), "error while calling GetBalance") + initialBalance := balRes.Balance + + // get rewards + rwRes, err := s.grpcHandler.GetDelegationRewards(s.keyring.GetAccAddr(0).String(), s.network.GetValidators()[0].OperatorAddress) + Expect(err).To(BeNil()) + expRewardsAmt := rwRes.Rewards.AmountOf(s.bondDenom).TruncateInt() + + txArgs.GasPrice = gasPrice.BigInt() + callArgs.Args = []interface{}{ + s.keyring.GetAddr(0), + s.network.GetValidators()[0].OperatorAddress, + } + + withdrawalCheck := passCheck. + WithExpEvents(distribution.EventTypeWithdrawDelegatorReward) + + txArgs.GasLimit = 300_000 + res, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + withdrawalCheck, + ) + Expect(err).To(BeNil(), "error while calling the precompile") + Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock") + + var rewards []cmn.Coin + err = s.precompile.UnpackIntoInterface(&rewards, distribution.WithdrawDelegatorRewardMethod, ethRes.Ret) + Expect(err).To(BeNil()) + Expect(len(rewards)).To(Equal(1)) + Expect(rewards[0].Denom).To(Equal(s.bondDenom)) + Expect(rewards[0].Amount).To(Equal(expRewardsAmt.BigInt())) + + // check tx sender balance is reduced by fees paid + balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + finalBalance := balRes.Balance + fees := gasPrice.MulRaw(res.GasUsed) + expFinal := initialBalance.Amount.Sub(fees) + Expect(finalBalance.Amount).To(Equal(expFinal), "expected final balance to be equal to initial balance - fees") + + // check that the rewards were added to the withdrawer balance + balRes, err = s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + finalWithdrawerBalance := balRes.Balance + Expect(finalWithdrawerBalance.Amount).To(Equal(expRewardsAmt)) + }) + }) + + Describe("Validator Commission: Execute WithdrawValidatorCommission tx", func() { + // expCommAmt is the expected commission amount + expCommAmt := math.NewInt(1) + + BeforeEach(func() { + // set the default call arguments + callArgs.MethodName = distribution.WithdrawValidatorCommissionMethod + valAddr := sdk.ValAddress(s.validatorsKeys[0].AccAddr) + + _, err := utils.WaitToAccrueCommission( + s.network, s.grpcHandler, + valAddr.String(), + sdk.NewDecCoins(sdk.NewDecCoin(s.bondDenom, expCommAmt)), + ) + Expect(err).To(BeNil()) + + // Send some funds to the validator to pay for fees + err = utils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), s.validatorsKeys[0].AccAddr, math.NewInt(1e17)) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + }) + + It("should return error if the provided gasLimit is too low", func() { + txArgs.GasLimit = 50000 + callArgs.Args = []interface{}{ + s.network.GetValidators()[0].OperatorAddress, + } + + _, _, err := s.factory.CallContractAndCheckLogs( + s.validatorsKeys[0].Priv, + txArgs, + callArgs, + outOfGasCheck, + ) + Expect(err).To(BeNil(), "error while calling the precompile") + }) + + It("should return error if the msg.sender is different than the validator", func() { + callArgs.Args = []interface{}{ + s.network.GetValidators()[0].OperatorAddress, + } + + validatorHexAddr := common.BytesToAddress(s.validatorsKeys[0].AccAddr) + + withdrawalCheck := defaultLogCheck.WithErrContains(cmn.ErrRequesterIsNotMsgSender, s.keyring.GetAddr(0).String(), validatorHexAddr.String()) + + _, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + withdrawalCheck, + ) + Expect(err).To(BeNil(), "error while calling the precompile") + }) + + It("should withdraw validator commission", func() { + // initial balance should be the initial amount minus the staked amount used to create the validator + queryRes, err := s.grpcHandler.GetBalanceFromBank(s.validatorsKeys[0].AccAddr, s.bondDenom) + Expect(err).To(BeNil(), "error while calling GetBalance") + + initialBalance := queryRes.Balance + + // get the accrued commission amount + commRes, err := s.grpcHandler.GetValidatorCommission(s.network.GetValidators()[0].OperatorAddress) + Expect(err).To(BeNil()) + expCommAmt := commRes.Commission.Commission.AmountOf(s.bondDenom).TruncateInt() + + callArgs.Args = []interface{}{s.network.GetValidators()[0].OperatorAddress} + txArgs.GasPrice = gasPrice.BigInt() + + withdrawalCheck := passCheck. + WithExpEvents(distribution.EventTypeWithdrawValidatorCommission) + + txArgs.GasLimit = 300_000 + res, ethRes, err := s.factory.CallContractAndCheckLogs( + s.validatorsKeys[0].Priv, + txArgs, + callArgs, + withdrawalCheck, + ) + Expect(err).To(BeNil(), "error while calling the precompile") + + var comm []cmn.Coin + err = s.precompile.UnpackIntoInterface(&comm, distribution.WithdrawValidatorCommissionMethod, ethRes.Ret) + Expect(err).To(BeNil()) + Expect(len(comm)).To(Equal(1)) + Expect(comm[0].Denom).To(Equal(s.bondDenom)) + Expect(comm[0].Amount).To(Equal(expCommAmt.BigInt())) + + Expect(s.network.NextBlock()).To(BeNil()) + + queryRes, err = s.grpcHandler.GetBalanceFromBank(s.validatorsKeys[0].AccAddr, s.bondDenom) + Expect(err).To(BeNil(), "error while calling GetBalance") + finalBalance := queryRes.Balance + + fees := gasPrice.Mul(math.NewInt(res.GasUsed)) + expFinal := initialBalance.Amount.Add(expCommAmt).Sub(fees) + + Expect(finalBalance.Amount).To(Equal(expFinal), "expected final balance to be equal to the final balance after withdrawing commission") + }) + + It("should withdraw validator commission to a smart contract", func() { + // deploy a smart contract to use as withdrawer + distributionCallerContract, err := contracts.LoadDistributionCallerContract() + Expect(err).To(BeNil(), "error while loading the smart contract: %v", err) + + contractAddr, err := s.factory.DeployContract( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values + testutiltypes.ContractDeploymentData{ + Contract: distributionCallerContract, + }, + ) + Expect(err).To(BeNil(), "error while deploying the smart contract: %v", err) + // persist state change + Expect(s.network.NextBlock()).To(BeNil()) + + balRes, err := s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + initialWithdrawerBalance := balRes.Balance + Expect(initialWithdrawerBalance.Amount).To(Equal(math.ZeroInt())) + + // set contract address as withdrawer address + err = s.factory.SetWithdrawAddress(s.validatorsKeys[0].Priv, contractAddr.Bytes()) + Expect(err).To(BeNil()) + // persist state change + Expect(s.network.NextBlock()).To(BeNil()) + + // get validator initial balance + balRes, err = s.grpcHandler.GetBalanceFromBank(s.validatorsKeys[0].AccAddr, s.bondDenom) + Expect(err).To(BeNil(), "error while calling GetBalance") + initialBalance := balRes.Balance + + // get the accrued commission amount + commRes, err := s.grpcHandler.GetValidatorCommission(s.network.GetValidators()[0].OperatorAddress) + Expect(err).To(BeNil()) + expCommAmt := commRes.Commission.Commission.AmountOf(s.bondDenom).TruncateInt() + + callArgs.Args = []interface{}{s.network.GetValidators()[0].OperatorAddress} + txArgs.GasPrice = gasPrice.BigInt() + + withdrawalCheck := passCheck. + WithExpEvents(distribution.EventTypeWithdrawValidatorCommission) + + txArgs.GasLimit = 300_000 + res, ethRes, err := s.factory.CallContractAndCheckLogs( + s.validatorsKeys[0].Priv, + txArgs, + callArgs, + withdrawalCheck, + ) + Expect(err).To(BeNil(), "error while calling the precompile") + // persist state change + Expect(s.network.NextBlock()).To(BeNil()) + + var comm []cmn.Coin + err = s.precompile.UnpackIntoInterface(&comm, distribution.WithdrawValidatorCommissionMethod, ethRes.Ret) + Expect(err).To(BeNil()) + Expect(len(comm)).To(Equal(1)) + Expect(comm[0].Denom).To(Equal(s.bondDenom)) + Expect(comm[0].Amount).To(Equal(expCommAmt.BigInt())) + + balRes, err = s.grpcHandler.GetBalanceFromBank(s.validatorsKeys[0].AccAddr, s.bondDenom) + Expect(err).To(BeNil(), "error while calling GetBalance") + finalBalance := balRes.Balance + + fees := gasPrice.MulRaw(res.GasUsed) + expFinal := initialBalance.Amount.Sub(fees) + Expect(finalBalance.Amount).To(Equal(expFinal), "expected final balance to be equal to the final balance after withdrawing commission") + + // check that the commission was added to the withdrawer balance + balRes, err = s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + finalWithdrawerBalance := balRes.Balance + Expect(finalWithdrawerBalance.Amount).To(Equal(expCommAmt)) + }) + }) + + Describe("Execute ClaimRewards transaction", func() { + // defaultWithdrawRewardsArgs are the default arguments to withdraw rewards + // + // NOTE: this has to be populated in the BeforeEach block because the private key otherwise is not yet initialized. + var accruedRewards sdk.DecCoins + + BeforeEach(func() { + var err error + // set the default call arguments + callArgs.MethodName = distribution.ClaimRewardsMethod + accruedRewards, err = utils.WaitToAccrueRewards( + s.network, + s.grpcHandler, + s.keyring.GetAccAddr(0).String(), + minExpRewardOrCommission) + Expect(err).To(BeNil(), "error waiting to accrue rewards") + }) + + It("should return err if the msg.sender is different than the delegator", func() { + callArgs.Args = []interface{}{ + differentAddr, uint32(1), + } + + claimRewardsCheck := defaultLogCheck.WithErrContains(cmn.ErrRequesterIsNotMsgSender, s.keyring.GetAddr(0).String(), differentAddr.String()) + + _, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + claimRewardsCheck, + ) + Expect(err).To(BeNil(), "error while calling the precompile") + }) + + It("should claim all rewards from all validators", func() { + queryRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil(), "error while calling GetBalance") + initialBalance := queryRes.Balance + + valCount := len(s.network.GetValidators()) + callArgs.Args = []interface{}{ + s.keyring.GetAddr(0), uint32(valCount), + } + txArgs.GasLimit = 250_000 + + // get base fee to use in tx to then calculate fee paid + bfQuery, err := s.grpcHandler.GetEvmBaseFee() + Expect(err).To(BeNil(), "error while calling BaseFee") + gasPrice := bfQuery.BaseFee.BigInt() + txArgs.GasPrice = gasPrice + + claimRewardsCheck := passCheck.WithExpEvents(distribution.EventTypeClaimRewards) + + txRes, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + claimRewardsCheck, + ) + Expect(err).To(BeNil(), "error while calling the precompile") + + // persist state change + Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock") + + // check that the rewards were added to the balance + queryRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil(), "error while calling GetBalance") + + // get the fee paid and calculate the expFinalBalance + fee := gasPrice.Mul(math.NewInt(txRes.GasUsed).BigInt(), gasPrice) + accruedRewardsAmt := accruedRewards.AmountOf(s.bondDenom).TruncateInt() + // expected balance is initial + rewards - fee + expBalanceAmt := initialBalance.Amount.Add(accruedRewardsAmt).Sub(math.NewIntFromBigInt(fee)) + + finalBalance := queryRes.Balance + Expect(finalBalance.Amount).To(Equal(expBalanceAmt), "expected final balance to be equal to initial balance + rewards - fees") + }) + }) + + Describe("Execute DepositValidatorRewardsPool transaction", func() { + const method = distribution.DepositValidatorRewardsPoolMethod + + BeforeEach(func() { + txArgs.GasLimit = 300_000 + txArgs.GasPrice = gasPrice.BigInt() + callArgs.MethodName = method + }) + + It("should revert if the msg.sender is different from the depositor", func() { + callArgs.Args = []interface{}{ + differentAddr, // depositor + s.network.GetValidators()[0].OperatorAddress, + []cmn.Coin{ + {Denom: s.bondDenom, Amount: big.NewInt(1_000_000)}, + }, + } + + failureCheck := defaultLogCheck.WithErrContains( + cmn.ErrRequesterIsNotMsgSender, + s.keyring.GetAddr(0).String(), + differentAddr, + ) + + _, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), // tx from Addr0 + txArgs, + callArgs, + failureCheck, + ) + Expect(err).To(BeNil()) + }) + + It("should revert if the depositor has insufficient funds", func() { + balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + excessAmount := balRes.Balance.Amount.Add(math.NewInt(1)) + + callArgs.Args = []interface{}{ + s.keyring.GetAddr(0), + s.network.GetValidators()[0].OperatorAddress, + []cmn.Coin{{Denom: s.bondDenom, Amount: excessAmount.BigInt()}}, + } + + failureCheck := defaultLogCheck.WithErrContains("insufficient funds") + + _, _, err = s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + failureCheck, + ) + Expect(err).To(BeNil()) + }) + + It("should deposit rewards to the validator rewards pool", func() { + // check initial balance + balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + initialBalance := balRes.Balance + + callArgs.Args = []interface{}{ + s.keyring.GetAddr(0), // depositor + s.network.GetValidators()[0].OperatorAddress, + []cmn.Coin{ + {Denom: s.bondDenom, Amount: big.NewInt(1_000_000)}, + }, + } + + passCheckWithEvent := passCheck.WithExpEvents(distribution.EventTypeDepositValidatorRewardsPool) + + _, txRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), // tx from Addr0 + txArgs, + callArgs, + passCheckWithEvent, + ) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + // check that the balance is reduced by the amount deposited + expBalance := initialBalance.Amount.Sub(math.NewInt(1_000_000)) + fees := math.NewIntFromUint64(txRes.GasUsed).Mul(math.NewIntFromBigInt(txArgs.GasPrice)) + expBalance = expBalance.Sub(fees) + + balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + Expect(balRes.Balance.Amount).To(Equal(expBalance), "expected final balance to be equal to initial balance - deposit amount") + }) + + It("should deposit rewards to the validator rewards pool with multiple coins", func() { + // get initial balances + balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + initialBalance := balRes.Balance + + balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.otherDenoms[0]) + Expect(err).To(BeNil()) + initialBalance1 := balRes.Balance + + balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.otherDenoms[1]) + Expect(err).To(BeNil()) + initialBalance2 := balRes.Balance + + callArgs.Args = []interface{}{ + s.keyring.GetAddr(0), // depositor + s.network.GetValidators()[0].OperatorAddress, + []cmn.Coin{ + {Denom: s.bondDenom, Amount: big.NewInt(1_000_000)}, + {Denom: s.otherDenoms[0], Amount: big.NewInt(1_000_001)}, + {Denom: s.otherDenoms[1], Amount: big.NewInt(1_000_002)}, + }, + } + + passCheckWithEvent := passCheck.WithExpEvents( + distribution.EventTypeDepositValidatorRewardsPool, + distribution.EventTypeDepositValidatorRewardsPool, + distribution.EventTypeDepositValidatorRewardsPool, + ) + + _, txRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), // tx from Addr0 + txArgs, + callArgs, + passCheckWithEvent, + ) + Expect(err).To(BeNil()) + Expect(txRes).NotTo(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + fees := math.NewIntFromUint64(txRes.GasUsed).Mul(math.NewIntFromBigInt(txArgs.GasPrice)) + + // check that the balance is reduced by the amount deposited + balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + expBalance := initialBalance.Amount.Sub(math.NewInt(1_000_000)).Sub(fees) + Expect(balRes.Balance.Amount).To(Equal(expBalance), "expected final balance to be equal to initial balance - deposit amount") + + balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.otherDenoms[0]) + Expect(err).To(BeNil()) + expBalance1 := initialBalance1.Amount.Sub(math.NewInt(1_000_001)) + Expect(balRes.Balance.Amount).To(Equal(expBalance1), "expected final balance to be equal to initial balance - deposit amount") + + balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.otherDenoms[1]) + Expect(err).To(BeNil()) + expBalance2 := initialBalance2.Amount.Sub(math.NewInt(1_000_002)) + Expect(balRes.Balance.Amount).To(Equal(expBalance2), "expected final balance to be equal to initial balance - deposit amount") + }) + }) + + Describe("Execute FundCommunityPool transaction", func() { + const method = distribution.FundCommunityPoolMethod + + BeforeEach(func() { + callArgs.MethodName = method + }) + + It("should fail if the depositor has insufficient balance", func() { + // Here, we attempt to deposit an amount that the EOA does not have. + + // 1) Query the current balance + balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + initialBalance := balRes.Balance + + // 2) Attempt to deposit more than current balance + deposit := initialBalance.Amount.Add(math.NewInt(9999999999)) + + callArgs.Args = []interface{}{ + s.keyring.GetAddr(0), + []cmn.Coin{ + {Denom: s.bondDenom, Amount: deposit.BigInt()}, + }, + } + + // We expect the tx to fail ("execution reverted") because of insufficient funds + insufficientFundsCheck := defaultLogCheck.WithErrContains("insufficient funds") + + _, _, err = s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + insufficientFundsCheck, + ) + Expect(err).To(BeNil()) + }) + + It("should fund the community pool successfully from EOA", func() { + // 1) Fund the EOA to ensure it has enough tokens + err := utils.FundAccountWithBaseDenom( + s.factory, s.network, + s.keyring.GetKey(0), + s.keyring.GetAccAddr(0), + math.NewInt(1_000_000), + ) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + initialEOABal := balRes.Balance + + // 2) Prepare and execute the FundCommunityPool call + fundAmt := math.NewInt(10) + callArgs.Args = []interface{}{ + s.keyring.GetAddr(0), + []cmn.Coin{ + {Denom: s.bondDenom, Amount: fundAmt.BigInt()}, + }, + } + + txArgs.GasPrice = gasPrice.BigInt() + txArgs.GasLimit = 500_000 + + logCheckArgs := passCheck.WithExpEvents(distribution.EventTypeFundCommunityPool) + + res, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil()) + + // Persist state changes + Expect(s.network.NextBlock()).To(BeNil()) + + // 3) Ensure the EOA's final balance is decreased by (fundAmt + fees) + balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + finalEOABal := balRes.Balance + + fees := gasPrice.Mul(math.NewInt(res.GasUsed)) + // The final balance must be: initialBalance - fundAmt - fees + // We only check if it's consistent ( >= ), because we funded the EOA in step 1 + expLowerBound := fundAmt.Add(fees) + + diff := initialEOABal.Amount.Sub(finalEOABal.Amount) + Expect(diff.GTE(expLowerBound)).To(BeTrue(), + "final EOA balance must be decreased at least by funded amt + fees") + }) + + It("should fund multiple coins to the community pool successfully from EOA", func() { + // 1) Fund the EOA to ensure it has enough tokens + err := utils.FundAccountWithBaseDenom( + s.factory, s.network, + s.keyring.GetKey(0), + s.keyring.GetAccAddr(0), + math.NewInt(1_000_000), + ) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + balRes, err := s.grpcHandler.GetAllBalances(s.keyring.GetAccAddr(0)) + Expect(err).To(BeNil()) + initialEOABals := balRes.Balances + + // 2) Prepare and execute the FundCommunityPool call + fundAmt := math.NewInt(10) + sendAmt := []cmn.Coin{ + {Denom: s.bondDenom, Amount: fundAmt.BigInt()}, + {Denom: testconstants.OtherCoinDenoms[0], Amount: fundAmt.BigInt()}, + {Denom: testconstants.OtherCoinDenoms[1], Amount: fundAmt.BigInt()}, + } + sendSdkCoins, err := cmn.NewSdkCoinsFromCoins(sendAmt) + Expect(err).To(BeNil()) + + callArgs.Args = []interface{}{s.keyring.GetAddr(0), sendAmt} + + txArgs.GasPrice = gasPrice.BigInt() + txArgs.GasLimit = 500_000 + + logCheckArgs := passCheck.WithExpEvents( + distribution.EventTypeFundCommunityPool, + distribution.EventTypeFundCommunityPool, + distribution.EventTypeFundCommunityPool, + ) + + _, _, err = s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil()) + + // Persist state changes + Expect(s.network.NextBlock()).To(BeNil()) + + // 3) Ensure the EOA's final balance is decreased by (fundAmt + fees) + balRes, err = s.grpcHandler.GetAllBalances(s.keyring.GetAccAddr(0)) + Expect(err).To(BeNil()) + finalEOABals := balRes.Balances + + diffs := initialEOABals.Sub(finalEOABals...) + Expect(diffs.IsAllGTE(sendSdkCoins)).To(BeTrue(), + "final EOA balance must be decreased at least by funded amt + fees") + }) + }) + + // ===================================== + // QUERIES + // ===================================== + Describe("Execute queries", func() { + It("should get validator distribution info - validatorDistributionInfo query", func() { + // fund validator account to make self-delegation + err := utils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), s.validatorsKeys[0].AccAddr, math.NewInt(1e17)) + Expect(err).To(BeNil()) + // persist changes + Expect(s.network.NextBlock()).To(BeNil()) + + opAddr := s.network.GetValidators()[0].OperatorAddress + // use the validator priv key + // make a self delegation + err = s.factory.Delegate(s.validatorsKeys[0].Priv, opAddr, sdk.NewCoin(s.bondDenom, math.NewInt(1))) + Expect(err).To(BeNil()) + // persist changes + Expect(s.network.NextBlock()).To(BeNil()) + + callArgs.MethodName = distribution.ValidatorDistributionInfoMethod + callArgs.Args = []interface{}{opAddr} + txArgs.GasLimit = 200_000 + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.validatorsKeys[0].Priv, + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the precompile") + + var out distribution.ValidatorDistributionInfoOutput + err = s.precompile.UnpackIntoInterface(&out, distribution.ValidatorDistributionInfoMethod, ethRes.Ret) + Expect(err).To(BeNil()) + + expAddr := s.validatorsKeys[0].AccAddr.String() + Expect(expAddr).To(Equal(out.DistributionInfo.OperatorAddress)) + Expect(1).To(Equal(len(out.DistributionInfo.Commission))) + Expect(1).To(Equal(len(out.DistributionInfo.SelfBondRewards))) + }) + + It("should get validator outstanding rewards - validatorOutstandingRewards query", func() { + accruedRewards, err := utils.WaitToAccrueRewards( + s.network, + s.grpcHandler, + s.keyring.GetAccAddr(0).String(), + minExpRewardOrCommission) + Expect(err).To(BeNil(), "error waiting to accrue rewards") + + callArgs.MethodName = distribution.ValidatorOutstandingRewardsMethod + callArgs.Args = []interface{}{s.network.GetValidators()[0].OperatorAddress} + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the precompile") + + var rewards []cmn.DecCoin + err = s.precompile.UnpackIntoInterface(&rewards, distribution.ValidatorOutstandingRewardsMethod, ethRes.Ret) + Expect(err).To(BeNil()) + Expect(len(rewards)).To(Equal(1)) + + Expect(uint8(18)).To(Equal(rewards[0].Precision)) + Expect(s.bondDenom).To(Equal(rewards[0].Denom)) + + // the expected rewards should be the accruedRewards per validator + // plus the 5% commission + expRewardAmt := accruedRewards.AmountOf(s.bondDenom). + Quo(math.LegacyNewDec(3)). + Quo(math.LegacyNewDecWithPrec(95, 2)). // add 5% commission + TruncateInt() + + Expect(rewards[0].Amount.String()).To(Equal(expRewardAmt.BigInt().String())) + }) + + It("should get validator commission - validatorCommission query", func() { + opAddr := s.network.GetValidators()[0].OperatorAddress + accruedCommission, err := utils.WaitToAccrueCommission( + s.network, + s.grpcHandler, + opAddr, + minExpRewardOrCommission) + Expect(err).To(BeNil(), "error waiting to accrue rewards") + + callArgs.MethodName = distribution.ValidatorCommissionMethod + callArgs.Args = []interface{}{opAddr} + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the precompile") + + var commission []cmn.DecCoin + err = s.precompile.UnpackIntoInterface(&commission, distribution.ValidatorCommissionMethod, ethRes.Ret) + Expect(err).To(BeNil()) + Expect(len(commission)).To(Equal(1)) + Expect(uint8(18)).To(Equal(commission[0].Precision)) + Expect(s.bondDenom).To(Equal(commission[0].Denom)) + + expCommissionAmt := accruedCommission.AmountOf(s.bondDenom).TruncateInt() + Expect(commission[0].Amount).To(Equal(expCommissionAmt.BigInt())) + }) + + Context("validatorSlashes query query", Ordered, func() { + BeforeAll(func() { + s.withValidatorSlashes = true + s.SetupTest() + }) + AfterAll(func() { + s.withValidatorSlashes = false + }) + + It("should get validator slashing events (default pagination)", func() { + callArgs.MethodName = distribution.ValidatorSlashesMethod + callArgs.Args = []interface{}{ + s.network.GetValidators()[0].OperatorAddress, + uint64(1), uint64(5), + query.PageRequest{}, + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil()) + + var out distribution.ValidatorSlashesOutput + err = s.precompile.UnpackIntoInterface(&out, distribution.ValidatorSlashesMethod, ethRes.Ret) + Expect(err).To(BeNil()) + Expect(len(out.Slashes)).To(Equal(2)) + // expected values according to the values used on test setup (custom genesis) + for _, s := range out.Slashes { + Expect(s.Fraction.Value).To(Equal(math.LegacyNewDecWithPrec(5, 2).BigInt())) + Expect(s.ValidatorPeriod).To(Equal(uint64(1))) + } + Expect(uint64(2)).To(Equal(out.PageResponse.Total)) + Expect(out.PageResponse.NextKey).To(BeEmpty()) + }) + + It("should get validator slashing events - query w/pagination limit = 1)", func() { + callArgs.MethodName = distribution.ValidatorSlashesMethod + callArgs.Args = []interface{}{ + s.network.GetValidators()[0].OperatorAddress, + uint64(1), uint64(5), + query.PageRequest{ + Limit: 1, + CountTotal: true, + }, + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil()) + + var out distribution.ValidatorSlashesOutput + err = s.precompile.UnpackIntoInterface(&out, distribution.ValidatorSlashesMethod, ethRes.Ret) + Expect(err).To(BeNil()) + Expect(len(out.Slashes)).To(Equal(1)) + Expect(out.Slashes[0].Fraction.Value).To(Equal(math.LegacyNewDecWithPrec(5, 2).BigInt())) + Expect(out.Slashes[0].ValidatorPeriod).To(Equal(uint64(1))) + // total slashes count is 2 + Expect(uint64(2)).To(Equal(out.PageResponse.Total)) + Expect(out.PageResponse.NextKey).NotTo(BeEmpty()) + }) + }) + + It("should get empty delegation rewards - delegationRewards query", func() { + callArgs.MethodName = distribution.DelegationRewardsMethod + callArgs.Args = []interface{}{ + s.keyring.GetAddr(0), + s.network.GetValidators()[0].OperatorAddress, + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the precompile") + + var rewards []cmn.DecCoin + err = s.precompile.UnpackIntoInterface(&rewards, distribution.DelegationRewardsMethod, ethRes.Ret) + Expect(err).To(BeNil()) + Expect(len(rewards)).To(Equal(0)) + }) + + It("should get delegation rewards - delegationRewards query", func() { + accruedRewards, err := utils.WaitToAccrueRewards(s.network, s.grpcHandler, s.keyring.GetAccAddr(0).String(), minExpRewardOrCommission) + Expect(err).To(BeNil()) + + callArgs.MethodName = distribution.DelegationRewardsMethod + callArgs.Args = []interface{}{ + s.keyring.GetAddr(0), + s.network.GetValidators()[0].OperatorAddress, + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the precompile") + + var rewards []cmn.DecCoin + err = s.precompile.UnpackIntoInterface(&rewards, distribution.DelegationRewardsMethod, ethRes.Ret) + Expect(err).To(BeNil()) + Expect(len(rewards)).To(Equal(1)) + + // The accrued rewards are based on 3 equal delegations to the existing 3 validators + // The query is from only 1 validator, thus, the expected reward + // for this delegation is totalAccruedRewards / validatorsCount (3) + expRewardAmt := accruedRewards.AmountOf(s.bondDenom).Quo(math.LegacyNewDec(3)) + + Expect(rewards[0].Denom).To(Equal(s.bondDenom)) + Expect(rewards[0].Amount).To(Equal(expRewardAmt.TruncateInt().BigInt())) + }) + + It("should get delegators's total rewards - delegationTotalRewards query", func() { + // wait for rewards to accrue + accruedRewards, err := utils.WaitToAccrueRewards(s.network, s.grpcHandler, s.keyring.GetAccAddr(0).String(), minExpRewardOrCommission) + Expect(err).To(BeNil()) + + callArgs.MethodName = distribution.DelegationTotalRewardsMethod + callArgs.Args = []interface{}{s.keyring.GetAddr(0)} + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the precompile") + + var out distribution.DelegationTotalRewardsOutput + + err = s.precompile.UnpackIntoInterface(&out, distribution.DelegationTotalRewardsMethod, ethRes.Ret) + Expect(err).To(BeNil()) + Expect(3).To(Equal(len(out.Rewards))) + + // The accrued rewards are based on 3 equal delegations to the existing 3 validators + // The query is from only 1 validator, thus, the expected reward + // for this delegation is totalAccruedRewards / validatorsCount (3) + accruedRewardsAmt := accruedRewards.AmountOf(s.bondDenom) + expRewardPerValidator := accruedRewardsAmt.Quo(math.LegacyNewDec(3)) + + // the response order may change + for _, or := range out.Rewards { + Expect(1).To(Equal(len(or.Reward))) + Expect(or.Reward[0].Denom).To(Equal(s.bondDenom)) + Expect(or.Reward[0].Amount).To(Equal(expRewardPerValidator.TruncateInt().BigInt())) + } + + Expect(1).To(Equal(len(out.Total))) + Expect(out.Total[0].Amount).To(Equal(accruedRewardsAmt.TruncateInt().BigInt())) + }) + + It("should get all validators a delegators has delegated to - delegatorValidators query", func() { + callArgs.MethodName = distribution.DelegatorValidatorsMethod + callArgs.Args = []interface{}{s.keyring.GetAddr(0)} + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the precompile") + + var validators []string + err = s.precompile.UnpackIntoInterface(&validators, distribution.DelegatorValidatorsMethod, ethRes.Ret) + Expect(err).To(BeNil()) + Expect(3).To(Equal(len(validators))) + }) + + It("should get withdraw address - delegatorWithdrawAddress query", func() { + callArgs.MethodName = distribution.DelegatorWithdrawAddressMethod + callArgs.Args = []interface{}{s.keyring.GetAddr(0)} + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the precompile") + + withdrawAddr, err := s.precompile.Unpack(distribution.DelegatorWithdrawAddressMethod, ethRes.Ret) + Expect(err).To(BeNil()) + // get the bech32 encoding + expAddr := s.keyring.GetAccAddr(0) + Expect(withdrawAddr[0]).To(Equal(expAddr.String())) + }) + + It("should get community pool coins - communityPool query", func() { + fundAmount := big.NewInt(1_000_000) + callArgs.MethodName = distribution.FundCommunityPoolMethod + callArgs.Args = []interface{}{ + s.keyring.GetAddr(0), + []cmn.Coin{ + {Denom: s.bondDenom, Amount: fundAmount}, + }, + } + + txArgs.GasLimit = 200_000 + + fundCheck := passCheck.WithExpEvents(distribution.EventTypeFundCommunityPool) + + _, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + fundCheck, + ) + Expect(err).To(BeNil(), "error while calling the precompile") + Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock") + + callArgs.MethodName = distribution.CommunityPoolMethod + callArgs.Args = []interface{}{} + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the precompile") + + var coins []cmn.DecCoin + err = s.precompile.UnpackIntoInterface(&coins, distribution.CommunityPoolMethod, ethRes.Ret) + Expect(err).To(BeNil()) + Expect(len(coins)).To(Equal(1)) + Expect(coins[0].Denom).To(Equal(s.bondDenom)) + Expect(coins[0].Amount.Cmp(fundAmount)).To(Equal(1)) + }) + }) + }) + var _ = Describe("Calling distribution precompile from contract", Ordered, func() { + s := NewPrecompileTestSuite(create, options...) + // testCase is a struct used for cases of contracts calls that have some operation + // performed before and/or after the precompile call + type testCase struct { + withdrawer *common.Address + before bool + after bool + } + + var ( + distrCallerContract evmtypes.CompiledContract + // contractAddr is the address of the smart contract that will be deployed + contractAddr common.Address + contractAccAddr sdk.AccAddress + err error + + // execRevertedCheck defines the default log checking arguments which includes the + // standard revert message. + execRevertedCheck testutil.LogCheckArgs + ) + + BeforeAll(func() { + distrCallerContract, err = contracts.LoadDistributionCallerContract() + Expect(err).To(BeNil(), "error while loading the smart contract: %v", err) + }) + + BeforeEach(func() { + s.SetupTest() + + // send funds to the contract + err := utils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), contractAddr.Bytes(), math.NewInt(2e18)) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + contractAddr, err = s.factory.DeployContract( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values + testutiltypes.ContractDeploymentData{ + Contract: distrCallerContract, + }, + ) + Expect(err).To(BeNil(), "error while deploying the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil(), "error calling NextBlock: %v", err) + contractAccAddr = sdk.AccAddress(contractAddr.Bytes()) + + // check contract was correctly deployed + cAcc := s.network.App.GetEVMKeeper().GetAccount(s.network.GetContext(), contractAddr) + Expect(cAcc).ToNot(BeNil(), "contract account should exist") + Expect(cAcc.IsContract()).To(BeTrue(), "account should be a contract") + + // Contract delegate + stkPrecompile, err := s.getStakingPrecompile() + Expect(err).To(BeNil(), "error while getting staking precompile: %v", err) + // make a delegation with contract as delegator + logCheck := testutil.LogCheckArgs{ + ExpPass: true, + ABIEvents: stkPrecompile.ABI.Events, + ExpEvents: []string{staking.EventTypeDelegate}, + } + delegateAmt := big.NewInt(1e18) + _, _, err = s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{ + To: &contractAddr, + GasLimit: 500_000, + Amount: delegateAmt, + }, + testutiltypes.CallArgs{ + ContractABI: distrCallerContract.ABI, + MethodName: "testDelegateFromContract", + Args: []interface{}{ + s.network.GetValidators()[0].OperatorAddress, + delegateAmt, + }, + }, + logCheck, + ) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + // wait to accrue some rewards for contract address + _, err = utils.WaitToAccrueRewards(s.network, s.grpcHandler, contractAccAddr.String(), minExpRewardOrCommission) + Expect(err).To(BeNil()) + + // populate default call args + callArgs = testutiltypes.CallArgs{ + ContractABI: distrCallerContract.ABI, + } + + // reset tx args each test to avoid keeping custom + // values of previous tests (e.g. gasLimit) + txArgs = evmtypes.EvmTxArgs{ + To: &contractAddr, + } + + // default log check arguments + defaultLogCheck = testutil.LogCheckArgs{ABIEvents: s.precompile.Events} + execRevertedCheck = defaultLogCheck.WithErrContains("execution reverted") + passCheck = defaultLogCheck.WithExpPass(true) + }) + + // ===================================== + // TRANSACTIONS + // ===================================== + Context("setWithdrawAddress", func() { + // newWithdrawer is the address to set the withdraw address to + newWithdrawer := differentAddr + + BeforeEach(func() { + // withdraw address should be same as address + res, err := s.grpcHandler.GetDelegatorWithdrawAddr(s.keyring.GetAccAddr(0).String()) + Expect(err).To(BeNil(), "error while calling the precompile") + Expect(res.WithdrawAddress).To(Equal(s.keyring.GetAccAddr(0).String())) + + // populate default arguments + callArgs.MethodName = "testSetWithdrawAddress" + }) + + It("should set withdraw address successfully", func() { + txArgs = evmtypes.EvmTxArgs{ + To: &contractAddr, + } + callArgs.Args = []interface{}{ + contractAddr, newWithdrawer.String(), + } + + setWithdrawCheck := passCheck.WithExpEvents(distribution.EventTypeSetWithdrawAddress) + + _, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + setWithdrawCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) + + queryRes, err := s.grpcHandler.GetDelegatorWithdrawAddr(contractAccAddr.String()) + Expect(err).To(BeNil(), "error while calling the precompile") + Expect(queryRes.WithdrawAddress).To(Equal(sdk.AccAddress(newWithdrawer.Bytes()).String())) + }) + }) + + Context("setWithdrawerAddress with contract as delegator", func() { + // newWithdrawer is the address to set the withdraw address to + newWithdrawer := differentAddr + + BeforeEach(func() { + // withdraw address should be same as address + res, err := s.grpcHandler.GetDelegatorWithdrawAddr(s.keyring.GetAccAddr(0).String()) + Expect(err).To(BeNil(), "error while calling the precompile") + Expect(res.WithdrawAddress).To(Equal(s.keyring.GetAccAddr(0).String())) + + // populate default arguments + callArgs.MethodName = "testSetWithdrawAddressFromContract" + }) + + It("should set withdraw address successfully", func() { + callArgs.Args = []interface{}{newWithdrawer.String()} + setWithdrawCheck := passCheck.WithExpEvents(distribution.EventTypeSetWithdrawAddress) + + _, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + setWithdrawCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) + + res, err := s.grpcHandler.GetDelegatorWithdrawAddr(sdk.AccAddress(contractAddr.Bytes()).String()) + Expect(err).To(BeNil(), "error while calling GetDelegatorWithdrawAddr: %v", err) + Expect(res.WithdrawAddress).To(Equal(sdk.AccAddress(newWithdrawer.Bytes()).String())) + }) + }) + + Context("withdrawDelegatorRewards", func() { + // initialBalance is the initial balance of the delegator + var initialBalance *sdk.Coin + + BeforeEach(func() { + // fund the diffAddr + err := utils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), differentAddr.Bytes(), math.NewInt(2e18)) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + // make a delegation + err = s.factory.Delegate(diffKey, s.network.GetValidators()[0].OperatorAddress, sdk.NewCoin(s.bondDenom, math.NewInt(1e18))) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + // wait to accrue some rewards for s.keyring.GetAddr(0) & another address + _, err = utils.WaitToAccrueRewards(s.network, s.grpcHandler, sdk.AccAddress(differentAddr.Bytes()).String(), minExpRewardOrCommission) + Expect(err).To(BeNil()) + + // check if s.keyring.GetAddr(0) accrued rewards too + _, err = utils.WaitToAccrueRewards(s.network, s.grpcHandler, s.keyring.GetAccAddr(0).String(), minExpRewardOrCommission) + Expect(err).To(BeNil()) + + balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + initialBalance = balRes.Balance + + callArgs.MethodName = "testWithdrawDelegatorReward" + + // set gas price to calculate fees paid + txArgs.GasPrice = gasPrice.BigInt() + }) + + It("should not withdraw rewards when sending from a different address", func() { + balRes, err := s.grpcHandler.GetBalanceFromBank(differentAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + differentAddrInitialBalance := balRes.Balance + + callArgs.Args = []interface{}{ + differentAddr, s.network.GetValidators()[0].OperatorAddress, + } + + res, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + execRevertedCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) + + // balance should be equal as initial balance or less (because of fees) + balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + finalBalance := balRes.Balance + fees := gasPrice.Mul(math.NewInt(res.GasUsed)) + Expect(finalBalance.Amount).To(Equal(initialBalance.Amount.Sub(fees))) + + // differentAddr balance should remain unchanged + balRes, err = s.grpcHandler.GetBalanceFromBank(differentAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + differentAddrFinalBalance := balRes.Balance + Expect(differentAddrFinalBalance.Amount).To(Equal(differentAddrInitialBalance.Amount)) + }) + + It("should withdraw rewards successfully", func() { + balRes, err := s.grpcHandler.GetBalanceFromBank(contractAccAddr, s.bondDenom) + Expect(err).To(BeNil()) + initBalanceAmt := balRes.Balance.Amount + + callArgs.Args = []interface{}{ + contractAddr, s.network.GetValidators()[0].OperatorAddress, + } + + rwRes, err := s.grpcHandler.GetDelegationRewards(contractAccAddr.String(), s.network.GetValidators()[0].OperatorAddress) + Expect(err).To(BeNil()) + expRewardsAmt := rwRes.Rewards.AmountOf(s.bondDenom).TruncateInt() + + logCheckArgs := passCheck. + WithExpEvents(distribution.EventTypeWithdrawDelegatorReward) + + _, _, err = s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) + + // balance should increase + balRes, err = s.grpcHandler.GetBalanceFromBank(contractAccAddr, s.bondDenom) + Expect(err).To(BeNil()) + + Expect(balRes.Balance.Amount).To(Equal(initBalanceAmt.Add(expRewardsAmt)), "expected final balance to be greater than initial balance after withdrawing rewards") + }) + + DescribeTable("should withdraw rewards successfully to the new withdrawer address", func(tc testCase) { + balRes, err := s.grpcHandler.GetBalanceFromBank(tc.withdrawer.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + withdrawerInitialBalance := balRes.Balance + + callArgs = testutiltypes.CallArgs{ + ContractABI: distrCallerContract.ABI, + MethodName: "testSetWithdrawAddressFromContract", + Args: []interface{}{sdk.AccAddress(tc.withdrawer.Bytes()).String()}, + } + logCheckArgs := passCheck.WithExpEvents(distribution.EventTypeSetWithdrawAddress) + _, _, err = s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) + + // get delegator initial balance + balRes, err = s.grpcHandler.GetBalanceFromBank(contractAccAddr, s.bondDenom) + Expect(err).To(BeNil()) + delegatorInitialBalance := balRes.Balance + + // get the expected rewards for the delegation + rwRes, err := s.grpcHandler.GetDelegationRewards(contractAccAddr.String(), s.network.GetValidators()[0].OperatorAddress) + Expect(err).To(BeNil()) + expRewardsAmt := rwRes.Rewards.AmountOf(s.bondDenom).TruncateInt() + + callArgs.MethodName = "testWithdrawDelegatorReward" + callArgs.Args = []interface{}{ + contractAddr, s.network.GetValidators()[0].OperatorAddress, + } + + logCheckArgs = passCheck. + WithExpEvents(distribution.EventTypeWithdrawDelegatorReward) + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) + + var rewards []cmn.Coin + err = s.precompile.UnpackIntoInterface(&rewards, distribution.WithdrawDelegatorRewardMethod, ethRes.Ret) + Expect(err).To(BeNil()) + Expect(len(rewards)).To(Equal(1)) + + Expect(rewards[0].Denom).To(Equal(s.bondDenom)) + Expect(rewards[0].Amount).To(Equal(expRewardsAmt.BigInt())) + + // should increase withdrawer balance by rewards + balRes, err = s.grpcHandler.GetBalanceFromBank(tc.withdrawer.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + Expect(balRes.Balance.Amount).To(Equal(withdrawerInitialBalance.Amount.Add(expRewardsAmt)), "expected final balance to be greater than initial balance after withdrawing rewards") + + // check that the delegator final balance is initialBalance - fee + balRes, err = s.grpcHandler.GetBalanceFromBank(contractAccAddr, s.bondDenom) + Expect(err).To(BeNil(), "error while calling GetBalance") + Expect(balRes.Balance.Amount).To(Equal(delegatorInitialBalance.Amount), "expected delegator final balance to be equal to initial balance") + }, + Entry("withdrawer addr is existing acc", testCase{ + withdrawer: &differentAddr, + }), + Entry("withdrawer addr is non-existing acc", testCase{ + withdrawer: func() *common.Address { + addr := testutiltx.GenerateAddress() + return &addr + }(), + }), + ) + + // Specific BeforeEach for table-driven tests + Context("Table-driven tests for Withdraw Delegator Rewards", func() { + contractInitialBalance := math.NewInt(100) + + BeforeEach(func() { + callArgs.MethodName = "testWithdrawDelegatorRewardWithTransfer" + + // send some funds to the contract + err := utils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), contractAddr.Bytes(), contractInitialBalance) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + }) + + DescribeTable("withdraw delegation rewards with internal transfers to delegator - should withdraw rewards successfully to the withdrawer address", + func(tc testCase) { + txSender := s.keyring.GetAccAddr(0) + txSenderKey := s.keyring.GetPrivKey(0) + balRes, err := s.grpcHandler.GetBalanceFromBank(contractAccAddr, s.bondDenom) + Expect(err).To(BeNil()) + if tc.withdrawer != nil { + callArgs = testutiltypes.CallArgs{ + ContractABI: distrCallerContract.ABI, + MethodName: "testSetWithdrawAddressFromContract", + Args: []interface{}{sdk.AccAddress(tc.withdrawer.Bytes()).String()}, + } + logCheckArgs := passCheck.WithExpEvents(distribution.EventTypeSetWithdrawAddress) + _, _, err = s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, logCheckArgs) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) + + balRes, err = s.grpcHandler.GetBalanceFromBank(tc.withdrawer.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + } + withdrawerInitialBalance := balRes.Balance + + balRes, err = s.grpcHandler.GetBalanceFromBank(txSender, s.bondDenom) + Expect(err).To(BeNil()) + txSenderInitialBalance := balRes.Balance + + // get the pending rewards to claim + qRes, err := s.grpcHandler.GetDelegationRewards(contractAccAddr.String(), s.network.GetValidators()[0].OperatorAddress) + Expect(err).To(BeNil()) + expRewards := qRes.Rewards.AmountOf(s.bondDenom).TruncateInt() + + callArgs.MethodName = "testWithdrawDelegatorRewardWithTransfer" + callArgs.Args = []interface{}{ + s.network.GetValidators()[0].OperatorAddress, tc.before, tc.after, + } + + logCheckArgs := passCheck. + WithExpEvents(distribution.EventTypeWithdrawDelegatorReward) + + res, _, err := s.factory.CallContractAndCheckLogs( + txSenderKey, + txArgs, + callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) + + fees := gasPrice.MulRaw(res.GasUsed) + + // check balances + contractTransferredAmt := math.ZeroInt() + for _, transferred := range []bool{tc.before, tc.after} { + if transferred { + contractTransferredAmt = contractTransferredAmt.AddRaw(15) + } + } + + if tc.withdrawer != nil { + expWithdrawerFinalBalance := withdrawerInitialBalance.Amount.Add(expRewards) + // withdrawer balance should have the rewards + balRes, err = s.grpcHandler.GetBalanceFromBank(tc.withdrawer.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + withdrawerFinalBalance := balRes.Balance + Expect(withdrawerFinalBalance.Amount).To(Equal(expWithdrawerFinalBalance), "expected final balance to be greater than initial balance after withdrawing rewards") + } else { // contract is the withdrawer + // contract balance be updated according to the transferred amount and rewards + balRes, err = s.grpcHandler.GetBalanceFromBank(contractAccAddr, s.bondDenom) + Expect(err).To(BeNil()) + contractFinalBalance := balRes.Balance + Expect(contractFinalBalance.Amount).To(Equal( + contractInitialBalance. + Add(expRewards). + Sub(contractTransferredAmt))) + } + + // delegator balance should have the transferred amt - fees + rewards (when is the withdrawer) + balRes, err = s.grpcHandler.GetBalanceFromBank(txSender, s.bondDenom) + Expect(err).To(BeNil()) + txSenderFinalBalance := balRes.Balance + Expect(txSenderFinalBalance.Amount).To(Equal( + txSenderInitialBalance.Amount. + Sub(fees). + Add(contractTransferredAmt))) + }, + + Entry("delegator == withdrawer - with internal transfers before and after precompile call", testCase{ + before: true, + after: true, + }), + + Entry("delegator == withdrawer - with internal transfers before precompile call", testCase{ + before: true, + after: false, + }), + + Entry("delegator == withdrawer - with internal transfers after precompile call", testCase{ + before: false, + after: true, + }), + Entry("delegator != withdrawer - with internal transfers before and after precompile call", testCase{ + withdrawer: &differentAddr, + before: true, + after: true, + }), + + Entry("delegator != withdrawer - with internal transfers before precompile call", testCase{ + withdrawer: &differentAddr, + before: true, + after: false, + }), + + Entry("delegator != withdrawer - with internal transfers after precompile call", testCase{ + withdrawer: &differentAddr, + before: false, + after: true, + }), + ) + + DescribeTable("should revert withdraw rewards successfully and update correspondingly the withdrawer and contract's balances", func(tc testCase) { + // Set new withdrawer address + err = s.factory.SetWithdrawAddress(s.keyring.GetPrivKey(0), tc.withdrawer.Bytes()) + Expect(err).To(BeNil()) + // persist state change + Expect(s.network.NextBlock()).To(BeNil()) + + // get the pending rewards to claim + qRes, err := s.grpcHandler.GetDelegationRewards(s.keyring.GetAccAddr(0).String(), s.network.GetValidators()[0].OperatorAddress) + Expect(err).To(BeNil()) + initRewards := qRes.Rewards.AmountOf(s.bondDenom).TruncateInt() + + balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + delInitBalance := balRes.Balance + balRes, err = s.grpcHandler.GetBalanceFromBank(tc.withdrawer.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + withdrawerInitBalance := balRes.Balance + + // update args to call the corresponding contract method + callArgs.MethodName = "revertWithdrawRewardsAndTransfer" + callArgs.Args = []interface{}{ + s.keyring.GetAddr(0), *tc.withdrawer, s.network.GetValidators()[0].OperatorAddress, true, + } + + res, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) + fees := gasPrice.MulRaw(res.GasUsed) + + // check balances + contractTransferredAmt := math.NewInt(15) + // contract balance be updated according to the transferred amount + balRes, err = s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + contractFinalBalance := balRes.Balance + Expect(contractFinalBalance.Amount).To(Equal(contractInitialBalance.Sub(contractTransferredAmt))) + + // delegator balance should be initial_balance - fees + balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + delFinalBalance := balRes.Balance + Expect(delFinalBalance.Amount).To(Equal(delInitBalance.Amount.Sub(fees))) + + // withdrawer balance should increase by the transferred amount only + // the rewards withdrawal should revert + balRes, err = s.grpcHandler.GetBalanceFromBank(tc.withdrawer.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + withdrawerFinalBalance := balRes.Balance + Expect(withdrawerFinalBalance.Amount).To(Equal(withdrawerInitBalance.Amount.Add(contractTransferredAmt)), "expected final balance to be greater than initial balance after withdrawing rewards") + + // rewards to claim should be the same or more than before + qRes, err = s.grpcHandler.GetDelegationRewards(s.keyring.GetAccAddr(0).String(), s.network.GetValidators()[0].OperatorAddress) + Expect(err).To(BeNil()) + finalRewards := qRes.Rewards.AmountOf(s.bondDenom).TruncateInt() + Expect(finalRewards.GTE(initRewards)).To(BeTrue()) + }, + Entry("withdrawer addr is existing acc", testCase{ + withdrawer: &differentAddr, + }), + Entry("withdrawer addr is non-existing acc", testCase{ + withdrawer: func() *common.Address { + addr := testutiltx.GenerateAddress() + return &addr + }(), + }), + ) + }) + }) + + Context("withdrawDelegatorRewards with contract as delegator", func() { + var ( + // initialBalance is the initial balance of the delegator + initialBalance *sdk.Coin + accruedRewardsAmt math.Int + ) + + BeforeEach(func() { //nolint:dupl + // send funds to the contract + err := utils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), contractAddr.Bytes(), math.NewInt(2e18)) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + stkPrecompile, err := s.getStakingPrecompile() + Expect(err).To(BeNil()) + // make a delegation with contract as delegator + logCheck := testutil.LogCheckArgs{ + ExpPass: true, + ABIEvents: stkPrecompile.ABI.Events, + ExpEvents: []string{staking.EventTypeDelegate}, + } + _, _, err = s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + testutiltypes.CallArgs{ + ContractABI: distrCallerContract.ABI, + MethodName: "testDelegateFromContract", + Args: []interface{}{ + s.network.GetValidators()[0].OperatorAddress, + big.NewInt(1e18), + }, + }, + logCheck, + ) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + // wait to accrue some rewards for contract address + rwRes, err := utils.WaitToAccrueRewards(s.network, s.grpcHandler, sdk.AccAddress(contractAddr.Bytes()).String(), minExpRewardOrCommission) + Expect(err).To(BeNil()) + + // contract's accrued rewards amt + accruedRewardsAmt = rwRes.AmountOf(s.bondDenom).TruncateInt() + + balRes, err := s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + initialBalance = balRes.Balance + + // populate default arguments + callArgs.MethodName = "testWithdrawDelegatorRewardFromContract" + }) + + It("should withdraw rewards successfully", func() { + callArgs.Args = []interface{}{s.network.GetValidators()[0].OperatorAddress} + + logCheckArgs := passCheck.WithExpEvents(distribution.EventTypeWithdrawDelegatorReward) + + _, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) + + // balance should increase + balRes, err := s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + finalBalance := balRes.Balance + Expect(finalBalance.Amount).To(Equal(initialBalance.Amount.Add(accruedRewardsAmt)), "expected final balance to be greater than initial balance after withdrawing rewards") + }) + + It("should withdraw rewards successfully", func() { + withdrawerAddr, _ := testutiltx.NewAccAddressAndKey() + + balRes, err := s.grpcHandler.GetBalanceFromBank(withdrawerAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + initialWithdrawerBalance := balRes.Balance + Expect(initialWithdrawerBalance.Amount).To(Equal(math.ZeroInt())) + + // call the smart contract to update the withdrawer + // Set new withdrawer address for the contract + setWithdrawCheck := passCheck.WithExpEvents(distribution.EventTypeSetWithdrawAddress) + res1, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + testutiltypes.CallArgs{ + ContractABI: distrCallerContract.ABI, + MethodName: "testSetWithdrawAddressFromContract", + Args: []interface{}{withdrawerAddr.String()}, + }, + setWithdrawCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(res1.IsOK()).To(BeTrue(), "error while calling the smart contract") + Expect(s.network.NextBlock()).To(BeNil()) + + // get accrued rewards prev to tx + rwRes, err := s.grpcHandler.GetDelegationRewards(sdk.AccAddress(contractAddr.Bytes()).String(), s.network.GetValidators()[0].OperatorAddress) + Expect(err).To(BeNil()) + accruedRewardsAmt = rwRes.Rewards.AmountOf(s.bondDenom).TruncateInt() + + callArgs.Args = []interface{}{s.network.GetValidators()[0].OperatorAddress} + logCheckArgs := passCheck.WithExpEvents(distribution.EventTypeWithdrawDelegatorReward) + + txArgs.GasLimit = 300_000 + _, _, err = s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) + + // withdrawer balance should increase with the rewards amt + balRes, err = s.grpcHandler.GetBalanceFromBank(withdrawerAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + finalWithdrawerBalance := balRes.Balance + Expect(finalWithdrawerBalance.Amount).To(Equal(accruedRewardsAmt), "expected final balance to be greater than initial balance after withdrawing rewards") + + // delegator balance (contract) should remain unchanged + balRes, err = s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + finalDelegatorBalance := balRes.Balance + Expect(finalDelegatorBalance.Amount.Equal(initialBalance.Amount)).To(BeTrue(), "expected delegator final balance remain unchanged after withdrawing rewards to withdrawer") + }) + + It("should withdraw rewards successfully", func() { + withdrawerAddr, _ := testutiltx.NewAccAddressAndKey() + + balRes, err := s.grpcHandler.GetBalanceFromBank(withdrawerAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + initialWithdrawerBalance := balRes.Balance + Expect(initialWithdrawerBalance.Amount).To(Equal(math.ZeroInt())) + + // Set new withdrawer address for the contract + setWithdrawCheck := passCheck.WithExpEvents(distribution.EventTypeSetWithdrawAddress) + res1, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + testutiltypes.CallArgs{ + ContractABI: distrCallerContract.ABI, + MethodName: "testSetWithdrawAddressFromContract", + Args: []interface{}{withdrawerAddr.String()}, + }, + setWithdrawCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(res1.IsOK()).To(BeTrue(), "error while calling the smart contract") + Expect(s.network.NextBlock()).To(BeNil()) + + // get the pending rewards to claim + rwRes, err := s.grpcHandler.GetDelegationRewards(sdk.AccAddress(contractAddr.Bytes()).String(), s.network.GetValidators()[0].OperatorAddress) + Expect(err).To(BeNil()) + expRewards := rwRes.Rewards.AmountOf(s.bondDenom).TruncateInt() + + logCheckArgs := passCheck.WithExpEvents(distribution.EventTypeWithdrawDelegatorReward) + + callArgs.Args = []interface{}{s.network.GetValidators()[0].OperatorAddress} + + txArgs.GasLimit = 500_000 + _, _, err = s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) + + // withdrawer balance should increase with the rewards amt + balRes, err = s.grpcHandler.GetBalanceFromBank(withdrawerAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + finalWithdrawerBalance := balRes.Balance + Expect(finalWithdrawerBalance.Amount.Equal(expRewards)).To(BeTrue(), "expected final balance to be greater than initial balance after withdrawing rewards") + + // delegator balance (contract) should remain unchanged + balRes, err = s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + finalDelegatorBalance := balRes.Balance + Expect(finalDelegatorBalance.Amount.Equal(initialBalance.Amount)).To(BeTrue(), "expected delegator final balance remain unchanged after withdrawing rewards to withdrawer") + }) + }) + + Context("claimRewards", func() { + var ( + // initialBalance is the initial balance of the delegator + initialBalance *sdk.Coin + // diffAddrInitialBalance is the initial balance of the different address + diffAddrInitialBalance *sdk.Coin + ) + + BeforeEach(func() { + // fund the diffAddr + err := utils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), contractAccAddr, math.NewInt(2e18)) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + stkPrecompile, err := s.getStakingPrecompile() + Expect(err).To(BeNil()) + // make a delegation with contract as delegator + logCheck := testutil.LogCheckArgs{ + ExpPass: true, + ABIEvents: stkPrecompile.ABI.Events, + ExpEvents: []string{staking.EventTypeDelegate}, + } + _, _, err = s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + testutiltypes.CallArgs{ + ContractABI: distrCallerContract.ABI, + MethodName: "testDelegateFromContract", + Args: []interface{}{ + s.network.GetValidators()[0].OperatorAddress, + big.NewInt(1e18), + }, + }, + logCheck, + ) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + // wait to accrue some rewards for contract address + _, err = utils.WaitToAccrueRewards(s.network, s.grpcHandler, contractAccAddr.String(), minExpRewardOrCommission) + Expect(err).To(BeNil()) + + balRes, err := s.grpcHandler.GetBalanceFromBank(contractAccAddr, s.bondDenom) + Expect(err).To(BeNil()) + initialBalance = balRes.Balance + + balRes, err = s.grpcHandler.GetBalanceFromBank(differentAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + diffAddrInitialBalance = balRes.Balance + + // populate default arguments + callArgs.MethodName = "testClaimRewards" + txArgs.GasPrice = gasPrice.BigInt() + }) + + It("should not claim rewards when sending from a different address", func() { + callArgs.Args = []interface{}{differentAddr, uint32(1)} + + _, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + execRevertedCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + // balance should be equal as initial balance or less (because of fees) + balRes, err := s.grpcHandler.GetBalanceFromBank(contractAccAddr, s.bondDenom) + Expect(err).To(BeNil()) + finalBalance := balRes.Balance + Expect(finalBalance.Amount).To(Equal(initialBalance.Amount)) + + // differentAddr balance should remain unchanged + balRes, err = s.grpcHandler.GetBalanceFromBank(differentAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + differentAddrFinalBalance := balRes.Balance + Expect(differentAddrFinalBalance.Amount).To(Equal(diffAddrInitialBalance.Amount)) + }) + + It("should claim rewards successfully", func() { + callArgs.Args = []interface{}{contractAddr, uint32(2)} + + logCheckArgs := passCheck. + WithExpEvents(distribution.EventTypeClaimRewards) + + _, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + // balance should remain unchanged + balRes, err := s.grpcHandler.GetBalanceFromBank(contractAccAddr, s.bondDenom) + Expect(err).To(BeNil()) + finalBalance := balRes.Balance + Expect(finalBalance.Amount.GT(initialBalance.Amount)).To(BeTrue(), "expected final balance to be greater than initial balance after claiming rewards") + }) + + Context("Table driven tests", func() { + BeforeEach(func() { + callArgs.MethodName = "testClaimRewardsWithTransfer" + + // send some funds to the contract + err = utils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), contractAddr.Bytes(), math.NewInt(1e18)) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + // make a delegation with key 1 + err = s.factory.Delegate(s.keyring.GetKey(1).Priv, s.network.GetValidators()[0].OperatorAddress, sdk.NewCoin(s.bondDenom, math.NewInt(1e18))) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + // wait to accrue some rewards for key 1 + _, err := utils.WaitToAccrueRewards(s.network, s.grpcHandler, s.keyring.GetAccAddr(1).String(), minExpRewardOrCommission) + Expect(err).To(BeNil()) + }) + + DescribeTable("claimRewards with transfer to withdrawer", func(tc testCase) { + txSender := s.keyring.GetAccAddr(1) + txSenderKey := s.keyring.GetPrivKey(1) + + txSenderInitialBalance := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), txSender, s.bondDenom) + contractInitialBalance := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), contractAccAddr, s.bondDenom) + + // get the pending rewards to claim + res, err := s.grpcHandler.GetDelegationTotalRewards(contractAccAddr.String()) + Expect(err).To(BeNil()) + expRewards := res.Total.AmountOf(s.bondDenom).TruncateInt() + + callArgs.Args = []interface{}{uint32(2), tc.before, tc.after} + + logCheckArgs := passCheck. + WithExpEvents(distribution.EventTypeClaimRewards) + txArgs.GasLimit = 400_000 // set gas limit to avoid out of gas error + _, evmRes, err := s.factory.CallContractAndCheckLogs( + txSenderKey, + txArgs, + callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + err = s.network.NextBlock() + Expect(err).To(BeNil()) + + fees := math.NewIntFromUint64(evmRes.GasUsed).Mul(math.NewIntFromBigInt(txArgs.GasPrice)) + + // calculate the transferred amt during the call + contractTransferredAmt := math.ZeroInt() + for _, transferred := range []bool{tc.before, tc.after} { + if transferred { + contractTransferredAmt = contractTransferredAmt.AddRaw(15) + } + } + + // check balances + expContractFinalBalance := contractInitialBalance.Amount.Sub(contractTransferredAmt).Add(expRewards) + expTxSenderFinalBalance := txSenderInitialBalance.Amount.Sub(fees).Add(contractTransferredAmt) + + contractFinalBalance := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), contractAccAddr, s.bondDenom) + Expect(contractFinalBalance.Amount).To(Equal(expContractFinalBalance), "expected final balance to be greater than initial balance after claiming rewards") + + txSenderFinalBalance := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), txSender, s.bondDenom) + Expect(txSenderFinalBalance.Amount).To(Equal(expTxSenderFinalBalance), "expected final balance to be greater than initial balance after claiming rewards") + }, + Entry("claim rewards with transfer to withdrawer before and after precompile call", testCase{ + before: true, + after: true, + }), + Entry("claim rewards with transfer to withdrawer before precompile call", testCase{ + before: true, + after: false, + }), + Entry("claim rewards with transfer to withdrawer after precompile call", testCase{ + before: false, + after: true, + }), + ) + }) + }) + + Context("tryClaimRewards", func() { + var ( + // initialBalance is the initial balance of the delegator + initialBalance *sdk.Coin + // diffAddrInitialBalance is the initial balance of the different address + // diffInitialBalance *sdk.Coin + accruedRewardsAmt math.Int + ) + + BeforeEach(func() { + // fund the diffAddr + err := utils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), differentAddr.Bytes(), math.NewInt(2e18)) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + // make a delegation + err = s.factory.Delegate(diffKey, s.network.GetValidators()[0].OperatorAddress, sdk.NewCoin(s.bondDenom, math.NewInt(1e18))) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + // wait to accrue some rewards for s.keyring.GetAddr(0) & another address + _, err = utils.WaitToAccrueRewards(s.network, s.grpcHandler, sdk.AccAddress(differentAddr.Bytes()).String(), minExpRewardOrCommission) + Expect(err).To(BeNil()) + + // check if s.keyring.GetAddr(0) accrued rewards too + res, err := s.grpcHandler.GetDelegationTotalRewards(s.keyring.GetAccAddr(0).String()) + Expect(err).To(BeNil()) + + accruedRewardsAmt = res.Total.AmountOf(s.bondDenom).TruncateInt() + Expect(accruedRewardsAmt.IsPositive()).To(BeTrue()) + + balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + initialBalance = balRes.Balance + + // populate default arguments + callArgs.MethodName = "testTryClaimRewards" + txArgs.GasPrice = gasPrice.BigInt() + }) + It("should claim rewards successfully", func() { + callArgs.Args = []interface{}{s.keyring.GetAddr(0), uint32(10)} + + // no logs should be emitted since the precompile call runs out of gas + logCheckArgs := passCheck //. + // WithExpEvents(EventTypeClaimRewards) + + res, err := s.grpcHandler.GetDelegationTotalRewards(s.keyring.GetAccAddr(0).String()) + Expect(err).To(BeNil()) + + accruedRewardsAmt = res.Total.AmountOf(s.bondDenom).TruncateInt() + Expect(accruedRewardsAmt.IsPositive()).To(BeTrue()) + + // set gas such that the internal keeper function called by the precompile fails out mid-execution + txArgs.GasLimit = 80_000 + _, _, err = s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + finalBalance := balRes.Balance + expectedGasCost := math.NewInt(79_416_000_000_000) + Expect(finalBalance.Amount.Equal(initialBalance.Amount.Sub(expectedGasCost))).To(BeTrue(), "expected final balance must be initial balance minus any gas spent") + + res, err = s.grpcHandler.GetDelegationTotalRewards(s.keyring.GetAccAddr(0).String()) + Expect(err).To(BeNil()) + + // accrued rewards should still be increasing + secondAccruedRewardsAmt := res.Total.AmountOf(s.bondDenom).TruncateInt() + Expect(secondAccruedRewardsAmt.IsPositive()).To(BeTrue()) + Expect(secondAccruedRewardsAmt.GTE(accruedRewardsAmt)).To(BeTrue()) + }) + }) + + Context("claimRewards with contract as delegator", func() { + var ( + initialBalance *sdk.Coin + accruedRewardsAmt math.Int + ) + + BeforeEach(func() { //nolint:dupl + // send funds to the contract + err := utils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), contractAddr.Bytes(), math.NewInt(2e18)) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + stkPrecompile, err := s.getStakingPrecompile() + Expect(err).To(BeNil()) + // make a delegation with contract as delegator + logCheck := testutil.LogCheckArgs{ + ExpPass: true, + ABIEvents: stkPrecompile.ABI.Events, + ExpEvents: []string{staking.EventTypeDelegate}, + } + txArgs.GasLimit = 500_000 + _, _, err = s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + testutiltypes.CallArgs{ + ContractABI: distrCallerContract.ABI, + MethodName: "testDelegateFromContract", + Args: []interface{}{ + s.network.GetValidators()[0].OperatorAddress, + big.NewInt(1e18), + }, + }, + logCheck, + ) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + // wait to accrue some rewards for contract address + rwRes, err := utils.WaitToAccrueRewards(s.network, s.grpcHandler, sdk.AccAddress(contractAddr.Bytes()).String(), minExpRewardOrCommission) + Expect(err).To(BeNil()) + + // contract's accrued rewards amt + accruedRewardsAmt = rwRes.AmountOf(s.bondDenom).TruncateInt() + + balRes, err := s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + initialBalance = balRes.Balance + + // populate default arguments + callArgs.MethodName = "testClaimRewards" + }) + + It("should withdraw rewards successfully", func() { + balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + signerInitialBalance := balRes.Balance + + callArgs.Args = []interface{}{contractAddr, uint32(2)} + txArgs.GasPrice = gasPrice.BigInt() + + logCheckArgs := passCheck.WithExpEvents(distribution.EventTypeClaimRewards) + + res, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + // tx signer should have paid the fees + fees := gasPrice.Mul(math.NewInt(res.GasUsed)) + balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + signerFinalBalance := balRes.Balance + Expect(signerFinalBalance.Amount).To(Equal(signerInitialBalance.Amount.Sub(fees))) + + // contract's balance should increase + balRes, err = s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + finalBalance := balRes.Balance + Expect(finalBalance.Amount).To(Equal(initialBalance.Amount.Add(accruedRewardsAmt)), "expected final balance to be greater than initial balance after withdrawing rewards") + }) + + It("should withdraw rewards successfully to a different address", func() { + balanceRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + signerInitialBalance := balanceRes.Balance + + balRes, err := s.grpcHandler.GetBalanceFromBank(differentAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + withdrawerInitialBalance := balRes.Balance + + balRes, err = s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + contractInitialBalance := balRes.Balance + + txArgs.GasPrice = gasPrice.BigInt() + + // Set new withdrawer address for the contract + setWithdrawCheck := passCheck.WithExpEvents(distribution.EventTypeSetWithdrawAddress) + res1, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + testutiltypes.CallArgs{ + ContractABI: distrCallerContract.ABI, + MethodName: "testSetWithdrawAddressFromContract", + Args: []interface{}{differentAddr.String()}, + }, + setWithdrawCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + callArgs.Args = []interface{}{contractAddr, uint32(2)} + + logCheckArgs := passCheck.WithExpEvents(distribution.EventTypeClaimRewards) + + rwRes, err := s.grpcHandler.GetDelegationRewards(sdk.AccAddress(contractAddr.Bytes()).String(), s.network.GetValidators()[0].OperatorAddress) + Expect(err).To(BeNil()) + accruedRewardsAmt = rwRes.Rewards.AmountOf(s.bondDenom).TruncateInt() + + txArgs.GasLimit = 200_000 + res2, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + // signer balance should decrease - paid for fees + fees := gasPrice.Mul(math.NewInt(res1.GasUsed)).Add(gasPrice.Mul(math.NewInt(res2.GasUsed))) + + balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + signerFinalBalance := balRes.Balance + Expect(signerFinalBalance.Amount).To(Equal(signerInitialBalance.Amount.Sub(fees)), "expected signer's final balance to be less than initial balance after withdrawing rewards") + + // withdrawer balance should increase + balRes, err = s.grpcHandler.GetBalanceFromBank(differentAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + withdrawerFinalBalance := balRes.Balance + Expect(withdrawerFinalBalance.Amount).To(Equal(withdrawerInitialBalance.Amount.Add(accruedRewardsAmt))) + + // contract balance should remain unchanged + balRes, err = s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + contractFinalBalance := balRes.Balance + Expect(contractFinalBalance.Amount).To(Equal(contractInitialBalance.Amount)) + }) + }) + + Context("depositValidatorRewardsPool", func() { + var depositAmt *big.Int + + BeforeEach(func() { //nolint:dupl + depositAmt = big.NewInt(1_000_000) + + // populate default arguments + callArgs.MethodName = "testDepositValidatorRewardsPool" + }) + + When("depositor is different from the depositing contract", func() { + It("should fail to deposit rewards to the validator rewards pool", func() { + callArgs.Args = []interface{}{ + differentAddr, + s.network.GetValidators()[0].OperatorAddress, + []cmn.Coin{ + {Denom: s.bondDenom, Amount: depositAmt}, + }, + } + txArgs.GasPrice = gasPrice.BigInt() + + failureCheck := defaultLogCheck.WithErrContains(vm.ErrExecutionReverted.Error()) + + _, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + failureCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + // check that the contract balance didn't change + balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + signerFinalBalance := balRes.Balance + Expect(signerFinalBalance.Amount).To(Equal(signerFinalBalance.Amount)) + }) + }) + + // Specific BeforeEach for table-driven tests + Context("Table-driven tests for DepositValidatorRewardsPool", func() { + BeforeEach(func() { + callArgs.MethodName = "testDepositValidatorRewardsPoolWithTransfer" + + // send some funds to the contract + err := utils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), contractAddr.Bytes(), math.NewInt(2e18)) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + }) + + DescribeTable("deposit vaidator rewards pool with internal transfers to delegator - should withdraw rewards successfully to the withdrawer address", + func(tc testCase) { + txSender := s.keyring.GetAccAddr(0) + txSenderKey := s.keyring.GetPrivKey(0) + + balRes, err := s.grpcHandler.GetBalanceFromBank(contractAccAddr, s.bondDenom) + Expect(err).To(BeNil()) + contractInitialBalance := balRes.Balance + balRes, err = s.grpcHandler.GetBalanceFromBank(txSender, s.bondDenom) + Expect(err).To(BeNil()) + txSenderInitialBalance := balRes.Balance + + callArgs.Args = []interface{}{ + s.network.GetValidators()[0].OperatorAddress, + []cmn.Coin{ + {Denom: s.bondDenom, Amount: depositAmt}, + }, + tc.before, + tc.after, + } + + txArgs.GasPrice = gasPrice.BigInt() + + logCheckArgs := passCheck. + WithExpEvents(distribution.EventTypeDepositValidatorRewardsPool) + + res, _, err := s.factory.CallContractAndCheckLogs( + txSenderKey, + txArgs, + callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil(), "error on NextBlock: %v", err) + + fees := math.NewIntFromBigInt(txArgs.GasPrice).MulRaw(res.GasUsed) + + // check balances + contractTransferredAmt := math.ZeroInt() + for _, transferred := range []bool{tc.before, tc.after} { + if transferred { + contractTransferredAmt = contractTransferredAmt.AddRaw(15) + } + } + // contract balance be updated according to the transferred amount and deposit amount + balRes, err = s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + contractFinalBalance := balRes.Balance + Expect(contractFinalBalance.Amount).To(Equal( + contractInitialBalance.Amount. + Sub(math.NewIntFromBigInt(depositAmt)). + Sub(contractTransferredAmt))) + + // tx sender balance should be updated according to the transferred amount and fees + balRes, err = s.grpcHandler.GetBalanceFromBank(txSender, s.bondDenom) + Expect(err).To(BeNil()) + txSenderFinalBalance := balRes.Balance + Expect(txSenderFinalBalance.Amount).To(Equal( + txSenderInitialBalance.Amount. + Sub(fees). + Add(contractTransferredAmt))) + }, + + Entry("delegator == withdrawer - with internal transfers before and after precompile call", testCase{ + before: true, + after: true, + }), + + Entry("delegator == withdrawer - with internal transfers before precompile call", testCase{ + before: true, + after: false, + }), + + Entry("delegator == withdrawer - with internal transfers after precompile call", testCase{ + before: false, + after: true, + }), + ) + }) + }) + + Context("depositValidatorRewardsPool with contract as depositor", func() { + var ( + contractInitialBalance *sdk.Coin + depositAmt *big.Int + ) + + BeforeEach(func() { //nolint:dupl + // send funds to the contract + err := utils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), contractAddr.Bytes(), math.NewInt(2e18)) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + balRes, err := s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + contractInitialBalance = balRes.Balance + + depositAmt = big.NewInt(1_000_000) + + // populate default arguments + callArgs.MethodName = "testDepositValidatorRewardsPool" + }) + + It("should deposit rewards to the validator rewards pool", func() { + callArgs.Args = []interface{}{ + contractAddr, + s.network.GetValidators()[0].OperatorAddress, + []cmn.Coin{ + {Denom: s.bondDenom, Amount: depositAmt}, + }, + } + txArgs.GasPrice = gasPrice.BigInt() + + logCheckArgs := passCheck.WithExpEvents(distribution.EventTypeDepositValidatorRewardsPool) + + _, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + // tx signer should have paid the fees + balRes, err := s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + contractFinalBalance := balRes.Balance + Expect(contractFinalBalance.Amount).To(Equal(contractInitialBalance.Amount.Sub(math.NewIntFromBigInt(depositAmt)))) + }) + }) + + Context("Forbidden operations", func() { + It("should revert state: modify withdraw address & then try to withdraw rewards corresponding to another user", func() { + // check signer address balance should've decreased (fees paid) + balanceRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + initBalanceAmt := balanceRes.Balance.Amount + + _, err = utils.WaitToAccrueRewards(s.network, s.grpcHandler, s.keyring.GetAccAddr(0).String(), minExpRewardOrCommission) + Expect(err).To(BeNil()) + + callArgs.MethodName = "testRevertState" + callArgs.Args = []interface{}{ + differentAddr.String(), differentAddr, s.network.GetValidators()[0].OperatorAddress, + } + + _, _, err = s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + execRevertedCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + // check withdraw address didn't change + res, err := s.grpcHandler.GetDelegatorWithdrawAddr(s.keyring.GetAccAddr(0).String()) + Expect(err).To(BeNil(), "error while calling the precompile") + Expect(res.WithdrawAddress).To(Equal(s.keyring.GetAccAddr(0).String())) + + // check signer address balance should've decreased (fees paid) + balanceRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + Expect(balanceRes.Balance.Amount.LTE(initBalanceAmt)).To(BeTrue()) + + // check other address' balance remained unchanged + balanceRes, err = s.grpcHandler.GetBalanceFromBank(differentAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + Expect(balanceRes.Balance.Amount).To(Equal(math.ZeroInt())) + }) + + It("should not allow to call SetWithdrawAddress using delegatecall", func() { + callArgs.MethodName = "delegateCallSetWithdrawAddress" + callArgs.Args = []interface{}{s.keyring.GetAddr(0), differentAddr.String()} + + _, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + execRevertedCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + // check withdraw address didn't change + res, err := s.grpcHandler.GetDelegatorWithdrawAddr(s.keyring.GetAccAddr(0).String()) + Expect(err).To(BeNil(), "error while calling the precompile") + Expect(res.WithdrawAddress).To(Equal(s.keyring.GetAccAddr(0).String())) + }) + + It("should not allow to call txs (SetWithdrawAddress) using staticcall", func() { + callArgs.MethodName = "staticCallSetWithdrawAddress" + callArgs.Args = []interface{}{s.keyring.GetAddr(0), differentAddr.String()} + + _, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + execRevertedCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + // check withdraw address didn't change + res, err := s.grpcHandler.GetDelegatorWithdrawAddr(s.keyring.GetAccAddr(0).String()) + Expect(err).To(BeNil(), "error while calling the precompile") + Expect(res.WithdrawAddress).To(Equal(s.keyring.GetAccAddr(0).String())) + }) + }) + + // =================================== + // QUERIES + // =================================== + Context("Distribution precompile queries", Ordered, func() { + It("should get validator distribution info", func() { + // fund validator account to make self-delegation + err := utils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), s.validatorsKeys[0].AccAddr, math.NewInt(1e17)) + Expect(err).To(BeNil()) + // persist changes + Expect(s.network.NextBlock()).To(BeNil()) + + opAddr := s.network.GetValidators()[0].OperatorAddress + // use the validator priv key + // make a self delegation + err = s.factory.Delegate(s.validatorsKeys[0].Priv, opAddr, sdk.NewCoin(s.bondDenom, math.NewInt(1))) + Expect(err).To(BeNil()) + // persist changes + Expect(s.network.NextBlock()).To(BeNil()) + + callArgs.MethodName = "getValidatorDistributionInfo" + callArgs.Args = []interface{}{opAddr} + txArgs.GasLimit = 200_000 + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.validatorsKeys[0].Priv, + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var out distribution.ValidatorDistributionInfoOutput + err = s.precompile.UnpackIntoInterface(&out, distribution.ValidatorDistributionInfoMethod, ethRes.Ret) + Expect(err).To(BeNil()) + + expAddr := s.validatorsKeys[0].AccAddr.String() + + Expect(expAddr).To(Equal(out.DistributionInfo.OperatorAddress)) + Expect(1).To(Equal(len(out.DistributionInfo.Commission))) + Expect(1).To(Equal(len(out.DistributionInfo.SelfBondRewards))) + }) + + It("should get validator outstanding rewards", func() { + opAddr := s.network.GetValidators()[0].OperatorAddress + callArgs.MethodName = "getValidatorOutstandingRewards" + callArgs.Args = []interface{}{opAddr} + + _, err := utils.WaitToAccrueRewards(s.network, s.grpcHandler, s.keyring.GetAccAddr(0).String(), minExpRewardOrCommission) + Expect(err).To(BeNil(), "error while calling the precompile") + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var rewards []cmn.DecCoin + err = s.precompile.UnpackIntoInterface(&rewards, distribution.ValidatorOutstandingRewardsMethod, ethRes.Ret) + Expect(err).To(BeNil()) + Expect(len(rewards)).To(Equal(1)) + Expect(uint8(18)).To(Equal(rewards[0].Precision)) + Expect(s.bondDenom).To(Equal(rewards[0].Denom)) + + res, err := s.grpcHandler.GetValidatorOutstandingRewards(opAddr) + Expect(err).To(BeNil()) + + expRewardsAmt := res.Rewards.Rewards.AmountOf(s.bondDenom).TruncateInt() + Expect(expRewardsAmt.IsPositive()).To(BeTrue()) + Expect(rewards[0].Amount).To(Equal(expRewardsAmt.BigInt())) + }) + + Context("get validator commission", func() { + BeforeEach(func() { + callArgs.MethodName = "getValidatorCommission" + callArgs.Args = []interface{}{s.network.GetValidators()[0].OperatorAddress} + }) + + // // TODO: currently does not work because the minting happens on the Beginning of each block + // // In future SDK releases this will be possible to adjust by passing a custom `MintFn` -> check + // // https://docs.cosmos.network/main/build/modules/mint#epoch-minting + // + // It("should not get commission - validator without commission", func() { + // // fund validator account to claim commission (if any) + // err = testutils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), s.validatorsKeys[0].AccAddr, math.NewInt(1e18)) + // Expect(err).To(BeNil()) + // Expect(s.network.NextBlock()).To(BeNil()) + // + // // withdraw validator commission + // err = s.factory.WithdrawValidatorCommission(s.validatorsKeys[0].Priv) + // Expect(err).To(BeNil()) + // Expect(s.network.NextBlock()).To(BeNil()) + // + // _, ethRes, err := s.factory.CallContractAndCheckLogs( + // s.keyring.GetPrivKey(0), + // txArgs, + // callArgs, + // passCheck, + // ) + // Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + // + // var commission []cmn.DecCoin + // err = s.precompile.UnpackIntoInterface(&commission, ValidatorCommissionMethod, ethRes.Ret) + // Expect(err).To(BeNil()) + // Expect(len(commission)).To(Equal(1)) + // Expect(commission[0].Amount.Int64()).To(Equal(int64(0))) + // }) + + It("should get commission - validator with commission", func() { + _, err = utils.WaitToAccrueCommission(s.network, s.grpcHandler, s.network.GetValidators()[0].OperatorAddress, minExpRewardOrCommission) + Expect(err).To(BeNil()) + + commRes, err := s.grpcHandler.GetValidatorCommission(s.network.GetValidators()[0].OperatorAddress) + Expect(err).To(BeNil()) + + accruedCommission := commRes.Commission.Commission + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var commission []cmn.DecCoin + err = s.precompile.UnpackIntoInterface(&commission, distribution.ValidatorCommissionMethod, ethRes.Ret) + Expect(err).To(BeNil()) + Expect(len(commission)).To(Equal(1)) + Expect(uint8(18)).To(Equal(commission[0].Precision)) + Expect(s.bondDenom).To(Equal(commission[0].Denom)) + + accruedCommissionAmt := accruedCommission.AmountOf(s.bondDenom).TruncateInt() + + Expect(commission[0].Amount).To(Equal(accruedCommissionAmt.BigInt())) + }) + }) + + Context("get validator slashing events", Ordered, func() { + BeforeEach(func() { + callArgs.MethodName = "getValidatorSlashes" + callArgs.Args = []interface{}{ + s.network.GetValidators()[0].OperatorAddress, + uint64(1), uint64(5), + query.PageRequest{}, + } + }) + + AfterEach(func() { + // NOTE: The first test case will not have the slashes + // so keep this in mind when adding/removing new testcases + s.withValidatorSlashes = true + }) + + AfterAll(func() { + s.withValidatorSlashes = false + }) + + It("should not get slashing events - validator without slashes", func() { + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var out distribution.ValidatorSlashesOutput + err = s.precompile.UnpackIntoInterface(&out, distribution.ValidatorSlashesMethod, ethRes.Ret) + Expect(err).To(BeNil()) + Expect(len(out.Slashes)).To(Equal(0)) + }) + + It("should get slashing events - validator with slashes (default pagination)", func() { + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var out distribution.ValidatorSlashesOutput + err = s.precompile.UnpackIntoInterface(&out, distribution.ValidatorSlashesMethod, ethRes.Ret) + Expect(err).To(BeNil()) + Expect(len(out.Slashes)).To(Equal(2)) + // expected values according to the values used on test setup (custom genesis) + for _, s := range out.Slashes { + Expect(s.Fraction.Value).To(Equal(math.LegacyNewDecWithPrec(5, 2).BigInt())) + Expect(s.ValidatorPeriod).To(Equal(uint64(1))) + } + Expect(uint64(2)).To(Equal(out.PageResponse.Total)) + Expect(out.PageResponse.NextKey).To(BeEmpty()) + }) + + It("should get slashing events - validator with slashes w/pagination", func() { + // set pagination + callArgs.Args = []interface{}{ + s.network.GetValidators()[0].OperatorAddress, + uint64(1), uint64(5), + query.PageRequest{ + Limit: 1, + CountTotal: true, + }, + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var out distribution.ValidatorSlashesOutput + err = s.precompile.UnpackIntoInterface(&out, distribution.ValidatorSlashesMethod, ethRes.Ret) + Expect(err).To(BeNil()) + Expect(len(out.Slashes)).To(Equal(1)) + Expect(out.Slashes[0].Fraction.Value).To(Equal(math.LegacyNewDecWithPrec(5, 2).BigInt())) + Expect(out.Slashes[0].ValidatorPeriod).To(Equal(uint64(1))) + Expect(uint64(2)).To(Equal(out.PageResponse.Total)) + Expect(out.PageResponse.NextKey).NotTo(BeEmpty()) + }) + }) + + Context("get delegation rewards", func() { + BeforeEach(func() { + callArgs.MethodName = "getDelegationRewards" + callArgs.Args = []interface{}{s.keyring.GetAddr(0), s.network.GetValidators()[0].OperatorAddress} + }) + + // // TODO: currently does not work because the minting happens on the Beginning of each block + // // In future SDK releases this will be possible to adjust by passing a custom `MintFn` -> check + // // https://docs.cosmos.network/main/build/modules/mint#epoch-minting + // + // It("should not get rewards - no rewards available", func() { + // // withdraw rewards if available + // err := s.factory.WithdrawDelegationRewards(s.keyring.GetPrivKey(0), s.network.GetValidators()[0].OperatorAddress) + // Expect(err).To(BeNil()) + // Expect(s.network.NextBlock()).To(BeNil()) + // + // // add gas limit to avoid out of gas error + // txArgs.GasLimit = 200_000 + // _, ethRes, err := s.factory.CallContractAndCheckLogs( + // s.keyring.GetPrivKey(0), + // txArgs, + // callArgs, + // passCheck, + // ) + // Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + // + // var rewards []cmn.DecCoin + // err = s.precompile.UnpackIntoInterface(&rewards, DelegationRewardsMethod, ethRes.Ret) + // Expect(err).To(BeNil()) + // Expect(len(rewards)).To(Equal(0)) + // }) + + It("should get rewards", func() { + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var rewards []cmn.DecCoin + err = s.precompile.UnpackIntoInterface(&rewards, distribution.DelegationRewardsMethod, ethRes.Ret) + Expect(err).To(BeNil()) + Expect(len(rewards)).To(Equal(1)) + Expect(len(rewards)).To(Equal(1)) + Expect(rewards[0].Denom).To(Equal(s.bondDenom)) + Expect(rewards[0].Amount.Int64()).To(BeNumerically(">", 0), "expected rewards amount to be greater than 0") + }) + }) + + Context("get delegator's total rewards", func() { + BeforeEach(func() { + callArgs.MethodName = "getDelegationTotalRewards" + callArgs.Args = []interface{}{s.keyring.GetAddr(0)} + }) + + // // TODO: currently does not work because the minting happens on the Beginning of each block + // // In future SDK releases this will be possible to adjust by passing a custom `MintFn` -> check + // // https://docs.cosmos.network/main/build/modules/mint#epoch-minting + // + // It("should not get rewards - no rewards available", func() { + // // create a delegation + // err := s.factory.Delegate(s.keyring.GetPrivKey(1), s.network.GetValidators()[0].OperatorAddress, sdk.NewCoin(s.bondDenom, math.NewInt(1))) + // Expect(err).To(BeNil()) + // Expect(s.network.NextBlock()).To(BeNil()) + // + // callArgs.Args = []interface{}{s.keyring.GetAddr(1)} + // txArgs.GasLimit = 200_000 // set gas limit to avoid out of gas error + // _, ethRes, err := s.factory.CallContractAndCheckLogs( + // s.keyring.GetPrivKey(1), + // txArgs, + // callArgs, + // passCheck, + // ) + // Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + // + // var out DelegationTotalRewardsOutput + // err = s.precompile.UnpackIntoInterface(&out, DelegationTotalRewardsMethod, ethRes.Ret) + // Expect(err).To(BeNil()) + // Expect(len(out.Rewards)).To(Equal(1)) + // Expect(len(out.Rewards[0].Reward)).To(Equal(0)) + // }) + + It("should get total rewards", func() { + // wait to get rewards + accruedRewards, err := utils.WaitToAccrueRewards(s.network, s.grpcHandler, s.keyring.GetAccAddr(0).String(), minExpRewardOrCommission) + Expect(err).To(BeNil()) + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var out distribution.DelegationTotalRewardsOutput + + err = s.precompile.UnpackIntoInterface(&out, distribution.DelegationTotalRewardsMethod, ethRes.Ret) + Expect(err).To(BeNil()) + + // The accrued rewards are based on 3 equal delegations to the existing 3 validators + accruedRewardsAmt := accruedRewards.AmountOf(s.bondDenom) + + // the response order may change + for _, or := range out.Rewards { + Expect(1).To(Equal(len(or.Reward))) + Expect(or.Reward[0].Denom).To(Equal(s.bondDenom)) + Expect(or.Reward[0].Amount.Int64()).To(BeNumerically(">", 0), "expected rewards amount to be greater than 0") + } + + Expect(1).To(Equal(len(out.Total))) + Expect(out.Total[0].Amount).To(Equal(accruedRewardsAmt.TruncateInt().BigInt())) + }) + + Context("query call with revert - all changes should revert to corresponding stateDB snapshot", func() { + var ( + reverterContract evmtypes.CompiledContract + reverterAddr common.Address + testContractInitialBalance = math.NewInt(1000) + ) + BeforeEach(func() { + var err error + // Deploy Reverter contract + reverterContract, err = contracts.LoadReverterContract() + Expect(err).To(BeNil(), "error while loading the Reverter contract") + + reverterAddr, err = s.factory.DeployContract( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values + testutiltypes.ContractDeploymentData{ + Contract: reverterContract, + }, + ) + Expect(err).To(BeNil(), "error while deploying the smart contract: %v", err) + // persist state change + Expect(s.network.NextBlock()).To(BeNil()) + + // send some funds to the Reverter contracts to transfer to the + // delegator during the tx + err = utils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), reverterAddr.Bytes(), testContractInitialBalance) + Expect(err).To(BeNil(), "error while funding the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + }) + + It("should revert the execution - Reverter contract", func() { + args := testutiltypes.CallArgs{ + ContractABI: reverterContract.ABI, + MethodName: "run", + } + _, _, err = s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{ + To: &reverterAddr, + GasPrice: gasPrice.BigInt(), + }, + args, + execRevertedCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + balRes, err := s.grpcHandler.GetBalanceFromBank(reverterAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + + contractFinalBalance := balRes.Balance + Expect(contractFinalBalance.Amount).To(Equal(testContractInitialBalance)) + }) + }) + }) + + Context("get all delegator validators", func() { + BeforeEach(func() { + callArgs.MethodName = "getDelegatorValidators" + callArgs.Args = []interface{}{s.keyring.GetAddr(0)} + }) + + It("should get all validators a delegator has delegated to", func() { + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var validators []string + err = s.precompile.UnpackIntoInterface(&validators, distribution.DelegatorValidatorsMethod, ethRes.Ret) + Expect(err).To(BeNil()) + Expect(3).To(Equal(len(validators))) + }) + }) + + Context("get withdraw address", func() { + BeforeEach(func() { + callArgs.MethodName = "getDelegatorWithdrawAddress" + callArgs.Args = []interface{}{s.keyring.GetAddr(0)} + }) + + It("should get withdraw address", func() { + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + withdrawAddr, err := s.precompile.Unpack(distribution.DelegatorWithdrawAddressMethod, ethRes.Ret) + Expect(err).To(BeNil()) + // get the bech32 encoding + expAddr := sdk.AccAddress(s.keyring.GetAddr(0).Bytes()) + Expect(withdrawAddr[0]).To(Equal(expAddr.String())) + }) + + It("should call GetWithdrawAddress using staticcall", func() { + callArgs.MethodName = "staticCallGetWithdrawAddress" + callArgs.Args = []interface{}{s.keyring.GetAddr(0)} + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + withdrawAddr, err := s.precompile.Unpack(distribution.DelegatorWithdrawAddressMethod, ethRes.Ret) + Expect(err).To(BeNil()) + // get the bech32 encoding + expAddr := sdk.AccAddress(s.keyring.GetAddr(0).Bytes()) + Expect(withdrawAddr[0]).To(ContainSubstring(expAddr.String())) + }) + }) + + Context("get community pool coins", func() { + It("should get community pool coins", func() { + callArgs.MethodName = "getCommunityPool" + callArgs.Args = []interface{}{} + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var coins []cmn.DecCoin + err = s.precompile.UnpackIntoInterface(&coins, distribution.CommunityPoolMethod, ethRes.Ret) + Expect(err).To(BeNil()) + Expect(len(coins)).To(Equal(1)) + Expect(s.bondDenom).To(Equal(coins[0].Denom)) + }) + }) + }) + }) + + // Run Ginkgo integration tests + RegisterFailHandler(Fail) + RunSpecs(t, "Distribution Precompile Suite") +} diff --git a/precompiles/distribution/query_test.go b/tests/integration/precompiles/distribution/test_query.go similarity index 96% rename from precompiles/distribution/query_test.go rename to tests/integration/precompiles/distribution/test_query.go index 06242e84e..5ae049a34 100644 --- a/precompiles/distribution/query_test.go +++ b/tests/integration/precompiles/distribution/test_query.go @@ -1,4 +1,4 @@ -package distribution_test +package distribution import ( "fmt" @@ -100,7 +100,7 @@ func (s *PrecompileTestSuite) TestValidatorDistributionInfo() { s.Require().NoError(err) // make a self delegation - _, err = s.network.App.StakingKeeper.Delegate(ctx, valAddr.Bytes(), amt, stakingtypes.Unspecified, s.network.GetValidators()[0], true) + _, err = s.network.App.GetStakingKeeper().Delegate(ctx, valAddr.Bytes(), amt, stakingtypes.Unspecified, s.network.GetValidators()[0], true) s.Require().NoError(err) return []interface{}{ s.network.GetValidators()[0].OperatorAddress, @@ -195,7 +195,7 @@ func (s *PrecompileTestSuite) TestValidatorOutstandingRewards() { valAddr, err := sdk.ValAddressFromBech32(s.network.GetValidators()[0].GetOperator()) s.Require().NoError(err) - err = s.network.App.DistrKeeper.SetValidatorOutstandingRewards(ctx, valAddr, types.ValidatorOutstandingRewards{Rewards: valRewards}) + err = s.network.App.GetDistrKeeper().SetValidatorOutstandingRewards(ctx, valAddr, types.ValidatorOutstandingRewards{Rewards: valRewards}) s.Require().NoError(err) return []interface{}{ @@ -288,7 +288,7 @@ func (s *PrecompileTestSuite) TestValidatorCommission() { valAddr, err := sdk.ValAddressFromBech32(validator.GetOperator()) s.Require().NoError(err) valCommission := sdk.DecCoins{sdk.NewDecCoinFromDec(s.bondDenom, commAmt)} - err = s.network.App.DistrKeeper.SetValidatorAccumulatedCommission(ctx, valAddr, types.ValidatorAccumulatedCommission{Commission: valCommission}) + err = s.network.App.GetDistrKeeper().SetValidatorAccumulatedCommission(ctx, valAddr, types.ValidatorAccumulatedCommission{Commission: valCommission}) s.Require().NoError(err) // set distribution module account balance which pays out the commission @@ -434,7 +434,7 @@ func (s *PrecompileTestSuite) TestValidatorSlashes() { func() []interface{} { valAddr, err := sdk.ValAddressFromBech32(s.network.GetValidators()[0].GetOperator()) s.Require().NoError(err) - err = s.network.App.DistrKeeper.SetValidatorSlashEvent(ctx, valAddr, 2, 1, types.ValidatorSlashEvent{ValidatorPeriod: 1, Fraction: math.LegacyNewDec(5)}) + err = s.network.App.GetDistrKeeper().SetValidatorSlashEvent(ctx, valAddr, 2, 1, types.ValidatorSlashEvent{ValidatorPeriod: 1, Fraction: math.LegacyNewDec(5)}) s.Require().NoError(err) return []interface{}{ s.network.GetValidators()[0].OperatorAddress, @@ -460,7 +460,7 @@ func (s *PrecompileTestSuite) TestValidatorSlashes() { func() []interface{} { valAddr, err := sdk.ValAddressFromBech32(s.network.GetValidators()[0].GetOperator()) s.Require().NoError(err) - err = s.network.App.DistrKeeper.SetValidatorSlashEvent(ctx, valAddr, 2, 1, types.ValidatorSlashEvent{ValidatorPeriod: 1, Fraction: math.LegacyNewDec(5)}) + err = s.network.App.GetDistrKeeper().SetValidatorSlashEvent(ctx, valAddr, 2, 1, types.ValidatorSlashEvent{ValidatorPeriod: 1, Fraction: math.LegacyNewDec(5)}) s.Require().NoError(err) return []interface{}{ s.network.GetValidators()[0].OperatorAddress, @@ -931,7 +931,7 @@ func (s *PrecompileTestSuite) TestCommunityPool() { "success - with community pool", func() []interface{} { amt := math.NewInt(expValAmount) - err := s.network.App.DistrKeeper.FundCommunityPool(ctx, sdk.NewCoins(sdk.NewCoin(s.bondDenom, amt)), s.keyring.GetAccAddr(0)) + err := s.network.App.GetDistrKeeper().FundCommunityPool(ctx, sdk.NewCoins(sdk.NewCoin(s.bondDenom, amt)), s.keyring.GetAccAddr(0)) s.Require().NoError(err) return []interface{}{} diff --git a/precompiles/distribution/setup_test.go b/tests/integration/precompiles/distribution/test_setup.go similarity index 78% rename from precompiles/distribution/setup_test.go rename to tests/integration/precompiles/distribution/test_setup.go index a3ef84c76..ff0bdb6ec 100644 --- a/precompiles/distribution/setup_test.go +++ b/tests/integration/precompiles/distribution/test_setup.go @@ -1,16 +1,14 @@ -package distribution_test +package distribution import ( - "testing" - "github.com/stretchr/testify/suite" "github.com/cosmos/evm/precompiles/distribution" testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + testkeyring "github.com/cosmos/evm/testutil/keyring" evmtypes "github.com/cosmos/evm/x/vm/types" "cosmossdk.io/math" @@ -23,6 +21,8 @@ import ( type PrecompileTestSuite struct { suite.Suite + create network.CreateEvmApp + options []network.ConfigOption network *network.UnitTestNetwork factory factory.TxFactory grpcHandler grpc.Handler @@ -36,8 +36,14 @@ type PrecompileTestSuite struct { withValidatorSlashes bool } -func TestPrecompileUnitTestSuite(t *testing.T) { - suite.Run(t, new(PrecompileTestSuite)) +func NewPrecompileTestSuite( + create network.CreateEvmApp, + options ...network.ConfigOption, +) *PrecompileTestSuite { + return &PrecompileTestSuite{ + create: create, + options: options, + } } func (s *PrecompileTestSuite) SetupTest() { @@ -80,18 +86,20 @@ func (s *PrecompileTestSuite) SetupTest() { testconstants.OtherCoinDenoms[1], } - nw := network.NewUnitTestNetwork( + options := []network.ConfigOption{ network.WithOtherDenoms(testconstants.OtherCoinDenoms), network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), network.WithOtherDenoms(s.otherDenoms), network.WithCustomGenesis(customGen), network.WithValidatorOperators(operatorsAddr), - ) + } + options = append(options, s.options...) + nw := network.NewUnitTestNetwork(s.create, options...) grpcHandler := grpc.NewIntegrationHandler(nw) txFactory := factory.New(nw, grpcHandler) ctx := nw.GetContext() - sk := nw.App.StakingKeeper + sk := nw.App.GetStakingKeeper() bondDenom, err := sk.BondDenom(ctx) if err != nil { panic(err) @@ -106,9 +114,9 @@ func (s *PrecompileTestSuite) SetupTest() { s.keyring = keyring s.network = nw s.precompile, err = distribution.NewPrecompile( - s.network.App.DistrKeeper, - *s.network.App.StakingKeeper, - s.network.App.EVMKeeper, + s.network.App.GetDistrKeeper(), + *s.network.App.GetStakingKeeper(), + s.network.App.GetEVMKeeper(), ) if err != nil { panic(err) diff --git a/precompiles/distribution/tx_test.go b/tests/integration/precompiles/distribution/test_tx.go similarity index 89% rename from precompiles/distribution/tx_test.go rename to tests/integration/precompiles/distribution/test_tx.go index dcebb4402..33db8c8b1 100644 --- a/precompiles/distribution/tx_test.go +++ b/tests/integration/precompiles/distribution/test_tx.go @@ -1,4 +1,4 @@ -package distribution_test +package distribution import ( "fmt" @@ -11,7 +11,7 @@ import ( "github.com/cosmos/evm/precompiles/distribution" "github.com/cosmos/evm/precompiles/testutil" testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/network" utiltx "github.com/cosmos/evm/testutil/tx" "cosmossdk.io/math" @@ -80,7 +80,7 @@ func (s *PrecompileTestSuite) TestSetWithdrawAddress() { } }, func() { - withdrawerAddr, err := s.network.App.DistrKeeper.GetDelegatorWithdrawAddr(ctx, s.keyring.GetAccAddr(0)) + withdrawerAddr, err := s.network.App.GetDistrKeeper().GetDelegatorWithdrawAddr(ctx, s.keyring.GetAccAddr(0)) s.Require().NoError(err) s.Require().Equal(withdrawerAddr.String(), s.keyring.GetAccAddr(0).String()) }, @@ -97,7 +97,7 @@ func (s *PrecompileTestSuite) TestSetWithdrawAddress() { } }, func() { - withdrawerAddr, err := s.network.App.DistrKeeper.GetDelegatorWithdrawAddr(ctx, s.keyring.GetAddr(0).Bytes()) + withdrawerAddr, err := s.network.App.GetDistrKeeper().GetDelegatorWithdrawAddr(ctx, s.keyring.GetAddr(0).Bytes()) s.Require().NoError(err) s.Require().Equal(withdrawerAddr.Bytes(), newWithdrawerAddr.Bytes()) }, @@ -202,7 +202,7 @@ func (s *PrecompileTestSuite) TestWithdrawDelegatorReward() { s.Require().Equal(coins[0].Denom, testconstants.ExampleAttoDenom) s.Require().Equal(coins[0].Amount.Int64(), expRewardsAmt.Int64()) // Check bank balance after the withdrawal of rewards - balance := s.network.App.BankKeeper.GetBalance(ctx, s.keyring.GetAddr(0).Bytes(), testconstants.ExampleAttoDenom) + balance := s.network.App.GetBankKeeper().GetBalance(ctx, s.keyring.GetAddr(0).Bytes(), testconstants.ExampleAttoDenom) s.Require().True(balance.Amount.GT(network.PrefundedAccountInitialBalance)) }, 20000, @@ -277,9 +277,9 @@ func (s *PrecompileTestSuite) TestWithdrawValidatorCommission() { amt := math.LegacyNewDecWithPrec(1000000000000000000, 1) valCommission := sdk.DecCoins{sdk.NewDecCoinFromDec(testconstants.ExampleAttoDenom, amt)} // set outstanding rewards - s.Require().NoError(s.network.App.DistrKeeper.SetValidatorOutstandingRewards(ctx, valAddr, types.ValidatorOutstandingRewards{Rewards: valCommission})) + s.Require().NoError(s.network.App.GetDistrKeeper().SetValidatorOutstandingRewards(ctx, valAddr, types.ValidatorOutstandingRewards{Rewards: valCommission})) // set commission - s.Require().NoError(s.network.App.DistrKeeper.SetValidatorAccumulatedCommission(ctx, valAddr, types.ValidatorAccumulatedCommission{Commission: valCommission})) + s.Require().NoError(s.network.App.GetDistrKeeper().SetValidatorAccumulatedCommission(ctx, valAddr, types.ValidatorAccumulatedCommission{Commission: valCommission})) // fund distr mod to pay for rewards + commission coins := sdk.NewCoins(sdk.NewCoin(testconstants.ExampleAttoDenom, amt.Mul(math.LegacyNewDec(2)).RoundInt())) @@ -300,7 +300,7 @@ func (s *PrecompileTestSuite) TestWithdrawValidatorCommission() { // Check bank balance after the withdrawal of commission valAddr, err := sdk.ValAddressFromBech32(s.network.GetValidators()[0].GetOperator()) s.Require().NoError(err) - balance := s.network.App.BankKeeper.GetBalance(ctx, valAddr.Bytes(), testconstants.ExampleAttoDenom) + balance := s.network.App.GetBankKeeper().GetBalance(ctx, valAddr.Bytes(), testconstants.ExampleAttoDenom) s.Require().Equal(balance.Amount, prevBalance.Amount.Add(amt)) s.Require().Equal(balance.Denom, testconstants.ExampleAttoDenom) }, @@ -318,7 +318,7 @@ func (s *PrecompileTestSuite) TestWithdrawValidatorCommission() { valAddr, err := sdk.ValAddressFromBech32(s.network.GetValidators()[0].GetOperator()) s.Require().NoError(err) - prevBalance = s.network.App.BankKeeper.GetBalance(ctx, valAddr.Bytes(), testconstants.ExampleAttoDenom) + prevBalance = s.network.App.GetBankKeeper().GetBalance(ctx, valAddr.Bytes(), testconstants.ExampleAttoDenom) validatorAddress := common.BytesToAddress(valAddr.Bytes()) var contract *vm.Contract @@ -409,7 +409,7 @@ func (s *PrecompileTestSuite) TestClaimRewards() { } }, func(_ []byte) { - balance := s.network.App.BankKeeper.GetBalance(ctx, s.keyring.GetAccAddr(0), testconstants.ExampleAttoDenom) + balance := s.network.App.GetBankKeeper().GetBalance(ctx, s.keyring.GetAccAddr(0), testconstants.ExampleAttoDenom) // rewards from 3 validators - 5% commission expRewards := expRewardsAmt.Mul(math.NewInt(3)) s.Require().Equal(balance.Amount, prevBalance.Amount.Add(expRewards)) @@ -427,7 +427,7 @@ func (s *PrecompileTestSuite) TestClaimRewards() { } }, func([]byte) { - balance := s.network.App.BankKeeper.GetBalance(ctx, s.keyring.GetAccAddr(0), testconstants.ExampleAttoDenom) + balance := s.network.App.GetBankKeeper().GetBalance(ctx, s.keyring.GetAccAddr(0), testconstants.ExampleAttoDenom) // rewards from 3 validators - 5% commission expRewards := expRewardsAmt.Mul(math.NewInt(3)) s.Require().Equal(balance.Amount, prevBalance.Amount.Add(expRewards)) @@ -445,7 +445,7 @@ func (s *PrecompileTestSuite) TestClaimRewards() { } }, func([]byte) { - balance := s.network.App.BankKeeper.GetBalance(ctx, s.keyring.GetAccAddr(0), testconstants.ExampleAttoDenom) + balance := s.network.App.GetBankKeeper().GetBalance(ctx, s.keyring.GetAccAddr(0), testconstants.ExampleAttoDenom) s.Require().Equal(balance.Amount, prevBalance.Amount.Add(expRewardsAmt)) }, 20000, @@ -480,7 +480,7 @@ func (s *PrecompileTestSuite) TestClaimRewards() { s.Require().NoError(err) // get previous balance to compare final balance in the postCheck func - prevBalance = s.network.App.BankKeeper.GetBalance(ctx, addr.Bytes(), testconstants.ExampleAttoDenom) + prevBalance = s.network.App.GetBankKeeper().GetBalance(ctx, addr.Bytes(), testconstants.ExampleAttoDenom) bz, err := s.precompile.ClaimRewards(ctx, contract, s.network.GetStateDB(), &method, tc.malleate()) @@ -543,12 +543,12 @@ func (s *PrecompileTestSuite) TestFundCommunityPool() { } }, func([]byte) { - pool, err := s.network.App.DistrKeeper.FeePool.Get(ctx) + pool, err := s.network.App.GetDistrKeeper().FeePool.Get(ctx) s.Require().NoError(err) coins := pool.CommunityPool expectedAmount := new(big.Int).Mul(big.NewInt(1e18), new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(math.LegacyPrecision)), nil)) s.Require().Equal(expectedAmount, coins.AmountOf(testconstants.ExampleAttoDenom).BigInt()) - userBalance := s.network.App.BankKeeper.GetBalance(ctx, s.keyring.GetAddr(0).Bytes(), testconstants.ExampleAttoDenom) + userBalance := s.network.App.GetBankKeeper().GetBalance(ctx, s.keyring.GetAddr(0).Bytes(), testconstants.ExampleAttoDenom) s.Require().Equal(network.PrefundedAccountInitialBalance.Sub(math.NewInt(1e18)), userBalance.Amount) }, 20000, @@ -566,7 +566,7 @@ func (s *PrecompileTestSuite) TestFundCommunityPool() { contract, ctx = testutil.NewPrecompileContract(s.T(), ctx, s.keyring.GetAddr(0), s.precompile.Address(), tc.gas) // Sanity check to make sure the starting balance is always 100k ATOM - balance := s.network.App.BankKeeper.GetBalance(ctx, s.keyring.GetAddr(0).Bytes(), testconstants.ExampleAttoDenom) + balance := s.network.App.GetBankKeeper().GetBalance(ctx, s.keyring.GetAddr(0).Bytes(), testconstants.ExampleAttoDenom) s.Require().Equal(balance.Amount, network.PrefundedAccountInitialBalance) bz, err := s.precompile.FundCommunityPool(ctx, contract, s.network.GetStateDB(), &method, tc.malleate()) @@ -689,22 +689,22 @@ func (s *PrecompileTestSuite) TestDepositValidatorRewardsPoolMethod() { expectedOutstandingRewards := depositCoins // check validation commission - valCommission, err := s.network.App.DistrKeeper.GetValidatorAccumulatedCommission(ctx, valBz) + valCommission, err := s.network.App.GetDistrKeeper().GetValidatorAccumulatedCommission(ctx, valBz) s.Require().NoError(err) s.Require().Equal(expectedValCommission, valCommission.Commission) // check current rewards - currentRewards, err := s.network.App.DistrKeeper.GetValidatorCurrentRewards(ctx, valBz) + currentRewards, err := s.network.App.GetDistrKeeper().GetValidatorCurrentRewards(ctx, valBz) s.Require().NoError(err) s.Require().Equal(expectedCurrentRewards, currentRewards.Rewards) // check outstanding rewards - outstandingRewards, err := s.network.App.DistrKeeper.GetValidatorOutstandingRewards(ctx, valBz) + outstandingRewards, err := s.network.App.GetDistrKeeper().GetValidatorOutstandingRewards(ctx, valBz) s.Require().NoError(err) s.Require().Equal(expectedOutstandingRewards, outstandingRewards.Rewards) // check bank balance after the deposit - balance := s.network.App.BankKeeper.GetBalance(ctx, s.keyring.GetAddr(0).Bytes(), testconstants.ExampleAttoDenom) + balance := s.network.App.GetBankKeeper().GetBalance(ctx, s.keyring.GetAddr(0).Bytes(), testconstants.ExampleAttoDenom) s.Require().Equal(balance.Amount, network.PrefundedAccountInitialBalance.Sub(math.NewInt(1e18))) s.Require().Equal(balance.Denom, testconstants.ExampleAttoDenom) }, diff --git a/precompiles/distribution/utils_test.go b/tests/integration/precompiles/distribution/test_utils.go similarity index 83% rename from precompiles/distribution/utils_test.go rename to tests/integration/precompiles/distribution/test_utils.go index 5071fbb3b..df6fe0fe6 100644 --- a/precompiles/distribution/utils_test.go +++ b/tests/integration/precompiles/distribution/test_utils.go @@ -1,8 +1,8 @@ -package distribution_test +package distribution import ( "github.com/cosmos/evm/precompiles/staking" - "github.com/cosmos/evm/testutil/integration/os/keyring" + "github.com/cosmos/evm/testutil/keyring" "cosmossdk.io/math" @@ -43,7 +43,7 @@ func (s *PrecompileTestSuite) prepareStakingRewards(ctx sdk.Context, stkRs ...st // allocate rewards to validator allocatedRewards := sdk.NewDecCoins(sdk.NewDecCoin(s.bondDenom, r.RewardAmt)) - if err := s.network.App.DistrKeeper.AllocateTokensToValidator(ctx, r.Validator, allocatedRewards); err != nil { + if err := s.network.App.GetDistrKeeper().AllocateTokensToValidator(ctx, r.Validator, allocatedRewards); err != nil { return ctx, err } } @@ -54,7 +54,7 @@ func (s *PrecompileTestSuite) prepareStakingRewards(ctx sdk.Context, stkRs ...st // distribution module to pay for staking rewards. func (s *PrecompileTestSuite) mintCoinsForDistrMod(ctx sdk.Context, amount sdk.Coins) error { // Minting tokens for the FeeCollector to simulate fee accrued. - if err := s.network.App.BankKeeper.MintCoins( + if err := s.network.App.GetBankKeeper().MintCoins( ctx, minttypes.ModuleName, amount, @@ -62,7 +62,7 @@ func (s *PrecompileTestSuite) mintCoinsForDistrMod(ctx sdk.Context, amount sdk.C return err } - return s.network.App.BankKeeper.SendCoinsFromModuleToModule( + return s.network.App.GetBankKeeper().SendCoinsFromModuleToModule( ctx, minttypes.ModuleName, distrtypes.ModuleName, @@ -74,15 +74,15 @@ func (s *PrecompileTestSuite) mintCoinsForDistrMod(ctx sdk.Context, amount sdk.C // base denomination. func (s *PrecompileTestSuite) fundAccountWithBaseDenom(ctx sdk.Context, addr sdk.AccAddress, amount math.Int) error { coins := sdk.NewCoins(sdk.NewCoin(s.bondDenom, amount)) - if err := s.network.App.BankKeeper.MintCoins(ctx, minttypes.ModuleName, coins); err != nil { + if err := s.network.App.GetBankKeeper().MintCoins(ctx, minttypes.ModuleName, coins); err != nil { return err } - return s.network.App.BankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, coins) + return s.network.App.GetBankKeeper().SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, coins) } func (s *PrecompileTestSuite) getStakingPrecompile() (*staking.Precompile, error) { return staking.NewPrecompile( - *s.network.App.StakingKeeper, + *s.network.App.GetStakingKeeper(), ) } diff --git a/precompiles/erc20/approve_test.go b/tests/integration/precompiles/erc20/test_approve.go similarity index 99% rename from precompiles/erc20/approve_test.go rename to tests/integration/precompiles/erc20/test_approve.go index 9bb4189a1..0f1f1a5a8 100644 --- a/precompiles/erc20/approve_test.go +++ b/tests/integration/precompiles/erc20/test_approve.go @@ -1,4 +1,4 @@ -package erc20_test +package erc20 import ( "errors" diff --git a/precompiles/erc20/erc20_test.go b/tests/integration/precompiles/erc20/test_erc20.go similarity index 99% rename from precompiles/erc20/erc20_test.go rename to tests/integration/precompiles/erc20/test_erc20.go index 86bd5c7e3..c8c783453 100644 --- a/precompiles/erc20/erc20_test.go +++ b/tests/integration/precompiles/erc20/test_erc20.go @@ -1,4 +1,4 @@ -package erc20_test +package erc20 import ( "math/big" diff --git a/precompiles/erc20/errors_test.go b/tests/integration/precompiles/erc20/test_errors.go similarity index 89% rename from precompiles/erc20/errors_test.go rename to tests/integration/precompiles/erc20/test_errors.go index e531a2430..4614c09c9 100644 --- a/precompiles/erc20/errors_test.go +++ b/tests/integration/precompiles/erc20/test_errors.go @@ -1,7 +1,7 @@ -package erc20_test +package erc20 import ( - "github.com/cosmos/evm/precompiles/erc20" + erc21 "github.com/cosmos/evm/precompiles/erc20" evmtypes "github.com/cosmos/evm/x/vm/types" ) @@ -11,7 +11,7 @@ func (s *PrecompileTestSuite) TestBuildExecRevertedError() { s.T().Skip("skipping until correctly implemented") reason := "ERC20: transfer amount exceeds balance" - revErr, err := erc20.BuildExecRevertedErr(reason) + revErr, err := erc21.BuildExecRevertedErr(reason) s.Require().NoError(err, "should not error when building revert error") revertErr, ok := revErr.(*evmtypes.RevertError) diff --git a/precompiles/erc20/events_test.go b/tests/integration/precompiles/erc20/test_events.go similarity index 85% rename from precompiles/erc20/events_test.go rename to tests/integration/precompiles/erc20/test_events.go index 462f87f6a..648cb0c7b 100644 --- a/precompiles/erc20/events_test.go +++ b/tests/integration/precompiles/erc20/test_events.go @@ -1,4 +1,4 @@ -package erc20_test +package erc20 import ( "math/big" @@ -7,7 +7,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" cmn "github.com/cosmos/evm/precompiles/common" - erc20precompile "github.com/cosmos/evm/precompiles/erc20" + "github.com/cosmos/evm/precompiles/erc20" utiltx "github.com/cosmos/evm/testutil/tx" ) @@ -41,13 +41,13 @@ func (s *PrecompileTestSuite) TestEmitTransferEvent() { s.Require().Equal(log.Address, s.precompile.Address()) // Check event signature matches the one emitted - event := s.precompile.ABI.Events[erc20precompile.EventTypeTransfer] + event := s.precompile.ABI.Events[erc20.EventTypeTransfer] s.Require().Equal(crypto.Keccak256Hash([]byte(event.Sig)), common.HexToHash(log.Topics[0].Hex())) s.Require().Equal(log.BlockNumber, uint64(s.network.GetContext().BlockHeight())) //nolint:gosec // G115 // Check the fully unpacked event matches the one emitted - var transferEvent erc20precompile.EventTransfer - err = cmn.UnpackLog(s.precompile.ABI, &transferEvent, erc20precompile.EventTypeTransfer, *log) + var transferEvent erc20.EventTransfer + err = cmn.UnpackLog(s.precompile.ABI, &transferEvent, erc20.EventTypeTransfer, *log) s.Require().NoError(err, "unable to unpack log into transfer event") s.Require().Equal(tc.from, transferEvent.From, "expected different from address") @@ -88,13 +88,13 @@ func (s *PrecompileTestSuite) TestEmitApprovalEvent() { s.Require().Equal(log.Address, s.precompile.Address()) // Check event signature matches the one emitted - event := s.precompile.ABI.Events[erc20precompile.EventTypeApproval] + event := s.precompile.ABI.Events[erc20.EventTypeApproval] s.Require().Equal(crypto.Keccak256Hash([]byte(event.Sig)), common.HexToHash(log.Topics[0].Hex())) s.Require().Equal(log.BlockNumber, uint64(s.network.GetContext().BlockHeight())) //nolint:gosec // G115 // Check the fully unpacked event matches the one emitted - var approvalEvent erc20precompile.EventApproval - err = cmn.UnpackLog(s.precompile.ABI, &approvalEvent, erc20precompile.EventTypeApproval, *log) + var approvalEvent erc20.EventApproval + err = cmn.UnpackLog(s.precompile.ABI, &approvalEvent, erc20.EventTypeApproval, *log) s.Require().NoError(err, "unable to unpack log into approval event") s.Require().Equal(tc.owner, approvalEvent.Owner, "expected different owner address") diff --git a/tests/integration/precompiles/erc20/test_integration.go b/tests/integration/precompiles/erc20/test_integration.go new file mode 100644 index 000000000..a5c6b8708 --- /dev/null +++ b/tests/integration/precompiles/erc20/test_integration.go @@ -0,0 +1,2802 @@ +package erc20 + +import ( + "fmt" + "math/big" + "slices" + "strings" + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/stretchr/testify/suite" + + //nolint:revive // dot imports are fine for Ginkgo + . "github.com/onsi/ginkgo/v2" + //nolint:revive // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" + + "github.com/cosmos/evm/contracts" + "github.com/cosmos/evm/precompiles/erc20" + "github.com/cosmos/evm/precompiles/erc20/testdata" + "github.com/cosmos/evm/precompiles/testutil" + testconstants "github.com/cosmos/evm/testutil/constants" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/integration/evm/utils" + "github.com/cosmos/evm/testutil/keyring" + utiltx "github.com/cosmos/evm/testutil/tx" + testutiltypes "github.com/cosmos/evm/testutil/types" + erc20types "github.com/cosmos/evm/x/erc20/types" + evmtypes "github.com/cosmos/evm/x/vm/types" + + "cosmossdk.io/math" + + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +var is *IntegrationTestSuite + +type IntegrationTestSuite struct { + suite.Suite + + create network.CreateEvmApp + options []network.ConfigOption + // NOTE: we have to use the Unit testing network because we access a keeper in a setup function. + // Might adjust this on a follow-up PR. + network *network.UnitTestNetwork + handler grpc.Handler + keyring keyring.Keyring + factory factory.TxFactory + + bondDenom string + tokenDenom string // erc20 precompile denom with supply + tokenDenomTwo string // erc20 precompile denom with zero supply + + precompile *erc20.Precompile // erc20 precompile with supply + precompileTwo *erc20.Precompile // erc20 precompile with zero supply +} + +func NewIntegrationTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *IntegrationTestSuite { + return &IntegrationTestSuite{ + create: create, + options: options, + } +} + +func (is *IntegrationTestSuite) SetupTest() { + is.tokenDenom = "xmpl" + is.tokenDenomTwo = "xmpl2" + + keys := keyring.New(2) + genesis := utils.CreateGenesisWithTokenPairs(keys, is.tokenDenom, is.tokenDenomTwo) + + options := []network.ConfigOption{ + network.WithPreFundedAccounts(keys.GetAllAccAddrs()...), + network.WithOtherDenoms([]string{is.tokenDenom}), // add balance (supply) to is.tokenDenom + network.WithCustomGenesis(genesis), + } + options = append(options, is.options...) + nw := network.NewUnitTestNetwork(is.create, options...) + gh := grpc.NewIntegrationHandler(nw) + tf := factory.New(nw, gh) + + is.network = nw + is.factory = tf + is.handler = gh + is.keyring = keys + + is.bondDenom = nw.GetBaseDenom() + + erc20Gen := genesis[erc20types.ModuleName].(*erc20types.GenesisState) + is.precompile = is.setupERC20Precompile(is.tokenDenom, erc20Gen.TokenPairs) + is.precompileTwo = is.setupERC20Precompile(is.tokenDenomTwo, erc20Gen.TokenPairs) +} + +var ( + revertContractAddr common.Address + gasLimit = uint64(5000000) + gasPrice = big.NewInt(800_000_000) +) + +func TestIntegrationTestSuite(t *testing.T, create network.CreateEvmApp, options ...network.ConfigOption) { + is = NewIntegrationTestSuite(create, options...) + var _ = Describe("ERC20 Extension -", func() { + var ( + // contractsData holds the addresses and ABIs for the different + // contract instances that are subject to testing here. + contractsData ContractsData + + allowanceCallerContract evmtypes.CompiledContract + revertCallerContract evmtypes.CompiledContract + erc20MinterV5Contract evmtypes.CompiledContract + + execRevertedCheck testutil.LogCheckArgs + failCheck testutil.LogCheckArgs + passCheck testutil.LogCheckArgs + ) + + BeforeEach(func() { + is.SetupTest() + + var err error + allowanceCallerContract, err = testdata.LoadERC20AllowanceCaller() + Expect(err).ToNot(HaveOccurred(), "failed to load ERC20 allowance caller contract") + + erc20MinterV5Contract, err = testdata.LoadERC20MinterV5Contract() + Expect(err).ToNot(HaveOccurred(), "failed to load ERC20 minter contract") + + revertCallerContract, err = testdata.LoadERC20TestCaller() + Expect(err).ToNot(HaveOccurred(), "failed to load ERC20 allowance caller contract") + + sender := is.keyring.GetKey(0) + contractAddr, err := is.factory.DeployContract( + sender.Priv, + evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values + testutiltypes.ContractDeploymentData{ + Contract: allowanceCallerContract, + // NOTE: we're passing the precompile address to the constructor because that initiates the contract + // to make calls to the correct ERC20 precompile. + ConstructorArgs: []interface{}{is.precompile.Address()}, + }, + ) + Expect(err).ToNot(HaveOccurred(), "failed to deploy contract") + + // commit the changes to update state (account nonce mostly) + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "failed to advance block") + + contractAddrTokenTwo, err := is.factory.DeployContract( + sender.Priv, + evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values + testutiltypes.ContractDeploymentData{ + Contract: allowanceCallerContract, + // NOTE: we're passing the precompile address to the constructor because that initiates the contract + // to make calls to the correct ERC20 precompile. + ConstructorArgs: []interface{}{is.precompileTwo.Address()}, + }, + ) + Expect(err).ToNot(HaveOccurred(), "failed to deploy contract") + + // commit the changes to update state (account nonce mostly) + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "failed to advance block") + + erc20MinterBurnerAddr, err := is.factory.DeployContract( + sender.Priv, + evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values + testutiltypes.ContractDeploymentData{ + Contract: contracts.ERC20MinterBurnerDecimalsContract, + ConstructorArgs: []interface{}{ + "Xmpl", "Xmpl", uint8(6), + }, + }, + ) + Expect(err).ToNot(HaveOccurred(), "failed to deploy ERC20 minter burner contract") + + // commit the changes to update state (account nonce mostly) + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "failed to advance block") + + ERC20MinterV5Addr, err := is.factory.DeployContract( + sender.Priv, + evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values + testutiltypes.ContractDeploymentData{ + Contract: erc20MinterV5Contract, + ConstructorArgs: []interface{}{ + "Xmpl", "Xmpl", + }, + }, + ) + Expect(err).ToNot(HaveOccurred(), "failed to deploy ERC20 minter contract") + + // commit the changes to update state (account nonce mostly) + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "failed to advance block") + + erc20MinterV5CallerAddr, err := is.factory.DeployContract( + sender.Priv, + evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values + testutiltypes.ContractDeploymentData{ + Contract: allowanceCallerContract, + ConstructorArgs: []interface{}{ + ERC20MinterV5Addr, + }, + }, + ) + Expect(err).ToNot(HaveOccurred(), "failed to deploy ERC20 minter caller contract") + + // commit the changes to update state (account nonce mostly) + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "failed to advance block") + + // Store the data of the deployed contracts + contractsData = ContractsData{ + ownerPriv: sender.Priv, + contractData: map[CallType]ContractData{ + directCall: { + Address: is.precompile.Address(), + ABI: is.precompile.ABI, + }, + directCallToken2: { + Address: is.precompileTwo.Address(), + ABI: is.precompileTwo.ABI, + }, + contractCall: { + Address: contractAddr, + ABI: allowanceCallerContract.ABI, + }, + contractCallToken2: { + Address: contractAddrTokenTwo, + ABI: allowanceCallerContract.ABI, + }, + erc20Call: { + Address: erc20MinterBurnerAddr, + ABI: contracts.ERC20MinterBurnerDecimalsContract.ABI, + }, + erc20V5Call: { + Address: ERC20MinterV5Addr, + ABI: erc20MinterV5Contract.ABI, + }, + erc20V5CallerCall: { + Address: erc20MinterV5CallerAddr, + ABI: allowanceCallerContract.ABI, + }, + }, + } + + failCheck = testutil.LogCheckArgs{ABIEvents: is.precompile.Events} + execRevertedCheck = failCheck.WithErrContains("execution reverted") + passCheck = failCheck.WithExpPass(true) + + erc20Params := is.network.App.GetErc20Keeper().GetParams(is.network.GetContext()) + Expect(len(erc20Params.NativePrecompiles)).To(Equal(1)) + Expect(common.HexToAddress(erc20Params.NativePrecompiles[0])).To(Equal(common.HexToAddress(testconstants.WEVMOSContractMainnet))) + + revertContractAddr, err = is.factory.DeployContract( + sender.Priv, + evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values + testutiltypes.ContractDeploymentData{ + Contract: revertCallerContract, + // NOTE: we're passing the precompile address to the constructor because that initiates the contract + // to make calls to the correct ERC20 precompile. + ConstructorArgs: []interface{}{common.HexToAddress(erc20Params.NativePrecompiles[0])}, + }, + ) + Expect(err).ToNot(HaveOccurred(), "failed to deploy reverter contract") + + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "failed to advance block") + }) + + Context("basic functionality -", func() { + When("sending tokens to contract", func() { + It("it should return error", func() { + sender := is.keyring.GetKey(0) + fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)} + + // Fund account with some tokens + is.fundWithTokens(directCall, contractsData, sender.Addr, fundCoins) + + // Taking custom args from the table entry + txArgs := evmtypes.EvmTxArgs{} + txArgs.Amount = big.NewInt(int64(1000)) + precompileAddress := is.precompile.Address() + txArgs.To = &precompileAddress + + _, err := is.factory.ExecuteEthTx(sender.Priv, txArgs) + // Currently, this check pass because the erc20 precompile does + // not expose a fallback handler. Adding a fallback handler, the + // test should pass again because of the check on the message + // value in the precompile before the setup. + Expect(err.Error()).To(ContainSubstring(vm.ErrExecutionReverted.Error()), "precompile should not accept transfers") + }, + ) + }) + When("transferring tokens", func() { + DescribeTable("it should transfer tokens to a non-existing address", func(callType CallType, expGasUsedLowerBound int64, expGasUsedUpperBound int64) { + sender := is.keyring.GetKey(0) + receiver := utiltx.GenerateAddress() + fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)} + transferCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)} + + senderInitialAmt := is.fundWithTokens(callType, contractsData, sender.Addr, fundCoins) + senderInitialBalance := sdk.Coins{sdk.NewCoin(is.tokenDenom, senderInitialAmt)} + + // Transfer tokens + txArgs, transferArgs := is.getTxAndCallArgs(callType, contractsData, erc20.TransferMethod, receiver, transferCoins[0].Amount.BigInt()) + + transferCheck := passCheck.WithExpEvents(erc20.EventTypeTransfer) + + res, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, transferArgs, transferCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.TransferMethod) + is.ExpectBalancesForContract( + callType, contractsData, + []ExpectedBalance{ + {address: sender.AccAddr, expCoins: senderInitialBalance.Sub(transferCoins...)}, + {address: receiver.Bytes(), expCoins: transferCoins}, + }, + ) + + Expect(res.GasUsed > expGasUsedLowerBound).To(BeTrue(), "expected different gas used") + Expect(res.GasUsed < expGasUsedUpperBound).To(BeTrue(), "expected different gas used") + }, + // FIXME: The gas used on the precompile is much higher than on the EVM + Entry(" - direct call", directCall, int64(3_021_000), int64(3_022_000)), + Entry(" - through erc20 contract", erc20Call, int64(54_000), int64(54_500)), + Entry(" - through erc20 v5 contract", erc20V5Call, int64(52_000), int64(52_200)), + ) + + DescribeTable("it should transfer tokens to an existing address", func(callType CallType) { + sender := is.keyring.GetKey(0) + receiver := is.keyring.GetKey(1) + fundCoinsSender := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)} + fundCoinsReceiver := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 500)} + transferCoin := sdk.NewInt64Coin(is.tokenDenom, 100) + + // Fund accounts with some tokens + receiverInitialAmt := is.fundWithTokens(callType, contractsData, receiver.Addr, fundCoinsReceiver) + receiverInitialBalance := sdk.Coins{sdk.NewCoin(is.tokenDenom, receiverInitialAmt)} + + senderInitialAmt := is.fundWithTokens(callType, contractsData, sender.Addr, fundCoinsSender) + senderInitialBalance := sdk.Coins{sdk.NewCoin(is.tokenDenom, senderInitialAmt)} + + // Transfer tokens + txArgs, transferArgs := is.getTxAndCallArgs(callType, contractsData, erc20.TransferMethod, receiver.Addr, transferCoin.Amount.BigInt()) + + transferCheck := passCheck.WithExpEvents(erc20.EventTypeTransfer) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, transferArgs, transferCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.TransferMethod) + is.ExpectBalancesForContract( + callType, contractsData, + []ExpectedBalance{ + {address: sender.AccAddr, expCoins: senderInitialBalance.Sub(transferCoin)}, + {address: receiver.AccAddr, expCoins: receiverInitialBalance.Add(transferCoin)}, + }, + ) + }, + Entry(" - direct call", directCall), + // NOTE: we are not passing the contract call here because transferring using a caller contract + // is only supported through transferFrom method. + Entry(" - through erc20 contract", erc20Call), + Entry(" - through erc20 v5 contract", erc20V5Call), + ) + + DescribeTable("it should return an error trying to call from a smart contract", func(callType CallType) { + sender := is.keyring.GetKey(0) + receiver := is.keyring.GetAddr(1) + fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)} + transferAmount := big.NewInt(100) + + // Fund account with some tokens + is.fundWithTokens(callType, contractsData, sender.Addr, fundCoins) + + // Transfer tokens + txArgs, transferArgs := is.getTxAndCallArgs(callType, contractsData, erc20.TransferMethod, receiver, transferAmount) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, transferArgs, execRevertedCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + Expect(ethRes).To(BeNil(), "expected empty result") + }, + // NOTE: we are not passing the direct call here because this test is specific to the contract calls + Entry(" - through contract", contractCall), + Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), + ) + + DescribeTable("it should return an error if the sender does not have enough tokens", func(callType CallType) { + sender := is.keyring.GetKey(0) + receiver := is.keyring.GetAddr(1) + fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 200)} + + // Fund account with some tokens + senderInitialAmt := is.fundWithTokens(callType, contractsData, sender.Addr, fundCoins) + transferAmt := new(big.Int).Add(senderInitialAmt.BigInt(), big.NewInt(100)) + + // Transfer tokens + txArgs, transferArgs := is.getTxAndCallArgs(callType, contractsData, erc20.TransferMethod, receiver, transferAmt) + + insufficientBalanceCheck := failCheck.WithErrContains( + erc20.ErrTransferAmountExceedsBalance.Error(), + ) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, transferArgs, insufficientBalanceCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + Expect(ethRes).To(BeNil(), "expected empty result") + }, + Entry(" - direct call", directCall), + // NOTE: we are not passing the contract call here because this test is for direct calls only + + Entry(" - through erc20 contract", erc20Call), + // // TODO: The ERC20 V5 contract is raising the ERC-6093 standardized error which we are not as of yet + // Entry(" - through erc20 v5 contract", erc20V5Call), + ) + }) + When("calling reverter contract", func() { + Context("in a direct call to the WEVMOS contract", func() { + var ( + args testutiltypes.CallArgs + txArgs evmtypes.EvmTxArgs + ) + BeforeEach(func() { + args = testutiltypes.CallArgs{ + ContractABI: revertCallerContract.ABI, + } + + txArgs = evmtypes.EvmTxArgs{ + To: &revertContractAddr, + GasLimit: gasLimit, + GasPrice: gasPrice, + } + }) + It("should transfer tokens", func() { + sender := is.keyring.GetKey(0) + receiver := is.keyring.GetKey(1) + amountToSend := big.NewInt(100) + + balRes, err := is.handler.GetBalanceFromBank(receiver.AccAddr, is.bondDenom) + Expect(err).To(BeNil()) + denomInitialBalance := balRes.Balance + balRes, err = is.handler.GetBalanceFromBank(sender.AccAddr, is.bondDenom) + Expect(err).To(BeNil()) + senderInitialBalance := balRes.Balance + + args.MethodName = "transferWithRevert" + args.Args = []interface{}{ + receiver.Addr, + amountToSend, + false, + false, + } + txArgs.Amount = amountToSend + + transferCheck := passCheck.WithExpEvents(erc20.EventTypeTransfer) + res, _, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, args, transferCheck) + Expect(err).To(BeNil()) + Expect(is.network.NextBlock()).To(BeNil()) + fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed) + + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "failed to advance block") + + balRes, err = is.handler.GetBalanceFromBank(receiver.AccAddr, is.bondDenom) + Expect(err).To(BeNil()) + denomFinalBalance := balRes.Balance + Expect(denomFinalBalance.Amount).To(Equal(denomInitialBalance.Amount.Add(math.NewInt(amountToSend.Int64())))) + + balRes, err = is.handler.GetBalanceFromBank(revertContractAddr.Bytes(), is.bondDenom) + Expect(err).To(BeNil()) + contractBalance := balRes.Balance + Expect(contractBalance.Amount).To(Equal(math.ZeroInt())) + + balRes, err = is.handler.GetBalanceFromBank(sender.AccAddr, is.bondDenom) + Expect(err).To(BeNil()) + senderFinalBalance := balRes.Balance + denomSpent := fees.Add(math.NewIntFromBigInt(amountToSend)) + Expect(senderFinalBalance.Amount).To(Equal(senderInitialBalance.Amount.Sub(denomSpent))) + }, + ) + DescribeTable("it should revert token transfer from the WEVMOS contract", func(before bool, after bool) { + sender := is.keyring.GetKey(0) + receiver := is.keyring.GetAddr(1) + amountToSend := big.NewInt(100) + balRes, err := is.handler.GetBalanceFromBank(receiver.Bytes(), is.bondDenom) + Expect(err).To(BeNil()) + denomInitialBalance := balRes.Balance + balRes, err = is.handler.GetBalanceFromBank(sender.AccAddr, is.bondDenom) + Expect(err).To(BeNil()) + senderInitialBalance := balRes.Balance + + args.MethodName = "transferWithRevert" + args.Args = []interface{}{ + receiver, + amountToSend, + before, + after, + } + txArgs.Amount = amountToSend + + res, _, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, args, execRevertedCheck) + Expect(err).To(BeNil()) + Expect(is.network.NextBlock()).To(BeNil()) + + fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed) + + // contract balance should remain unchanged + balRes, err = is.handler.GetBalanceFromBank(receiver.Bytes(), is.bondDenom) + Expect(err).To(BeNil()) + denomFinalBalance := balRes.Balance + Expect(denomFinalBalance.Amount).To(Equal(denomInitialBalance.Amount)) + + balRes, err = is.handler.GetBalanceFromBank(revertContractAddr.Bytes(), is.bondDenom) + Expect(err).To(BeNil()) + contractBalance := balRes.Balance + Expect(contractBalance.Amount).To(Equal(math.ZeroInt())) + + balRes, err = is.handler.GetBalanceFromBank(sender.AccAddr, is.bondDenom) + Expect(err).To(BeNil()) + senderFinalBalance := balRes.Balance + Expect(senderFinalBalance.Amount).To(Equal(senderInitialBalance.Amount.Sub(fees))) + }, + Entry("revert before", true, false), + Entry("revert after", false, true), + ) + It("it should send token transfer and send from WEVMOS contract", func() { + sender := is.keyring.GetKey(0) + receiver := is.keyring.GetAddr(1) + totalToSend := int64(350) + balRes, err := is.handler.GetBalanceFromBank(receiver.Bytes(), is.bondDenom) + Expect(err).To(BeNil()) + denomInitialBalance := balRes.Balance + balRes, err = is.handler.GetBalanceFromBank(sender.AccAddr, is.bondDenom) + Expect(err).To(BeNil()) + senderInitialBalance := balRes.Balance + + args.MethodName = "testTransferAndSend" + args.Args = []interface{}{ + receiver, + big.NewInt(100), + big.NewInt(100), + big.NewInt(150), + false, + false, + } + txArgs.Amount = big.NewInt(totalToSend) + + transferCheck := passCheck.WithExpEvents(erc20.EventTypeTransfer) + res, _, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, args, transferCheck) + Expect(err).To(BeNil()) + Expect(is.network.NextBlock()).To(BeNil()) + fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed) + + // contract balance should remain unchanged + balRes, err = is.handler.GetBalanceFromBank(receiver.Bytes(), is.bondDenom) + Expect(err).To(BeNil()) + denomFinalBalance := balRes.Balance + Expect(denomFinalBalance.Amount).To(Equal(denomInitialBalance.Amount.Add(math.NewInt(totalToSend)))) + + balRes, err = is.handler.GetBalanceFromBank(revertContractAddr.Bytes(), is.bondDenom) + Expect(err).To(BeNil()) + contractBalance := balRes.Balance + Expect(contractBalance.Amount).To(Equal(math.ZeroInt())) + + balRes, err = is.handler.GetBalanceFromBank(sender.AccAddr, is.bondDenom) + Expect(err).To(BeNil()) + senderFinalBalance := balRes.Balance + denomSpent := fees.AddRaw(totalToSend) + Expect(senderFinalBalance.Amount).To(Equal(senderInitialBalance.Amount.Sub(denomSpent))) + }, + ) + DescribeTable("it should revert token transfer and send from WEVMOS contract", func(before bool, after bool) { + sender := is.keyring.GetKey(0) + receiver := is.keyring.GetAddr(1) + balRes, err := is.handler.GetBalanceFromBank(receiver.Bytes(), is.bondDenom) + Expect(err).To(BeNil()) + denomInitialBalance := balRes.Balance + balRes, err = is.handler.GetBalanceFromBank(sender.AccAddr, is.bondDenom) + Expect(err).To(BeNil()) + senderInitialBalance := balRes.Balance + + args.MethodName = "testTransferAndSend" + args.Args = []interface{}{ + receiver, + big.NewInt(100), + big.NewInt(100), + big.NewInt(100), + before, + after, + } + txArgs.Amount = big.NewInt(300) + + res, _, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, args, execRevertedCheck) + Expect(err).To(BeNil()) + Expect(is.network.NextBlock()).To(BeNil()) + fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed) + + // contract balance should remain unchanged + balRes, err = is.handler.GetBalanceFromBank(receiver.Bytes(), is.bondDenom) + Expect(err).To(BeNil()) + denomFinalBalance := balRes.Balance + Expect(denomFinalBalance.Amount).To(Equal(denomInitialBalance.Amount)) + + balRes, err = is.handler.GetBalanceFromBank(revertContractAddr.Bytes(), is.bondDenom) + Expect(err).To(BeNil()) + contractBalance := balRes.Balance + Expect(contractBalance.Amount).To(Equal(math.ZeroInt())) + + balRes, err = is.handler.GetBalanceFromBank(sender.AccAddr, is.bondDenom) + Expect(err).To(BeNil()) + senderFinalBalance := balRes.Balance + Expect(senderFinalBalance.Amount).To(Equal(senderInitialBalance.Amount.Sub(fees))) + }, + Entry("revert before", true, false), + Entry("revert after", false, true), + ) + It("revert when transfer with try", func() { + sender := is.keyring.GetKey(0) + receiver := is.keyring.GetAddr(1) + amountToSend := big.NewInt(100) + balRes, err := is.handler.GetBalanceFromBank(receiver.Bytes(), is.bondDenom) + Expect(err).To(BeNil()) + denomInitialBalance := balRes.Balance + balRes, err = is.handler.GetBalanceFromBank(sender.AccAddr, is.bondDenom) + Expect(err).To(BeNil()) + senderInitialBalance := balRes.Balance + + args.MethodName = "transfersWithTry" + args.Args = []interface{}{ + receiver, + amountToSend, + amountToSend, + } + txArgs.Amount = big.NewInt(200) + + transferCheck := passCheck.WithExpEvents(erc20.EventTypeTransfer) + res, _, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, args, transferCheck) + Expect(err).To(BeNil()) + Expect(is.network.NextBlock()).To(BeNil()) + fees := math.NewIntFromBigInt(gasPrice).MulRaw(res.GasUsed) + + balRes, err = is.handler.GetBalanceFromBank(receiver.Bytes(), is.bondDenom) + Expect(err).To(BeNil()) + denomFinalBalance := balRes.Balance + Expect(denomFinalBalance.Amount).To(Equal(denomInitialBalance.Amount.Add(math.NewInt(amountToSend.Int64())))) + + balRes, err = is.handler.GetBalanceFromBank(revertContractAddr.Bytes(), is.bondDenom) + Expect(err).To(BeNil()) + contractBalance := balRes.Balance + Expect(contractBalance.Amount.Int64()).To(Equal(amountToSend.Int64())) + + balRes, err = is.handler.GetBalanceFromBank(sender.AccAddr, is.bondDenom) + Expect(err).To(BeNil()) + senderFinalBalance := balRes.Balance + denomSpent := fees.AddRaw(amountToSend.Int64() + amountToSend.Int64()) + Expect(senderFinalBalance.Amount).To(Equal(senderInitialBalance.Amount.Sub(denomSpent))) + }) + }) + }) + + When("transferring tokens from another account", func() { + Context("in a direct call to the token contract", func() { + DescribeTable("it should transfer tokens from another account with a sufficient approval set", func(callType CallType) { + owner := is.keyring.GetKey(0) + spender := is.keyring.GetKey(1) + receiver := utiltx.GenerateAddress() + + fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)} + transferAmount := big.NewInt(100) + transferCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, transferAmount.Int64())} + + // Fund account with some tokens + ownerInitialAmt := is.fundWithTokens(callType, contractsData, owner.Addr, fundCoins) + ownerInitialBalance := sdk.Coins{sdk.NewCoin(is.tokenDenom, ownerInitialAmt)} + + // Set allowance + is.setAllowanceForContract(callType, contractsData, owner.Priv, spender.Addr, transferAmount) + + // Transfer tokens + txArgs, transferArgs := is.getTxAndCallArgs( + callType, contractsData, + erc20.TransferFromMethod, + owner.Addr, receiver, transferAmount, + ) + + transferCheck := passCheck.WithExpEvents( + erc20.EventTypeTransfer, + erc20.EventTypeApproval, + ) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(spender.Priv, txArgs, transferArgs, transferCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit the changes to the chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.TransferFromMethod) + is.ExpectBalancesForContract( + callType, contractsData, + []ExpectedBalance{ + {address: owner.AccAddr, expCoins: ownerInitialBalance.Sub(transferCoins...)}, + {address: receiver.Bytes(), expCoins: transferCoins}, + }, + ) + + // Check that the allowance was removed since we approved only the transferred amount + is.ExpectAllowanceForContract( + callType, contractsData, + spender.Addr, owner.Addr, common.Big0, + ) + }, + Entry(" - direct call", directCall), + // NOTE: we are not passing the contract call here because this test is for direct calls only + + Entry(" - through erc20 contract", erc20Call), + Entry(" - through erc20 v5 contract", erc20V5Call), + ) + + When("the spender is the same as the sender", func() { + It("should return an error when transfer funds without an approval when calling the erc20 precompile", func() { + owner := is.keyring.GetKey(0) + spender := owner + receiver := utiltx.GenerateAddress() + + fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)} + transferCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)} + + // Fund account with some tokens + ownerInitialAmt := is.fundWithTokens(directCall, contractsData, owner.Addr, fundCoins) + ownerInitialBalance := sdk.Coins{sdk.NewCoin(is.tokenDenom, ownerInitialAmt)} + + // Transfer tokens + txArgs, transferArgs := is.getTxAndCallArgs( + directCall, contractsData, + erc20.TransferFromMethod, + owner.Addr, receiver, transferCoins[0].Amount.BigInt(), + ) + + insufficientAllowanceCheck := failCheck.WithErrContains( + erc20.ErrInsufficientAllowance.Error(), + ) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(spender.Priv, txArgs, transferArgs, insufficientAllowanceCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + Expect(ethRes).To(BeNil(), "expected empty result") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectBalancesForContract( + directCall, contractsData, + []ExpectedBalance{ + {address: owner.AccAddr, expCoins: ownerInitialBalance}, + {address: receiver.Bytes(), expCoins: sdk.NewCoins(sdk.NewCoin(is.tokenDenom, math.ZeroInt()))}, + }, + ) + }) + + DescribeTable("it should transfer funds from the own account in case sufficient approval is set", func(callType CallType) { + owner := is.keyring.GetKey(0) + receiver := utiltx.GenerateAddress() + + fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)} + transferCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)} + + // Fund account with some tokens + ownerInitialAmt := is.fundWithTokens(callType, contractsData, owner.Addr, fundCoins) + ownerInitialBalance := sdk.Coins{sdk.NewCoin(is.tokenDenom, ownerInitialAmt)} + + is.setAllowanceForContract( + callType, contractsData, + owner.Priv, owner.Addr, transferCoins[0].Amount.BigInt(), + ) + + is.ExpectAllowanceForContract( + callType, contractsData, + owner.Addr, owner.Addr, transferCoins[0].Amount.BigInt(), + ) + + err := is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + // Transfer tokens + txArgs, transferArgs := is.getTxAndCallArgs( + callType, contractsData, + erc20.TransferFromMethod, + owner.Addr, receiver, transferCoins[0].Amount.BigInt(), + ) + + transferCheck := passCheck.WithExpEvents( + erc20.EventTypeTransfer, + erc20.EventTypeApproval, + ) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, transferArgs, transferCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.TransferFromMethod) + is.ExpectBalancesForContract( + callType, contractsData, + []ExpectedBalance{ + {address: owner.AccAddr, expCoins: ownerInitialBalance.Sub(transferCoins...)}, + {address: receiver.Bytes(), expCoins: transferCoins}, + }, + ) + + // Check that the allowance was removed since we approved only the transferred amount + // FIXME: This is not working for the case where we transfer from the own account + // because the allowance is not removed on the SDK side. + is.ExpectAllowanceForContract( + callType, contractsData, + owner.Addr, owner.Addr, common.Big0, + ) + }, + Entry(" - through erc20 contract", erc20Call), + Entry(" - through erc20 v5 contract", erc20V5Call), + ) + }) + + DescribeTable("it should return an error when the spender does not have enough allowance", func(callType CallType) { + owner := is.keyring.GetKey(0) + spender := is.keyring.GetKey(1) + receiver := utiltx.GenerateAddress() + fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)} + approveAmount := big.NewInt(100) + transferAmount := big.NewInt(200) + + // Fund account with some tokens + is.fundWithTokens(callType, contractsData, owner.Addr, fundCoins) + // Set allowance + is.setAllowanceForContract( + callType, contractsData, + owner.Priv, spender.Addr, approveAmount, + ) + + // Transfer tokens + txArgs, transferArgs := is.getTxAndCallArgs( + callType, contractsData, + erc20.TransferFromMethod, + owner.Addr, receiver, transferAmount, + ) + + insufficientAllowanceCheck := failCheck.WithErrContains(erc20.ErrInsufficientAllowance.Error()) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(spender.Priv, txArgs, transferArgs, insufficientAllowanceCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + Expect(ethRes).To(BeNil(), "expected empty result") + }, + Entry(" - direct call", directCall), + // NOTE: we are not passing the contract call here because this test case only covers direct calls + + Entry(" - through erc20 contract", erc20Call), + + // TODO: the ERC20 V5 contract is raising the ERC-6093 standardized error which we are not using as of yet + // Entry(" - through erc20 v5 contract", erc20V5Call), + ) + + DescribeTable("it should return an error if there is no allowance set", func(callType CallType) { + sender := is.keyring.GetKey(0) + from := is.keyring.GetKey(1) + receiver := utiltx.GenerateAddress() + fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)} + transferAmount := big.NewInt(100) + + // Fund account with some tokens + is.fundWithTokens(callType, contractsData, from.Addr, fundCoins) + + // Transfer tokens + txArgs, transferArgs := is.getTxAndCallArgs( + callType, contractsData, + erc20.TransferFromMethod, + from.Addr, receiver, transferAmount, + ) + + insufficientAllowanceCheck := failCheck.WithErrContains( + erc20.ErrInsufficientAllowance.Error(), + ) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, transferArgs, insufficientAllowanceCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + Expect(ethRes).To(BeNil(), "expected empty result") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + }, + Entry(" - direct call", directCall), + // NOTE: we are not passing the contract call here because this test case only covers direct calls + + Entry(" - through erc20 contract", erc20Call), + + // TODO: the ERC20 V5 contract is raising the ERC-6093 standardized error which we are not using as of yet + // Entry(" - through erc20 v5 contract", erc20V5Call), + ) + + DescribeTable("it should return an error if the sender does not have enough tokens", func(callType CallType) { + sender := is.keyring.GetKey(0) + from := is.keyring.GetKey(1) + receiver := utiltx.GenerateAddress() + fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 200)} + + // Fund account with some tokens + senderInitialAmt := is.fundWithTokens(callType, contractsData, from.Addr, fundCoins) + transferAmt := new(big.Int).Add(senderInitialAmt.BigInt(), big.NewInt(100)) + + // Set allowance + is.setAllowanceForContract( + callType, contractsData, + from.Priv, sender.Addr, transferAmt, + ) + + // Transfer tokens + txArgs, transferArgs := is.getTxAndCallArgs(callType, contractsData, erc20.TransferFromMethod, from.Addr, receiver, transferAmt) + + insufficientBalanceCheck := failCheck.WithErrContains( + erc20.ErrTransferAmountExceedsBalance.Error(), + ) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, transferArgs, insufficientBalanceCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + Expect(ethRes).To(BeNil(), "expected empty result") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + }, + Entry(" - direct call", directCall), + // NOTE: we are not passing the contract call here because this test case only covers direct calls + + Entry(" - through erc20 contract", erc20Call), + + // TODO: the ERC20 V5 contract is raising the ERC-6093 standardized error which we are not using as of yet + // Entry(" - through erc20 v5 contract", erc20V5Call), + ) + }) + + Context("in a call from another smart contract to the token contract", func() { + DescribeTable("it should transfer tokens with a sufficient approval set", func(callType CallType) { + owner := is.keyring.GetKey(0) + receiver := utiltx.GenerateAddress() + fundCoin := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)} + transferAmount := big.NewInt(100) + transferCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, transferAmount.Int64())} + + // NOTE: the spender will be the contract address + spender := contractsData.GetContractData(callType).Address + + // Fund account with some tokens + ownerInitialAmt := is.fundWithTokens(callType, contractsData, owner.Addr, fundCoin) + ownerInitialBalance := sdk.Coins{sdk.NewCoin(is.tokenDenom, ownerInitialAmt)} + + // Set allowance + is.setAllowanceForContract( + callType, contractsData, + owner.Priv, spender, transferAmount, + ) + + // Transfer tokens + txArgs, transferArgs := is.getTxAndCallArgs( + callType, contractsData, + erc20.TransferFromMethod, + owner.Addr, receiver, transferCoins[0].Amount.BigInt(), + ) + + transferCheck := passCheck.WithExpEvents( + erc20.EventTypeTransfer, + erc20.EventTypeApproval, + ) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, transferArgs, transferCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.TransferFromMethod) + is.ExpectBalancesForContract( + callType, contractsData, + []ExpectedBalance{ + {address: owner.AccAddr, expCoins: ownerInitialBalance.Sub(transferCoins...)}, + {address: receiver.Bytes(), expCoins: transferCoins}, + }, + ) + + // Check that the allowance was removed since we approved only the transferred amount + is.ExpectAllowanceForContract( + callType, contractsData, + spender, owner.Addr, common.Big0, + ) + }, + // Entry(" - direct call", directCall), + Entry(" - through contract", contractCall), + // NOTE: we are not passing the erc20 contract call here because this is supposed to + // test external contract calls + Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), + ) + + DescribeTable("it should transfer funds with a sufficient allowance and triggered from another account", func(callType CallType) { + msgSender := is.keyring.GetKey(0) + owner := is.keyring.GetKey(1) + receiver := utiltx.GenerateAddress() + + // NOTE: the spender will be the contract address + spender := contractsData.GetContractData(callType).Address + + fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 300)} + transferCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)} + + // Fund account with some tokens + ownerInitialAmt := is.fundWithTokens(callType, contractsData, owner.Addr, fundCoins) + ownerInitialBalance := sdk.Coins{sdk.NewCoin(is.tokenDenom, ownerInitialAmt)} + + // Set allowance + is.setAllowanceForContract( + callType, contractsData, + owner.Priv, spender, transferCoins.AmountOf(is.tokenDenom).BigInt(), + ) + + // Transfer tokens + txArgs, transferArgs := is.getTxAndCallArgs( + callType, contractsData, + erc20.TransferFromMethod, + owner.Addr, receiver, transferCoins[0].Amount.BigInt(), + ) + + transferCheck := passCheck.WithExpEvents( + erc20.EventTypeTransfer, + erc20.EventTypeApproval, + ) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(msgSender.Priv, txArgs, transferArgs, transferCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.TransferFromMethod) + is.ExpectBalancesForContract( + callType, contractsData, + []ExpectedBalance{ + {address: owner.AccAddr, expCoins: ownerInitialBalance.Sub(transferCoins...)}, + {address: receiver.Bytes(), expCoins: transferCoins}, + }, + ) + + // Check that the allowance was removed since we approved only the transferred amount + is.ExpectAllowanceForContract( + callType, contractsData, + spender, owner.Addr, common.Big0, + ) + }, + // NOTE: we are not passing the direct call here because this test is specific to the contract calls + + Entry(" - through contract", contractCall), + Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), + ) + + DescribeTable("it should return an error when the spender does not have enough allowance", func(callType CallType) { + from := is.keyring.GetKey(0) + receiver := utiltx.GenerateAddress() + fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 400)} + approveAmount := big.NewInt(100) + transferAmount := big.NewInt(300) + + // NOTE: the spender will be the contract address + spender := contractsData.GetContractData(callType).Address + + // Fund account with some tokens + is.fundWithTokens(callType, contractsData, from.Addr, fundCoins) + + // Set allowance + is.setAllowanceForContract(callType, contractsData, from.Priv, spender, approveAmount) + + // Transfer tokens + txArgs, transferArgs := is.getTxAndCallArgs( + callType, contractsData, + erc20.TransferFromMethod, + from.Addr, receiver, transferAmount, + ) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(from.Priv, txArgs, transferArgs, execRevertedCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + Expect(ethRes).To(BeNil(), "expected empty result") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + }, + // NOTE: we are not passing the direct call here because this test is for contract calls only + Entry(" - through contract", contractCall), + Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), + ) + }) + }) + + When("querying balance", func() { + DescribeTable("it should return an existing balance", func(callType CallType) { + sender := is.keyring.GetKey(0) + addedAmt := big.NewInt(100) + fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, addedAmt.Int64())} + + // Fund account with some tokens + ownerInitialAmt := is.fundWithTokens(callType, contractsData, sender.Addr, fundCoins) + + // Query the balance + txArgs, balancesArgs := is.getTxAndCallArgs(callType, contractsData, erc20.BalanceOfMethod, sender.Addr) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, balancesArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + var balance *big.Int + err = is.precompile.UnpackIntoInterface(&balance, erc20.BalanceOfMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack result") + Expect(math.NewIntFromBigInt(balance)).To(Equal(ownerInitialAmt), "expected different balance") + }, + Entry(" - direct call", directCall), + Entry(" - through contract", contractCall), + Entry(" - through erc20 contract", erc20Call), + Entry(" - through erc20 v5 contract", erc20V5Call), + Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), + ) + + DescribeTable("it should return zero if balance only exists for other tokens", func(callType CallType) { + sender := is.keyring.GetKey(0) + address := utiltx.GenerateAddress() + fundCoins := sdk.Coins{sdk.NewInt64Coin(is.network.GetBaseDenom(), 100)} + + // Fund account with some tokens + err := is.factory.FundAccount(is.keyring.GetKey(0), sender.AccAddr, fundCoins) + Expect(err).ToNot(HaveOccurred(), "failed to fund account") + Expect(is.network.NextBlock()).To(BeNil()) + + // Query the balance + txArgs, balancesArgs := is.getTxAndCallArgs(callType, contractsData, erc20.BalanceOfMethod, address) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, balancesArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + var balance *big.Int + err = is.precompile.UnpackIntoInterface(&balance, erc20.BalanceOfMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack result") + Expect(balance.Int64()).To(BeZero(), "expected zero balance") + }, + Entry(" - direct call", directCall), + Entry(" - through contract", contractCall), + // NOTE: we are not passing the erc20 contract call here because the ERC20 contracts + // only support the actual token denomination and don't know of other balances. + ) + + DescribeTable("it should return zero if the account does not exist", func(callType CallType) { + sender := is.keyring.GetKey(0) + address := utiltx.GenerateAddress() + + // Query the balance + txArgs, balancesArgs := is.getTxAndCallArgs(callType, contractsData, erc20.BalanceOfMethod, address) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, balancesArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + var balance *big.Int + err = is.precompile.UnpackIntoInterface(&balance, erc20.BalanceOfMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack result") + Expect(balance.Int64()).To(BeZero(), "expected zero balance") + }, + Entry(" - direct call", directCall), + Entry(" - through contract", contractCall), + Entry(" - through erc20 contract", erc20Call), + Entry(" - through erc20 v5 contract", erc20V5Call), + Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), + ) + }) + + When("querying allowance", func() { + DescribeTable("it should return an existing allowance", func(callType CallType) { + spender := utiltx.GenerateAddress() + owner := is.keyring.GetKey(0) + approveAmount := big.NewInt(100) + + is.setAllowanceForContract(callType, contractsData, owner.Priv, spender, approveAmount) + + txArgs, allowanceArgs := is.getTxAndCallArgs(callType, contractsData, erc20.AllowanceMethod, owner.Addr, spender) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, allowanceArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + var allowance *big.Int + err = is.precompile.UnpackIntoInterface(&allowance, erc20.AllowanceMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack result") + Expect(allowance).To(Equal(approveAmount), "expected different allowance") + }, + Entry(" - direct call", directCall), + Entry(" - through contract", contractCall), + Entry(" - through erc20 contract", erc20Call), + Entry(" - through erc20 v5 contract", erc20V5Call), + Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), + ) + + When("querying the allowance for the own address", func() { + It("should return the 0 value when calling the erc20 precompile", func() { + spender := is.keyring.GetAddr(0) + owner := is.keyring.GetKey(0) + + txArgs, allowanceArgs := is.getTxAndCallArgs(directCall, contractsData, erc20.AllowanceMethod, spender, spender) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, allowanceArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + var allowance *big.Int + err = is.precompile.UnpackIntoInterface(&allowance, erc20.AllowanceMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack result") + Expect(allowance.Sign()).To(Equal(0), "expected different allowance") + }) + + // NOTE: Since it's possible to set an allowance for the own address with the Solidity ERC20 contracts, + // we describe this case here for completion purposes, to describe the difference in behavior. + DescribeTable("should return the actual allowance value when calling the ERC20 contract", func(callType CallType) { + owner := is.keyring.GetKey(0) + approveAmount := big.NewInt(100) + + is.setAllowanceForContract(callType, contractsData, owner.Priv, owner.Addr, approveAmount) + + txArgs, allowanceArgs := is.getTxAndCallArgs(callType, contractsData, erc20.AllowanceMethod, owner.Addr, owner.Addr) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, allowanceArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + var allowance *big.Int + err = is.precompile.UnpackIntoInterface(&allowance, erc20.AllowanceMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack result") + Expect(allowance).To(Equal(approveAmount), "expected different allowance") + }, + Entry(" - through erc20 contract", erc20Call), + Entry(" - through erc20 v5 contract", erc20V5Call), + ) + }) + + DescribeTable("it should return zero if no allowance exists", func(callType CallType) { + spender := is.keyring.GetAddr(1) + owner := is.keyring.GetKey(0) + + txArgs, allowanceArgs := is.getTxAndCallArgs(callType, contractsData, erc20.AllowanceMethod, owner.Addr, spender) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, allowanceArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + var allowance *big.Int + err = is.precompile.UnpackIntoInterface(&allowance, erc20.AllowanceMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack result") + Expect(allowance.Int64()).To(BeZero(), "expected zero allowance") + }, + Entry(" - direct call", directCall), + Entry(" - through contract", contractCall), + Entry(" - through erc20 contract", erc20Call), + Entry(" - through erc20 v5 contract", erc20V5Call), + Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), + ) + + DescribeTable("it should return zero if the account does not exist", func(callType CallType) { + spender := utiltx.GenerateAddress() + owner := is.keyring.GetKey(0) + + txArgs, allowanceArgs := is.getTxAndCallArgs(callType, contractsData, erc20.AllowanceMethod, owner.Addr, spender) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, allowanceArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + var allowance *big.Int + err = is.precompile.UnpackIntoInterface(&allowance, erc20.AllowanceMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack result") + Expect(allowance.Int64()).To(BeZero(), "expected zero allowance") + }, + Entry(" - direct call", directCall), + Entry(" - through contract", contractCall), + Entry(" - through erc20 contract", erc20Call), + Entry(" - through erc20 v5 contract", erc20V5Call), + Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), + ) + }) + + When("querying total supply", func() { + DescribeTable("it should return the total supply", func(callType CallType) { + sender := is.keyring.GetKey(0) + expSupply := big.NewInt(100) + fundCoins := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, expSupply.Int64())} + + // Fund account with some tokens + is.fundWithTokens(callType, contractsData, sender.Addr, fundCoins) + + // if is native coin, get expSupply from the bank mod + if slices.Contains(nativeCallTypes, callType) { + qc := is.network.GetBankClient() + qRes, err := qc.SupplyOf(is.network.GetContext(), &banktypes.QuerySupplyOfRequest{Denom: is.tokenDenom}) + Expect(err).To(BeNil()) + Expect(qRes).NotTo(BeNil()) + expSupply = qRes.Amount.Amount.BigInt() + } + + // Query the balance + txArgs, supplyArgs := is.getTxAndCallArgs(callType, contractsData, erc20.TotalSupplyMethod) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, supplyArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + var supply *big.Int + err = is.precompile.UnpackIntoInterface(&supply, erc20.TotalSupplyMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack result") + Expect(supply).To(Equal(expSupply), "expected different supply") + }, + Entry(" - direct call", directCall), + Entry(" - through contract", contractCall), + Entry(" - through erc20 contract", erc20Call), + Entry(" - through erc20 v5 contract", erc20V5Call), + Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), + ) + + DescribeTable("it should return zero if no tokens exist", func(callType CallType) { + sender := is.keyring.GetKey(0) + txArgs, supplyArgs := is.getTxAndCallArgs(callType, contractsData, erc20.TotalSupplyMethod) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, supplyArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + var supply *big.Int + err = is.precompile.UnpackIntoInterface(&supply, erc20.TotalSupplyMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack result") + Expect(supply.Int64()).To(BeZero(), "expected zero supply") + }, + Entry(" - direct call", directCallToken2), + Entry(" - through contract", contractCallToken2), + Entry(" - through erc20 contract", erc20Call), + Entry(" - through erc20 v5 contract", erc20V5Call), + Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), + ) + }) + + When("approving an allowance", func() { + Context("in a call to the token contract", func() { + DescribeTable("it should approve an allowance", func(callType CallType) { + spender := is.keyring.GetKey(0) + owner := is.keyring.GetKey(1) + approveAmount := big.NewInt(200) + + // Approve allowance + txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, erc20.ApproveMethod, spender.Addr, approveAmount) + + approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, approveArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) + is.ExpectAllowanceForContract( + callType, contractsData, + owner.Addr, spender.Addr, approveAmount, + ) + }, + Entry(" - direct call", directCall), + Entry(" - through erc20 contract", erc20Call), + Entry(" - through erc20 v5 contract", erc20V5Call), + ) + + DescribeTable("it should set the new spend limit for an existing allowance", func(callType CallType) { + spender := is.keyring.GetKey(1) + owner := is.keyring.GetKey(0) + prevAllowance := big.NewInt(200) + approveAmount := big.NewInt(100) + + // set up a previous allowance + is.setAllowanceForContract(callType, contractsData, owner.Priv, spender.Addr, prevAllowance) + + // Approve allowance + txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, erc20.ApproveMethod, spender.Addr, approveAmount) + + approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, approveArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) + // Check allowance contains both spend limits + is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, approveAmount) + }, + Entry(" - direct call", directCall), + Entry(" - through erc20 contract", erc20Call), + Entry(" - through erc20 v5 contract", erc20V5Call), + ) + + DescribeTable("it should remove the token from the spend limit of an existing allowance when approving zero", func(callType CallType) { + owner := is.keyring.GetKey(0) + spender := is.keyring.GetKey(1) + approveAmount := big.NewInt(100) + + // set up a previous allowance + is.setAllowanceForContract(callType, contractsData, owner.Priv, spender.Addr, approveAmount) + + // Approve allowance + txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, erc20.ApproveMethod, spender.Addr, common.Big0) + + approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, approveArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) + + // commit the changes to state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") + + // Check allowance is set to zero + is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, common.Big0) + }, + Entry(" - direct call", directCall), + // NOTE: we are not passing the erc20 contract call here because the ERC20 contract + // only supports the actual token denomination and doesn't know of other allowances. + ) + + DescribeTable("it should delete the allowance when approving zero with no other spend limits", func(callType CallType) { + spender := is.keyring.GetKey(1) + owner := is.keyring.GetKey(0) + allowance := big.NewInt(100) + + // set up a previous allowance + is.setAllowanceForContract(callType, contractsData, owner.Priv, spender.Addr, allowance) + + // Approve allowance + txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, erc20.ApproveMethod, spender.Addr, common.Big0) + + approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, approveArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) + // Check allowance was deleted + is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, common.Big0) + }, + Entry(" - direct call", directCall), + Entry(" - through erc20 contract", erc20Call), + Entry(" - through erc20 v5 contract", erc20V5Call), + ) + + DescribeTable("it should no-op if approving 0 and no allowance exists", func(callType CallType) { + spender := is.keyring.GetKey(1) + owner := is.keyring.GetKey(0) + + // Approve allowance + txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, erc20.ApproveMethod, spender.Addr, common.Big0) + + // We are expecting an approval to be made, but no allowance stored since it's 0 + approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, approveArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) + // Check still no allowance exists + is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, common.Big0) + }, + Entry(" - direct call", directCall), + Entry(" - through erc20 contract", erc20Call), + Entry(" - through erc20 v5 contract", erc20V5Call), + ) + + When("the spender is the same as the owner", func() { + It("should return an error when calling the erc20 precompile", func() { + spender := is.keyring.GetKey(0) + owner := is.keyring.GetKey(0) + approveAmount := big.NewInt(100) + + // Approve allowance + txArgs, approveArgs := is.getTxAndCallArgs( + directCall, contractsData, + erc20.ApproveMethod, + spender.Addr, approveAmount, + ) + + approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, approveArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) + is.ExpectAllowanceForContract( + directCall, contractsData, + owner.Addr, spender.Addr, approveAmount, + ) + }) + + DescribeTable("it should create an allowance", func(callType CallType) { + spender := is.keyring.GetKey(0) + owner := is.keyring.GetKey(0) + allowance := big.NewInt(100) + + // Approve allowance + txArgs, approveArgs := is.getTxAndCallArgs( + callType, contractsData, + erc20.ApproveMethod, + spender.Addr, allowance, + ) + + approvalCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, approveArgs, approvalCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) + is.ExpectAllowanceForContract( + callType, contractsData, + owner.Addr, spender.Addr, allowance, + ) + }, + Entry(" - through erc20 contract", erc20Call), + Entry(" - through erc20 v5 contract", erc20V5Call), + ) + }) + + DescribeTable("it should return an error if approving 0 and allowance only exists for other tokens", func(callType CallType) { + owner := is.keyring.GetKey(0) + spender := is.keyring.GetKey(1) + prevAllowance := big.NewInt(200) + + callTypeForOtherToken := directCallToken2 + + // set up a previous allowance for other token + is.setAllowanceForContract(callTypeForOtherToken, contractsData, owner.Priv, spender.Addr, prevAllowance) + + // Approve allowance for target token + txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, erc20.ApproveMethod, spender.Addr, common.Big0) + + approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, approveArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) + is.ExpectAllowanceForContract( + callType, contractsData, + owner.Addr, spender.Addr, common.Big0, + ) + + // Check allowance of other token is not chaged + is.ExpectAllowanceForContract( + callTypeForOtherToken, contractsData, + owner.Addr, spender.Addr, prevAllowance, + ) + }, + Entry(" - direct call", directCall), + // NOTE: we are not passing the erc20 contract call here because the ERC20 contract + // only supports the actual token denomination and doesn't know of other allowances. + ) + }) + + // NOTE: We have to split the tests for contract calls into a separate context because + // when approving through a smart contract, the approval is created between the contract address and the + // spender, instead of the sender address and the spender. + Context("in a contract call", func() { + DescribeTable("it should approve an allowance", func(callType CallType) { + sender := is.keyring.GetKey(0) + spender := is.keyring.GetKey(1) + owner := contractsData.GetContractData(callType).Address // the owner will be the contract address + transferAmount := big.NewInt(200) + + // Approve allowance + txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, erc20.ApproveMethod, spender.Addr, transferAmount) + + approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, approveArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) + // Check allowance + is.ExpectAllowanceForContract( + callType, contractsData, + owner, spender.Addr, transferAmount, + ) + }, + Entry(" - through contract", contractCall), + Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), + ) + + DescribeTable("it should set the new spend limit for an existing allowance with the same token", func(callType CallType) { + sender := is.keyring.GetKey(0) + spender := is.keyring.GetKey(1) + owner := contractsData.GetContractData(callType).Address // the owner will be the contract address + initialAmount := sdk.Coins{sdk.NewInt64Coin(is.tokenDenom, 100)} + newAmount := big.NewInt(200) + + // Set up a first approval + txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, erc20.ApproveMethod, spender.Addr, initialAmount[0].Amount.BigInt()) + approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, approveArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) + + // Set up a second approval which should overwrite the initial one + txArgs, approveArgs = is.getTxAndCallArgs(callType, contractsData, erc20.ApproveMethod, spender.Addr, newAmount) + approveCheck = passCheck.WithExpEvents(erc20.EventTypeApproval) + _, ethRes, err = is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, approveArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + // Check allowance has been updated + is.ExpectAllowanceForContract( + callType, contractsData, + owner, spender.Addr, newAmount, + ) + }, + Entry(" - through contract", contractCall), + Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), + ) + + DescribeTable("it should delete the allowance when approving zero with no other spend limits", func(callType CallType) { + sender := is.keyring.GetKey(0) + spender := is.keyring.GetKey(1) + owner := contractsData.GetContractData(callType).Address // the owner will be the contract address + approveAmount := big.NewInt(100) + + // set up a previous allowance + // + // TODO: refactor using helper + txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, erc20.ApproveMethod, spender.Addr, approveAmount) + approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, approveArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) + + // Approve allowance + txArgs, approveArgs = is.getTxAndCallArgs(callType, contractsData, erc20.ApproveMethod, spender.Addr, common.Big0) + _, ethRes, err = is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, approveArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) + + // Check allowance was deleted from the keeper / is returning 0 for smart contracts + is.ExpectAllowanceForContract(callType, contractsData, owner, spender.Addr, common.Big0) + }, + Entry(" - through contract", contractCall), + Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), + ) + + DescribeTable("it should no-op if approving 0 and no allowance exists", func(callType CallType) { + sender := is.keyring.GetKey(0) + spender := is.keyring.GetKey(1) + owner := contractsData.GetContractData(callType).Address // the owner will be the contract address + + // Approve allowance + txArgs, approveArgs := is.getTxAndCallArgs(callType, contractsData, erc20.ApproveMethod, spender.Addr, common.Big0) + + // We are expecting an approval event to be emitted, but no allowance to be stored + approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, approveArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) + // Check still no allowance exists + is.ExpectAllowanceForContract(callType, contractsData, owner, spender.Addr, common.Big0) + }, + Entry(" - through contract", contractCall), + Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), + ) + + When("the spender is the same as the owner", func() { + It("should approve an allowance", func() { + callType := contractCall + sender := is.keyring.GetKey(0) + owner := contractsData.GetContractData(callType).Address // the owner will be the contract address + spender := owner + approveAmount := big.NewInt(100) + + // Approve allowance + txArgs, approveArgs := is.getTxAndCallArgs( + callType, contractsData, + erc20.ApproveMethod, + spender, approveAmount, + ) + + approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, approveArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) + is.ExpectAllowanceForContract( + callType, contractsData, + owner, spender, approveAmount, + ) + }) + + DescribeTable("it should create an allowance when calling an ERC20 Solidity contract", func(callType CallType) { + sender := is.keyring.GetKey(0) + owner := contractsData.GetContractData(callType).Address // the owner will be the contract address + spender := owner + allowance := big.NewInt(100) + + // Approve allowance + txArgs, approveArgs := is.getTxAndCallArgs( + callType, contractsData, + erc20.ApproveMethod, + spender, allowance, + ) + + approvalCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(sender.Priv, txArgs, approveArgs, approvalCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) + is.ExpectAllowanceForContract( + callType, contractsData, + owner, spender, allowance, + ) + }, + Entry(" - through erc20 v5 caller contract", erc20V5CallerCall), + ) + }) + }) + }) + }) + + Context("metadata query -", func() { + Context("for a token without registered metadata", func() { + BeforeEach(func() { + // Deploy ERC20NoMetadata contract for this test + erc20NoMetadataContract, err := testdata.LoadERC20NoMetadataContract() + Expect(err).ToNot(HaveOccurred(), "failed to load contract") + + erc20NoMetadataAddr, err := is.factory.DeployContract( + is.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{}, + testutiltypes.ContractDeploymentData{ + Contract: erc20NoMetadataContract, + }, + ) + Expect(err).ToNot(HaveOccurred(), "failed to deploy contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + // NOTE: update the address but leave the ABI as it is, so that the ABI includes + // the metadata methods but the contract doesn't have them. + contractsData.contractData[erc20Call] = ContractData{ + Address: erc20NoMetadataAddr, + ABI: contracts.ERC20MinterBurnerDecimalsContract.ABI, + } + }) + + DescribeTable("querying the name should return an error", func(callType CallType) { + txArgs, nameArgs := is.getTxAndCallArgs(callType, contractsData, erc20.NameMethod) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(is.keyring.GetPrivKey(0), txArgs, nameArgs, execRevertedCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + Expect(ethRes).To(BeNil(), "expected empty result") + }, + Entry(" - direct call", directCall), + Entry(" - through contract", contractCall), + Entry(" - through erc20 contract", erc20Call), // NOTE: we're passing the ERC20 contract call here which was adjusted to point to a contract without metadata to expect the same errors + ) + + DescribeTable("querying the symbol should return an error", func(callType CallType) { + txArgs, symbolArgs := is.getTxAndCallArgs(callType, contractsData, erc20.SymbolMethod) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(is.keyring.GetPrivKey(0), txArgs, symbolArgs, execRevertedCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + Expect(ethRes).To(BeNil(), "expected empty result") + }, + Entry(" - direct call", directCall), + Entry(" - through contract", contractCall), + Entry(" - through erc20 contract", erc20Call), // NOTE: we're passing the ERC20 contract call here which was adjusted to point to a contract without metadata to expect the same errors + ) + + DescribeTable("querying the decimals should return an error", func(callType CallType) { + txArgs, decimalsArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecimalsMethod) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(is.keyring.GetPrivKey(0), txArgs, decimalsArgs, execRevertedCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + Expect(ethRes).To(BeNil(), "expected empty result") + }, + Entry(" - direct call", directCall), + Entry(" - through contract", contractCall), + Entry(" - through erc20 contract", erc20Call), // NOTE: we're passing the ERC20 contract call here which was adjusted to point to a contract without metadata to expect the same errors + ) + }) + + Context("for a token with available metadata", func() { + const ( + expSymbol = "Xmpl" + expDecimals = uint8(18) + ) + + var ( + erc20Addr common.Address + expName string + ) + + BeforeEach(func() { + erc20Addr = contractsData.GetContractData(erc20V5Call).Address + expName = erc20types.CreateDenom(erc20Addr.String()) + + // Register ERC20 token pair for this test + tokenPairs, err := utils.RegisterERC20(is.factory, is.network, utils.ERC20RegistrationData{ + Addresses: []string{erc20Addr.Hex()}, + ProposerPriv: is.keyring.GetPrivKey(0), + }) + Expect(err).ToNot(HaveOccurred(), "failed to register ERC20 token") + Expect(tokenPairs).To(HaveLen(1)) + + // overwrite the other precompile with this one, so that the test utils like is.getTxAndCallArgs still work. + is.precompile, err = setupNewERC20PrecompileForTokenPair(is.keyring.GetPrivKey(0), is.network, is.factory, tokenPairs[0]) + Expect(err).ToNot(HaveOccurred(), "failed to set up erc20 precompile") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + // update this in the global contractsData + contractsData.contractData[directCall] = ContractData{ + Address: is.precompile.Address(), + ABI: is.precompile.ABI, + } + + // Deploy contract calling the ERC20 precompile + callerAddr, err := is.factory.DeployContract( + is.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{}, + testutiltypes.ContractDeploymentData{ + Contract: allowanceCallerContract, + ConstructorArgs: []interface{}{ + is.precompile.Address(), + }, + }, + ) + Expect(err).ToNot(HaveOccurred(), "failed to deploy contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + contractsData.contractData[contractCall] = ContractData{ + Address: callerAddr, + ABI: allowanceCallerContract.ABI, + } + }) + + DescribeTable("querying the name should return the name", func(callType CallType) { + txArgs, nameArgs := is.getTxAndCallArgs(callType, contractsData, erc20.NameMethod) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(is.keyring.GetPrivKey(0), txArgs, nameArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + var name string + err = is.precompile.UnpackIntoInterface(&name, erc20.NameMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack result") + Expect(name).To(Equal(expName), "expected different name") + }, + Entry(" - direct call", directCall), + Entry(" - through contract", contractCall), + Entry(" - through erc20 v5 contract", erc20V5Call), + ) + + DescribeTable("querying the symbol should return the symbol", func(callType CallType) { + txArgs, symbolArgs := is.getTxAndCallArgs(callType, contractsData, erc20.SymbolMethod) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(is.keyring.GetPrivKey(0), txArgs, symbolArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + var symbol string + err = is.precompile.UnpackIntoInterface(&symbol, erc20.SymbolMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack result") + Expect(symbol).To(Equal(expSymbol), "expected different symbol") + }, + Entry(" - direct call", directCall), + Entry(" - through contract", contractCall), + Entry(" - through erc20 v5 contract", erc20V5Call), + ) + + DescribeTable("querying the decimals should return the decimals", func(callType CallType) { + txArgs, decimalsArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecimalsMethod) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(is.keyring.GetPrivKey(0), txArgs, decimalsArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + var decimals uint8 + err = is.precompile.UnpackIntoInterface(&decimals, erc20.DecimalsMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack result") + Expect(decimals).To(Equal(expDecimals), "expected different decimals") + }, + Entry(" - direct call", directCall), + Entry(" - through contract", contractCall), + Entry(" - through erc20 v5 contract", erc20V5Call), + ) + }) + }) + + Context("allowance adjustments -", func() { + var ( + spender keyring.Key + owner keyring.Key + ) + + BeforeEach(func() { + // Deploying the contract which has the increase / decrease allowance methods + contractAddr, err := is.factory.DeployContract( + is.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values + testutiltypes.ContractDeploymentData{ + Contract: allowanceCallerContract, + ConstructorArgs: []interface{}{is.precompile.Address()}, + }, + ) + Expect(err).ToNot(HaveOccurred(), "failed to deploy contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + contractsData.contractData[erc20CallerCall] = ContractData{ + Address: contractAddr, + ABI: allowanceCallerContract.ABI, + } + + spender = is.keyring.GetKey(0) + owner = is.keyring.GetKey(1) + }) + + When("the spender is the same as the owner", func() { + Context("increasing allowance", func() { + It("should approve an allowance", func() { + owner := is.keyring.GetKey(0) + spender := owner + allowance := big.NewInt(100) + + txArgs, increaseArgs := is.getTxAndCallArgs( + directCall, contractsData, + erc20.IncreaseAllowanceMethod, + spender.Addr, allowance, + ) + + transferCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, increaseArgs, transferCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.IncreaseAllowanceMethod) + is.ExpectAllowanceForContract( + directCall, contractsData, + owner.Addr, spender.Addr, allowance, + ) + }) + + DescribeTable("it should create an allowance if none existed before", func(callType CallType) { + owner := is.keyring.GetKey(0) + spender := owner + allowance := big.NewInt(100) + + txArgs, increaseArgs := is.getTxAndCallArgs( + callType, contractsData, + erc20.IncreaseAllowanceMethod, + spender.Addr, allowance, + ) + + approvalCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, increaseArgs, approvalCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.IncreaseAllowanceMethod) + is.ExpectAllowanceForContract( + callType, contractsData, + owner.Addr, spender.Addr, allowance, + ) + }, + Entry(" - through erc20 contract", erc20Call), + Entry(" - through erc20 v5 contract", erc20V5Call), + ) + }) + + Context("decreasing allowance", func() { + It("should return an error when allowance does not exist", func() { + owner := is.keyring.GetKey(0) + spender := owner + allowance := big.NewInt(100) + + txArgs, decreaseArgs := is.getTxAndCallArgs( + directCall, contractsData, + erc20.DecreaseAllowanceMethod, + spender.Addr, allowance, + ) + + noAllowanceCheck := failCheck.WithErrContains( + fmt.Sprintf(erc20.ErrNoAllowanceForToken, is.tokenDenom), + ) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, decreaseArgs, noAllowanceCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + Expect(ethRes).To(BeNil(), "expected empty result") + + is.ExpectAllowanceForContract( + directCall, contractsData, + owner.Addr, spender.Addr, common.Big0, + ) + // commit the changes to state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") + }) + + DescribeTable("it should decrease an existing allowance", func(callType CallType) { + owner := is.keyring.GetKey(0) + spender := owner + approveAmount := big.NewInt(200) + decreaseAmount := big.NewInt(100) + + is.setAllowanceForContract( + callType, contractsData, + owner.Priv, spender.Addr, approveAmount, + ) + + txArgs, decreaseArgs := is.getTxAndCallArgs( + callType, contractsData, + erc20.DecreaseAllowanceMethod, + spender.Addr, decreaseAmount, + ) + + approvalCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, decreaseArgs, approvalCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit the changes to state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") + + is.ExpectTrueToBeReturned(ethRes, erc20.IncreaseAllowanceMethod) + is.ExpectAllowanceForContract( + callType, contractsData, + owner.Addr, spender.Addr, decreaseAmount, + ) + }, + Entry(" - through erc20 contract", erc20Call), + Entry(" - through erc20 v5 contract", erc20V5Call), + ) + }) + }) + + When("no allowance exists", func() { + DescribeTable("decreasing the allowance should return an error", func(callType CallType) { + approveAmount := big.NewInt(100) + + txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecreaseAllowanceMethod, spender.Addr, approveAmount) + + notFoundCheck := execRevertedCheck + if callType == directCall { + notFoundCheck = failCheck.WithErrContains( + fmt.Sprintf(erc20.ErrNoAllowanceForToken, is.tokenDenom), + ) + } + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, decreaseArgs, notFoundCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + Expect(ethRes).To(BeNil(), "expected empty result") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + }, + Entry(" - direct call", directCall), + Entry(" - through erc20 contract", erc20Call), + // NOTE: The ERC20 V5 contract does not contain these methods + // Entry(" - through erc20 v5 contract", erc20V5Call), + Entry(" - contract call", contractCall), + Entry(" - through erc20 caller contract", erc20CallerCall), + ) + + // NOTE: We have to split between direct and contract calls here because the ERC20 behavior + // for approvals is different, so we expect different allowances here + Context("in direct calls", func() { + DescribeTable("increasing the allowance should create a new allowance", func(callType CallType) { + approveAmount := big.NewInt(100) + + txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.IncreaseAllowanceMethod, spender.Addr, approveAmount) + + approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, increaseArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.ApproveMethod) + is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, approveAmount) + }, + Entry(" - direct call", directCall), + Entry(" - through erc20 contract", erc20Call), + // NOTE: The ERC20 V5 contract does not contain these methods + // Entry(" - through erc20 v5 contract", erc20V5Call), + ) + }) + + Context("in contract calls", func() { + DescribeTable("increasing the allowance should create a new allowance", func(callType CallType) { + contractAddr := contractsData.GetContractData(callType).Address + approveAmount := big.NewInt(100) + + txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.IncreaseAllowanceMethod, spender.Addr, approveAmount) + + approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, increaseArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.IncreaseAllowanceMethod) + is.ExpectAllowanceForContract(callType, contractsData, contractAddr, spender.Addr, approveAmount) + }, + Entry(" - contract call", contractCall), + Entry(" - through erc20 caller contract", erc20CallerCall), + ) + }) + }) + + When("an allowance exists for other tokens", func() { + var prevAllowance *big.Int + + BeforeEach(func() { + prevAllowance = big.NewInt(200) + }) + + DescribeTable("increasing the allowance should add the token to the spend limit", func(callType, callTypeForOtherToken CallType) { + is.setAllowanceForContract(callTypeForOtherToken, contractsData, owner.Priv, spender.Addr, prevAllowance) + + // Increase the allowance for target token + increaseAmount := big.NewInt(100) + + txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.IncreaseAllowanceMethod, spender.Addr, increaseAmount) + + approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, increaseArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.IncreaseAllowanceMethod) + is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, increaseAmount) + + // Check that the other token allowance is not affected + is.ExpectAllowanceForContract(callTypeForOtherToken, contractsData, owner.Addr, spender.Addr, prevAllowance) + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + }, + Entry(" - direct call", directCall, directCallToken2), + // NOTE: we are not passing the erc20 contract call here because the ERC20 contract + // only supports the actual token denomination and doesn't know of other allowances. + ) + + DescribeTable("decreasing the allowance should return an error", func(callType, callTypeForOtherToken CallType) { + is.setAllowanceForContract(callTypeForOtherToken, contractsData, owner.Priv, spender.Addr, prevAllowance) + + // Decrease the allowance for target token + decreaseAmount := big.NewInt(100) + + txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecreaseAllowanceMethod, spender.Addr, decreaseAmount) + + noAllowanceCheck := failCheck.WithErrContains(erc20.ErrNoAllowanceForToken, is.tokenDenom) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, decreaseArgs, noAllowanceCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + Expect(ethRes).To(BeNil(), "expected empty result") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, common.Big0) + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + // Check that the other token allowance is not affected + is.ExpectAllowanceForContract(callTypeForOtherToken, contractsData, owner.Addr, spender.Addr, prevAllowance) + }, + Entry(" - direct call", directCall, directCallToken2), + // NOTE: we are not passing the erc20 contract call here because the ERC20 contract + // only supports the actual token denomination and doesn't know of other allowances. + ) + }) + + When("an allowance exists for the same token", func() { + var approveAmount *big.Int + + BeforeEach(func() { + approveAmount = big.NewInt(200) + is.setAllowanceForContract(directCall, contractsData, owner.Priv, spender.Addr, approveAmount) + }) + + DescribeTable("increasing the allowance should increase the spend limit", func(callType CallType) { + increaseAmount := big.NewInt(100) + + txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.IncreaseAllowanceMethod, spender.Addr, increaseAmount) + + approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, increaseArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.IncreaseAllowanceMethod) + is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, new(big.Int).Add(approveAmount, increaseAmount)) + }, + Entry(" - direct call", directCall), + // NOTE: we are not passing the erc20 contract call here because the ERC20 contract + // only supports the actual token denomination and doesn't know of other allowances. + ) + + DescribeTable("decreasing the allowance should decrease the spend limit", func(callType CallType) { + decreaseAmount := big.NewInt(100) + + txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecreaseAllowanceMethod, spender.Addr, decreaseAmount) + + approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, decreaseArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + is.ExpectTrueToBeReturned(ethRes, erc20.DecreaseAllowanceMethod) + is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, new(big.Int).Sub(approveAmount, decreaseAmount)) + }, + Entry(" - direct call", directCall), + // NOTE: we are not passing the erc20 contract call here because the ERC20 contract + // only supports the actual token denomination and doesn't know of other allowances. + ) + + DescribeTable("increasing the allowance beyond the max uint256 value should return an error", func(callType CallType) { + increaseAmount := abi.MaxUint256 + + txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.IncreaseAllowanceMethod, spender.Addr, increaseAmount) + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, increaseArgs, execRevertedCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + Expect(ethRes).To(BeNil(), "expected empty result") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + }, + Entry(" - direct call", directCall), + // NOTE: we are not passing the erc20 contract call here because the ERC20 contract + // only supports the actual token denomination and doesn't know of other allowances. + ) + + DescribeTable("decreasing the allowance to zero should remove the token from the spend limit", func(callType CallType) { + txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecreaseAllowanceMethod, spender.Addr, approveAmount) + + approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, decreaseArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + is.ExpectTrueToBeReturned(ethRes, erc20.DecreaseAllowanceMethod) + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + // Check that only the spend limit in the network denomination remains + expAllowance := common.Big0 + is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, expAllowance) + }, + Entry(" - direct call", directCall), + // NOTE: we are not passing the erc20 contract call here because the ERC20 contract + // only supports the actual token denomination and doesn't know of other allowances. + ) + + DescribeTable("decreasing the allowance below zero should return an error", func(callType CallType) { + decreaseAmount := new(big.Int).Add(approveAmount, big.NewInt(100)) + + txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecreaseAllowanceMethod, spender.Addr, decreaseAmount) + belowZeroCheck := failCheck.WithErrContains(erc20.ErrDecreasedAllowanceBelowZero.Error()) + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, decreaseArgs, belowZeroCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + Expect(ethRes).To(BeNil(), "expected empty result") + + // commit changes to chain state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error on NextBlock call") + + // Check that the allowance was not changed + is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, approveAmount) + }, + Entry(" - direct call", directCall), + ) + }) + + When("an allowance exists for only the same token", func() { + // NOTE: we have to split between direct and contract calls here because the ERC20 contract + // handles the allowance differently by creating an approval between the contract and the spender, instead + // of the message sender and the spender, so we expect different allowances. + Context("in direct calls", func() { + var approveAmount *big.Int + + BeforeEach(func() { + approveAmount = big.NewInt(100) + + // NOTE: We set up the allowance here for the erc20 precompile and then also + // set up the allowance for the ERC20 contract, so that we can test both. + is.setAllowanceForContract(directCall, contractsData, owner.Priv, spender.Addr, approveAmount) + is.setAllowanceForContract(erc20Call, contractsData, owner.Priv, spender.Addr, approveAmount) + }) + + DescribeTable("increasing the allowance should increase the spend limit", func(callType CallType) { + increaseAmount := big.NewInt(100) + + txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.IncreaseAllowanceMethod, spender.Addr, increaseAmount) + approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, increaseArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit the changes to state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") + + is.ExpectTrueToBeReturned(ethRes, erc20.DecreaseAllowanceMethod) + is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, new(big.Int).Add(approveAmount, increaseAmount)) + }, + Entry(" - direct call", directCall), + Entry(" - through erc20 contract", erc20Call), + // NOTE: The ERC20 V5 contract does not contain these methods + // Entry(" - through erc20 v5 contract", erc20V5Call), + ) + + DescribeTable("decreasing the allowance should decrease the spend limit", func(callType CallType) { + decreaseAmount := big.NewInt(50) + + txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecreaseAllowanceMethod, spender.Addr, decreaseAmount) + approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, decreaseArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit the changes to state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") + + is.ExpectTrueToBeReturned(ethRes, erc20.DecreaseAllowanceMethod) + is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, new(big.Int).Sub(approveAmount, decreaseAmount)) + }, + Entry(" - direct call", directCall), + Entry(" - through erc20 contract", erc20Call), + // NOTE: The ERC20 V5 contract does not contain these methods + // Entry(" - through erc20 v5 contract", erc20V5Call), + ) + + DescribeTable("decreasing the allowance to zero should delete the allowance", func(callType CallType) { + txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecreaseAllowanceMethod, spender.Addr, approveAmount) + approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, decreaseArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit the changes to state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") + + is.ExpectTrueToBeReturned(ethRes, erc20.DecreaseAllowanceMethod) + is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, common.Big0) + }, + Entry(" - direct call", directCall), + Entry(" - through erc20 contract", erc20Call), + // NOTE: The ERC20 V5 contract does not contain these methods + // Entry(" - through erc20 v5 contract", erc20V5Call), + ) + + DescribeTable("decreasing the allowance below zero should return an error", func(callType CallType) { + decreaseAmount := big.NewInt(200) + + txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecreaseAllowanceMethod, spender.Addr, decreaseAmount) + + belowZeroCheck := failCheck.WithErrContains(erc20.ErrDecreasedAllowanceBelowZero.Error()) + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, decreaseArgs, belowZeroCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + Expect(ethRes).To(BeNil(), "expected empty result") + + // commit the changes to state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") + + // Check that the allowance was not changed + is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, approveAmount) + }, + Entry(" - direct call", directCall), + Entry(" - through erc20 contract", erc20Call), + // NOTE: The ERC20 V5 contract does not contain these methods + // Entry(" - through erc20 v5 contract", erc20V5Call), + ) + + DescribeTable("increasing the allowance beyond the max uint256 value should return an error", func(callType CallType) { + increaseAmount := abi.MaxUint256 + + txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.IncreaseAllowanceMethod, spender.Addr, increaseAmount) + _, ethRes, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, increaseArgs, execRevertedCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + Expect(ethRes).To(BeNil(), "expected empty result") + + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") + + // Check that the allowance was not changed + is.ExpectAllowanceForContract(callType, contractsData, owner.Addr, spender.Addr, approveAmount) + }, + Entry(" - direct call", directCall), + Entry(" - through erc20 contract", erc20Call), + // NOTE: The ERC20 V5 contract does not contain these methods + // Entry(" - through erc20 v5 contract", erc20V5Call), + ) + }) + + Context("in contract calls", func() { + var ( + approveAmount *big.Int + spender keyring.Key + ) + + BeforeEach(func() { + approveAmount = big.NewInt(100) + + spender = is.keyring.GetKey(1) + callerContractAddr := contractsData.GetContractData(contractCall).Address + erc20CallerContractAddr := contractsData.GetContractData(erc20CallerCall).Address + + // NOTE: Here we create an allowance between the contract and the spender for both contracts. + // This is different from the direct calls, where the allowance is created between the + // message sender and the spender. + txArgs, approveArgs := is.getTxAndCallArgs(contractCall, contractsData, erc20.ApproveMethod, spender.Addr, approveAmount) + approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + _, _, err := is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, approveArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit the changes to state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") + + is.ExpectAllowanceForContract(contractCall, contractsData, callerContractAddr, spender.Addr, approveAmount) + + // CreateApp the allowance for the ERC20 caller contract + txArgs, approveArgs = is.getTxAndCallArgs(erc20CallerCall, contractsData, erc20.ApproveMethod, spender.Addr, approveAmount) + _, _, err = is.factory.CallContractAndCheckLogs(owner.Priv, txArgs, approveArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit the changes to state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") + + is.ExpectAllowanceForContract(erc20CallerCall, contractsData, erc20CallerContractAddr, spender.Addr, approveAmount) + }) + + DescribeTable("increasing the allowance should increase the spend limit", func(callType CallType) { //nolint:dupl + senderPriv := is.keyring.GetPrivKey(0) + ownerAddr := contractsData.GetContractData(callType).Address + increaseAmount := big.NewInt(100) + + txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.IncreaseAllowanceMethod, spender.Addr, increaseAmount) + approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + _, ethRes, err := is.factory.CallContractAndCheckLogs(senderPriv, txArgs, increaseArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit the changes to state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") + + is.ExpectTrueToBeReturned(ethRes, erc20.IncreaseAllowanceMethod) + is.ExpectAllowanceForContract(callType, contractsData, ownerAddr, spender.Addr, new(big.Int).Add(approveAmount, increaseAmount)) + }, + Entry(" - contract call", contractCall), + Entry(" - through erc20 caller contract", erc20CallerCall), + ) + + DescribeTable("increasing the allowance beyond the max uint256 value should return an error", func(callType CallType) { + senderPriv := is.keyring.GetPrivKey(0) + ownerAddr := contractsData.GetContractData(callType).Address + increaseAmount := abi.MaxUint256 + + txArgs, increaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.IncreaseAllowanceMethod, spender.Addr, increaseAmount) + _, ethRes, err := is.factory.CallContractAndCheckLogs(senderPriv, txArgs, increaseArgs, execRevertedCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + Expect(ethRes).To(BeNil(), "expected empty result") + + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") + + // Check that the allowance was not changed + is.ExpectAllowanceForContract(callType, contractsData, ownerAddr, spender.Addr, approveAmount) + }, + Entry(" - contract call", contractCall), + Entry(" - through erc20 caller contract", erc20CallerCall), + ) + + DescribeTable("decreasing the allowance should decrease the spend limit", func(callType CallType) { //nolint:dupl + senderPriv := is.keyring.GetPrivKey(0) + ownerAddr := contractsData.GetContractData(callType).Address + decreaseAmount := big.NewInt(50) + + txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecreaseAllowanceMethod, spender.Addr, decreaseAmount) + approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + _, ethRes, err := is.factory.CallContractAndCheckLogs(senderPriv, txArgs, decreaseArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit the changes to state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") + + is.ExpectTrueToBeReturned(ethRes, erc20.DecreaseAllowanceMethod) + is.ExpectAllowanceForContract(callType, contractsData, ownerAddr, spender.Addr, new(big.Int).Sub(approveAmount, decreaseAmount)) + }, + Entry(" - contract call", contractCall), + Entry(" - through erc20 caller contract", erc20CallerCall), + ) + + DescribeTable("decreasing the allowance to zero should delete the allowance", func(callType CallType) { + senderPriv := is.keyring.GetPrivKey(0) + ownerAddr := contractsData.GetContractData(callType).Address + + txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecreaseAllowanceMethod, spender.Addr, approveAmount) + approveCheck := passCheck.WithExpEvents(erc20.EventTypeApproval) + _, ethRes, err := is.factory.CallContractAndCheckLogs(senderPriv, txArgs, decreaseArgs, approveCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + // commit the changes to state + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") + + is.ExpectTrueToBeReturned(ethRes, erc20.DecreaseAllowanceMethod) + is.ExpectAllowanceForContract(callType, contractsData, ownerAddr, spender.Addr, common.Big0) + }, + Entry(" - contract call", contractCall), + Entry(" - through erc20 caller contract", erc20CallerCall), + ) + + DescribeTable("decreasing the allowance below zero should return an error", func(callType CallType) { + senderPriv := is.keyring.GetPrivKey(0) + ownerAddr := contractsData.GetContractData(callType).Address + decreaseAmount := new(big.Int).Add(approveAmount, big.NewInt(100)) + + txArgs, decreaseArgs := is.getTxAndCallArgs(callType, contractsData, erc20.DecreaseAllowanceMethod, spender.Addr, decreaseAmount) + _, ethRes, err := is.factory.CallContractAndCheckLogs(senderPriv, txArgs, decreaseArgs, execRevertedCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + Expect(ethRes).To(BeNil(), "expected empty result") + + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "error while calling NextBlock") + + // Check that the allowance was not changed + is.ExpectAllowanceForContract(callType, contractsData, ownerAddr, spender.Addr, approveAmount) + }, + Entry(" - contract call", contractCall), + Entry(" - through erc20 caller contract", erc20CallerCall), + ) + }) + }) + }) + }) + var _ = Describe("ERC20 Extension migration Flows -", func() { + When("migrating an existing ERC20 token", func() { + var ( + contractData ContractsData + erc20MinterV5Contract evmtypes.CompiledContract + + tokenDenom = "xmpl" + tokenName = "Xmpl" + tokenSymbol = strings.ToUpper(tokenDenom) + + supply = sdk.NewInt64Coin(tokenDenom, 1000000000000000000) + ) + + BeforeEach(func() { + is.SetupTest() + + var err error + erc20MinterV5Contract, err = testdata.LoadERC20MinterV5Contract() + Expect(err).ToNot(HaveOccurred(), "failed to load ERC20 minter contract") + + contractOwner := is.keyring.GetKey(0) + + // Deploy an ERC20 contract + erc20Addr, err := is.factory.DeployContract( + contractOwner.Priv, + evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values + testutiltypes.ContractDeploymentData{ + Contract: erc20MinterV5Contract, + ConstructorArgs: []interface{}{ + tokenName, tokenSymbol, + }, + }, + ) + Expect(err).ToNot(HaveOccurred(), "failed to deploy contract") + + // NOTE: We need to overwrite the information in the contractData here for this specific + // deployed contract. + contractData = ContractsData{ + ownerPriv: contractOwner.Priv, + contractData: map[CallType]ContractData{ + erc20V5Call: { + Address: erc20Addr, + ABI: erc20MinterV5Contract.ABI, + }, + }, + } + + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "failed to commit block") + + // Register the deployed erc20 contract as a token pair + _, err = utils.RegisterERC20(is.factory, is.network, utils.ERC20RegistrationData{ + Addresses: []string{erc20Addr.Hex()}, + ProposerPriv: contractOwner.Priv, + }) + Expect(err).ToNot(HaveOccurred(), "failed to register ERC20 token") + + err = is.network.NextBlock() + Expect(err).ToNot(HaveOccurred(), "failed to commit block") + + // Mint the supply of tokens + err = is.MintERC20(erc20V5Call, contractData, contractOwner.Addr, supply.Amount.BigInt()) + Expect(err).ToNot(HaveOccurred(), "failed to mint tokens") + + // Check that the supply was minted + is.ExpectBalancesForERC20(erc20V5Call, contractData, []ExpectedBalance{{ + address: contractOwner.AccAddr, + expCoins: sdk.Coins{supply}, + }}) + }) + + It("should migrate the full token balance to the bank module", func() { + // TODO: implement test on follow-up PR + Skip("will be addressed on follow-up PR") + + Expect(true).To(BeFalse(), "not implemented") + }) + }) + + When("migrating an extended ERC20 token (e.g. ERC20Votes)", func() { + It("should migrate the full token balance to the bank module", func() { + // TODO: make sure that extended tokens are compatible with the ERC20 extensions + Skip("not included in first tranche") + + Expect(true).To(BeFalse(), "not implemented") + }) + }) + + When("running the migration logic for a set of existing ERC20 tokens", func() { + BeforeEach(func() { + // TODO: Add some ERC20 tokens and then run migration logic + // TODO: check here that the balance cannot be queried from the bank keeper before migrating the token + }) + + It("should add and enable the corresponding erc20 precompiles", func() { + Skip("will be addressed in follow-up PR") + + Expect(true).To(BeFalse(), "not implemented") + }) + + It("should be possible to query the balances through the bank module", func() { + Skip("will be addressed in follow-up PR") + + Expect(true).To(BeFalse(), "not implemented") + }) + + It("should return all tokens when querying all balances for an account", func() { + Skip("will be addressed in follow-up PR") + + Expect(true).To(BeFalse(), "not implemented") + }) + }) + + When("registering a native IBC coin", func() { + BeforeEach(func() { + // TODO: Add some IBC coins, register the token pair and then run migration logic + }) + + It("should add the corresponding erc20 precompiles", func() { + Skip("will be addressed in follow-up PR") + + Expect(true).To(BeFalse(), "not implemented") + }) + + It("should be possible to query the balances using an EVM transaction", func() { + Skip("will be addressed in follow-up PR") + + Expect(true).To(BeFalse(), "not implemented") + }) + }) + + When("using Evmos (not wEvmos) in smart contracts", func() { + It("should be using straight Evmos for sending funds in smart contracts", func() { + Skip("will be addressed in follow-up PR") + + Expect(true).To(BeFalse(), "not implemented") + }) + }) + }) + + // Run Ginkgo integration tests + RegisterFailHandler(Fail) + RunSpecs(t, "ERC20 Extension Suite") +} diff --git a/precompiles/erc20/query_test.go b/tests/integration/precompiles/erc20/test_query.go similarity index 76% rename from precompiles/erc20/query_test.go rename to tests/integration/precompiles/erc20/test_query.go index 9925c4738..896e65ce1 100644 --- a/precompiles/erc20/query_test.go +++ b/tests/integration/precompiles/erc20/test_query.go @@ -1,4 +1,4 @@ -package erc20_test +package erc20 import ( "math" @@ -7,14 +7,15 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" - app "github.com/cosmos/evm/evmd" - chainutil "github.com/cosmos/evm/evmd/testutil" "github.com/cosmos/evm/precompiles/erc20" + "github.com/cosmos/evm/testutil" + transferkeeper "github.com/cosmos/evm/x/ibc/transfer/keeper" "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" ) @@ -111,7 +112,7 @@ func (s *PrecompileTestSuite) TestNameSymbol() { testcases := []struct { name string denom string - malleate func(sdk.Context, *app.EVMD) + malleate func(sdk.Context, bankkeeper.Keeper, transferkeeper.Keeper) expPass bool errContains string expName string @@ -130,8 +131,8 @@ func (s *PrecompileTestSuite) TestNameSymbol() { { name: "fail - invalid denom (too short < 3 chars)", denom: tooShort.IBCDenom(), - malleate: func(ctx sdk.Context, app *app.EVMD) { - app.TransferKeeper.SetDenom(ctx, tooShort) + malleate: func(ctx sdk.Context, _ bankkeeper.Keeper, keeper transferkeeper.Keeper) { + keeper.SetDenom(ctx, tooShort) }, errContains: vm.ErrExecutionReverted.Error(), }, @@ -143,8 +144,8 @@ func (s *PrecompileTestSuite) TestNameSymbol() { { name: "pass - valid ibc denom without metadata and neither atto nor micro prefix", denom: validDenomNoMicroAtto.IBCDenom(), - malleate: func(ctx sdk.Context, app *app.EVMD) { - app.TransferKeeper.SetDenom(ctx, validDenomNoMicroAtto) + malleate: func(ctx sdk.Context, _ bankkeeper.Keeper, keeper transferkeeper.Keeper) { + keeper.SetDenom(ctx, validDenomNoMicroAtto) }, expPass: true, expName: "Atom", @@ -153,13 +154,13 @@ func (s *PrecompileTestSuite) TestNameSymbol() { { name: "pass - valid denom with metadata", denom: validMetadataDenom, - malleate: func(ctx sdk.Context, app *app.EVMD) { + malleate: func(ctx sdk.Context, keeper bankkeeper.Keeper, _ transferkeeper.Keeper) { // NOTE: we mint some coins to the inflation module address to be able to set denom metadata - err := app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, sdk.Coins{sdk.NewInt64Coin(validMetadata.Base, 1)}) + err := keeper.MintCoins(ctx, minttypes.ModuleName, sdk.Coins{sdk.NewInt64Coin(validMetadata.Base, 1)}) s.Require().NoError(err) // NOTE: we set the denom metadata for the coin - app.BankKeeper.SetDenomMetaData(ctx, validMetadata) + keeper.SetDenomMetaData(ctx, validMetadata) }, expPass: true, expName: "Atom", @@ -168,8 +169,8 @@ func (s *PrecompileTestSuite) TestNameSymbol() { { name: "pass - valid ibc denom without metadata", denom: validDenom.IBCDenom(), - malleate: func(ctx sdk.Context, app *app.EVMD) { - app.TransferKeeper.SetDenom(ctx, validDenom) + malleate: func(ctx sdk.Context, _ bankkeeper.Keeper, keeper transferkeeper.Keeper) { + keeper.SetDenom(ctx, validDenom) }, expPass: true, expName: "Osmo", @@ -182,7 +183,7 @@ func (s *PrecompileTestSuite) TestNameSymbol() { s.SetupTest() if tc.malleate != nil { - tc.malleate(s.network.GetContext(), s.network.App) + tc.malleate(s.network.GetContext(), s.network.App.GetBankKeeper(), s.network.App.GetTransferKeeper()) } precompile := s.setupERC20Precompile(tc.denom) @@ -222,7 +223,7 @@ func (s *PrecompileTestSuite) TestDecimals() { testcases := []struct { name string denom string - malleate func(sdk.Context, *app.EVMD) + malleate func(sdk.Context, bankkeeper.Keeper, transferkeeper.Keeper) expPass bool errContains string expDecimals uint8 @@ -245,16 +246,16 @@ func (s *PrecompileTestSuite) TestDecimals() { { name: "fail - valid ibc denom without metadata and neither atto nor micro prefix", denom: validDenomNoMicroAtto.IBCDenom(), - malleate: func(ctx sdk.Context, app *app.EVMD) { - app.TransferKeeper.SetDenom(ctx, validDenomNoMicroAtto) + malleate: func(ctx sdk.Context, _ bankkeeper.Keeper, keeper transferkeeper.Keeper) { + keeper.SetDenom(ctx, validDenomNoMicroAtto) }, errContains: vm.ErrExecutionReverted.Error(), }, { name: "pass - invalid denom (too short < 3 chars)", denom: tooShort.IBCDenom(), - malleate: func(ctx sdk.Context, app *app.EVMD) { - app.TransferKeeper.SetDenom(ctx, tooShort) + malleate: func(ctx sdk.Context, _ bankkeeper.Keeper, keeper transferkeeper.Keeper) { + keeper.SetDenom(ctx, tooShort) }, expPass: true, // TODO: do we want to check in decimals query for the above error? expDecimals: 18, // expect 18 decimals here because of "a" prefix @@ -262,13 +263,13 @@ func (s *PrecompileTestSuite) TestDecimals() { { name: "pass - valid denom with metadata", denom: validMetadataDenom, - malleate: func(ctx sdk.Context, app *app.EVMD) { + malleate: func(ctx sdk.Context, keeper bankkeeper.Keeper, _ transferkeeper.Keeper) { // NOTE: we mint some coins to the inflation module address to be able to set denom metadata - err := app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, sdk.Coins{sdk.NewInt64Coin(validMetadata.Base, 1)}) + err := keeper.MintCoins(ctx, minttypes.ModuleName, sdk.Coins{sdk.NewInt64Coin(validMetadata.Base, 1)}) s.Require().NoError(err) // NOTE: we set the denom metadata for the coin - app.BankKeeper.SetDenomMetaData(ctx, validMetadata) + keeper.SetDenomMetaData(ctx, validMetadata) }, expPass: true, expDecimals: 6, @@ -276,8 +277,8 @@ func (s *PrecompileTestSuite) TestDecimals() { { name: "pass - valid ibc denom without metadata", denom: validDenom.IBCDenom(), - malleate: func(ctx sdk.Context, app *app.EVMD) { - app.TransferKeeper.SetDenom(ctx, validDenom) + malleate: func(ctx sdk.Context, _ bankkeeper.Keeper, keeper transferkeeper.Keeper) { + keeper.SetDenom(ctx, validDenom) }, expPass: true, expDecimals: 6, @@ -285,8 +286,8 @@ func (s *PrecompileTestSuite) TestDecimals() { { name: "pass - valid ibc denom without metadata and 18 decimals", denom: validAttoDenom.IBCDenom(), - malleate: func(ctx sdk.Context, app *app.EVMD) { - app.TransferKeeper.SetDenom(ctx, validAttoDenom) + malleate: func(ctx sdk.Context, _ bankkeeper.Keeper, keeper transferkeeper.Keeper) { + keeper.SetDenom(ctx, validAttoDenom) }, expPass: true, expDecimals: 18, @@ -294,26 +295,26 @@ func (s *PrecompileTestSuite) TestDecimals() { { name: "pass - valid denom with metadata but decimals overflow", denom: validMetadataDenom, - malleate: func(ctx sdk.Context, app *app.EVMD) { + malleate: func(ctx sdk.Context, keeper bankkeeper.Keeper, _ transferkeeper.Keeper) { // NOTE: we mint some coins to the inflation module address to be able to set denom metadata - err := app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, sdk.Coins{sdk.NewInt64Coin(validMetadata.Base, 1)}) + err := keeper.MintCoins(ctx, minttypes.ModuleName, sdk.Coins{sdk.NewInt64Coin(validMetadata.Base, 1)}) s.Require().NoError(err) // NOTE: we set the denom metadata for the coin - app.BankKeeper.SetDenomMetaData(s.network.GetContext(), overflowMetadata) + keeper.SetDenomMetaData(s.network.GetContext(), overflowMetadata) }, errContains: vm.ErrExecutionReverted.Error(), }, { name: "pass - valid ibc denom with metadata but no display denom", denom: validMetadataDenom, - malleate: func(ctx sdk.Context, app *app.EVMD) { + malleate: func(ctx sdk.Context, keeper bankkeeper.Keeper, _ transferkeeper.Keeper) { // NOTE: we mint some coins to the inflation module address to be able to set denom metadata - err := app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, sdk.Coins{sdk.NewInt64Coin(validMetadata.Base, 1)}) + err := keeper.MintCoins(ctx, minttypes.ModuleName, sdk.Coins{sdk.NewInt64Coin(validMetadata.Base, 1)}) s.Require().NoError(err) // NOTE: we set the denom metadata for the coin - app.BankKeeper.SetDenomMetaData(ctx, noDisplayMetadata) + keeper.SetDenomMetaData(ctx, noDisplayMetadata) }, errContains: vm.ErrExecutionReverted.Error(), }, @@ -324,7 +325,7 @@ func (s *PrecompileTestSuite) TestDecimals() { s.SetupTest() if tc.malleate != nil { - tc.malleate(s.network.GetContext(), s.network.App) + tc.malleate(s.network.GetContext(), s.network.App.GetBankKeeper(), s.network.App.GetTransferKeeper()) } precompile := s.setupERC20Precompile(tc.denom) @@ -348,7 +349,7 @@ func (s *PrecompileTestSuite) TestTotalSupply() { testcases := []struct { name string - malleate func(sdk.Context, *app.EVMD, *big.Int) + malleate func(sdk.Context, bankkeeper.Keeper, *big.Int) expPass bool errContains string expTotal *big.Int @@ -360,9 +361,9 @@ func (s *PrecompileTestSuite) TestTotalSupply() { }, { name: "pass - some coins", - malleate: func(ctx sdk.Context, app *app.EVMD, amount *big.Int) { + malleate: func(ctx sdk.Context, keeper bankkeeper.Keeper, amount *big.Int) { // NOTE: we mint some coins to the inflation module address to be able to set denom metadata - err := app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, sdk.Coins{sdk.NewCoin(validMetadata.Base, sdkmath.NewIntFromBigInt(amount))}) + err := keeper.MintCoins(ctx, minttypes.ModuleName, sdk.Coins{sdk.NewCoin(validMetadata.Base, sdkmath.NewIntFromBigInt(amount))}) s.Require().NoError(err) }, expPass: true, @@ -375,7 +376,7 @@ func (s *PrecompileTestSuite) TestTotalSupply() { s.SetupTest() if tc.malleate != nil { - tc.malleate(s.network.GetContext(), s.network.App, tc.expTotal) + tc.malleate(s.network.GetContext(), s.network.App.GetBankKeeper(), tc.expTotal) } precompile := s.setupERC20Precompile(validMetadataDenom) @@ -399,31 +400,31 @@ func (s *PrecompileTestSuite) TestBalanceOf() { testcases := []struct { name string - malleate func(sdk.Context, *app.EVMD, *big.Int) []interface{} + malleate func(sdk.Context, bankkeeper.Keeper, *big.Int) []interface{} expPass bool errContains string expBalance *big.Int }{ { name: "fail - invalid number of arguments", - malleate: func(_ sdk.Context, _ *app.EVMD, _ *big.Int) []interface{} { + malleate: func(_ sdk.Context, _ bankkeeper.Keeper, _ *big.Int) []interface{} { return []interface{}{} }, errContains: "invalid number of arguments; expected 1; got: 0", }, { name: "fail - invalid address", - malleate: func(_ sdk.Context, _ *app.EVMD, _ *big.Int) []interface{} { + malleate: func(_ sdk.Context, _ bankkeeper.Keeper, _ *big.Int) []interface{} { return []interface{}{"invalid address"} }, errContains: "invalid account address: invalid address", }, { name: "pass - no coins in token denomination of precompile token pair", - malleate: func(_ sdk.Context, _ *app.EVMD, _ *big.Int) []interface{} { + malleate: func(_ sdk.Context, keeper bankkeeper.Keeper, _ *big.Int) []interface{} { // NOTE: we fund the account with some coins in a different denomination from what was used in the precompile. - err := chainutil.FundAccount( - s.network.GetContext(), s.network.App.BankKeeper, s.keyring.GetAccAddr(0), sdk.NewCoins(sdk.NewInt64Coin(s.bondDenom, 100)), + err := testutil.FundAccount( + s.network.GetContext(), keeper, s.keyring.GetAccAddr(0), sdk.NewCoins(sdk.NewInt64Coin(s.bondDenom, 100)), ) s.Require().NoError(err, "expected no error funding account") @@ -434,10 +435,10 @@ func (s *PrecompileTestSuite) TestBalanceOf() { }, { name: "pass - some coins", - malleate: func(ctx sdk.Context, app *app.EVMD, amount *big.Int) []interface{} { + malleate: func(ctx sdk.Context, keeper bankkeeper.Keeper, amount *big.Int) []interface{} { // NOTE: we fund the account with some coins of the token denomination that was used for the precompile - err := chainutil.FundAccount( - ctx, app.BankKeeper, s.keyring.GetAccAddr(0), sdk.NewCoins(sdk.NewCoin(s.tokenDenom, sdkmath.NewIntFromBigInt(amount))), + err := testutil.FundAccount( + ctx, keeper, s.keyring.GetAccAddr(0), sdk.NewCoins(sdk.NewCoin(s.tokenDenom, sdkmath.NewIntFromBigInt(amount))), ) s.Require().NoError(err, "expected no error funding account") @@ -454,7 +455,7 @@ func (s *PrecompileTestSuite) TestBalanceOf() { var balanceOfArgs []interface{} if tc.malleate != nil { - balanceOfArgs = tc.malleate(s.network.GetContext(), s.network.App, tc.expBalance) + balanceOfArgs = tc.malleate(s.network.GetContext(), s.network.App.GetBankKeeper(), tc.expBalance) } precompile := s.setupERC20Precompile(s.tokenDenom) @@ -478,35 +479,35 @@ func (s *PrecompileTestSuite) TestAllowance() { testcases := []struct { name string - malleate func(sdk.Context, *app.EVMD, *big.Int) []interface{} + malleate func(sdk.Context, *big.Int) []interface{} expPass bool errContains string expAllow *big.Int }{ { name: "fail - invalid number of arguments", - malleate: func(_ sdk.Context, _ *app.EVMD, _ *big.Int) []interface{} { + malleate: func(_ sdk.Context, _ *big.Int) []interface{} { return []interface{}{1} }, errContains: "invalid number of arguments; expected 2; got: 1", }, { name: "fail - invalid owner address", - malleate: func(_ sdk.Context, _ *app.EVMD, _ *big.Int) []interface{} { + malleate: func(_ sdk.Context, _ *big.Int) []interface{} { return []interface{}{"invalid address", s.keyring.GetAddr(1)} }, errContains: "invalid owner address: invalid address", }, { name: "fail - invalid spender address", - malleate: func(_ sdk.Context, _ *app.EVMD, _ *big.Int) []interface{} { + malleate: func(_ sdk.Context, _ *big.Int) []interface{} { return []interface{}{s.keyring.GetAddr(0), "invalid address"} }, errContains: "invalid spender address: invalid address", }, { name: "pass - no allowance exists should return 0", - malleate: func(_ sdk.Context, _ *app.EVMD, _ *big.Int) []interface{} { + malleate: func(_ sdk.Context, _ *big.Int) []interface{} { return []interface{}{s.keyring.GetAddr(0), s.keyring.GetAddr(1)} }, expPass: true, @@ -514,7 +515,7 @@ func (s *PrecompileTestSuite) TestAllowance() { }, { name: "pass - allowance exists for precompile token pair denom", - malleate: func(_ sdk.Context, _ *app.EVMD, amount *big.Int) []interface{} { + malleate: func(_ sdk.Context, amount *big.Int) []interface{} { ownerIdx := 0 spenderIdx := 1 @@ -538,7 +539,7 @@ func (s *PrecompileTestSuite) TestAllowance() { var allowanceArgs []interface{} if tc.malleate != nil { - allowanceArgs = tc.malleate(s.network.GetContext(), s.network.App, tc.expAllow) + allowanceArgs = tc.malleate(s.network.GetContext(), tc.expAllow) } bz, err := s.precompile.Allowance( diff --git a/precompiles/erc20/setup_test.go b/tests/integration/precompiles/erc20/test_setup.go similarity index 65% rename from precompiles/erc20/setup_test.go rename to tests/integration/precompiles/erc20/test_setup.go index 6deb51430..6348ce493 100644 --- a/precompiles/erc20/setup_test.go +++ b/tests/integration/precompiles/erc20/test_setup.go @@ -1,15 +1,13 @@ -package erc20_test +package erc20 import ( - "testing" - "github.com/stretchr/testify/suite" - erc20precompile "github.com/cosmos/evm/precompiles/erc20" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/precompiles/erc20" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + testkeyring "github.com/cosmos/evm/testutil/keyring" ) var s *PrecompileTestSuite @@ -19,6 +17,8 @@ var s *PrecompileTestSuite type PrecompileTestSuite struct { suite.Suite + create network.CreateEvmApp + options []network.ConfigOption bondDenom string // tokenDenom is the specific token denomination used in testing the ERC20 precompile. // This denomination is used to instantiate the precompile. @@ -28,27 +28,31 @@ type PrecompileTestSuite struct { grpcHandler grpc.Handler keyring testkeyring.Keyring - precompile *erc20precompile.Precompile + precompile *erc20.Precompile // precompile2 is a second instance of the ERC20 precompile whose denom is bondDenom. - precompile2 *erc20precompile.Precompile + precompile2 *erc20.Precompile } -func TestPrecompileTestSuite(t *testing.T) { - s = new(PrecompileTestSuite) - suite.Run(t, s) +func NewPrecompileTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *PrecompileTestSuite { + return &PrecompileTestSuite{ + create: create, + options: options, + } } func (s *PrecompileTestSuite) SetupTest() { keyring := testkeyring.New(2) - integrationNetwork := network.NewUnitTestNetwork( + options := []network.ConfigOption{ network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), - ) + } + options = append(options, s.options...) + integrationNetwork := network.NewUnitTestNetwork(s.create, options...) grpcHandler := grpc.NewIntegrationHandler(integrationNetwork) txFactory := factory.New(integrationNetwork, grpcHandler) ctx := integrationNetwork.GetContext() - sk := integrationNetwork.App.StakingKeeper + sk := integrationNetwork.App.GetStakingKeeper() bondDenom, err := sk.BondDenom(ctx) s.Require().NoError(err) s.Require().NotEmpty(bondDenom, "bond denom cannot be empty") diff --git a/precompiles/erc20/tx_test.go b/tests/integration/precompiles/erc20/test_tx.go similarity index 79% rename from precompiles/erc20/tx_test.go rename to tests/integration/precompiles/erc20/test_tx.go index c4aa60175..13c30ae14 100644 --- a/precompiles/erc20/tx_test.go +++ b/tests/integration/precompiles/erc20/test_tx.go @@ -1,4 +1,4 @@ -package erc20_test +package erc20 import ( "math/big" @@ -7,7 +7,6 @@ import ( "github.com/cosmos/evm/precompiles/erc20" "github.com/cosmos/evm/precompiles/testutil" - utiltx "github.com/cosmos/evm/testutil/tx" erc20types "github.com/cosmos/evm/x/erc20/types" "github.com/cosmos/evm/x/vm/statedb" @@ -19,7 +18,7 @@ var ( // XMPLCoin is a dummy coin used for testing purposes. XMPLCoin = sdk.NewCoins(sdk.NewInt64Coin(tokenDenom, 1e18)) // toAddr is a dummy address used for testing purposes. - toAddr = utiltx.GenerateAddress() + toAddr = GenerateAddress() ) func (s *PrecompileTestSuite) TestTransfer() { @@ -75,7 +74,7 @@ func (s *PrecompileTestSuite) TestTransfer() { return []interface{}{toAddr, big.NewInt(100)} }, func() { - toAddrBalance := s.network.App.BankKeeper.GetBalance(s.network.GetContext(), toAddr.Bytes(), tokenDenom) + toAddrBalance := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), toAddr.Bytes(), tokenDenom) s.Require().Equal(big.NewInt(100), toAddrBalance.Amount.BigInt(), "expected toAddr to have 100 XMPL") }, false, @@ -92,9 +91,9 @@ func (s *PrecompileTestSuite) TestTransfer() { contract, ctx := testutil.NewPrecompileContract(s.T(), s.network.GetContext(), fromAddr, s.precompile.Address(), 0) // Mint some coins to the module account and then send to the from address - err := s.network.App.BankKeeper.MintCoins(s.network.GetContext(), erc20types.ModuleName, XMPLCoin) + err := s.network.App.GetBankKeeper().MintCoins(s.network.GetContext(), erc20types.ModuleName, XMPLCoin) s.Require().NoError(err, "failed to mint coins") - err = s.network.App.BankKeeper.SendCoinsFromModuleToAccount(s.network.GetContext(), erc20types.ModuleName, fromAddr.Bytes(), XMPLCoin) + err = s.network.App.GetBankKeeper().SendCoinsFromModuleToAccount(s.network.GetContext(), erc20types.ModuleName, fromAddr.Bytes(), XMPLCoin) s.Require().NoError(err, "failed to send coins from module to account") _, err = s.precompile.Transfer(ctx, contract, stateDB, &method, tc.malleate()) @@ -175,7 +174,7 @@ func (s *PrecompileTestSuite) TestTransferFrom() { { "fail - not enough balance", func() []interface{} { - err := s.network.App.Erc20Keeper.SetAllowance(ctx, s.precompile.Address(), owner.Addr, spender.Addr, big.NewInt(5e18)) + err := s.network.App.GetErc20Keeper().SetAllowance(ctx, s.precompile.Address(), owner.Addr, spender.Addr, big.NewInt(5e18)) s.Require().NoError(err, "failed to set allowance") return []interface{}{owner.Addr, toAddr, big.NewInt(2e18)} @@ -188,16 +187,16 @@ func (s *PrecompileTestSuite) TestTransferFrom() { "fail - spend on behalf of own account without allowance", func() []interface{} { // Mint some coins to the module account and then send to the spender address - err := s.network.App.BankKeeper.MintCoins(ctx, erc20types.ModuleName, XMPLCoin) + err := s.network.App.GetBankKeeper().MintCoins(ctx, erc20types.ModuleName, XMPLCoin) s.Require().NoError(err, "failed to mint coins") - err = s.network.App.BankKeeper.SendCoinsFromModuleToAccount(ctx, erc20types.ModuleName, spender.AccAddr, XMPLCoin) + err = s.network.App.GetBankKeeper().SendCoinsFromModuleToAccount(ctx, erc20types.ModuleName, spender.AccAddr, XMPLCoin) s.Require().NoError(err, "failed to send coins from module to account") // NOTE: no allowance is necessary to spend on behalf of the same account return []interface{}{spender.Addr, toAddr, big.NewInt(100)} }, func() { - toAddrBalance := s.network.App.BankKeeper.GetBalance(ctx, toAddr.Bytes(), tokenDenom) + toAddrBalance := s.network.App.GetBankKeeper().GetBalance(ctx, toAddr.Bytes(), tokenDenom) s.Require().Equal(big.NewInt(100), toAddrBalance.Amount.BigInt(), "expected toAddr to have 100 XMPL") }, true, @@ -207,19 +206,19 @@ func (s *PrecompileTestSuite) TestTransferFrom() { "pass - spend on behalf of own account with allowance", func() []interface{} { // Mint some coins to the module account and then send to the spender address - err := s.network.App.BankKeeper.MintCoins(ctx, erc20types.ModuleName, XMPLCoin) + err := s.network.App.GetBankKeeper().MintCoins(ctx, erc20types.ModuleName, XMPLCoin) s.Require().NoError(err, "failed to mint coins") - err = s.network.App.BankKeeper.SendCoinsFromModuleToAccount(ctx, erc20types.ModuleName, spender.AccAddr, XMPLCoin) + err = s.network.App.GetBankKeeper().SendCoinsFromModuleToAccount(ctx, erc20types.ModuleName, spender.AccAddr, XMPLCoin) s.Require().NoError(err, "failed to send coins from module to account") - err = s.network.App.Erc20Keeper.SetAllowance(ctx, s.precompile.Address(), spender.Addr, spender.Addr, big.NewInt(100)) + err = s.network.App.GetErc20Keeper().SetAllowance(ctx, s.precompile.Address(), spender.Addr, spender.Addr, big.NewInt(100)) s.Require().NoError(err, "failed to set allowance") // NOTE: no allowance is necessary to spend on behalf of the same account return []interface{}{spender.Addr, toAddr, big.NewInt(100)} }, func() { - toAddrBalance := s.network.App.BankKeeper.GetBalance(ctx, toAddr.Bytes(), tokenDenom) + toAddrBalance := s.network.App.GetBankKeeper().GetBalance(ctx, toAddr.Bytes(), tokenDenom) s.Require().Equal(big.NewInt(100), toAddrBalance.Amount.BigInt(), "expected toAddr to have 100 XMPL") }, false, @@ -228,13 +227,13 @@ func (s *PrecompileTestSuite) TestTransferFrom() { { "pass - spend on behalf of other account", func() []interface{} { - err := s.network.App.Erc20Keeper.SetAllowance(ctx, s.precompile.Address(), owner.Addr, spender.Addr, big.NewInt(300)) + err := s.network.App.GetErc20Keeper().SetAllowance(ctx, s.precompile.Address(), owner.Addr, spender.Addr, big.NewInt(300)) s.Require().NoError(err, "failed to set allowance") return []interface{}{owner.Addr, toAddr, big.NewInt(100)} }, func() { - toAddrBalance := s.network.App.BankKeeper.GetBalance(ctx, toAddr.Bytes(), tokenDenom) + toAddrBalance := s.network.App.GetBankKeeper().GetBalance(ctx, toAddr.Bytes(), tokenDenom) s.Require().Equal(big.NewInt(100), toAddrBalance.Amount.BigInt(), "expected toAddr to have 100 XMPL") }, false, @@ -252,9 +251,9 @@ func (s *PrecompileTestSuite) TestTransferFrom() { contract, ctx = testutil.NewPrecompileContract(s.T(), ctx, spender.Addr, s.precompile.Address(), 0) // Mint some coins to the module account and then send to the from address - err := s.network.App.BankKeeper.MintCoins(ctx, erc20types.ModuleName, XMPLCoin) + err := s.network.App.GetBankKeeper().MintCoins(ctx, erc20types.ModuleName, XMPLCoin) s.Require().NoError(err, "failed to mint coins") - err = s.network.App.BankKeeper.SendCoinsFromModuleToAccount(ctx, erc20types.ModuleName, owner.AccAddr, XMPLCoin) + err = s.network.App.GetBankKeeper().SendCoinsFromModuleToAccount(ctx, erc20types.ModuleName, owner.AccAddr, XMPLCoin) s.Require().NoError(err, "failed to send coins from module to account") _, err = s.precompile.TransferFrom(ctx, contract, stDB, &method, tc.malleate()) diff --git a/precompiles/erc20/types_test.go b/tests/integration/precompiles/erc20/test_types.go similarity index 99% rename from precompiles/erc20/types_test.go rename to tests/integration/precompiles/erc20/test_types.go index 5675a9e84..46cbfecd5 100644 --- a/precompiles/erc20/types_test.go +++ b/tests/integration/precompiles/erc20/test_types.go @@ -1,4 +1,4 @@ -package erc20_test +package erc20 import ( "math/big" diff --git a/precompiles/erc20/utils_test.go b/tests/integration/precompiles/erc20/test_utils.go similarity index 90% rename from precompiles/erc20/utils_test.go rename to tests/integration/precompiles/erc20/test_utils.go index f8353ae11..56e7082aa 100644 --- a/precompiles/erc20/utils_test.go +++ b/tests/integration/precompiles/erc20/test_utils.go @@ -1,4 +1,4 @@ -package erc20_test +package erc20 import ( "fmt" @@ -7,16 +7,19 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" //nolint:revive // dot imports are fine for Gomega . "github.com/onsi/gomega" + "github.com/cosmos/evm/crypto/ethsecp256k1" "github.com/cosmos/evm/precompiles/erc20" "github.com/cosmos/evm/precompiles/testutil" - "github.com/cosmos/evm/testutil/integration/os/factory" - network "github.com/cosmos/evm/testutil/integration/os/network" - testutils "github.com/cosmos/evm/testutil/integration/os/utils" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/integration/evm/utils" utiltx "github.com/cosmos/evm/testutil/tx" + testutiltypes "github.com/cosmos/evm/testutil/types" erc20types "github.com/cosmos/evm/x/erc20/types" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -55,7 +58,7 @@ func (s *PrecompileTestSuite) setAllowance( erc20Addr common.Address, ownerPriv cryptotypes.PrivKey, spender common.Address, amount *big.Int, ) { owner := common.BytesToAddress(ownerPriv.PubKey().Address().Bytes()) - err := s.network.App.Erc20Keeper.SetAllowance(s.network.GetContext(), erc20Addr, owner, spender, amount) + err := s.network.App.GetErc20Keeper().SetAllowance(s.network.GetContext(), erc20Addr, owner, spender, amount) s.Require().NoError(err, "failed to set set allowance") } @@ -135,7 +138,7 @@ func (s *PrecompileTestSuite) requireOut( // requireAllowance is a helper function to check that a SendAuthorization // exists for a given owner and spender combination for a given amount. func (s *PrecompileTestSuite) requireAllowance(erc20Addr, owner, spender common.Address, amount *big.Int) { - allowance, err := s.network.App.Erc20Keeper.GetAllowance(s.network.GetContext(), erc20Addr, owner, spender) + allowance, err := s.network.App.GetErc20Keeper().GetAllowance(s.network.GetContext(), erc20Addr, owner, spender) s.Require().NoError(err, "expected no error unpacking the allowance") s.Require().Equal(allowance.Int64(), amount.Int64(), "expected different allowance") } @@ -145,7 +148,7 @@ func (s *PrecompileTestSuite) requireAllowance(erc20Addr, owner, spender common. // to the available and active precompiles. func (s *PrecompileTestSuite) setupERC20Precompile(denom string) *erc20.Precompile { tokenPair := erc20types.NewTokenPair(utiltx.GenerateAddress(), denom, erc20types.OWNER_MODULE) - s.network.App.Erc20Keeper.SetToken(s.network.GetContext(), tokenPair) + s.network.App.GetErc20Keeper().SetToken(s.network.GetContext(), tokenPair) precompile, err := setupERC20PrecompileForTokenPair(*s.network, tokenPair) s.Require().NoError(err, "failed to set up %q erc20 precompile", tokenPair.Denom) @@ -167,9 +170,9 @@ func (is *IntegrationTestSuite) setupERC20Precompile(denom string, tokenPairs [] precompile, err := erc20.NewPrecompile( tokenPair, - is.network.App.BankKeeper, - is.network.App.Erc20Keeper, - is.network.App.TransferKeeper, + is.network.App.GetBankKeeper(), + is.network.App.GetErc20Keeper(), + is.network.App.GetTransferKeeper(), ) Expect(err).ToNot(HaveOccurred(), "failed to set up %q erc20 precompile", tokenPair.Denom) @@ -184,15 +187,15 @@ func setupERC20PrecompileForTokenPair( ) (*erc20.Precompile, error) { precompile, err := erc20.NewPrecompile( tokenPair, - unitNetwork.App.BankKeeper, - unitNetwork.App.Erc20Keeper, - unitNetwork.App.TransferKeeper, + unitNetwork.App.GetBankKeeper(), + unitNetwork.App.GetErc20Keeper(), + unitNetwork.App.GetTransferKeeper(), ) if err != nil { return nil, errorsmod.Wrapf(err, "failed to create %q erc20 precompile", tokenPair.Denom) } - err = unitNetwork.App.Erc20Keeper.EnableDynamicPrecompiles( + err = unitNetwork.App.GetErc20Keeper().EnableDynamicPrecompiles( unitNetwork.GetContext(), precompile.Address(), ) @@ -213,16 +216,16 @@ func setupNewERC20PrecompileForTokenPair( ) (*erc20.Precompile, error) { precompile, err := erc20.NewPrecompile( tokenPair, - unitNetwork.App.BankKeeper, - unitNetwork.App.Erc20Keeper, - unitNetwork.App.TransferKeeper, + unitNetwork.App.GetBankKeeper(), + unitNetwork.App.GetErc20Keeper(), + unitNetwork.App.GetTransferKeeper(), ) if err != nil { return nil, errorsmod.Wrapf(err, "failed to create %q erc20 precompile", tokenPair.Denom) } // Update the params via gov proposal - params := unitNetwork.App.Erc20Keeper.GetParams(unitNetwork.GetContext()) + params := unitNetwork.App.GetErc20Keeper().GetParams(unitNetwork.GetContext()) params.DynamicPrecompiles = append(params.DynamicPrecompiles, precompile.Address().Hex()) slices.Sort(params.DynamicPrecompiles) @@ -230,7 +233,7 @@ func setupNewERC20PrecompileForTokenPair( return nil, err } - if err := testutils.UpdateERC20Params(testutils.UpdateParamsInput{ + if err := utils.UpdateERC20Params(utils.UpdateParamsInput{ Pk: privKey, Tf: tf, Network: unitNetwork, @@ -251,7 +254,7 @@ func (is *IntegrationTestSuite) getTxAndCallArgs( contractData ContractsData, methodName string, args ...interface{}, -) (evmtypes.EvmTxArgs, factory.CallArgs) { +) (evmtypes.EvmTxArgs, testutiltypes.CallArgs) { cd := contractData.GetContractData(callType) txArgs := evmtypes.EvmTxArgs{ @@ -259,7 +262,7 @@ func (is *IntegrationTestSuite) getTxAndCallArgs( GasPrice: gasPrice, } - callArgs := factory.CallArgs{ + callArgs := testutiltypes.CallArgs{ ContractABI: cd.ABI, MethodName: methodName, Args: args, @@ -440,3 +443,22 @@ func (is *IntegrationTestSuite) MintERC20(callType CallType, contractData Contra // commit changes to chain state return is.network.NextBlock() } + +// NewAddrKey generates an Ethereum address and its corresponding private key. +func NewAddrKey() (common.Address, *ethsecp256k1.PrivKey) { + privkey, _ := ethsecp256k1.GenerateKey() + key, err := privkey.ToECDSA() + if err != nil { + return common.Address{}, nil + } + + addr := crypto.PubkeyToAddress(key.PublicKey) + + return addr, privkey +} + +// GenerateAddress generates an Ethereum address. +func GenerateAddress() common.Address { + addr, _ := NewAddrKey() + return addr +} diff --git a/precompiles/evidence/query_test.go b/tests/integration/precompiles/evidence/test_query.go similarity index 92% rename from precompiles/evidence/query_test.go rename to tests/integration/precompiles/evidence/test_query.go index 29e730f21..1a1070483 100644 --- a/precompiles/evidence/query_test.go +++ b/tests/integration/precompiles/evidence/test_query.go @@ -1,4 +1,4 @@ -package evidence_test +package evidence import ( "fmt" @@ -62,7 +62,7 @@ func (s *PrecompileTestSuite) TestEvidence() { } }, func() []byte { - validators, err := s.network.App.StakingKeeper.GetAllValidators(s.network.GetContext()) + validators, err := s.network.App.GetStakingKeeper().GetAllValidators(s.network.GetContext()) s.Require().NoError(err) s.Require().NotEmpty(validators) @@ -77,7 +77,7 @@ func (s *PrecompileTestSuite) TestEvidence() { ConsensusAddress: sdk.ConsAddress(valConsAddr).String(), } - err = s.network.App.EvidenceKeeper.SubmitEvidence(s.network.GetContext(), evidenceData) + err = s.network.App.GetEvidenceKeeper().SubmitEvidence(s.network.GetContext(), evidenceData) s.Require().NoError(err) return evidenceData.Hash() @@ -170,7 +170,7 @@ func (s *PrecompileTestSuite) TestGetAllEvidence() { } }, func() { - validators, err := s.network.App.StakingKeeper.GetAllValidators(s.network.GetContext()) + validators, err := s.network.App.GetStakingKeeper().GetAllValidators(s.network.GetContext()) s.Require().NoError(err) s.Require().NotEmpty(validators) @@ -185,7 +185,7 @@ func (s *PrecompileTestSuite) TestGetAllEvidence() { ConsensusAddress: sdk.ConsAddress(valConsAddr).String(), } - err = s.network.App.EvidenceKeeper.SubmitEvidence(s.network.GetContext(), evidenceData) + err = s.network.App.GetEvidenceKeeper().SubmitEvidence(s.network.GetContext(), evidenceData) s.Require().NoError(err) }, 200000, diff --git a/precompiles/evidence/setup_test.go b/tests/integration/precompiles/evidence/test_setup.go similarity index 62% rename from precompiles/evidence/setup_test.go rename to tests/integration/precompiles/evidence/test_setup.go index b2ba0af6d..af5f1a3db 100644 --- a/precompiles/evidence/setup_test.go +++ b/tests/integration/precompiles/evidence/test_setup.go @@ -1,17 +1,16 @@ -package evidence_test +package evidence import ( "context" "fmt" - "testing" "github.com/stretchr/testify/suite" "github.com/cosmos/evm/precompiles/evidence" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + testkeyring "github.com/cosmos/evm/testutil/keyring" "cosmossdk.io/x/evidence/exported" "cosmossdk.io/x/evidence/types" @@ -20,6 +19,8 @@ import ( type PrecompileTestSuite struct { suite.Suite + create network.CreateEvmApp + opts []network.ConfigOption network *network.UnitTestNetwork factory factory.TxFactory grpcHandler grpc.Handler @@ -28,23 +29,25 @@ type PrecompileTestSuite struct { precompile *evidence.Precompile } -func TestPrecompileTestSuite(t *testing.T) { - suite.Run(t, new(PrecompileTestSuite)) +func NewPrecompileTestSuite(create network.CreateEvmApp, opts ...network.ConfigOption) *PrecompileTestSuite { + return &PrecompileTestSuite{ + create: create, + opts: opts, + } } func (s *PrecompileTestSuite) SetupTest() { keyring := testkeyring.New(2) var err error - nw := network.NewUnitTestNetwork( - network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), - ) + s.opts = append(s.opts, network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...)) + nw := network.NewUnitTestNetwork(s.create, s.opts...) grpcHandler := grpc.NewIntegrationHandler(nw) txFactory := factory.New(nw, grpcHandler) router := types.NewRouter() - router = router.AddRoute(types.RouteEquivocation, testEquivocationHandler(nw.App.EvidenceKeeper)) - nw.App.EvidenceKeeper.SetRouter(router) + router = router.AddRoute(types.RouteEquivocation, testEquivocationHandler(nw.App.GetEvidenceKeeper())) + nw.App.GetEvidenceKeeper().SetRouter(router) s.network = nw s.factory = txFactory @@ -52,7 +55,7 @@ func (s *PrecompileTestSuite) SetupTest() { s.keyring = keyring if s.precompile, err = evidence.NewPrecompile( - s.network.App.EvidenceKeeper, + *s.network.App.GetEvidenceKeeper(), ); err != nil { panic(err) } diff --git a/precompiles/evidence/tx_test.go b/tests/integration/precompiles/evidence/test_tx.go similarity index 93% rename from precompiles/evidence/tx_test.go rename to tests/integration/precompiles/evidence/test_tx.go index a1d3b279f..d14e00f02 100644 --- a/precompiles/evidence/tx_test.go +++ b/tests/integration/precompiles/evidence/test_tx.go @@ -1,4 +1,4 @@ -package evidence_test +package evidence import ( "fmt" @@ -33,7 +33,7 @@ func (s *PrecompileTestSuite) TestSubmitEvidence() { { "success - submit equivocation evidence", func() []interface{} { - validators, err := s.network.App.StakingKeeper.GetAllValidators(s.network.GetContext()) + validators, err := s.network.App.GetStakingKeeper().GetAllValidators(s.network.GetContext()) s.Require().NoError(err) s.Require().NotEmpty(validators) diff --git a/precompiles/gov/events_test.go b/tests/integration/precompiles/gov/test_events.go similarity index 99% rename from precompiles/gov/events_test.go rename to tests/integration/precompiles/gov/test_events.go index bf5bee7e0..2e72f058b 100644 --- a/precompiles/gov/events_test.go +++ b/tests/integration/precompiles/gov/test_events.go @@ -1,4 +1,4 @@ -package gov_test +package gov import ( "github.com/ethereum/go-ethereum/common" diff --git a/precompiles/gov/gov_test.go b/tests/integration/precompiles/gov/test_gov.go similarity index 88% rename from precompiles/gov/gov_test.go rename to tests/integration/precompiles/gov/test_gov.go index e2ec3f435..79e207d36 100644 --- a/precompiles/gov/gov_test.go +++ b/tests/integration/precompiles/gov/test_gov.go @@ -1,4 +1,4 @@ -package gov_test +package gov import ( "math/big" @@ -9,8 +9,8 @@ import ( "github.com/ethereum/go-ethereum/core/vm" "github.com/holiman/uint256" - chainutil "github.com/cosmos/evm/evmd/testutil" "github.com/cosmos/evm/precompiles/gov" + "github.com/cosmos/evm/testutil" "github.com/cosmos/evm/x/vm/statedb" evmtypes "github.com/cosmos/evm/x/vm/types" ) @@ -77,7 +77,7 @@ func (s *PrecompileTestSuite) TestRun() { s.SetupTest() ctx := s.network.GetContext() - baseFee := s.network.App.EVMKeeper.GetBaseFee(ctx) + baseFee := s.network.App.GetEVMKeeper().GetBaseFee(ctx) // malleate testcase caller, input := tc.malleate() @@ -93,7 +93,7 @@ func (s *PrecompileTestSuite) TestRun() { To: &contractAddr, Amount: nil, GasLimit: 100000, - GasPrice: chainutil.ExampleMinGasPrices.BigInt(), + GasPrice: testutil.ExampleMinGasPrices.BigInt(), GasFeeCap: baseFee, GasTipCap: big.NewInt(1), Accesses: ðtypes.AccessList{}, @@ -103,21 +103,21 @@ func (s *PrecompileTestSuite) TestRun() { // Instantiate config proposerAddress := ctx.BlockHeader().ProposerAddress - cfg, err := s.network.App.EVMKeeper.EVMConfig(ctx, proposerAddress) + cfg, err := s.network.App.GetEVMKeeper().EVMConfig(ctx, proposerAddress) s.Require().NoError(err, "failed to instantiate EVM config") // Instantiate EVM headerHash := ctx.HeaderHash() stDB := statedb.New( ctx, - s.network.App.EVMKeeper, + s.network.App.GetEVMKeeper(), statedb.NewEmptyTxConfig(common.BytesToHash(headerHash)), ) - evm := s.network.App.EVMKeeper.NewEVM( + evm := s.network.App.GetEVMKeeper().NewEVM( ctx, *msg, cfg, nil, stDB, ) - precompiles, found, err := s.network.App.EVMKeeper.GetPrecompileInstance(ctx, contractAddr) + precompiles, found, err := s.network.App.GetEVMKeeper().GetPrecompileInstance(ctx, contractAddr) s.Require().NoError(err, "failed to instantiate precompile") s.Require().True(found, "not found precompile") evm.WithPrecompiles(precompiles.Map) diff --git a/tests/integration/precompiles/gov/test_integration.go b/tests/integration/precompiles/gov/test_integration.go new file mode 100644 index 000000000..5393ee9ec --- /dev/null +++ b/tests/integration/precompiles/gov/test_integration.go @@ -0,0 +1,2068 @@ +package gov + +import ( + "encoding/json" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" + + //nolint:revive // dot imports are fine for Ginkgo + . "github.com/onsi/ginkgo/v2" + //nolint:revive // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" + + cmn "github.com/cosmos/evm/precompiles/common" + "github.com/cosmos/evm/precompiles/gov" + "github.com/cosmos/evm/precompiles/testutil" + "github.com/cosmos/evm/precompiles/testutil/contracts" + commonfactory "github.com/cosmos/evm/testutil/integration/base/factory" + "github.com/cosmos/evm/testutil/integration/evm/network" + testutiltx "github.com/cosmos/evm/testutil/tx" + testutiltypes "github.com/cosmos/evm/testutil/types" + evmtypes "github.com/cosmos/evm/x/vm/types" + + "cosmossdk.io/math" + + "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" + "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" +) + +// General variables used for integration tests +var ( + // differentAddr is an address generated for testing purposes that e.g. raises the different origin error + differentAddr = testutiltx.GenerateAddress() + // defaultCallArgs are the default arguments for calling the smart contract + // + // NOTE: this has to be populated in a BeforeEach block because the contractAddr would otherwise be a nil address. + callArgs testutiltypes.CallArgs + // txArgs are the EVM transaction arguments to use in the transactions + txArgs evmtypes.EvmTxArgs + // defaultLogCheck instantiates a log check arguments struct with the precompile ABI events populated. + defaultLogCheck testutil.LogCheckArgs + // passCheck defines the arguments to check if the precompile returns no error + passCheck testutil.LogCheckArgs + // outOfGasCheck defines the arguments to check if the precompile returns out of gas error + outOfGasCheck testutil.LogCheckArgs + // govModuleAddr is the address of the gov module account + govModuleAddr sdk.AccAddress +) + +const ( + testSubmitProposalFromContract = "testSubmitProposalFromContract" +) + +func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmApp, options ...network.ConfigOption) { + var _ = Describe("Calling governance precompile from EOA", func() { + var ( + s *PrecompileTestSuite + proposerKey types.PrivKey + proposerAddr common.Address + proposerAccAddr sdk.AccAddress + ) + const ( + proposalID uint64 = 1 + option uint8 = 1 + metadata = "metadata" + ) + BeforeEach(func() { + s = NewPrecompileTestSuite(create, options...) + s.SetupTest() + + // set the default call arguments + callArgs = testutiltypes.CallArgs{ + ContractABI: s.precompile.ABI, + } + defaultLogCheck = testutil.LogCheckArgs{ + ABIEvents: s.precompile.ABI.Events, + } + passCheck = defaultLogCheck.WithExpPass(true) + outOfGasCheck = defaultLogCheck.WithErrContains(vm.ErrOutOfGas.Error()) + + // reset tx args each test to avoid keeping custom + // values of previous tests (e.g. gasLimit) + precompileAddr := s.precompile.Address() + txArgs = evmtypes.EvmTxArgs{ + To: &precompileAddr, + } + txArgs.GasLimit = 200_000 + + proposerKey = s.keyring.GetPrivKey(0) + proposerAddr = s.keyring.GetAddr(0) + proposerAccAddr = sdk.AccAddress(proposerAddr.Bytes()) + govModuleAddr = authtypes.NewModuleAddress(govtypes.ModuleName) + }) + + // ===================================== + // TRANSACTIONS + // ===================================== + Describe("Execute SubmitProposal transaction", func() { + const method = gov.SubmitProposalMethod + + BeforeEach(func() { callArgs.MethodName = method }) + + It("fails with low gas", func() { + txArgs.GasLimit = 30_000 + jsonBlob := minimalBankSendProposalJSON(proposerAccAddr, s.network.GetBaseDenom(), "50") + callArgs.Args = []interface{}{proposerAddr, jsonBlob, minimalDeposit(s.network.GetBaseDenom(), big.NewInt(1))} + + _, _, err := s.factory.CallContractAndCheckLogs(proposerKey, txArgs, callArgs, outOfGasCheck) + Expect(err).To(BeNil()) + }) + + It("creates a proposal and emits event", func() { + jsonBlob := minimalBankSendProposalJSON(proposerAccAddr, s.network.GetBaseDenom(), "1") + callArgs.Args = []interface{}{proposerAddr, jsonBlob, minimalDeposit(s.network.GetBaseDenom(), big.NewInt(1))} + eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) + + _, ethRes, err := s.factory.CallContractAndCheckLogs(proposerKey, txArgs, callArgs, eventCheck) + Expect(err).To(BeNil()) + + // unpack return → proposalId + var out uint64 + err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) + Expect(err).To(BeNil()) + Expect(out).To(BeNumerically(">", 0)) + + // ensure proposal exists on-chain + prop, err := s.network.App.GetGovKeeper().Proposals.Get(s.network.GetContext(), out) + Expect(err).To(BeNil()) + Expect(prop.Proposer).To(Equal(sdk.AccAddress(proposerAddr.Bytes()).String())) + }) + + It("fails with invalid JSON", func() { + callArgs.Args = []interface{}{proposerAddr, []byte("{invalid}"), minimalDeposit(s.network.GetBaseDenom(), big.NewInt(1))} + errCheck := defaultLogCheck.WithErrContains("invalid proposal JSON") + _, _, err := s.factory.CallContractAndCheckLogs( + proposerKey, txArgs, callArgs, errCheck) + Expect(err).To(BeNil()) + }) + + It("fails with invalid deposit denom", func() { + jsonBlob := minimalBankSendProposalJSON(proposerAccAddr, s.network.GetBaseDenom(), "1") + invalidDep := []cmn.Coin{{Denom: "bad", Amount: big.NewInt(1)}} + callArgs.Args = []interface{}{proposerAddr, jsonBlob, invalidDep} + errCheck := defaultLogCheck.WithErrContains("invalid deposit denom") + _, _, err := s.factory.CallContractAndCheckLogs( + proposerKey, txArgs, callArgs, errCheck) + Expect(err).To(BeNil()) + }) + }) + + Describe("Execute Deposit transaction", func() { + const method = gov.DepositMethod + + BeforeEach(func() { callArgs.MethodName = method }) + + It("fails with wrong proposal id", func() { + callArgs.Args = []interface{}{proposerAddr, uint64(999), minimalDeposit(s.network.GetBaseDenom(), big.NewInt(1))} + errCheck := defaultLogCheck.WithErrContains("not found") + _, _, err := s.factory.CallContractAndCheckLogs(proposerKey, txArgs, callArgs, errCheck) + Expect(err).To(BeNil()) + }) + + It("deposits successfully and emits event", func() { + jsonBlob := minimalBankSendProposalJSON(proposerAccAddr, s.network.GetBaseDenom(), "1") + eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) + callArgs.MethodName = gov.SubmitProposalMethod + minDeposit := minimalDeposit(s.network.GetBaseDenom(), big.NewInt(1)) + callArgs.Args = []interface{}{proposerAddr, jsonBlob, minDeposit} + _, evmRes, err := s.factory.CallContractAndCheckLogs(proposerKey, txArgs, callArgs, eventCheck) + Expect(err).To(BeNil()) + var propID uint64 + err = s.precompile.UnpackIntoInterface(&propID, gov.SubmitProposalMethod, evmRes.Ret) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + // get proposal by propID + prop, err := s.network.App.GetGovKeeper().Proposals.Get(s.network.GetContext(), propID) + Expect(err).To(BeNil()) + Expect(prop.Status).To(Equal(govv1.StatusDepositPeriod)) + Expect(prop.Proposer).To(Equal(sdk.AccAddress(proposerAddr.Bytes()).String())) + minDepositCoins, err := cmn.NewSdkCoinsFromCoins(minDeposit) + Expect(err).To(BeNil()) + td := prop.GetTotalDeposit() + Expect(td).To(HaveLen(1)) + Expect(td[0].Denom).To(Equal(minDepositCoins[0].Denom)) + Expect(td[0].Amount.String()).To(Equal(minDepositCoins[0].Amount.String())) + + callArgs.MethodName = gov.DepositMethod + callArgs.Args = []interface{}{proposerAddr, propID, minimalDeposit(s.network.GetBaseDenom(), big.NewInt(1))} + eventCheck = passCheck.WithExpEvents(gov.EventTypeDeposit) + _, _, err = s.factory.CallContractAndCheckLogs(proposerKey, txArgs, callArgs, eventCheck) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + // Update expected total deposit + td[0].Amount = td[0].Amount.Add(minDepositCoins[0].Amount) + + // verify via query + callArgs.MethodName = gov.GetProposalMethod + callArgs.Args = []interface{}{propID} + _, ethRes, err := s.factory.CallContractAndCheckLogs(proposerKey, txArgs, callArgs, passCheck) + Expect(err).To(BeNil()) + + var out gov.ProposalOutput + err = s.precompile.UnpackIntoInterface(&out, gov.GetProposalMethod, ethRes.Ret) + Expect(err).To(BeNil()) + Expect(out.Proposal.Id).To(Equal(propID)) + Expect(out.Proposal.Status).To(Equal(uint32(govv1.StatusDepositPeriod))) + newTd := out.Proposal.TotalDeposit + Expect(newTd).To(HaveLen(1)) + Expect(newTd[0].Denom).To(Equal(minDepositCoins[0].Denom)) + Expect(newTd[0].Amount.String()).To(Equal(td[0].Amount.String())) + }) + }) + + Describe("Execute CancelProposal transaction", func() { + const method = gov.CancelProposalMethod + + BeforeEach(func() { + callArgs.MethodName = method + }) + + It("fails when called by a non-proposer", func() { + callArgs.Args = []interface{}{proposerAddr, proposalID} + notProposerKey := s.keyring.GetPrivKey(1) + notProposerAddr := s.keyring.GetAddr(1) + errCheck := defaultLogCheck.WithErrContains( + cmn.ErrRequesterIsNotMsgSender, + notProposerAddr.String(), + proposerAddr.String(), + ) + + _, _, err := s.factory.CallContractAndCheckLogs(notProposerKey, txArgs, callArgs, errCheck) + Expect(err).To(BeNil()) + }) + + It("cancels a live proposal and emits event", func() { + proposal, err := s.network.App.GetGovKeeper().Proposals.Get(s.network.GetContext(), proposalID) + Expect(err).To(BeNil()) + + // Cancel proposal + callArgs.Args = []interface{}{proposerAddr, proposal.Id} + eventCheck := passCheck.WithExpEvents(gov.EventTypeCancelProposal) + _, evmRes, err := s.factory.CallContractAndCheckLogs(proposerKey, txArgs, callArgs, eventCheck) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + var succeeded bool + err = s.precompile.UnpackIntoInterface(&succeeded, gov.CancelProposalMethod, evmRes.Ret) + Expect(err).To(BeNil()) + Expect(succeeded).To(BeTrue()) + + // 3. Check that the proposal is not found + _, err = s.network.App.GetGovKeeper().Proposals.Get(s.network.GetContext(), proposal.Id) + Expect(err.Error()).To(ContainSubstring("not found")) + }) + + It("cancels a proposal and see cancellation fee charged", func() { + // Fix the gas limit and gas price for predictable gas usage. + // This is for calculating expected cancellation fee. + baseFee := s.network.App.GetFeeMarketKeeper().GetBaseFee(s.network.GetContext()) + baseFeeInt := baseFee.TruncateInt64() + txArgs.GasPrice = new(big.Int).SetInt64(baseFeeInt) + txArgs.GasLimit = 500_000 + + // Get the prposal for cancellation + proposal, err := s.network.App.GetGovKeeper().Proposals.Get(s.network.GetContext(), 1) + Expect(err).To(BeNil()) + + // Calc cancellation fee + proposalDeposits, err := s.network.App.GetGovKeeper().GetDeposits(s.network.GetContext(), proposal.Id) + Expect(err).To(BeNil()) + proposalDepositAmt := proposalDeposits[0].Amount[0].Amount + params, err := s.network.App.GetGovKeeper().Params.Get(s.network.GetContext()) + Expect(err).To(BeNil()) + rate := math.LegacyMustNewDecFromStr(params.ProposalCancelRatio) + cancelFee := proposalDepositAmt.ToLegacyDec().Mul(rate).TruncateInt() + remaining := proposalDepositAmt.Sub(cancelFee) + + // Cancel it + callArgs.Args = []interface{}{proposerAddr, proposal.Id} + eventCheck := passCheck.WithExpEvents(gov.EventTypeCancelProposal) + // Balance of proposer + proposalBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), proposerAccAddr, s.network.GetBaseDenom()) + res, _, err := s.factory.CallContractAndCheckLogs(proposerKey, txArgs, callArgs, eventCheck) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + gasCost := math.NewInt(res.GasUsed).Mul(math.NewInt(txArgs.GasPrice.Int64())) + + // 6. Check that the cancellation fee is charged, diff should be less than the deposit amount + afterCancelBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), proposerAccAddr, s.network.GetBaseDenom()) + Expect(afterCancelBal.Amount).To(Equal( + proposalBal.Amount. + Sub(gasCost). + Add(remaining), + ), + "expected cancellation fee to be deducted from proposer balance") + + // 7. Check that the proposal is not found + _, err = s.network.App.GetGovKeeper().Proposals.Get(s.network.GetContext(), proposal.Id) + Expect(err.Error()).To(ContainSubstring("not found")) + }) + }) + + Describe("Execute Vote transaction", func() { + const method = gov.VoteMethod + + BeforeEach(func() { + // set the default call arguments + callArgs.MethodName = method + }) + + It("should return error if the provided gasLimit is too low", func() { + txArgs.GasLimit = 30000 + callArgs.Args = []interface{}{ + s.keyring.GetAddr(0), proposalID, option, metadata, + } + + _, _, err := s.factory.CallContractAndCheckLogs(s.keyring.GetPrivKey(0), txArgs, callArgs, outOfGasCheck) + Expect(err).To(BeNil()) + + // tally result yes count should remain unchanged + proposal, _ := s.network.App.GetGovKeeper().Proposals.Get(s.network.GetContext(), proposalID) + _, _, tallyResult, err := s.network.App.GetGovKeeper().Tally(s.network.GetContext(), proposal) + Expect(err).To(BeNil()) + Expect(tallyResult.YesCount).To(Equal("0"), "expected tally result yes count to remain unchanged") + }) + + It("should return error if the origin is different than the voter", func() { + callArgs.Args = []interface{}{ + differentAddr, proposalID, option, metadata, + } + + voterSetCheck := defaultLogCheck.WithErrContains(cmn.ErrRequesterIsNotMsgSender, s.keyring.GetAddr(0).String(), differentAddr.String()) + + _, _, err := s.factory.CallContractAndCheckLogs(s.keyring.GetPrivKey(0), txArgs, callArgs, voterSetCheck) + Expect(err).To(BeNil()) + }) + + It("should vote success", func() { + callArgs.Args = []interface{}{ + s.keyring.GetAddr(0), proposalID, option, metadata, + } + + voterSetCheck := passCheck.WithExpEvents(gov.EventTypeVote) + + _, _, err := s.factory.CallContractAndCheckLogs(s.keyring.GetPrivKey(0), txArgs, callArgs, voterSetCheck) + Expect(err).To(BeNil(), "error while calling the precompile") + + // tally result yes count should updated + proposal, _ := s.network.App.GetGovKeeper().Proposals.Get(s.network.GetContext(), proposalID) + _, _, tallyResult, err := s.network.App.GetGovKeeper().Tally(s.network.GetContext(), proposal) + Expect(err).To(BeNil()) + + Expect(tallyResult.YesCount).To(Equal(math.NewInt(3e18).String()), "expected tally result yes count updated") + }) + }) + + Describe("Execute VoteWeighted transaction", func() { + const method = gov.VoteWeightedMethod + + BeforeEach(func() { + callArgs.MethodName = method + }) + + It("should return error if the provided gasLimit is too low", func() { + txArgs.GasLimit = 30000 + callArgs.Args = []interface{}{ + s.keyring.GetAddr(0), + proposalID, + []gov.WeightedVoteOption{ + {Option: 1, Weight: "0.5"}, + {Option: 2, Weight: "0.5"}, + }, + metadata, + } + + _, _, err := s.factory.CallContractAndCheckLogs(s.keyring.GetPrivKey(0), txArgs, callArgs, outOfGasCheck) + Expect(err).To(BeNil()) + + // tally result should remain unchanged + proposal, _ := s.network.App.GetGovKeeper().Proposals.Get(s.network.GetContext(), proposalID) + _, _, tallyResult, err := s.network.App.GetGovKeeper().Tally(s.network.GetContext(), proposal) + Expect(err).To(BeNil()) + Expect(tallyResult.YesCount).To(Equal("0"), "expected tally result to remain unchanged") + }) + + It("should return error if the origin is different than the voter", func() { + callArgs.Args = []interface{}{ + differentAddr, + proposalID, + []gov.WeightedVoteOption{ + {Option: 1, Weight: "0.5"}, + {Option: 2, Weight: "0.5"}, + }, + metadata, + } + + voterSetCheck := defaultLogCheck.WithErrContains(cmn.ErrRequesterIsNotMsgSender, s.keyring.GetAddr(0).String(), differentAddr.String()) + + _, _, err := s.factory.CallContractAndCheckLogs(s.keyring.GetPrivKey(0), txArgs, callArgs, voterSetCheck) + Expect(err).To(BeNil()) + }) + + It("should vote weighted success", func() { + callArgs.Args = []interface{}{ + s.keyring.GetAddr(0), + proposalID, + []gov.WeightedVoteOption{ + {Option: 1, Weight: "0.7"}, + {Option: 2, Weight: "0.3"}, + }, + metadata, + } + + voterSetCheck := passCheck.WithExpEvents(gov.EventTypeVoteWeighted) + + _, _, err := s.factory.CallContractAndCheckLogs(s.keyring.GetPrivKey(0), txArgs, callArgs, voterSetCheck) + Expect(err).To(BeNil(), "error while calling the precompile") + + // tally result should be updated + proposal, _ := s.network.App.GetGovKeeper().Proposals.Get(s.network.GetContext(), proposalID) + _, _, tallyResult, err := s.network.App.GetGovKeeper().Tally(s.network.GetContext(), proposal) + Expect(err).To(BeNil()) + + expectedYesCount := math.NewInt(21e17) // 70% of 3e18 + Expect(tallyResult.YesCount).To(Equal(expectedYesCount.String()), "expected tally result yes count updated") + + expectedAbstainCount := math.NewInt(9e17) // 30% of 3e18 + Expect(tallyResult.AbstainCount).To(Equal(expectedAbstainCount.String()), "expected tally result no count updated") + }) + }) + + // ===================================== + // QUERIES + // ===================================== + Describe("Execute queries", func() { + Context("vote query", func() { + method := gov.GetVoteMethod + BeforeEach(func() { + // submit a vote + voteArgs := testutiltypes.CallArgs{ + ContractABI: s.precompile.ABI, + MethodName: gov.VoteMethod, + Args: []interface{}{ + s.keyring.GetAddr(0), proposalID, option, metadata, + }, + } + + voterSetCheck := passCheck.WithExpEvents(gov.EventTypeVote) + + _, _, err := s.factory.CallContractAndCheckLogs(s.keyring.GetPrivKey(0), txArgs, voteArgs, voterSetCheck) + Expect(err).To(BeNil(), "error while calling the precompile") + Expect(s.network.NextBlock()).To(BeNil()) + }) + It("should return a vote", func() { + callArgs.MethodName = method + callArgs.Args = []interface{}{proposalID, s.keyring.GetAddr(0)} + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var out gov.VoteOutput + err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) + Expect(err).To(BeNil()) + + Expect(out.Vote.Voter).To(Equal(s.keyring.GetAddr(0))) + Expect(out.Vote.ProposalId).To(Equal(proposalID)) + Expect(out.Vote.Metadata).To(Equal(metadata)) + Expect(out.Vote.Options).To(HaveLen(1)) + Expect(out.Vote.Options[0].Option).To(Equal(option)) + Expect(out.Vote.Options[0].Weight).To(Equal(math.LegacyOneDec().String())) + }) + }) + + Context("weighted vote query", func() { + method := gov.GetVoteMethod + BeforeEach(func() { + // submit a weighted vote + voteArgs := testutiltypes.CallArgs{ + ContractABI: s.precompile.ABI, + MethodName: gov.VoteWeightedMethod, + Args: []interface{}{ + s.keyring.GetAddr(0), + proposalID, + []gov.WeightedVoteOption{ + {Option: 1, Weight: "0.7"}, + {Option: 2, Weight: "0.3"}, + }, + metadata, + }, + } + + voterSetCheck := passCheck.WithExpEvents(gov.EventTypeVoteWeighted) + + _, _, err := s.factory.CallContractAndCheckLogs(s.keyring.GetPrivKey(0), txArgs, voteArgs, voterSetCheck) + Expect(err).To(BeNil(), "error while calling the precompile") + Expect(s.network.NextBlock()).To(BeNil()) + }) + + It("should return a weighted vote", func() { + callArgs.MethodName = method + callArgs.Args = []interface{}{proposalID, s.keyring.GetAddr(0)} + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var out gov.VoteOutput + err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) + Expect(err).To(BeNil()) + + Expect(out.Vote.Voter).To(Equal(s.keyring.GetAddr(0))) + Expect(out.Vote.ProposalId).To(Equal(proposalID)) + Expect(out.Vote.Metadata).To(Equal(metadata)) + Expect(out.Vote.Options).To(HaveLen(2)) + Expect(out.Vote.Options[0].Option).To(Equal(uint8(1))) + Expect(out.Vote.Options[0].Weight).To(Equal("0.7")) + Expect(out.Vote.Options[1].Option).To(Equal(uint8(2))) + Expect(out.Vote.Options[1].Weight).To(Equal("0.3")) + }) + }) + + Context("votes query", func() { + method := gov.GetVotesMethod + BeforeEach(func() { + // submit votes + for _, key := range s.keyring.GetKeys() { + voteArgs := testutiltypes.CallArgs{ + ContractABI: s.precompile.ABI, + MethodName: gov.VoteMethod, + Args: []interface{}{ + key.Addr, proposalID, option, metadata, + }, + } + + voterSetCheck := passCheck.WithExpEvents(gov.EventTypeVote) + + _, _, err := s.factory.CallContractAndCheckLogs(key.Priv, txArgs, voteArgs, voterSetCheck) + Expect(err).To(BeNil(), "error while calling the precompile") + Expect(s.network.NextBlock()).To(BeNil()) + } + }) + It("should return all votes", func() { + callArgs.MethodName = method + callArgs.Args = []interface{}{ + proposalID, + query.PageRequest{ + CountTotal: true, + }, + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var out gov.VotesOutput + err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) + Expect(err).To(BeNil()) + + votersCount := len(s.keyring.GetKeys()) + Expect(out.PageResponse.Total).To(Equal(uint64(votersCount))) + Expect(out.PageResponse.NextKey).To(Equal([]byte{})) + Expect(out.Votes).To(HaveLen(votersCount)) + for _, v := range out.Votes { + Expect(v.ProposalId).To(Equal(proposalID)) + Expect(v.Metadata).To(Equal(metadata)) + Expect(v.Options).To(HaveLen(1)) + Expect(v.Options[0].Option).To(Equal(option)) + Expect(v.Options[0].Weight).To(Equal(math.LegacyOneDec().String())) + } + }) + }) + + Context("deposit query", func() { + method := gov.GetDepositMethod + BeforeEach(func() { + callArgs.MethodName = method + }) + + It("should return a deposit", func() { + callArgs.Args = []interface{}{proposalID, s.keyring.GetAddr(0)} + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var out gov.DepositOutput + err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) + Expect(err).To(BeNil()) + + Expect(out.Deposit.ProposalId).To(Equal(proposalID)) + Expect(out.Deposit.Depositor).To(Equal(s.keyring.GetAddr(0))) + Expect(out.Deposit.Amount).To(HaveLen(1)) + Expect(out.Deposit.Amount[0].Denom).To(Equal(s.network.GetBaseDenom())) + Expect(out.Deposit.Amount[0].Amount.Cmp(big.NewInt(100))).To(Equal(0)) + }) + }) + + Context("deposits query", func() { + method := gov.GetDepositsMethod + BeforeEach(func() { + callArgs.MethodName = method + }) + + It("should return all deposits", func() { + callArgs.Args = []interface{}{ + proposalID, + query.PageRequest{ + CountTotal: true, + }, + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var out gov.DepositsOutput + err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) + Expect(err).To(BeNil()) + + Expect(out.PageResponse.Total).To(Equal(uint64(1))) + Expect(out.PageResponse.NextKey).To(Equal([]byte{})) + Expect(out.Deposits).To(HaveLen(1)) + for _, d := range out.Deposits { + Expect(d.ProposalId).To(Equal(proposalID)) + Expect(d.Amount).To(HaveLen(1)) + Expect(d.Amount[0].Denom).To(Equal(s.network.GetBaseDenom())) + Expect(d.Amount[0].Amount.Cmp(big.NewInt(100))).To(Equal(0)) + } + }) + }) + + Context("tally result query", func() { + method := gov.GetTallyResultMethod + BeforeEach(func() { + callArgs.MethodName = method + voteArgs := testutiltypes.CallArgs{ + ContractABI: s.precompile.ABI, + MethodName: gov.VoteMethod, + Args: []interface{}{ + s.keyring.GetAddr(0), proposalID, option, metadata, + }, + } + + voterSetCheck := passCheck.WithExpEvents(gov.EventTypeVote) + + _, _, err := s.factory.CallContractAndCheckLogs(s.keyring.GetPrivKey(0), txArgs, voteArgs, voterSetCheck) + Expect(err).To(BeNil(), "error while calling the precompile") + Expect(s.network.NextBlock()).To(BeNil()) + }) + + It("should return the tally result", func() { + callArgs.Args = []interface{}{proposalID} + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var out gov.TallyResultOutput + err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) + Expect(err).To(BeNil()) + + Expect(out.TallyResult.Yes).To(Equal("3000000000000000000")) + Expect(out.TallyResult.Abstain).To(Equal("0")) + Expect(out.TallyResult.No).To(Equal("0")) + Expect(out.TallyResult.NoWithVeto).To(Equal("0")) + }) + }) + + Context("proposal query", func() { + method := gov.GetProposalMethod + BeforeEach(func() { + callArgs.MethodName = method + }) + + It("should return a proposal", func() { + callArgs.Args = []interface{}{uint64(1)} + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var out gov.ProposalOutput + err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) + Expect(err).To(BeNil()) + + // Check proposal details + Expect(out.Proposal.Id).To(Equal(uint64(1))) + Expect(out.Proposal.Status).To(Equal(uint32(govv1.StatusVotingPeriod))) + Expect(out.Proposal.Proposer).To(Equal(s.keyring.GetAddr(0))) + Expect(out.Proposal.Metadata).To(Equal("ipfs://CID")) + Expect(out.Proposal.Title).To(Equal("test prop")) + Expect(out.Proposal.Summary).To(Equal("test prop")) + Expect(out.Proposal.Messages).To(HaveLen(1)) + Expect(out.Proposal.Messages[0]).To(Equal("/cosmos.bank.v1beta1.MsgSend")) + + // Check tally result + Expect(out.Proposal.FinalTallyResult.Yes).To(Equal("0")) + Expect(out.Proposal.FinalTallyResult.Abstain).To(Equal("0")) + Expect(out.Proposal.FinalTallyResult.No).To(Equal("0")) + Expect(out.Proposal.FinalTallyResult.NoWithVeto).To(Equal("0")) + }) + + It("should fail when proposal doesn't exist", func() { + callArgs.Args = []interface{}{uint64(999)} + + _, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + defaultLogCheck.WithErrContains("proposal 999 doesn't exist"), + ) + Expect(err).To(BeNil()) + }) + }) + + Context("proposals query", func() { + method := gov.GetProposalsMethod + BeforeEach(func() { + callArgs.MethodName = method + }) + + It("should return all proposals", func() { + callArgs.Args = []interface{}{ + uint32(0), // StatusNil to get all proposals + common.Address{}, + common.Address{}, + query.PageRequest{ + CountTotal: true, + }, + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var out gov.ProposalsOutput + err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) + Expect(err).To(BeNil()) + + Expect(out.Proposals).To(HaveLen(2)) + Expect(out.PageResponse.Total).To(Equal(uint64(2))) + + proposal := out.Proposals[0] + Expect(proposal.Id).To(Equal(uint64(1))) + Expect(proposal.Status).To(Equal(uint32(govv1.StatusVotingPeriod))) + Expect(proposal.Proposer).To(Equal(s.keyring.GetAddr(0))) + Expect(proposal.Messages).To(HaveLen(1)) + Expect(proposal.Messages[0]).To(Equal("/cosmos.bank.v1beta1.MsgSend")) + }) + + It("should filter proposals by status", func() { + callArgs.Args = []interface{}{ + uint32(govv1.StatusVotingPeriod), + common.Address{}, + common.Address{}, + query.PageRequest{ + CountTotal: true, + }, + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil()) + + var out gov.ProposalsOutput + err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) + Expect(err).To(BeNil()) + + Expect(out.Proposals).To(HaveLen(2)) + Expect(out.Proposals[0].Status).To(Equal(uint32(govv1.StatusVotingPeriod))) + Expect(out.Proposals[1].Status).To(Equal(uint32(govv1.StatusVotingPeriod))) + }) + + It("should filter proposals by voter", func() { + // First add a vote + voteArgs := testutiltypes.CallArgs{ + ContractABI: s.precompile.ABI, + MethodName: gov.VoteMethod, + Args: []interface{}{ + s.keyring.GetAddr(0), uint64(1), uint8(govv1.OptionYes), "", + }, + } + _, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + voteArgs, + passCheck.WithExpEvents(gov.EventTypeVote), + ) + Expect(err).To(BeNil()) + + // Wait for the vote to be included in the block + Expect(s.network.NextBlock()).To(BeNil()) + + // Query proposals filtered by voter + callArgs.Args = []interface{}{ + uint32(0), // StatusNil + s.keyring.GetAddr(0), + common.Address{}, + query.PageRequest{ + CountTotal: true, + }, + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil()) + + var out gov.ProposalsOutput + err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) + Expect(err).To(BeNil()) + + Expect(out.Proposals).To(HaveLen(1)) + }) + + It("should filter proposals by depositor", func() { + callArgs.Args = []interface{}{ + uint32(0), // StatusNil + common.Address{}, + s.keyring.GetAddr(0), + query.PageRequest{ + CountTotal: true, + }, + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil()) + + var out gov.ProposalsOutput + err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) + Expect(err).To(BeNil()) + + Expect(out.Proposals).To(HaveLen(1)) + }) + }) + + Context("params query", func() { + var ( + err error + callsData CallsData + govCallerContractAddr common.Address + govCallerContract evmtypes.CompiledContract + ) + + BeforeEach(func() { + // Setting gas tip cap to zero to have zero gas price. + txArgs.GasTipCap = new(big.Int).SetInt64(0) + + govCallerContract, err = contracts.LoadGovCallerContract() + Expect(err).ToNot(HaveOccurred(), "failed to load GovCaller contract") + + govCallerContractAddr, err = s.factory.DeployContract( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values + testutiltypes.ContractDeploymentData{ + Contract: govCallerContract, + }, + ) + Expect(err).ToNot(HaveOccurred(), "failed to deploy gov caller contract") + Expect(s.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + callsData = CallsData{ + precompileAddr: s.precompile.Address(), + precompileABI: s.precompile.ABI, + + precompileCallerAddr: govCallerContractAddr, + precompileCallerABI: govCallerContract.ABI, + } + }) + + DescribeTable("should return all params", func(callType callType) { + txArgs, callArgs = callsData.getTxAndCallArgs(callArgs, txArgs, callType) + + switch callType { + case directCall: + callArgs.MethodName = gov.GetParamsMethod + case contractCall: + callArgs.MethodName = "getParams" + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil()) + + var output struct { + Params gov.ParamsOutput `json:"params"` + } + err = s.precompile.UnpackIntoInterface(&output, gov.GetParamsMethod, ethRes.Ret) + Expect(err).To(BeNil()) + + params, err := s.network.GetGovClient().Params(s.network.GetContext(), &govv1.QueryParamsRequest{}) + Expect(err).To(BeNil()) + + Expect(output.Params.MinDeposit).To(HaveLen(len(params.Params.MinDeposit)), "expected min deposit to have same amount of token") + Expect(output.Params.MinDeposit[0].Denom).To(Equal(params.Params.MinDeposit[0].Denom), "expected min deposit to have same denom") + Expect(output.Params.MinDeposit[0].Amount.String()).To(Equal(params.Params.MinDeposit[0].Amount.String()), "expected min deposit to have same amount") + Expect(output.Params.MaxDepositPeriod).To(Equal(int64(*params.Params.MaxDepositPeriod)), "expected max deposit period to be equal") + Expect(output.Params.VotingPeriod).To(Equal(int64(*params.Params.VotingPeriod)), "expected voting period to be equal") + Expect(output.Params.Quorum).To(Equal(params.Params.Quorum), "expected quorum to be equal") + Expect(output.Params.Threshold).To(Equal(params.Params.Threshold), "expected threshold to be equal") + Expect(output.Params.VetoThreshold).To(Equal(params.Params.VetoThreshold), "expected veto threshold to be equal") + Expect(output.Params.MinDepositRatio).To(Equal(params.Params.MinDepositRatio), "expected min deposit ratio to be equal") + Expect(output.Params.ProposalCancelRatio).To(Equal(params.Params.ProposalCancelRatio), "expected proposal cancel ratio to be equal") + Expect(output.Params.ProposalCancelDest).To(Equal(params.Params.ProposalCancelDest), "expected proposal cancel dest to be equal") + Expect(output.Params.ExpeditedVotingPeriod).To(Equal(int64(*params.Params.ExpeditedVotingPeriod)), "expected expedited voting period to be equal") + Expect(output.Params.ExpeditedThreshold).To(Equal(params.Params.ExpeditedThreshold), "expected expedited threshold to be equal") + Expect(output.Params.ExpeditedMinDeposit).To(HaveLen(len(params.Params.ExpeditedMinDeposit)), "expected expedited min deposit to have same amount of token") + Expect(output.Params.ExpeditedMinDeposit[0].Denom).To(Equal(params.Params.ExpeditedMinDeposit[0].Denom), "expected expedited min deposit to have same denom") + Expect(output.Params.ExpeditedMinDeposit[0].Amount.String()).To(Equal(params.Params.ExpeditedMinDeposit[0].Amount.String()), "expected expedited min deposit to have same amount") + Expect(output.Params.BurnVoteQuorum).To(Equal(params.Params.BurnVoteQuorum), "expected burn vote quorum to be equal") + Expect(output.Params.BurnProposalDepositPrevote).To(Equal(params.Params.BurnProposalDepositPrevote), "expected burn proposal deposit prevote to be equal") + Expect(output.Params.BurnVoteVeto).To(Equal(params.Params.BurnVoteVeto), "expected burn vote veto to be equal") + Expect(output.Params.MinDepositRatio).To(Equal(params.Params.MinDepositRatio), "expected min deposit ratio to be equal") + }, + Entry("directly calling the precompile", directCall), + Entry("through a caller contract", contractCall), + ) + }) + + Context("constitution query", func() { + method := gov.GetConstitutionMethod + BeforeEach(func() { + callArgs.MethodName = method + }) + + It("should return a constitution", func() { + callArgs.Args = []interface{}{} + + _, ethRes, err := s.factory.CallContractAndCheckLogs(proposerKey, txArgs, callArgs, passCheck) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var out string + err = s.precompile.UnpackIntoInterface(&out, method, ethRes.Ret) + Expect(err).To(BeNil()) + }) + }) + }) + }) + var _ = Describe("Calling governance precompile from contract", Ordered, func() { + s := NewPrecompileTestSuite(create, options...) + // testCase is a struct used for cases of contracts calls that have some operation + // performed before and/or after the precompile call + type testCase struct { + before bool + after bool + } + + var ( + govCallerContract evmtypes.CompiledContract + contractAddr common.Address + contractAccAddr sdk.AccAddress + txSenderKey types.PrivKey + txSenderAddr common.Address + err error + + proposalID uint64 // proposal id submitted by eoa + contractProposalID uint64 // proposal id submitted by contract account + + cancelFee math.Int + remaining math.Int + + depositor1 sdk.AccAddress + depositorKey1 types.PrivKey + + // The following variables are used to check the cancellation fees and + // remaining fess for multiple deposits case + // key: acc address + // value: fee amount + cancelFees map[string]math.Int + remainingFees map[string]math.Int + ) + + BeforeAll(func() { + govCallerContract, err = contracts.LoadGovCallerContract() + Expect(err).ToNot(HaveOccurred(), "failed to load GovCaller contract") + }) + + BeforeEach(func() { + s.SetupTest() + + txSenderKey = s.keyring.GetPrivKey(0) + txSenderAddr = s.keyring.GetAddr(0) + contractAddr, err = s.factory.DeployContract( + txSenderKey, + evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values + testutiltypes.ContractDeploymentData{ + Contract: govCallerContract, + }, + ) + Expect(err).ToNot(HaveOccurred(), "failed to deploy gov caller contract") + Expect(s.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + contractAccAddr = sdk.AccAddress(contractAddr.Bytes()) + + cAcc := s.network.App.GetEVMKeeper().GetAccount(s.network.GetContext(), contractAddr) + Expect(cAcc).ToNot(BeNil(), "failed to get contract account") + Expect(cAcc.IsContract()).To(BeTrue(), "expected contract account") + + callArgs = testutiltypes.CallArgs{ + ContractABI: govCallerContract.ABI, + } + + txArgs = evmtypes.EvmTxArgs{ + To: &contractAddr, + GasLimit: 200_000, + } + govModuleAddr = authtypes.NewModuleAddress(govtypes.ModuleName) + + defaultLogCheck = testutil.LogCheckArgs{ABIEvents: s.precompile.Events} + passCheck = defaultLogCheck.WithExpPass(true) + }) + + // ===================================== + // TRANSACTIONS + // ===================================== + Context("submitProposal as a contract proposer", func() { + BeforeEach(func() { callArgs.MethodName = testSubmitProposalFromContract }) + It("should submit proposal successfully", func() { + // Prepare the proposal + toAddr := s.keyring.GetAccAddr(1) + denom := s.network.GetBaseDenom() + amount := "100" + jsonBlob := minimalBankSendProposalJSON(toAddr, denom, amount) + callArgs.Args = []interface{}{ + jsonBlob, + minimalDeposit(s.network.GetBaseDenom(), big.NewInt(100)), + } + + eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) + + txArgs := evmtypes.EvmTxArgs{ + To: &contractAddr, + GasLimit: 500_000, + Amount: big.NewInt(1000), + } + _, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + var proposalID uint64 + err = s.precompile.UnpackIntoInterface(&proposalID, gov.SubmitProposalMethod, evmRes.Ret) + Expect(err).To(BeNil()) + // Expect ProposalID greater than 0 + Expect(proposalID).To(BeNumerically(">", 0)) + + contractProposer := sdk.AccAddress(contractAddr.Bytes()).String() + // ensure proposal exists on-chain + prop, err := s.network.App.GetGovKeeper().Proposals.Get(s.network.GetContext(), proposalID) + Expect(err).To(BeNil()) + Expect(prop.Id).To(Equal(proposalID)) + Expect(prop.Proposer).To(Equal(contractProposer), "expected contract proposer to be equal") + }) + }) + + Context("cancelProposal as contract proposer", func() { + BeforeEach(func() { callArgs.MethodName = "testCancelProposalFromContract" }) + It("should cancel proposal successfully", func() { + // submit a proposal + toAddr := s.keyring.GetAccAddr(1) + denom := s.network.GetBaseDenom() + jsonBlob := minimalBankSendProposalJSON(toAddr, denom, "100") + callArgs.MethodName = testSubmitProposalFromContract + minDepositAmt := math.NewInt(100) + callArgs.Args = []interface{}{ + jsonBlob, + minimalDeposit(s.network.GetBaseDenom(), minDepositAmt.BigInt()), + } + + eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) + + txArgs := evmtypes.EvmTxArgs{ + To: &contractAddr, + GasLimit: 500_000, + Amount: minDepositAmt.BigInt(), + } + _, evmRes, _ := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) + Expect(s.network.NextBlock()).To(BeNil()) + + var proposalID uint64 + Expect(s.precompile.UnpackIntoInterface(&proposalID, gov.SubmitProposalMethod, evmRes.Ret)).To(BeNil()) + + // Get the proposal for cancellation + proposal, err := s.network.App.GetGovKeeper().Proposals.Get(s.network.GetContext(), proposalID) + Expect(err).To(BeNil()) + + // Calc cancellation fee + proposalDeposits, err := s.network.App.GetGovKeeper().GetDeposits(s.network.GetContext(), proposal.Id) + Expect(err).To(BeNil()) + proposalDepositAmt := proposalDeposits[0].Amount[0].Amount + params, err := s.network.App.GetGovKeeper().Params.Get(s.network.GetContext()) + Expect(err).To(BeNil()) + rate := math.LegacyMustNewDecFromStr(params.ProposalCancelRatio) + cancelFee := proposalDepositAmt.ToLegacyDec().Mul(rate).TruncateInt() + + // Cancel it + callArgs.MethodName = "testCancelProposalFromContract" + callArgs.Args = []interface{}{proposal.Id} + eventCheck = passCheck.WithExpEvents(gov.EventTypeCancelProposal) + // Balance of contract proposer + proposerBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), contractAccAddr, s.network.GetBaseDenom()) + txArgs.Amount = common.Big0 + _, _, err = s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + // 6. Check that the cancellation fee is charged, diff should be less than the deposit amount + afterCancelBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), contractAccAddr, s.network.GetBaseDenom()) + Expect(afterCancelBal.Amount).To(Equal( + proposerBal.Amount. + Sub(cancelFee). + Add(proposalDepositAmt)), + "expected cancellation fee to be deducted from proposer balance") + + // 7. Check that the proposal is not found + _, err = s.network.App.GetGovKeeper().Proposals.Get(s.network.GetContext(), proposal.Id) + Expect(err.Error()).To(ContainSubstring("not found")) + }) + }) + + Context("deposit as contract proposer", func() { + BeforeEach(func() { callArgs.MethodName = "testDepositFromContract" }) + It("should deposit successfully", func() { + // submit a proposal + toAddr := s.keyring.GetAccAddr(1) + denom := s.network.GetBaseDenom() + jsonBlob := minimalBankSendProposalJSON(toAddr, denom, "100") + callArgs.MethodName = testSubmitProposalFromContract + minDepositAmt := math.NewInt(100) + callArgs.Args = []interface{}{ + jsonBlob, + minimalDeposit(s.network.GetBaseDenom(), minDepositAmt.BigInt()), + } + + eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) + txArgs := evmtypes.EvmTxArgs{ + To: &contractAddr, + GasLimit: 500_000, + Amount: minDepositAmt.BigInt(), + } + _, evmRes, _ := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) + Expect(s.network.NextBlock()).To(BeNil()) + + var proposalID uint64 + Expect(s.precompile.UnpackIntoInterface(&proposalID, gov.SubmitProposalMethod, evmRes.Ret)).To(BeNil()) + + // Get the proposal for deposit + proposal, err := s.network.App.GetGovKeeper().Proposals.Get(s.network.GetContext(), proposalID) + Expect(err).To(BeNil()) + + // Deposit it + callArgs.MethodName = "testDepositFromContract" + callArgs.Args = []interface{}{ + proposal.Id, + minimalDeposit(s.network.GetBaseDenom(), big.NewInt(100)), + } + eventCheck = passCheck.WithExpEvents(gov.EventTypeDeposit) + _, _, err = s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + // Check that the deposit is found + deposits, err := s.network.App.GetGovKeeper().GetDeposits(s.network.GetContext(), proposal.Id) + Expect(err).To(BeNil()) + Expect(deposits).To(HaveLen(1)) + Expect(deposits[0].Amount[0].Amount).To(Equal(math.NewInt(200))) + }) + }) + + Context("testSubmitProposal with transfer", func() { + BeforeEach(func() { callArgs.MethodName = "testSubmitProposalWithTransfer" }) + + DescribeTable("contract proposer should submit proposal with transfer", + func(tc testCase) { + // Fix the gas limit and gas price for predictable gas usage. + // This is for calculating expected cancellation fee. + baseFee := s.network.App.GetFeeMarketKeeper().GetBaseFee(s.network.GetContext()) + baseFeeInt := baseFee.TruncateInt64() + txArgs.GasPrice = new(big.Int).SetInt64(baseFeeInt) + txArgs.GasLimit = 500_000 + + // Prepare the proposal + toAddr := s.keyring.GetAccAddr(1) + denom := s.network.GetBaseDenom() + amount := "100" + jsonBlob := minimalBankSendProposalJSON(toAddr, denom, amount) + minDepositAmt := math.NewInt(100) + callArgs.Args = []interface{}{ + jsonBlob, minimalDeposit(s.network.GetBaseDenom(), minDepositAmt.BigInt()), + tc.before, tc.after, + } + txArgs.Amount = minDepositAmt.Mul(math.NewInt(2)).BigInt() + eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) + txArgs.To = &contractAddr + baseDenom := s.network.GetBaseDenom() + txSender := s.keyring.GetAccAddr(0) + txSenderKey := s.keyring.GetPrivKey(0) + txSenderBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), txSender, baseDenom) + contractBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) + res, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + fees := math.NewInt(res.GasUsed).Mul(math.NewInt(txArgs.GasPrice.Int64())) + + // check submitted proposal + var proposalID uint64 + err = s.precompile.UnpackIntoInterface(&proposalID, gov.SubmitProposalMethod, evmRes.Ret) + Expect(err).To(BeNil()) + Expect(proposalID).To(BeNumerically(">", 0)) + + afterSubmitTxSenderBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), txSender, baseDenom) + afterSubmitContractBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) + + amtFromContract := math.ZeroInt() + for _, transferred := range []bool{tc.before, tc.after} { + if transferred { + amtFromContract = amtFromContract.AddRaw(15) + } + } + Expect(afterSubmitTxSenderBal.Amount).To(Equal( + txSenderBal.Amount.Sub(math.NewIntFromBigInt(txArgs.Amount)). + Sub(fees).Add(amtFromContract))) + Expect(afterSubmitContractBal.Amount).To(Equal( + contractBal.Amount. + Add(math.NewIntFromBigInt(txArgs.Amount). + Sub(amtFromContract)).Sub(minDepositAmt), + )) + }, + Entry("with internal transfers before and after precompile call", testCase{ + before: true, + after: true, + }), + Entry("with internal transfers before precompile call", testCase{ + before: true, + after: false, + }), + Entry("with internal transfers after precompile call", testCase{ + before: false, + after: true, + }), + ) + }) + + Context("testSubmitProposalFromContract with transfer", func() { + BeforeEach(func() { callArgs.MethodName = "testSubmitProposalFromContractWithTransfer" }) + + DescribeTable("contract proposer should submit proposal with transfer", + func(tc testCase) { + // Fix the gas limit and gas price for predictable gas usage. + // This is for calculating expected cancellation fee. + baseFee := s.network.App.GetFeeMarketKeeper().GetBaseFee(s.network.GetContext()) + baseFeeInt := baseFee.TruncateInt64() + txArgs.GasPrice = new(big.Int).SetInt64(baseFeeInt) + txArgs.GasLimit = 500_000 + + // Prepare the proposal + toAddr := s.keyring.GetAccAddr(1) + denom := s.network.GetBaseDenom() + amount := "100" + jsonBlob := minimalBankSendProposalJSON(toAddr, denom, amount) + minDepositAmt := math.NewInt(100) + randomAddr := testutiltx.GenerateAddress() + callArgs.Args = []interface{}{ + randomAddr, jsonBlob, + minimalDeposit(s.network.GetBaseDenom(), minDepositAmt.BigInt()), + tc.before, tc.after, + } + extraContractFundinAmt := math.NewInt(100) + txArgs.Amount = minDepositAmt.Add(extraContractFundinAmt).BigInt() + eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) + txArgs.To = &contractAddr + baseDenom := s.network.GetBaseDenom() + contractBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) + randomAddrBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), randomAddr.Bytes(), baseDenom) + _, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + // check submitted proposal + var proposalID uint64 + err = s.precompile.UnpackIntoInterface(&proposalID, gov.SubmitProposalMethod, evmRes.Ret) + Expect(err).To(BeNil()) + Expect(proposalID).To(BeNumerically(">", 0)) + + afterSubmitRandomAddrBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), randomAddr.Bytes(), baseDenom) + afterSubmitContractBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) + + amtFromContract := math.ZeroInt() + for _, transferred := range []bool{tc.before, tc.after} { + if transferred { + amtFromContract = amtFromContract.AddRaw(15) + } + } + Expect(afterSubmitRandomAddrBal.Amount).To(Equal( + randomAddrBal.Amount. + Add(amtFromContract), + )) + + Expect(afterSubmitContractBal.Amount).To(Equal( + contractBal.Amount.Add(math.NewIntFromBigInt(txArgs.Amount).Sub(minDepositAmt).Sub(amtFromContract)), + )) + }, + Entry("with internal transfers before and after precompile call", testCase{ + before: true, + after: true, + }), + Entry("with internal transfers before precompile call", testCase{ + before: true, + after: false, + }), + Entry("with internal transfers after precompile call", testCase{ + before: false, + after: true, + }), + ) + }) + + Context("testDeposit with transfer", func() { + BeforeEach(func() { + toAddr := s.keyring.GetAccAddr(1) + denom := s.network.GetBaseDenom() + amount := "100" + jsonBlob := minimalBankSendProposalJSON(toAddr, denom, amount) + minDepositAmt := math.NewInt(100) + callArgs.MethodName = testSubmitProposalFromContract + callArgs.Args = []interface{}{ + jsonBlob, + minimalDeposit(s.network.GetBaseDenom(), minDepositAmt.BigInt()), + } + txArgs.Amount = minDepositAmt.BigInt() + eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) + txArgs.To = &contractAddr + _, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + err = s.precompile.UnpackIntoInterface(&contractProposalID, gov.SubmitProposalMethod, evmRes.Ret) + Expect(err).To(BeNil()) + + callArgs.MethodName = "testDepositWithTransfer" + }) + + DescribeTable("all balance changes should be correct", + func(tc testCase) { + // Fix the gas limit and gas price for predictable gas usage. + // This is for calculating expected cancellation fee. + baseFee := s.network.App.GetFeeMarketKeeper().GetBaseFee(s.network.GetContext()) + baseFeeInt := baseFee.TruncateInt64() + txArgs.GasPrice = new(big.Int).SetInt64(baseFeeInt) + txArgs.GasLimit = 500_000 + txArgs.Amount = big.NewInt(300) + + minDepositAmt := math.NewInt(100) + callArgs.Args = []interface{}{ + contractProposalID, + minimalDeposit(s.network.GetBaseDenom(), minDepositAmt.BigInt()), + tc.before, tc.after, + } + eventCheck := passCheck.WithExpEvents(gov.EventTypeDeposit) + + baseDenom := s.network.GetBaseDenom() + contractBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) + txSenderBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), txSenderAddr.Bytes(), baseDenom) + res, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + gasCost := math.NewInt(res.GasUsed).Mul(math.NewInt(txArgs.GasPrice.Int64())) + + var success bool + err = s.precompile.UnpackIntoInterface(&success, gov.DepositMethod, evmRes.Ret) + Expect(err).To(BeNil()) + Expect(success).To(BeTrue()) + + afterTxSenderBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), txSenderAddr.Bytes(), baseDenom) + afterContractBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) + + amtFromContract := math.ZeroInt() + for _, transferred := range []bool{tc.before, tc.after} { + if transferred { + amtFromContract = amtFromContract.AddRaw(15) + } + } + Expect(afterTxSenderBal.Amount).To(Equal( + txSenderBal.Amount. + Sub(gasCost). + Sub(math.NewIntFromBigInt(txArgs.Amount)). + Add(amtFromContract), + )) + + Expect(afterContractBal.Amount).To(Equal( + contractBal.Amount. + Add(math.NewIntFromBigInt(txArgs.Amount). + Sub(amtFromContract). + Sub(minDepositAmt)), + )) + }, + Entry("with internal transfers before and after precompile call", testCase{ + before: true, + after: true, + }), + Entry("with internal transfers before precompile call", testCase{ + before: true, + after: false, + }), + Entry("with internal transfers after precompile call", testCase{ + before: false, + after: true, + }), + ) + }) + + Context("testDepositFromContract with transfer", func() { + BeforeEach(func() { + toAddr := s.keyring.GetAccAddr(1) + denom := s.network.GetBaseDenom() + amount := "100" + jsonBlob := minimalBankSendProposalJSON(toAddr, denom, amount) + minDepositAmt := math.NewInt(100) + callArgs.MethodName = testSubmitProposalFromContract + callArgs.Args = []interface{}{ + jsonBlob, + minimalDeposit(s.network.GetBaseDenom(), minDepositAmt.BigInt()), + } + txArgs.Amount = minDepositAmt.BigInt() + eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) + txArgs.To = &contractAddr + _, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + err = s.precompile.UnpackIntoInterface(&contractProposalID, gov.SubmitProposalMethod, evmRes.Ret) + Expect(err).To(BeNil()) + + callArgs.MethodName = "testDepositFromContractWithTransfer" + }) + + DescribeTable("all balance changes should be correct", + func(tc testCase) { + minDepositAmt := math.NewInt(100) + randomAddr := testutiltx.GenerateAddress() + callArgs.Args = []interface{}{ + randomAddr, contractProposalID, + minimalDeposit(s.network.GetBaseDenom(), minDepositAmt.BigInt()), + tc.before, tc.after, + } + extraContractFundinAmt := math.NewInt(100) + txArgs.Amount = minDepositAmt.Add(extraContractFundinAmt).BigInt() + eventCheck := passCheck.WithExpEvents(gov.EventTypeDeposit) + + baseDenom := s.network.GetBaseDenom() + randomAddrBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), randomAddr.Bytes(), baseDenom) + contractBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) + + _, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + var success bool + err = s.precompile.UnpackIntoInterface(&success, gov.DepositMethod, evmRes.Ret) + Expect(err).To(BeNil()) + Expect(success).To(BeTrue()) + + afterRandomAddrBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), randomAddr.Bytes(), baseDenom) + afterContractBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) + + amtFromContract := math.ZeroInt() + for _, transferred := range []bool{tc.before, tc.after} { + if transferred { + amtFromContract = amtFromContract.AddRaw(15) + } + } + + Expect(afterRandomAddrBal.Amount).To(Equal( + randomAddrBal.Amount. + Add(amtFromContract), + )) + Expect(afterContractBal.Amount).To(Equal( + contractBal.Amount. + Add(math.NewIntFromBigInt(txArgs.Amount). + Sub(minDepositAmt). + Sub(amtFromContract)), + )) + }, + Entry("with internal transfers before and after precompile call", testCase{ + before: true, + after: true, + }), + Entry("with internal transfers before precompile call", testCase{ + before: true, + after: false, + }), + Entry("with internal transfers after precompile call", testCase{ + before: false, + after: true, + }), + ) + }) + + Context("testCancel with transfer", func() { + BeforeEach(func() { + toAddr := s.keyring.GetAccAddr(1) + denom := s.network.GetBaseDenom() + amount := "100" + jsonBlob := minimalBankSendProposalJSON(toAddr, denom, amount) + minDepositAmt := math.NewInt(100) + callArgs.MethodName = testSubmitProposalFromContract + callArgs.Args = []interface{}{ + jsonBlob, + minimalDeposit(s.network.GetBaseDenom(), minDepositAmt.BigInt()), + } + txArgs.Amount = minDepositAmt.BigInt() + eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) + txArgs.To = &contractAddr + _, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + err = s.precompile.UnpackIntoInterface(&proposalID, gov.SubmitProposalMethod, evmRes.Ret) + Expect(err).To(BeNil()) + + // Calc cancellation fee + proposalDeposits, err := s.network.App.GetGovKeeper().GetDeposits(s.network.GetContext(), proposalID) + Expect(err).To(BeNil()) + proposalDepositAmt := proposalDeposits[0].Amount[0].Amount + params, err := s.network.App.GetGovKeeper().Params.Get(s.network.GetContext()) + Expect(err).To(BeNil()) + rate := math.LegacyMustNewDecFromStr(params.ProposalCancelRatio) + cancelFee = proposalDepositAmt.ToLegacyDec().Mul(rate).TruncateInt() + remaining = proposalDepositAmt.Sub(cancelFee) + + callArgs.MethodName = "testCancelWithTransfer" + }) + + DescribeTable("eoa proposer should cancel proposal with transfer", + func(tc testCase) { + // Fix the gas limit and gas ice for predictable gas usage. + // This is for calculating expected cancellation fee. + baseFee := s.network.App.GetFeeMarketKeeper().GetBaseFee(s.network.GetContext()) + baseFeeInt := baseFee.TruncateInt64() + txArgs.GasPrice = new(big.Int).SetInt64(baseFeeInt) + txArgs.GasLimit = 500_000 + txArgs.Amount = big.NewInt(100) + + callArgs.Args = []interface{}{ + proposalID, + tc.before, tc.after, + } + eventCheck := passCheck.WithExpEvents(gov.EventTypeCancelProposal) + + baseDenom := s.network.GetBaseDenom() + txSenderBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), txSenderAddr.Bytes(), baseDenom) + contractBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) + + res, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + var success bool + err = s.precompile.UnpackIntoInterface(&success, gov.CancelProposalMethod, evmRes.Ret) + Expect(err).To(BeNil()) + Expect(success).To(BeTrue()) + + afterTxSenderBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), txSenderAddr.Bytes(), baseDenom) + afterContractBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) + gasCost := math.NewInt(res.GasUsed).Mul(math.NewInt(txArgs.GasPrice.Int64())) + amtFromContract := math.ZeroInt() + for _, transferred := range []bool{tc.before, tc.after} { + if transferred { + amtFromContract = amtFromContract.AddRaw(15) + } + } + + Expect(afterTxSenderBal.Amount).To(Equal( + txSenderBal.Amount. + Sub(gasCost). + Sub(math.NewIntFromBigInt(txArgs.Amount)). + Add(amtFromContract), + )) + Expect(afterContractBal.Amount).To(Equal( + contractBal.Amount. + Add(remaining). + Add(math.NewIntFromBigInt(txArgs.Amount). + Sub(amtFromContract)), + )) + }, + Entry("with internal transfers before and after precompile call", testCase{ + before: true, + after: true, + }), + Entry("with internal transfers before precompile call", testCase{ + before: true, + after: false, + }), + Entry("with internal transfers after precompile call", testCase{ + before: false, + after: true, + }), + ) + }) + + Context("testCancelFromContract with transfer", func() { + BeforeEach(func() { + toAddr := s.keyring.GetAccAddr(1) + denom := s.network.GetBaseDenom() + amount := "100" + jsonBlob := minimalBankSendProposalJSON(toAddr, denom, amount) + minDepositAmt := math.NewInt(100) + callArgs.MethodName = testSubmitProposalFromContract + callArgs.Args = []interface{}{ + jsonBlob, + minimalDeposit(s.network.GetBaseDenom(), minDepositAmt.BigInt()), + } + txArgs.Amount = minDepositAmt.BigInt() + eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) + txArgs.To = &contractAddr + _, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + err = s.precompile.UnpackIntoInterface(&contractProposalID, gov.SubmitProposalMethod, evmRes.Ret) + Expect(err).To(BeNil()) + + // Calc cancellation fee + proposalDeposits, err := s.network.App.GetGovKeeper().GetDeposits(s.network.GetContext(), contractProposalID) + Expect(err).To(BeNil()) + proposalDepositAmt := proposalDeposits[0].Amount[0].Amount + params, err := s.network.App.GetGovKeeper().Params.Get(s.network.GetContext()) + Expect(err).To(BeNil()) + rate := math.LegacyMustNewDecFromStr(params.ProposalCancelRatio) + cancelFee = proposalDepositAmt.ToLegacyDec().Mul(rate).TruncateInt() + remaining = proposalDepositAmt.Sub(cancelFee) + + callArgs.MethodName = "testCancelFromContractWithTransfer" + }) + + DescribeTable("contract proposer should cancel proposal with transfer", + func(tc testCase) { + randomAddr := testutiltx.GenerateAddress() + callArgs.Args = []interface{}{ + randomAddr, + contractProposalID, + tc.before, tc.after, + } + eventCheck := passCheck.WithExpEvents(gov.EventTypeCancelProposal) + + baseDenom := s.network.GetBaseDenom() + cancellerBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) + randomAddrBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), randomAddr.Bytes(), baseDenom) + + _, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + var success bool + err = s.precompile.UnpackIntoInterface(&success, gov.CancelProposalMethod, evmRes.Ret) + Expect(err).To(BeNil()) + Expect(success).To(BeTrue()) + + afterCancellerBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) + afterRandomAddrBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), randomAddr.Bytes(), baseDenom) + amtFromContract := math.ZeroInt() + for _, transferred := range []bool{tc.before, tc.after} { + if transferred { + amtFromContract = amtFromContract.AddRaw(15) + } + } + + Expect(afterCancellerBal.Amount).To(Equal( + cancellerBal.Amount. + Add(remaining). + Add(math.NewIntFromBigInt(txArgs.Amount). + Sub(amtFromContract)), + )) + Expect(afterRandomAddrBal.Amount).To(Equal( + randomAddrBal.Amount. + Add(amtFromContract), + )) + }, + Entry("with internal transfers before and after precompile call", testCase{ + before: true, + after: true, + }), + Entry("with internal transfers before precompile call", testCase{ + before: true, + after: false, + }), + Entry("with internal transfers after precompile call", testCase{ + before: false, + after: true, + }), + ) + }) + + Context("testCancel with transfer (multiple deposits & refund)", func() { + BeforeEach(func() { + // Submit a proposal with deposit from depositor0 + denom := s.network.GetBaseDenom() + amount := "100" + randomRecipient := sdk.AccAddress(testutiltx.GenerateAddress().Bytes()) + jsonBlob := minimalBankSendProposalJSON(randomRecipient, denom, amount) + minDepositAmt := math.NewInt(100) + callArgs.MethodName = testSubmitProposalFromContract + callArgs.Args = []interface{}{ + jsonBlob, + minimalDeposit(denom, minDepositAmt.BigInt()), + } + txArgs.Amount = minDepositAmt.BigInt() + eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) + txArgs.To = &contractAddr + _, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + err = s.precompile.UnpackIntoInterface(&proposalID, gov.SubmitProposalMethod, evmRes.Ret) + Expect(err).To(BeNil()) + + // Deposit from depositor1 + minDeposits := minimalDeposit(s.network.GetBaseDenom(), minDepositAmt.BigInt()) + minDepositCoins, err := cmn.NewSdkCoinsFromCoins(minDeposits) + Expect(err).To(BeNil()) + + depositor1 = s.keyring.GetAccAddr(1) + depositorKey1 = s.keyring.GetPrivKey(1) + + msg := &v1beta1.MsgDeposit{ + ProposalId: proposalID, + Depositor: depositor1.String(), + Amount: minDepositCoins, + } + var gas uint64 = 500_000 + res, err := s.factory.ExecuteCosmosTx(depositorKey1, commonfactory.CosmosTxArgs{ + Gas: &gas, + Msgs: []sdk.Msg{msg}, + }) + Expect(err).To(BeNil()) + Expect(res.Code).To(BeZero(), "expected no error code in response") + + // Calc cancellation fees for both deposits + params, err := s.network.App.GetGovKeeper().Params.Get(s.network.GetContext()) + Expect(err).To(BeNil()) + rate := math.LegacyMustNewDecFromStr(params.ProposalCancelRatio) + proposalDeposits, err := s.network.App.GetGovKeeper().GetDeposits(s.network.GetContext(), proposalID) + Expect(err).To(BeNil()) + Expect(proposalDeposits).To(HaveLen(2)) + + cancelFees = make(map[string]math.Int) + remainingFees = make(map[string]math.Int) + + for _, deposit := range proposalDeposits { + for _, amount := range deposit.Amount { + if amount.Denom == s.network.GetBaseDenom() { + proposalDepositAmt := amount.Amount + cancelFee = proposalDepositAmt.ToLegacyDec().Mul(rate).TruncateInt() + cancelFees[deposit.Depositor] = cancelFee + remaining = proposalDepositAmt.Sub(cancelFee) + remainingFees[deposit.Depositor] = remaining + } + } + } + Expect(cancelFees).To(HaveLen(2)) + Expect(remainingFees).To(HaveLen(2)) + + callArgs.MethodName = "testCancelWithTransfer" + }) + + DescribeTable("contract proposer should cancel proposal with transfer", + func(tc testCase) { + // Fix the gas limit and gas ice for predictable gas usage. + // This is for calculating expected cancellation fee. + baseFee := s.network.App.GetFeeMarketKeeper().GetBaseFee(s.network.GetContext()) + baseFeeInt := baseFee.TruncateInt64() + txArgs.GasPrice = new(big.Int).SetInt64(baseFeeInt) + txArgs.GasLimit = 500_000 + txArgs.Amount = big.NewInt(100) + + callArgs.Args = []interface{}{ + proposalID, + tc.before, tc.after, + } + eventCheck := passCheck.WithExpEvents(gov.EventTypeCancelProposal) + + baseDenom := s.network.GetBaseDenom() + contractBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) + depositor1Bal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), depositor1, baseDenom) + txSenderBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), txSenderAddr.Bytes(), baseDenom) + + res, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + var success bool + err = s.precompile.UnpackIntoInterface(&success, gov.CancelProposalMethod, evmRes.Ret) + Expect(err).To(BeNil()) + Expect(success).To(BeTrue()) + gasCost := math.NewInt(res.GasUsed).Mul(math.NewInt(txArgs.GasPrice.Int64())) + + afterContractBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) + afterDepositor1Bal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), depositor1, baseDenom) + afterTxSenderBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), txSenderAddr.Bytes(), baseDenom) + amtFromContract := math.ZeroInt() + for _, transferred := range []bool{tc.before, tc.after} { + if transferred { + amtFromContract = amtFromContract.AddRaw(15) + } + } + + Expect(afterTxSenderBal.Amount).To(Equal( + txSenderBal.Amount. + Sub(gasCost). + Sub(math.NewIntFromBigInt(txArgs.Amount)). + Add(amtFromContract), + )) + Expect(afterDepositor1Bal.Amount).To(Equal( + depositor1Bal.Amount. + Add(remainingFees[depositor1.String()]), + )) + Expect(afterContractBal.Amount).To(Equal( + contractBal.Amount. + Add(remainingFees[contractAccAddr.String()]). + Add(math.NewIntFromBigInt(txArgs.Amount). + Sub(amtFromContract)), + )) + }, + Entry("with internal transfers before and after precompile call", testCase{ + before: true, + after: true, + }), + Entry("with internal transfers before precompile call", testCase{ + before: true, + after: false, + }), + Entry("with internal transfers after precompile call", testCase{ + before: false, + after: true, + }), + ) + }) + + Context("testCancelFromContract with transfer (multiple deposits & refund)", func() { + BeforeEach(func() { + // Submit a proposal with deposit from depositor0 + denom := s.network.GetBaseDenom() + amount := "100" + randomRecipient := sdk.AccAddress(testutiltx.GenerateAddress().Bytes()) + jsonBlob := minimalBankSendProposalJSON(randomRecipient, denom, amount) + minDepositAmt := math.NewInt(100) + callArgs.MethodName = testSubmitProposalFromContract + callArgs.Args = []interface{}{ + jsonBlob, + minimalDeposit(denom, minDepositAmt.BigInt()), + } + txArgs.Amount = minDepositAmt.BigInt() + eventCheck := passCheck.WithExpEvents(gov.EventTypeSubmitProposal) + txArgs.To = &contractAddr + _, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + + err = s.precompile.UnpackIntoInterface(&proposalID, gov.SubmitProposalMethod, evmRes.Ret) + Expect(err).To(BeNil()) + + // Deposit from depositor1 + minDeposits := minimalDeposit(s.network.GetBaseDenom(), minDepositAmt.BigInt()) + minDepositCoins, err := cmn.NewSdkCoinsFromCoins(minDeposits) + Expect(err).To(BeNil()) + + depositor1 = s.keyring.GetAccAddr(1) + depositorKey1 = s.keyring.GetPrivKey(1) + + msg := &v1beta1.MsgDeposit{ + ProposalId: proposalID, + Depositor: depositor1.String(), + Amount: minDepositCoins, + } + var gas uint64 = 500_000 + res, err := s.factory.ExecuteCosmosTx(depositorKey1, commonfactory.CosmosTxArgs{ + Gas: &gas, + Msgs: []sdk.Msg{msg}, + }) + Expect(err).To(BeNil()) + Expect(res.Code).To(BeZero(), "expected no error code in response") + + // Calc cancellation fees for both deposits + params, err := s.network.App.GetGovKeeper().Params.Get(s.network.GetContext()) + Expect(err).To(BeNil()) + rate := math.LegacyMustNewDecFromStr(params.ProposalCancelRatio) + proposalDeposits, err := s.network.App.GetGovKeeper().GetDeposits(s.network.GetContext(), proposalID) + Expect(err).To(BeNil()) + Expect(proposalDeposits).To(HaveLen(2)) + + cancelFees = make(map[string]math.Int) + remainingFees = make(map[string]math.Int) + + for _, deposit := range proposalDeposits { + for _, amount := range deposit.Amount { + if amount.Denom == s.network.GetBaseDenom() { + proposalDepositAmt := amount.Amount + cancelFee = proposalDepositAmt.ToLegacyDec().Mul(rate).TruncateInt() + cancelFees[deposit.Depositor] = cancelFee + remaining = proposalDepositAmt.Sub(cancelFee) + remainingFees[deposit.Depositor] = remaining + } + } + } + Expect(cancelFees).To(HaveLen(2)) + Expect(remainingFees).To(HaveLen(2)) + + callArgs.MethodName = "testCancelFromContractWithTransfer" + }) + + DescribeTable("contract proposer should cancel proposal with transfer", + func(tc testCase) { + // Fix the gas limit and gas price for predictable gas usage. + // This is for calculating expected cancellation fee. + baseFee := s.network.App.GetFeeMarketKeeper().GetBaseFee(s.network.GetContext()) + baseFeeInt := baseFee.TruncateInt64() + txArgs.GasPrice = new(big.Int).SetInt64(baseFeeInt) + txArgs.GasLimit = 500_000 + txArgs.Amount = big.NewInt(100) + randomAddr := testutiltx.GenerateAddress() + callArgs.Args = []interface{}{ + randomAddr, + contractProposalID, + tc.before, tc.after, + } + eventCheck := passCheck.WithExpEvents(gov.EventTypeCancelProposal) + + baseDenom := s.network.GetBaseDenom() + cancellerBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) + depositor1Bal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), depositor1, baseDenom) + randomAccBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), randomAddr.Bytes(), baseDenom) + + txSenderKey := s.keyring.GetPrivKey(0) + _, evmRes, err := s.factory.CallContractAndCheckLogs(txSenderKey, txArgs, callArgs, eventCheck) + Expect(err).To(BeNil()) + Expect(s.network.NextBlock()).To(BeNil()) + var success bool + err = s.precompile.UnpackIntoInterface(&success, gov.CancelProposalMethod, evmRes.Ret) + Expect(err).To(BeNil()) + Expect(success).To(BeTrue()) + + afterCancellerBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), contractAccAddr, baseDenom) + afterDepositor1Bal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), depositor1, baseDenom) + afterRandomAccBal := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), randomAddr.Bytes(), baseDenom) + amtFromContract := math.ZeroInt() + for _, transferred := range []bool{tc.before, tc.after} { + if transferred { + amtFromContract = amtFromContract.AddRaw(15) + } + } + + Expect(afterCancellerBal.Amount).To(Equal( + cancellerBal.Amount. + Add(remaining). + Add(math.NewIntFromBigInt(txArgs.Amount). + Sub(amtFromContract)), + )) + Expect(afterRandomAccBal.Amount).To(Equal( + randomAccBal.Amount. + Add(amtFromContract), + )) + Expect(afterDepositor1Bal.Amount).To(Equal( + depositor1Bal.Amount. + Add(remainingFees[depositor1.String()]), + )) + }, + Entry("with internal transfers before and after precompile call", testCase{ + before: true, + after: true, + }), + Entry("with internal transfers before precompile call", testCase{ + before: true, + after: false, + }), + Entry("with internal transfers after precompile call", testCase{ + before: false, + after: true, + }), + ) + }) + }) + + // Run Ginkgo integration tests + RegisterFailHandler(Fail) + RunSpecs(t, "Keeper Suite") +} + +// ----------------------------------------------------------------------------- +// Helper functions (test‑only) +// ----------------------------------------------------------------------------- + +func minimalDeposit(denom string, amount *big.Int) []cmn.Coin { + return []cmn.Coin{{Denom: denom, Amount: amount}} +} + +// minimalBankSendProposalJSON returns a valid governance proposal encoded as UTF‑8 bytes. +func minimalBankSendProposalJSON(to sdk.AccAddress, denom, amount string) []byte { + // proto‑JSON marshal via std JSON since test helpers don’t expose codec here. + // We craft by hand for brevity. + msgJSON, _ := json.Marshal(map[string]interface{}{ + "@type": "/cosmos.bank.v1beta1.MsgSend", + // from_address must be gov module account + "from_address": govModuleAddr.String(), + "to_address": to.String(), + "amount": []map[string]string{{"denom": denom, "amount": amount}}, + }) + + prop := map[string]interface{}{ + "messages": []json.RawMessage{msgJSON}, + "metadata": "ipfs://CID", + "title": "test prop", + "summary": "test prop", + "expedited": false, + } + blob, _ := json.Marshal(prop) + return blob +} diff --git a/precompiles/gov/query_test.go b/tests/integration/precompiles/gov/test_query.go similarity index 94% rename from precompiles/gov/query_test.go rename to tests/integration/precompiles/gov/test_query.go index 8dd9cf713..8f6a1517d 100644 --- a/precompiles/gov/query_test.go +++ b/tests/integration/precompiles/gov/test_query.go @@ -1,4 +1,4 @@ -package gov_test +package gov import ( "fmt" @@ -55,7 +55,7 @@ func (s *PrecompileTestSuite) TestGetVotes() { Weight: "1.0", } - err := s.network.App.GovKeeper.AddVote( + err := s.network.App.GetGovKeeper().AddVote( s.network.GetContext(), proposalID, voter, @@ -143,7 +143,7 @@ func (s *PrecompileTestSuite) TestGetVote() { { name: "valid query", malleate: func() []interface{} { - err := s.network.App.GovKeeper.AddVote(s.network.GetContext(), 1, voter, []*govv1.WeightedVoteOption{{Option: govv1.OptionYes, Weight: "1.0"}}, "") + err := s.network.App.GetGovKeeper().AddVote(s.network.GetContext(), 1, voter, []*govv1.WeightedVoteOption{{Option: govv1.OptionYes, Weight: "1.0"}}, "") s.Require().NoError(err) return []interface{}{uint64(1), voterAddr} @@ -156,7 +156,7 @@ func (s *PrecompileTestSuite) TestGetVote() { name: "invalid proposal ID", expPass: false, malleate: func() []interface{} { - err := s.network.App.GovKeeper.AddVote(s.network.GetContext(), 1, voter, []*govv1.WeightedVoteOption{{Option: govv1.OptionYes, Weight: "1.0"}}, "") + err := s.network.App.GetGovKeeper().AddVote(s.network.GetContext(), 1, voter, []*govv1.WeightedVoteOption{{Option: govv1.OptionYes, Weight: "1.0"}}, "") s.Require().NoError(err) return []interface{}{uint64(10), voterAddr} @@ -364,12 +364,12 @@ func (s *PrecompileTestSuite) TestGetTallyResult() { { name: "valid query", malleate: func() (gov.TallyResultData, uint64) { - proposal, err := s.network.App.GovKeeper.SubmitProposal(s.network.GetContext(), TestProposalMsgs, "", "Proposal", "testing proposal", s.keyring.GetAccAddr(0), false) + proposal, err := s.network.App.GetGovKeeper().SubmitProposal(s.network.GetContext(), TestProposalMsgs, "", "Proposal", "testing proposal", s.keyring.GetAccAddr(0), false) s.Require().NoError(err) - votingStarted, err := s.network.App.GovKeeper.AddDeposit(s.network.GetContext(), proposal.Id, s.keyring.GetAccAddr(0), sdk.NewCoins(sdk.NewCoin(s.network.GetBaseDenom(), math.NewInt(100)))) + votingStarted, err := s.network.App.GetGovKeeper().AddDeposit(s.network.GetContext(), proposal.Id, s.keyring.GetAccAddr(0), sdk.NewCoins(sdk.NewCoin(s.network.GetBaseDenom(), math.NewInt(100)))) s.Require().NoError(err) s.Require().True(votingStarted) - err = s.network.App.GovKeeper.AddVote(s.network.GetContext(), proposal.Id, s.keyring.GetAccAddr(0), govv1.NewNonSplitVoteOption(govv1.OptionYes), "") + err = s.network.App.GetGovKeeper().AddVote(s.network.GetContext(), proposal.Id, s.keyring.GetAccAddr(0), govv1.NewNonSplitVoteOption(govv1.OptionYes), "") s.Require().NoError(err) return gov.TallyResultData{ Yes: "3000000000000000000", @@ -579,7 +579,7 @@ func (s *PrecompileTestSuite) TestGetProposals() { "success - filter by voter", func() []interface{} { // First add a vote - err := s.network.App.GovKeeper.AddVote(s.network.GetContext(), 1, s.keyring.GetAccAddr(0), govv1.NewNonSplitVoteOption(govv1.OptionYes), "") + err := s.network.App.GetGovKeeper().AddVote(s.network.GetContext(), 1, s.keyring.GetAccAddr(0), govv1.NewNonSplitVoteOption(govv1.OptionYes), "") s.Require().NoError(err) return []interface{}{ diff --git a/precompiles/gov/setup_test.go b/tests/integration/precompiles/gov/test_setup.go similarity index 84% rename from precompiles/gov/setup_test.go rename to tests/integration/precompiles/gov/test_setup.go index 94f262f0b..264b5e61e 100644 --- a/precompiles/gov/setup_test.go +++ b/tests/integration/precompiles/gov/test_setup.go @@ -1,17 +1,16 @@ -package gov_test +package gov import ( - "testing" "time" "github.com/stretchr/testify/suite" "github.com/cosmos/evm/precompiles/gov" testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + testkeyring "github.com/cosmos/evm/testutil/keyring" "cosmossdk.io/math" @@ -26,6 +25,8 @@ import ( type PrecompileTestSuite struct { suite.Suite + create network.CreateEvmApp + options []network.ConfigOption network *network.UnitTestNetwork factory factory.TxFactory grpcHandler grpc.Handler @@ -34,8 +35,11 @@ type PrecompileTestSuite struct { precompile *gov.Precompile } -func TestPrecompileUnitTestSuite(t *testing.T) { - suite.Run(t, new(PrecompileTestSuite)) +func NewPrecompileTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *PrecompileTestSuite { + return &PrecompileTestSuite{ + create: create, + options: options, + } } func (s *PrecompileTestSuite) SetupTest() { @@ -116,10 +120,12 @@ func (s *PrecompileTestSuite) SetupTest() { customGen[govtypes.ModuleName] = govGen customGen[banktypes.ModuleName] = bankGen - nw := network.NewUnitTestNetwork( + options := []network.ConfigOption{ network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), network.WithCustomGenesis(customGen), - ) + } + options = append(options, s.options...) + nw := network.NewUnitTestNetwork(s.create, options...) grpcHandler := grpc.NewIntegrationHandler(nw) txFactory := factory.New(nw, grpcHandler) @@ -129,7 +135,7 @@ func (s *PrecompileTestSuite) SetupTest() { s.network = nw if s.precompile, err = gov.NewPrecompile( - s.network.App.GovKeeper, + s.network.App.GetGovKeeper(), s.network.App.AppCodec(), ); err != nil { panic(err) diff --git a/precompiles/gov/tx_test.go b/tests/integration/precompiles/gov/test_tx.go similarity index 94% rename from precompiles/gov/tx_test.go rename to tests/integration/precompiles/gov/test_tx.go index fbebfc47e..3611b6e6d 100644 --- a/precompiles/gov/tx_test.go +++ b/tests/integration/precompiles/gov/test_tx.go @@ -1,4 +1,4 @@ -package gov_test +package gov import ( "fmt" @@ -113,8 +113,8 @@ func (s *PrecompileTestSuite) TestVote() { } }, func() { - proposal, _ := s.network.App.GovKeeper.Proposals.Get(ctx, proposalID) - _, _, tallyResult, err := s.network.App.GovKeeper.Tally(ctx, proposal) + proposal, _ := s.network.App.GetGovKeeper().Proposals.Get(ctx, proposalID) + _, _, tallyResult, err := s.network.App.GetGovKeeper().Tally(ctx, proposal) s.Require().NoError(err) s.Require().Equal(math.NewInt(3e18).String(), tallyResult.YesCount) }, @@ -246,8 +246,8 @@ func (s *PrecompileTestSuite) TestVoteWeighted() { } }, func() { - proposal, _ := s.network.App.GovKeeper.Proposals.Get(ctx, proposalID) - _, _, tallyResult, err := s.network.App.GovKeeper.Tally(ctx, proposal) + proposal, _ := s.network.App.GetGovKeeper().Proposals.Get(ctx, proposalID) + _, _, tallyResult, err := s.network.App.GetGovKeeper().Tally(ctx, proposal) s.Require().NoError(err) s.Require().Equal("2100000000000000000", tallyResult.YesCount) s.Require().Equal("900000000000000000", tallyResult.AbstainCount) diff --git a/precompiles/gov/utils_test.go b/tests/integration/precompiles/gov/test_utils.go similarity index 89% rename from precompiles/gov/utils_test.go rename to tests/integration/precompiles/gov/test_utils.go index b63bee910..77547937c 100644 --- a/precompiles/gov/utils_test.go +++ b/tests/integration/precompiles/gov/test_utils.go @@ -1,4 +1,4 @@ -package gov_test +package gov import ( "math/big" @@ -6,7 +6,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" - "github.com/cosmos/evm/testutil/integration/os/factory" + testutiltypes "github.com/cosmos/evm/testutil/types" evmtypes "github.com/cosmos/evm/x/vm/types" ) @@ -32,11 +32,11 @@ type CallsData struct { // getTxCallArgs is a helper function to return the correct call arguments and // transaction data for a given call type. func (cd CallsData) getTxAndCallArgs( - callArgs factory.CallArgs, + callArgs testutiltypes.CallArgs, txArgs evmtypes.EvmTxArgs, callType callType, args ...interface{}, -) (evmtypes.EvmTxArgs, factory.CallArgs) { +) (evmtypes.EvmTxArgs, testutiltypes.CallArgs) { switch callType { case directCall: txArgs.To = &cd.precompileAddr diff --git a/tests/integration/precompiles/p256/test_integration.go b/tests/integration/precompiles/p256/test_integration.go new file mode 100644 index 000000000..8c4302d76 --- /dev/null +++ b/tests/integration/precompiles/p256/test_integration.go @@ -0,0 +1,211 @@ +package p256 + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "testing" + + "github.com/ethereum/go-ethereum/common" + + //nolint:revive // dot imports are fine for Ginkgo + . "github.com/onsi/ginkgo/v2" + //nolint:revive // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" + + "github.com/cometbft/cometbft/crypto" + + "github.com/cosmos/evm/precompiles/p256" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/integration/evm/utils" + testkeyring "github.com/cosmos/evm/testutil/keyring" + evmtypes "github.com/cosmos/evm/x/vm/types" +) + +type IntegrationTestSuite struct { + network network.Network + factory factory.TxFactory + keyring testkeyring.Keyring + precompileAddress common.Address + p256Priv *ecdsa.PrivateKey +} + +func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmApp, options ...network.ConfigOption) { + var _ = Describe("Calling p256 precompile directly", Label("P256 Precompile"), Ordered, func() { + var s *IntegrationTestSuite + + BeforeAll(func() { + keyring := testkeyring.New(1) + opts := []network.ConfigOption{ + network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), + } + opts = append(opts, options...) + integrationNetwork := network.New(create, opts...) + grpcHandler := grpc.NewIntegrationHandler(integrationNetwork) + txFactory := factory.New(integrationNetwork, grpcHandler) + p256Priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + Expect(err).To(BeNil()) + + s = &IntegrationTestSuite{ + network: integrationNetwork, + factory: txFactory, + keyring: keyring, + precompileAddress: p256.Precompile{}.Address(), + p256Priv: p256Priv, + } + }) + + AfterEach(func() { + // Start each test with a fresh block + err := s.network.NextBlock() + Expect(err).To(BeNil()) + }) + + When("the precompile is enabled in the EVM params", func() { + BeforeAll(func() { + s = setupIntegrationTestSuite(nil, create, options...) + }) + + DescribeTable("execute contract call", func(inputFn func() (input, expOutput []byte, expErr string)) { + senderKey := s.keyring.GetKey(0) + + input, expOutput, expErr := inputFn() + args := evmtypes.EvmTxArgs{ + To: &s.precompileAddress, + Input: input, + } + + txResult, err := s.factory.ExecuteEthTx(senderKey.Priv, args) + Expect(err).To(BeNil()) + Expect(txResult.IsOK()).To(Equal(true), "transaction should have succeeded", txResult.GetLog()) + + res, err := utils.DecodeExecTxResult(txResult) + Expect(err).To(BeNil()) + Expect(res.VmError).To(Equal(expErr), "expected different vm error") + Expect(res.Ret).To(Equal(expOutput)) + }, + Entry( + "valid signature", + func() (input, expOutput []byte, expErr string) { + input = signMsg(t, []byte("hello world"), s.p256Priv) + return input, trueValue, "" + }, + ), + Entry( + "invalid signature", + func() (input, expOutput []byte, expErr string) { + privB, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + Expect(err).To(BeNil()) + + hash := crypto.Sha256([]byte("hello world")) + + rInt, sInt, err := ecdsa.Sign(rand.Reader, s.p256Priv, hash) + Expect(err).To(BeNil()) + + input = make([]byte, p256.VerifyInputLength) + copy(input[0:32], hash) + copy(input[32:64], rInt.Bytes()) + copy(input[64:96], sInt.Bytes()) + copy(input[96:128], privB.PublicKey.X.Bytes()) + copy(input[128:160], privB.PublicKey.Y.Bytes()) + return input, nil, "" + }, + ), + ) + }) + + When("the precompile is not enabled in the EVM params", func() { + BeforeAll(func() { + customGenesis := evmtypes.DefaultGenesisState() + customGenesis.Params.ActiveStaticPrecompiles = evmtypes.AvailableStaticPrecompiles + params := customGenesis.Params + addr := s.precompileAddress.String() + var activePrecompiles []string + for _, precompile := range params.ActiveStaticPrecompiles { + if precompile != addr { + activePrecompiles = append(activePrecompiles, precompile) + } + } + params.ActiveStaticPrecompiles = activePrecompiles + customGenesis.Params = params + s = setupIntegrationTestSuite(customGenesis, create, options...) + }) + + DescribeTable("execute contract call", func(inputFn func() (input []byte)) { + senderKey := s.keyring.GetKey(0) + + input := inputFn() + args := evmtypes.EvmTxArgs{ + To: &s.precompileAddress, + Input: input, + } + + _, err := s.factory.ExecuteEthTx(senderKey.Priv, args) + Expect(err).To(BeNil(), "expected no error since contract doesn't exists") + }, + Entry( + "valid signature", + func() (input []byte) { + input = signMsg(t, []byte("hello world"), s.p256Priv) + return input + }, + ), + Entry( + "invalid signature", + func() (input []byte) { + privB, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + Expect(err).To(BeNil()) + + hash := crypto.Sha256([]byte("hello world")) + + rInt, sInt, err := ecdsa.Sign(rand.Reader, s.p256Priv, hash) + Expect(err).To(BeNil()) + + input = make([]byte, p256.VerifyInputLength) + copy(input[0:32], hash) + copy(input[32:64], rInt.Bytes()) + copy(input[64:96], sInt.Bytes()) + copy(input[96:128], privB.PublicKey.X.Bytes()) + copy(input[128:160], privB.PublicKey.Y.Bytes()) + return input + }, + ), + ) + }) + }) + + RegisterFailHandler(Fail) + RunSpecs(t, "P256 Precompile Integration Test Suite") +} + +// setupIntegrationTestSuite is a helper function to setup a integration test suite +// with a network with a specified custom genesis state for the EVM module +func setupIntegrationTestSuite(customEVMGenesis *evmtypes.GenesisState, create network.CreateEvmApp, options ...network.ConfigOption) *IntegrationTestSuite { + customGenesis := network.CustomGenesisState{} + if customEVMGenesis != nil { + customGenesis[evmtypes.ModuleName] = customEVMGenesis + } + keyring := testkeyring.New(1) + opts := []network.ConfigOption{ + network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), + network.WithCustomGenesis(customGenesis), + } + opts = append(opts, options...) + integrationNetwork := network.New(create, opts...) + grpcHandler := grpc.NewIntegrationHandler(integrationNetwork) + txFactory := factory.New(integrationNetwork, grpcHandler) + p256Priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + Expect(err).To(BeNil()) + + suite := &IntegrationTestSuite{ + network: integrationNetwork, + factory: txFactory, + keyring: keyring, + precompileAddress: p256.Precompile{}.Address(), + p256Priv: p256Priv, + } + + return suite +} diff --git a/precompiles/p256/p256_test.go b/tests/integration/precompiles/p256/test_p256.go similarity index 99% rename from precompiles/p256/p256_test.go rename to tests/integration/precompiles/p256/test_p256.go index 92d577ef1..06c599016 100644 --- a/precompiles/p256/p256_test.go +++ b/tests/integration/precompiles/p256/test_p256.go @@ -1,4 +1,4 @@ -package p256_test +package p256 import ( "crypto/ecdsa" diff --git a/precompiles/p256/setup_test.go b/tests/integration/precompiles/p256/test_setup.go similarity index 73% rename from precompiles/p256/setup_test.go rename to tests/integration/precompiles/p256/test_setup.go index 35ffd6c38..683cfb71d 100644 --- a/precompiles/p256/setup_test.go +++ b/tests/integration/precompiles/p256/test_setup.go @@ -1,4 +1,4 @@ -package p256_test +package p256 import ( "crypto/ecdsa" @@ -11,31 +11,27 @@ import ( "golang.org/x/crypto/cryptobyte" "golang.org/x/crypto/cryptobyte/asn1" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" - "github.com/cometbft/cometbft/crypto" "github.com/cosmos/evm/precompiles/p256" + "github.com/cosmos/evm/testutil/integration/evm/network" ) var s *PrecompileTestSuite type PrecompileTestSuite struct { suite.Suite + + create network.CreateEvmApp p256Priv *ecdsa.PrivateKey precompile *p256.Precompile } -func TestPrecompileTestSuite(t *testing.T) { - s = new(PrecompileTestSuite) - suite.Run(t, s) - - // Run Ginkgo integration tests - RegisterFailHandler(Fail) - RunSpecs(t, "Precompile Test Suite") +func NewPrecompileTestSuite(create network.CreateEvmApp) *PrecompileTestSuite { + return &PrecompileTestSuite{ + create: create, + precompile: &p256.Precompile{}, + } } func (s *PrecompileTestSuite) SetupTest() { @@ -45,11 +41,13 @@ func (s *PrecompileTestSuite) SetupTest() { s.precompile = &p256.Precompile{} } -func signMsg(msg []byte, priv *ecdsa.PrivateKey) []byte { +func signMsg(t *testing.T, msg []byte, priv *ecdsa.PrivateKey) []byte { hash := crypto.Sha256(msg) rInt, sInt, err := ecdsa.Sign(rand.Reader, priv, hash) - s.Require().NoError(err) + if err != nil { + t.Fatalf("failed to sign message: %v", err) + } input := make([]byte, p256.VerifyInputLength) copy(input[0:32], hash) diff --git a/precompiles/slashing/events_test.go b/tests/integration/precompiles/slashing/test_events.go similarity index 93% rename from precompiles/slashing/events_test.go rename to tests/integration/precompiles/slashing/test_events.go index 881b370f8..f0de6cfc9 100644 --- a/precompiles/slashing/events_test.go +++ b/tests/integration/precompiles/slashing/test_events.go @@ -1,4 +1,4 @@ -package slashing_test +package slashing import ( "github.com/ethereum/go-ethereum/common" @@ -33,13 +33,13 @@ func (s *PrecompileTestSuite) TestUnjailEvent() { { "success - the correct event is emitted", func() []interface{} { - validator, err := s.network.App.StakingKeeper.GetValidator(ctx, sdk.ValAddress(s.keyring.GetAccAddr(0))) + validator, err := s.network.App.GetStakingKeeper().GetValidator(ctx, sdk.ValAddress(s.keyring.GetAccAddr(0))) s.Require().NoError(err) consAddr, err := validator.GetConsAddr() s.Require().NoError(err) - err = s.network.App.SlashingKeeper.Jail( + err = s.network.App.GetSlashingKeeper().Jail( s.network.GetContext(), consAddr, ) diff --git a/precompiles/slashing/query_test.go b/tests/integration/precompiles/slashing/test_query.go similarity index 96% rename from precompiles/slashing/query_test.go rename to tests/integration/precompiles/slashing/test_query.go index 778678667..721c8bd0d 100644 --- a/precompiles/slashing/query_test.go +++ b/tests/integration/precompiles/slashing/test_query.go @@ -1,4 +1,4 @@ -package slashing_test +package slashing import ( "fmt" @@ -50,7 +50,7 @@ func (s *PrecompileTestSuite) TestGetSigningInfo() { { "success - get signing info for validator", func() []interface{} { - err := s.network.App.SlashingKeeper.SetValidatorSigningInfo( + err := s.network.App.GetSlashingKeeper().SetValidatorSigningInfo( s.network.GetContext(), types.ConsAddress(s.keyring.GetAddr(0).Bytes()), slashingtypes.ValidatorSigningInfo{ @@ -81,8 +81,7 @@ func (s *PrecompileTestSuite) TestGetSigningInfo() { s.Run(tc.name, func() { s.SetupTest() - contract, ctx := testutil.NewPrecompileContract(s.T(), s.network.GetContext(), s.keyring.GetAddr(0), - s.precompile.Address(), tc.gas) + contract, ctx := testutil.NewPrecompileContract(s.T(), s.network.GetContext(), s.keyring.GetAddr(0), s.precompile.Address(), tc.gas) bz, err := s.precompile.GetSigningInfo(ctx, &method, contract, tc.malleate()) @@ -224,7 +223,7 @@ func (s *PrecompileTestSuite) TestGetParams() { }, func(params *slashing.Params) { // Get the default params from the network - defaultParams, err := s.network.App.SlashingKeeper.GetParams(s.network.GetContext()) + defaultParams, err := s.network.App.GetSlashingKeeper().GetParams(s.network.GetContext()) s.Require().NoError(err) s.Require().Equal(defaultParams.SignedBlocksWindow, params.SignedBlocksWindow) s.Require().Equal(defaultParams.MinSignedPerWindow.BigInt(), params.MinSignedPerWindow.Value) diff --git a/precompiles/slashing/setup_test.go b/tests/integration/precompiles/slashing/test_setup.go similarity index 57% rename from precompiles/slashing/setup_test.go rename to tests/integration/precompiles/slashing/test_setup.go index 307e88b67..d3f4f85e5 100644 --- a/precompiles/slashing/setup_test.go +++ b/tests/integration/precompiles/slashing/test_setup.go @@ -1,15 +1,13 @@ -package slashing_test +package slashing import ( - "testing" - "github.com/stretchr/testify/suite" "github.com/cosmos/evm/precompiles/slashing" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + testkeyring "github.com/cosmos/evm/testutil/keyring" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -17,6 +15,8 @@ import ( type PrecompileTestSuite struct { suite.Suite + create network.CreateEvmApp + options []network.ConfigOption network *network.UnitTestNetwork factory factory.TxFactory grpcHandler grpc.Handler @@ -25,22 +25,26 @@ type PrecompileTestSuite struct { precompile *slashing.Precompile } -func TestPrecompileTestSuite(t *testing.T) { - suite.Run(t, new(PrecompileTestSuite)) +func NewPrecompileTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *PrecompileTestSuite { + return &PrecompileTestSuite{ + create: create, + options: options, + } } func (s *PrecompileTestSuite) SetupTest() { keyring := testkeyring.New(3) var err error - nw := network.NewUnitTestNetwork( + options := []network.ConfigOption{ network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), network.WithValidatorOperators([]sdk.AccAddress{ keyring.GetAccAddr(0), keyring.GetAccAddr(1), keyring.GetAccAddr(2), }), - ) - + } + options = append(options, s.options...) + nw := network.NewUnitTestNetwork(s.create, options...) grpcHandler := grpc.NewIntegrationHandler(nw) txFactory := factory.New(nw, grpcHandler) @@ -50,7 +54,7 @@ func (s *PrecompileTestSuite) SetupTest() { s.keyring = keyring if s.precompile, err = slashing.NewPrecompile( - s.network.App.SlashingKeeper, + s.network.App.GetSlashingKeeper(), ); err != nil { panic(err) } diff --git a/precompiles/slashing/tx_test.go b/tests/integration/precompiles/slashing/test_tx.go similarity index 84% rename from precompiles/slashing/tx_test.go rename to tests/integration/precompiles/slashing/test_tx.go index b3b810b7a..c8be3828e 100644 --- a/precompiles/slashing/tx_test.go +++ b/tests/integration/precompiles/slashing/test_tx.go @@ -1,4 +1,4 @@ -package slashing_test +package slashing import ( "fmt" @@ -84,18 +84,18 @@ func (s *PrecompileTestSuite) TestUnjail() { { "success - validator unjailed", func() []interface{} { - validator, err := s.network.App.StakingKeeper.GetValidator(s.network.GetContext(), sdk.ValAddress(s.keyring.GetAccAddr(0))) + validator, err := s.network.App.GetStakingKeeper().GetValidator(s.network.GetContext(), sdk.ValAddress(s.keyring.GetAccAddr(0))) s.Require().NoError(err) valConsAddr, err := validator.GetConsAddr() s.Require().NoError(err) - err = s.network.App.SlashingKeeper.Jail( + err = s.network.App.GetSlashingKeeper().Jail( s.network.GetContext(), valConsAddr, ) s.Require().NoError(err) - validatorAfterJail, err := s.network.App.StakingKeeper.GetValidator(s.network.GetContext(), sdk.ValAddress(s.keyring.GetAddr(0).Bytes())) + validatorAfterJail, err := s.network.App.GetStakingKeeper().GetValidator(s.network.GetContext(), sdk.ValAddress(s.keyring.GetAddr(0).Bytes())) s.Require().NoError(err) s.Require().True(validatorAfterJail.IsJailed()) @@ -104,7 +104,7 @@ func (s *PrecompileTestSuite) TestUnjail() { } }, func() { - validatorAfterUnjail, err := s.network.App.StakingKeeper.GetValidator(s.network.GetContext(), sdk.ValAddress(s.keyring.GetAddr(0).Bytes())) + validatorAfterUnjail, err := s.network.App.GetStakingKeeper().GetValidator(s.network.GetContext(), sdk.ValAddress(s.keyring.GetAddr(0).Bytes())) s.Require().NoError(err) s.Require().False(validatorAfterUnjail.IsJailed()) }, diff --git a/precompiles/staking/events_test.go b/tests/integration/precompiles/staking/test_events.go similarity index 99% rename from precompiles/staking/events_test.go rename to tests/integration/precompiles/staking/test_events.go index ad015835f..b9b9fbdb3 100644 --- a/precompiles/staking/events_test.go +++ b/tests/integration/precompiles/staking/test_events.go @@ -1,4 +1,4 @@ -package staking_test +package staking import ( "math/big" @@ -10,7 +10,7 @@ import ( cmn "github.com/cosmos/evm/precompiles/common" "github.com/cosmos/evm/precompiles/staking" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" + testkeyring "github.com/cosmos/evm/testutil/keyring" "github.com/cosmos/evm/x/vm/statedb" "cosmossdk.io/math" diff --git a/tests/integration/precompiles/staking/test_integration.go b/tests/integration/precompiles/staking/test_integration.go new file mode 100644 index 000000000..cccdc4542 --- /dev/null +++ b/tests/integration/precompiles/staking/test_integration.go @@ -0,0 +1,3353 @@ +package staking + +import ( + "fmt" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" + + //nolint:revive // dot imports are fine for Ginkgo + . "github.com/onsi/ginkgo/v2" + //nolint:revive // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" + + compiledcontracts "github.com/cosmos/evm/contracts" + "github.com/cosmos/evm/crypto/ethsecp256k1" + cmn "github.com/cosmos/evm/precompiles/common" + "github.com/cosmos/evm/precompiles/staking" + "github.com/cosmos/evm/precompiles/staking/testdata" + "github.com/cosmos/evm/precompiles/testutil" + "github.com/cosmos/evm/precompiles/testutil/contracts" + cosmosevmutil "github.com/cosmos/evm/testutil/constants" + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/integration/evm/utils" + testutiltx "github.com/cosmos/evm/testutil/tx" + testutiltypes "github.com/cosmos/evm/testutil/types" + evmtypes "github.com/cosmos/evm/x/vm/types" + + "cosmossdk.io/math" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +var ( + // valAddr and valAddr2 are the two validator addresses used for testing + valAddr, valAddr2 sdk.ValAddress + + // callArgs is the default arguments for calling the smart contract. + // + // NOTE: this has to be populated in a BeforeEach block because the contractAddr would otherwise be a nil address. + callArgs testutiltypes.CallArgs + // txArgs are the EVM transaction arguments to use in the transactions + txArgs evmtypes.EvmTxArgs + // defaultLogCheck instantiates a log check arguments struct with the precompile ABI events populated. + defaultLogCheck testutil.LogCheckArgs + // passCheck defines the arguments to check if the precompile returns no error + passCheck testutil.LogCheckArgs + // outOfGasCheck defines the arguments to check if the precompile returns out of gas error + outOfGasCheck testutil.LogCheckArgs +) + +func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmApp, options ...network.ConfigOption) { + var _ = Describe("Calling staking precompile directly", func() { + // s is the precompile test suite to use for the tests + var s *PrecompileTestSuite + + BeforeEach(func() { + var err error + s = NewPrecompileTestSuite(create, options...) + s.SetupTest() + + valAddr, err = sdk.ValAddressFromBech32(s.network.GetValidators()[0].GetOperator()) + Expect(err).To(BeNil()) + valAddr2, err = sdk.ValAddressFromBech32(s.network.GetValidators()[1].GetOperator()) + Expect(err).To(BeNil()) + + callArgs = testutiltypes.CallArgs{ + ContractABI: s.precompile.ABI, + } + + precompileAddr := s.precompile.Address() + txArgs = evmtypes.EvmTxArgs{ + To: &precompileAddr, + } + + defaultLogCheck = testutil.LogCheckArgs{ABIEvents: s.precompile.ABI.Events} + passCheck = defaultLogCheck.WithExpPass(true) + outOfGasCheck = defaultLogCheck.WithErrContains(vm.ErrOutOfGas.Error()) + }) + + Describe("when the precompile is not enabled in the EVM params", func() { + It("should succeed but not perform delegation", func() { + delegator := s.keyring.GetKey(0) + // disable the precompile + res, err := s.grpcHandler.GetEvmParams() + Expect(err).To(BeNil()) + + var activePrecompiles []string + for _, precompile := range res.Params.ActiveStaticPrecompiles { + if precompile != s.precompile.Address().String() { + activePrecompiles = append(activePrecompiles, precompile) + } + } + res.Params.ActiveStaticPrecompiles = activePrecompiles + + err = utils.UpdateEvmParams(utils.UpdateParamsInput{ + Tf: s.factory, + Network: s.network, + Pk: delegator.Priv, + Params: res.Params, + }) + Expect(err).To(BeNil(), "error while setting params") + + // get the delegation that is available prior to the test + qRes, err := s.grpcHandler.GetDelegation(delegator.AccAddr.String(), valAddr.String()) + Expect(err).To(BeNil()) + prevDelegation := qRes.DelegationResponse.Balance + // try to call the precompile + callArgs.MethodName = staking.DelegateMethod + callArgs.Args = []interface{}{delegator.Addr, valAddr.String(), big.NewInt(2e18)} + + // Contract should not be called but the transaction should be successful + // This is the expected behavior in Ethereum where there is a contract call + // to a non existing contract + expectedCheck := defaultLogCheck. + WithExpEvents([]string{}...). + WithExpPass(true) + + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, + callArgs, + expectedCheck, + ) + Expect(err).To(BeNil(), "error while calling the contract and checking logs") + qRes, err = s.grpcHandler.GetDelegation(delegator.AccAddr.String(), valAddr.String()) + Expect(err).To(BeNil()) + postDelegation := qRes.DelegationResponse.Balance + Expect(postDelegation).To(Equal(prevDelegation), "expected delegation to not change") + }) + }) + + Describe("Revert transaction", func() { + It("should run out of gas if the gas limit is too low", func() { + delegator := s.keyring.GetKey(0) + + callArgs.MethodName = staking.DelegateMethod + callArgs.Args = []interface{}{ + delegator.Addr, + valAddr.String(), + big.NewInt(2e18), + } + txArgs.GasLimit = 30000 + + _, _, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, + callArgs, + outOfGasCheck, + ) + Expect(err).To(BeNil(), "error while calling precompile") + }) + }) + + Describe("to create validator", func() { + var ( + defaultDescription = staking.Description{ + Moniker: "new node", + Identity: "", + Website: "", + SecurityContact: "", + Details: "", + } + defaultCommission = staking.Commission{ + Rate: big.NewInt(100000000000000000), + MaxRate: big.NewInt(100000000000000000), + MaxChangeRate: big.NewInt(100000000000000000), + } + defaultMinSelfDelegation = big.NewInt(1) + defaultPubkeyBase64Str = GenerateBase64PubKey() + defaultValue = big.NewInt(1) + ) + + BeforeEach(func() { + // populate the default createValidator args + callArgs.MethodName = staking.CreateValidatorMethod + }) + + Context("when validator address is the msg.sender & EoA", func() { + It("should succeed", func() { + callArgs.Args = []interface{}{ + defaultDescription, defaultCommission, defaultMinSelfDelegation, s.keyring.GetAddr(0), defaultPubkeyBase64Str, defaultValue, + } + // NOTE: increase gas limit here + txArgs.GasLimit = 2e5 + + logCheckArgs := passCheck.WithExpEvents(staking.EventTypeCreateValidator) + + _, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the contract and checking logs") + Expect(s.network.NextBlock()).To(BeNil()) + + valOperAddr := sdk.ValAddress(s.keyring.GetAccAddr(0)).String() + qc := s.network.GetStakingClient() + res, err := qc.Validator(s.network.GetContext(), &stakingtypes.QueryValidatorRequest{ValidatorAddr: valOperAddr}) + Expect(err).To(BeNil()) + Expect(res).NotTo(BeNil()) + Expect(res.Validator.OperatorAddress).To(Equal(valOperAddr)) + }) + }) + + Context("when validator address is not the msg.sender", func() { + It("should fail", func() { + differentAddr := testutiltx.GenerateAddress() + + callArgs.Args = []interface{}{ + defaultDescription, defaultCommission, defaultMinSelfDelegation, differentAddr, defaultPubkeyBase64Str, defaultValue, + } + + logCheckArgs := defaultLogCheck.WithErrContains( + fmt.Sprintf(cmn.ErrRequesterIsNotMsgSender, s.keyring.GetAddr(0), differentAddr), + ) + + _, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the contract and checking logs") + }) + }) + }) + + Describe("to edit validator", func() { + var ( + defaultDescription = staking.Description{ + Moniker: "edit node", + Identity: "[do-not-modify]", + Website: "[do-not-modify]", + SecurityContact: "[do-not-modify]", + Details: "[do-not-modify]", + } + defaultCommissionRate = big.NewInt(staking.DoNotModifyCommissionRate) + defaultMinSelfDelegation = big.NewInt(staking.DoNotModifyMinSelfDelegation) + ) + + BeforeEach(func() { + // populate the default editValidator args + callArgs.MethodName = staking.EditValidatorMethod + }) + + Context("when msg.sender is equal to validator address", func() { + It("should succeed", func() { + // create a new validator + newAddr, newPriv := testutiltx.NewAccAddressAndKey() + hexAddr := common.BytesToAddress(newAddr.Bytes()) + + err := utils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), newAddr, math.NewInt(2e18)) + Expect(err).To(BeNil(), "error while sending coins") + Expect(s.network.NextBlock()).To(BeNil()) + + description := staking.Description{ + Moniker: "new node", + Identity: "", + Website: "", + SecurityContact: "", + Details: "", + } + commission := staking.Commission{ + Rate: big.NewInt(100000000000000000), + MaxRate: big.NewInt(100000000000000000), + MaxChangeRate: big.NewInt(100000000000000000), + } + minSelfDelegation := big.NewInt(1) + pubkeyBase64Str := "UuhHQmkUh2cPBA6Rg4ei0M2B04cVYGNn/F8SAUsYIb4=" + value := big.NewInt(1e18) + + createValidatorArgs := testutiltypes.CallArgs{ + ContractABI: s.precompile.ABI, + MethodName: staking.CreateValidatorMethod, + Args: []interface{}{description, commission, minSelfDelegation, hexAddr, pubkeyBase64Str, value}, + } + + logCheckArgs := passCheck.WithExpEvents(staking.EventTypeCreateValidator) + _, _, err = s.factory.CallContractAndCheckLogs( + newPriv, + txArgs, createValidatorArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the contract and checking logs") + Expect(s.network.NextBlock()).To(BeNil()) + + // edit validator + callArgs.Args = []interface{}{defaultDescription, hexAddr, defaultCommissionRate, defaultMinSelfDelegation} + + logCheckArgs = passCheck.WithExpEvents(staking.EventTypeEditValidator) + _, _, err = s.factory.CallContractAndCheckLogs( + newPriv, + txArgs, callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the contract and checking logs") + Expect(s.network.NextBlock()).To(BeNil()) + + valOperAddr := sdk.ValAddress(newAddr.Bytes()).String() + qc := s.network.GetStakingClient() + res, err := qc.Validator(s.network.GetContext(), &stakingtypes.QueryValidatorRequest{ValidatorAddr: valOperAddr}) + Expect(err).To(BeNil()) + Expect(res).NotTo(BeNil()) + validator := res.Validator + Expect(validator.OperatorAddress).To(Equal(valOperAddr)) + Expect(validator.Description.Moniker).To(Equal(defaultDescription.Moniker), "expected validator moniker is updated") + // Other fields should not be modified due to the value "[do-not-modify]". + Expect(validator.Description.Identity).To(Equal(description.Identity), "expected validator identity not to be updated") + Expect(validator.Description.Website).To(Equal(description.Website), "expected validator website not to be updated") + Expect(validator.Description.SecurityContact).To(Equal(description.SecurityContact), "expected validator security contact not to be updated") + Expect(validator.Description.Details).To(Equal(description.Details), "expected validator details not to be updated") + + Expect(validator.Commission.Rate.BigInt().String()).To(Equal(commission.Rate.String()), "expected validator commission rate remain unchanged") + Expect(validator.Commission.MaxRate.BigInt().String()).To(Equal(commission.MaxRate.String()), "expected validator max commission rate remain unchanged") + Expect(validator.Commission.MaxChangeRate.BigInt().String()).To(Equal(commission.MaxChangeRate.String()), "expected validator max change rate remain unchanged") + Expect(validator.MinSelfDelegation.String()).To(Equal(minSelfDelegation.String()), "expected validator min self delegation remain unchanged") + }) + }) + + Context("with msg.sender different than validator address", func() { + It("should fail", func() { + valHexAddr := common.BytesToAddress(valAddr.Bytes()) + callArgs.Args = []interface{}{ + defaultDescription, valHexAddr, defaultCommissionRate, defaultMinSelfDelegation, + } + + logCheckArgs := passCheck.WithExpEvents(staking.EventTypeEditValidator) + _, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(1), + txArgs, callArgs, + logCheckArgs, + ) + Expect(err).NotTo(BeNil(), "error while calling the contract and checking logs") + Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("msg.sender address %s does not match the requester address %s", s.keyring.GetAddr(1), valHexAddr))) + }) + }) + }) + Describe("to delegate", func() { + // prevDelegation is the delegation that is available prior to the test (an initial delegation is + // added in the test suite setup). + var prevDelegation stakingtypes.Delegation + + BeforeEach(func() { + delegator := s.keyring.GetKey(0) + + // get the delegation that is available prior to the test + res, err := s.grpcHandler.GetDelegation(delegator.AccAddr.String(), valAddr.String()) + Expect(err).To(BeNil()) + Expect(res.DelegationResponse).NotTo(BeNil()) + + prevDelegation = res.DelegationResponse.Delegation + // populate the default delegate args + callArgs.MethodName = staking.DelegateMethod + }) + + Context("as the token owner", func() { + It("should delegate", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + delegator.Addr, valAddr.String(), big.NewInt(2e18), + } + + logCheckArgs := passCheck.WithExpEvents(staking.EventTypeDelegate) + + _, _, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + res, err := s.grpcHandler.GetDelegation(delegator.AccAddr.String(), valAddr.String()) + Expect(err).To(BeNil()) + Expect(res.DelegationResponse).NotTo(BeNil()) + expShares := prevDelegation.GetShares().Add(math.LegacyNewDec(2)) + Expect(res.DelegationResponse.Delegation.GetShares()).To(Equal(expShares), "expected different delegation shares") + }) + + It("should not delegate if the account has no sufficient balance", func() { + newAddr, newAddrPriv := testutiltx.NewAccAddressAndKey() + err := utils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), newAddr, math.NewInt(1e17)) + Expect(err).To(BeNil(), "error while sending coins") + Expect(s.network.NextBlock()).To(BeNil()) + + // try to delegate more than left in account + callArgs.Args = []interface{}{ + common.BytesToAddress(newAddr), valAddr.String(), big.NewInt(1e18), + } + + logCheckArgs := defaultLogCheck.WithErrContains("insufficient funds") + + _, _, err = s.factory.CallContractAndCheckLogs( + newAddrPriv, + txArgs, + callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + }) + + It("should not delegate if the validator does not exist", func() { + nonExistingAddr := testutiltx.GenerateAddress() + nonExistingValAddr := sdk.ValAddress(nonExistingAddr.Bytes()) + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + delegator.Addr, nonExistingValAddr.String(), big.NewInt(2e18), + } + + logCheckArgs := defaultLogCheck.WithErrContains("validator does not exist") + + _, _, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, + callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + }) + }) + + Context("on behalf of another account", func() { + It("should not delegate if delegator address is not the msg.sender", func() { + delegator := s.keyring.GetKey(0) + differentAddr := testutiltx.GenerateAddress() + + callArgs.Args = []interface{}{ + differentAddr, valAddr.String(), big.NewInt(2e18), + } + + logCheckArgs := defaultLogCheck.WithErrContains( + fmt.Sprintf(cmn.ErrRequesterIsNotMsgSender, delegator.Addr, differentAddr), + ) + + _, _, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, + callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + }) + }) + }) + + Describe("to undelegate", func() { + BeforeEach(func() { + callArgs.MethodName = staking.UndelegateMethod + }) + + Context("as the token owner", func() { + It("should undelegate", func() { + delegator := s.keyring.GetKey(0) + + valAddr, err := sdk.ValAddressFromBech32(s.network.GetValidators()[0].GetOperator()) + Expect(err).To(BeNil()) + + res, err := s.grpcHandler.GetValidatorUnbondingDelegations(valAddr.String()) + Expect(err).To(BeNil()) + Expect(res.UnbondingResponses).To(HaveLen(0), "expected no unbonding delegations before test") + + callArgs.Args = []interface{}{ + delegator.Addr, valAddr.String(), big.NewInt(1e18), + } + + logCheckArgs := passCheck.WithExpEvents(staking.EventTypeUnbond) + + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + delUbdRes, err := s.grpcHandler.GetDelegatorUnbondingDelegations(delegator.AccAddr.String()) + Expect(err).To(BeNil()) + Expect(delUbdRes.UnbondingResponses).To(HaveLen(1), "expected one undelegation") + Expect(delUbdRes.UnbondingResponses[0].ValidatorAddress).To(Equal(valAddr.String()), "expected validator address to be %s", valAddr) + }) + + It("should not undelegate if the amount exceeds the delegation", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + delegator.Addr, valAddr.String(), big.NewInt(2e18), + } + + logCheckArgs := defaultLogCheck.WithErrContains("invalid shares amount") + + _, _, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + }) + + It("should not undelegate if the validator does not exist", func() { + delegator := s.keyring.GetKey(0) + nonExistingAddr := testutiltx.GenerateAddress() + nonExistingValAddr := sdk.ValAddress(nonExistingAddr.Bytes()) + + callArgs.Args = []interface{}{ + delegator.Addr, nonExistingValAddr.String(), big.NewInt(1e18), + } + + logCheckArgs := defaultLogCheck.WithErrContains("validator does not exist") + + _, _, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + logCheckArgs) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + }) + }) + + Context("on behalf of another account", func() { + It("should not undelegate if delegator address is not the msg.sender", func() { + differentAddr := testutiltx.GenerateAddress() + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + differentAddr, valAddr.String(), big.NewInt(1e18), + } + + logCheckArgs := defaultLogCheck.WithErrContains( + fmt.Sprintf(cmn.ErrRequesterIsNotMsgSender, delegator.Addr, differentAddr), + ) + + _, _, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + }) + }) + }) + + Describe("to redelegate", func() { + BeforeEach(func() { + callArgs.MethodName = staking.RedelegateMethod + }) + + Context("as the token owner", func() { + It("should redelegate", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + delegator.Addr, valAddr.String(), valAddr2.String(), big.NewInt(1e18), + } + + logCheckArgs := passCheck. + WithExpEvents(staking.EventTypeRedelegate) + + _, _, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + res, err := s.grpcHandler.GetRedelegations(delegator.AccAddr.String(), valAddr.String(), valAddr2.String()) + Expect(err).To(BeNil()) + Expect(res.RedelegationResponses).To(HaveLen(1), "expected one redelegation to be found") + bech32Addr := delegator.AccAddr + Expect(res.RedelegationResponses[0].Redelegation.DelegatorAddress).To(Equal(bech32Addr.String()), "expected delegator address to be %s", delegator.Addr) + Expect(res.RedelegationResponses[0].Redelegation.ValidatorSrcAddress).To(Equal(valAddr.String()), "expected source validator address to be %s", valAddr) + Expect(res.RedelegationResponses[0].Redelegation.ValidatorDstAddress).To(Equal(valAddr2.String()), "expected destination validator address to be %s", valAddr2) + }) + + It("should not redelegate if the amount exceeds the delegation", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + delegator.Addr, valAddr.String(), valAddr2.String(), big.NewInt(2e18), + } + + logCheckArgs := defaultLogCheck.WithErrContains("invalid shares amount") + + _, _, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + }) + + It("should not redelegate if the validator does not exist", func() { + nonExistingAddr := testutiltx.GenerateAddress() + nonExistingValAddr := sdk.ValAddress(nonExistingAddr.Bytes()) + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + delegator.Addr, valAddr.String(), nonExistingValAddr.String(), big.NewInt(1e18), + } + + logCheckArgs := defaultLogCheck.WithErrContains("redelegation destination validator not found") + + _, _, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + }) + }) + + Context("on behalf of another account", func() { + It("should not redelegate if delegator address is not the msg.sender", func() { + differentAddr := testutiltx.GenerateAddress() + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + differentAddr, valAddr.String(), valAddr2.String(), big.NewInt(1e18), + } + + logCheckArgs := defaultLogCheck.WithErrContains( + fmt.Sprintf(cmn.ErrRequesterIsNotMsgSender, delegator.Addr, differentAddr), + ) + + _, _, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + }) + }) + }) + + Describe("to cancel an unbonding delegation", func() { + BeforeEach(func() { + callArgs.MethodName = staking.CancelUnbondingDelegationMethod + delegator := s.keyring.GetKey(0) + + // Set up an unbonding delegation + undelegateArgs := testutiltypes.CallArgs{ + ContractABI: s.precompile.ABI, + MethodName: staking.UndelegateMethod, + Args: []interface{}{ + delegator.Addr, valAddr.String(), big.NewInt(1e18), + }, + } + + logCheckArgs := passCheck. + WithExpEvents(staking.EventTypeUnbond) + + _, _, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, + undelegateArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while setting up an unbonding delegation: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + creationHeight := s.network.GetContext().BlockHeight() + + // Check that the unbonding delegation was created + res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(delegator.AccAddr.String()) + Expect(err).To(BeNil()) + Expect(res.UnbondingResponses).To(HaveLen(1), "expected one unbonding delegation to be found") + Expect(res.UnbondingResponses[0].DelegatorAddress).To(Equal(delegator.AccAddr.String()), "expected delegator address to be %s", delegator.Addr) + Expect(res.UnbondingResponses[0].ValidatorAddress).To(Equal(valAddr.String()), "expected validator address to be %s", valAddr) + Expect(res.UnbondingResponses[0].Entries).To(HaveLen(1), "expected one unbonding delegation entry to be found") + Expect(res.UnbondingResponses[0].Entries[0].CreationHeight).To(Equal(creationHeight), "expected different creation height") + Expect(res.UnbondingResponses[0].Entries[0].Balance).To(Equal(math.NewInt(1e18)), "expected different balance") + }) + + Context("as the token owner", func() { + It("should cancel unbonding delegation", func() { + delegator := s.keyring.GetKey(0) + + valDelRes, err := s.grpcHandler.GetValidatorDelegations(s.network.GetValidators()[0].GetOperator()) + Expect(err).To(BeNil()) + Expect(valDelRes.DelegationResponses).To(HaveLen(0)) + + creationHeight := s.network.GetContext().BlockHeight() + callArgs.Args = []interface{}{ + delegator.Addr, valAddr.String(), big.NewInt(1e18), big.NewInt(creationHeight), + } + + logCheckArgs := passCheck. + WithExpEvents(staking.EventTypeCancelUnbondingDelegation) + + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, + callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(delegator.AccAddr.String()) + Expect(err).To(BeNil()) + Expect(res.UnbondingResponses).To(HaveLen(0), "expected unbonding delegation to be canceled") + + valDelRes, err = s.grpcHandler.GetValidatorDelegations(s.network.GetValidators()[0].GetOperator()) + Expect(err).To(BeNil()) + Expect(valDelRes.DelegationResponses).To(HaveLen(1), "expected one delegation to be found") + }) + + It("should not cancel an unbonding delegation if the amount is not correct", func() { + delegator := s.keyring.GetKey(0) + + creationHeight := s.network.GetContext().BlockHeight() + callArgs.Args = []interface{}{ + delegator.Addr, valAddr.String(), big.NewInt(2e18), big.NewInt(creationHeight), + } + + logCheckArgs := defaultLogCheck.WithErrContains("amount is greater than the unbonding delegation entry balance") + + _, _, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(delegator.AccAddr.String()) + Expect(err).To(BeNil()) + Expect(res.UnbondingResponses).To(HaveLen(1), "expected unbonding delegation not to have been canceled") + }) + + It("should not cancel an unbonding delegation if the creation height is not correct", func() { + delegator := s.keyring.GetKey(0) + + creationHeight := s.network.GetContext().BlockHeight() + callArgs.Args = []interface{}{ + delegator.Addr, valAddr.String(), big.NewInt(1e18), big.NewInt(creationHeight + 1), + } + + logCheckArgs := defaultLogCheck.WithErrContains("unbonding delegation entry is not found at block height") + + _, _, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(delegator.AccAddr.String()) + Expect(err).To(BeNil()) + Expect(res.UnbondingResponses).To(HaveLen(1), "expected unbonding delegation not to have been canceled") + }) + }) + }) + + Describe("Validator queries", func() { + BeforeEach(func() { + callArgs.MethodName = staking.ValidatorMethod + }) + + It("should return validator", func() { + delegator := s.keyring.GetKey(0) + + varHexAddr := common.BytesToAddress(valAddr.Bytes()) + callArgs.Args = []interface{}{varHexAddr} + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var valOut staking.ValidatorOutput + err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) + Expect(valOut.Validator.OperatorAddress).To(Equal(varHexAddr.String()), "expected validator address to match") + Expect(valOut.Validator.DelegatorShares).To(Equal(big.NewInt(1e18)), "expected different delegator shares") + }) + + It("should return an empty validator if the validator is not found", func() { + delegator := s.keyring.GetKey(0) + + newValHexAddr := testutiltx.GenerateAddress() + callArgs.Args = []interface{}{newValHexAddr} + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var valOut staking.ValidatorOutput + err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) + Expect(valOut.Validator.OperatorAddress).To(Equal(""), "expected validator address to be empty") + Expect(valOut.Validator.Status).To(BeZero(), "expected unspecified bonding status") + }) + }) + + Describe("Validators queries", func() { + BeforeEach(func() { + callArgs.MethodName = staking.ValidatorsMethod + }) + + It("should return validators (default pagination)", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + stakingtypes.Bonded.String(), + query.PageRequest{}, + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var valOut staking.ValidatorsOutput + err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorsMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) + + Expect(valOut.PageResponse.NextKey).To(BeEmpty()) + Expect(valOut.PageResponse.Total).To(Equal(uint64(len(s.network.GetValidators())))) + + Expect(valOut.Validators).To(HaveLen(len(s.network.GetValidators())), "expected two validators to be returned") + // return order can change, that's why each validator is checked individually + for _, val := range valOut.Validators { + s.CheckValidatorOutput(val) + } + }) + + //nolint:dupl // this is a duplicate of the test for smart contract calls to the precompile + It("should return validators w/pagination limit = 1", func() { + const limit uint64 = 1 + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + stakingtypes.Bonded.String(), + query.PageRequest{ + Limit: limit, + CountTotal: true, + }, + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var valOut staking.ValidatorsOutput + err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorsMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) + + // no pagination, should return default values + Expect(valOut.PageResponse.NextKey).NotTo(BeEmpty()) + Expect(valOut.PageResponse.Total).To(Equal(uint64(len(s.network.GetValidators())))) + + Expect(valOut.Validators).To(HaveLen(int(limit)), "expected one validator to be returned") + + // return order can change, that's why each validator is checked individually + for _, val := range valOut.Validators { + s.CheckValidatorOutput(val) + } + }) + + It("should return an error if the bonding type is not known", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + "15", // invalid bonding type + query.PageRequest{}, + } + + invalidStatusCheck := defaultLogCheck.WithErrContains("invalid validator status 15") + + _, _, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, + callArgs, + invalidStatusCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + }) + + It("should return an empty array if there are no validators with the given bonding type", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + stakingtypes.Unbonded.String(), + query.PageRequest{}, + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var valOut staking.ValidatorsOutput + err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorsMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) + + Expect(valOut.PageResponse.NextKey).To(BeEmpty()) + Expect(valOut.PageResponse.Total).To(Equal(uint64(0))) + Expect(valOut.Validators).To(HaveLen(0), "expected no validators to be returned") + }) + }) + + Describe("Delegation queries", func() { + BeforeEach(func() { + callArgs.MethodName = staking.DelegationMethod + }) + + It("should return a delegation if it is found", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + delegator.Addr, + valAddr.String(), + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var delOut staking.DelegationOutput + err = s.precompile.UnpackIntoInterface(&delOut, staking.DelegationMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the delegation output: %v", err) + Expect(delOut.Shares).To(Equal(big.NewInt(1e18)), "expected different shares") + Expect(delOut.Balance).To(Equal(cmn.Coin{Denom: s.bondDenom, Amount: big.NewInt(1e18)}), "expected different shares") + }) + + It("should return an empty delegation if it is not found", func() { + delegator := s.keyring.GetKey(0) + + newValAddr := sdk.ValAddress(testutiltx.GenerateAddress().Bytes()) + callArgs.Args = []interface{}{ + delegator.Addr, + newValAddr.String(), + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var delOut staking.DelegationOutput + err = s.precompile.UnpackIntoInterface(&delOut, staking.DelegationMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the delegation output: %v", err) + Expect(delOut.Shares.Int64()).To(BeZero(), "expected no shares") + Expect(delOut.Balance.Denom).To(Equal(s.bondDenom), "expected different denomination") + Expect(delOut.Balance.Amount.Int64()).To(BeZero(), "expected a zero amount") + }) + }) + + Describe("UnbondingDelegation queries", func() { + // undelAmount is the amount of tokens to be unbonded + undelAmount := big.NewInt(1e17) + + BeforeEach(func() { + callArgs.MethodName = staking.UnbondingDelegationMethod + + delegator := s.keyring.GetKey(0) + + undelegateArgs := testutiltypes.CallArgs{ + ContractABI: s.precompile.ABI, + MethodName: staking.UndelegateMethod, + Args: []interface{}{ + delegator.Addr, valAddr.String(), undelAmount, + }, + } + + unbondCheck := passCheck.WithExpEvents(staking.EventTypeUnbond) + _, _, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, undelegateArgs, + unbondCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + // check that the unbonding delegation exists + res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(delegator.AccAddr.String()) + Expect(err).To(BeNil()) + Expect(res.UnbondingResponses).To(HaveLen(1), "expected one unbonding delegation") + }) + + It("should return an unbonding delegation if it is found", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + delegator.Addr, + valAddr.String(), + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var unbondingDelegationOutput staking.UnbondingDelegationOutput + err = s.precompile.UnpackIntoInterface(&unbondingDelegationOutput, staking.UnbondingDelegationMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the unbonding delegation output: %v", err) + Expect(unbondingDelegationOutput.UnbondingDelegation.Entries).To(HaveLen(1), "expected one unbonding delegation entry") + // TODO: why are initial balance and balance the same always? + Expect(unbondingDelegationOutput.UnbondingDelegation.Entries[0].InitialBalance).To(Equal(undelAmount), "expected different initial balance") + Expect(unbondingDelegationOutput.UnbondingDelegation.Entries[0].Balance).To(Equal(undelAmount), "expected different balance") + }) + + It("should return an empty slice if the unbonding delegation is not found", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + delegator.Addr, + valAddr2.String(), + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var unbondingDelegationOutput staking.UnbondingDelegationOutput + err = s.precompile.UnpackIntoInterface(&unbondingDelegationOutput, staking.UnbondingDelegationMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the unbonding delegation output: %v", err) + Expect(unbondingDelegationOutput.UnbondingDelegation.Entries).To(HaveLen(0), "expected one unbonding delegation entry") + }) + }) + + Describe("to query a redelegation", func() { + BeforeEach(func() { + callArgs.MethodName = staking.RedelegationMethod + }) + + It("should return the redelegation if it exists", func() { + delegator := s.keyring.GetKey(0) + + // create a redelegation + redelegateArgs := testutiltypes.CallArgs{ + ContractABI: s.precompile.ABI, + MethodName: staking.RedelegateMethod, + Args: []interface{}{ + delegator.Addr, valAddr.String(), valAddr2.String(), big.NewInt(1e17), + }, + } + + redelegateCheck := passCheck.WithExpEvents(staking.EventTypeRedelegate) + + _, _, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, redelegateArgs, + redelegateCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + // query the redelegation + callArgs.Args = []interface{}{ + delegator.Addr, + valAddr.String(), + valAddr2.String(), + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var redelegationOutput staking.RedelegationOutput + err = s.precompile.UnpackIntoInterface(&redelegationOutput, staking.RedelegationMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the redelegation output: %v", err) + Expect(redelegationOutput.Redelegation.Entries).To(HaveLen(1), "expected one redelegation entry") + Expect(redelegationOutput.Redelegation.Entries[0].InitialBalance).To(Equal(big.NewInt(1e17)), "expected different initial balance") + Expect(redelegationOutput.Redelegation.Entries[0].SharesDst).To(Equal(big.NewInt(1e17)), "expected different balance") + }) + + It("should return an empty output if the redelegation is not found", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + delegator.Addr, + valAddr.String(), + valAddr2.String(), + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var redelegationOutput staking.RedelegationOutput + err = s.precompile.UnpackIntoInterface(&redelegationOutput, staking.RedelegationMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the redelegation output: %v", err) + Expect(redelegationOutput.Redelegation.Entries).To(HaveLen(0), "expected no redelegation entries") + }) + }) + + Describe("Redelegations queries", func() { + var ( + // delAmt is the amount of tokens to be delegated + delAmt = big.NewInt(3e17) + // redelTotalCount is the total number of redelegations + redelTotalCount uint64 = 1 + ) + + BeforeEach(func() { + delegator := s.keyring.GetKey(0) + + callArgs.MethodName = staking.RedelegationsMethod + // create some redelegations + redelegationsArgs := []testutiltypes.CallArgs{ + { + ContractABI: s.precompile.ABI, + MethodName: staking.RedelegateMethod, + Args: []interface{}{ + delegator.Addr, valAddr.String(), valAddr2.String(), delAmt, + }, + }, + { + ContractABI: s.precompile.ABI, + MethodName: staking.RedelegateMethod, + Args: []interface{}{ + delegator.Addr, valAddr.String(), valAddr2.String(), delAmt, + }, + }, + } + + logCheckArgs := passCheck. + WithExpEvents(staking.EventTypeRedelegate) + + txArgs.GasLimit = 500_000 + for _, args := range redelegationsArgs { + _, _, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, args, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while creating redelegation: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + } + }) + + It("should return all redelegations for delegator (default pagination)", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + delegator.Addr, + "", + "", + query.PageRequest{}, + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var redelOut staking.RedelegationsOutput + err = s.precompile.UnpackIntoInterface(&redelOut, staking.RedelegationsMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) + + Expect(redelOut.PageResponse.NextKey).To(BeEmpty()) + Expect(redelOut.PageResponse.Total).To(Equal(redelTotalCount)) + + Expect(redelOut.Response).To(HaveLen(int(redelTotalCount)), "expected two redelegations to be returned") + // return order can change + redOrder := []int{0, 1} + if len(redelOut.Response[0].Entries) == 2 { + redOrder = []int{1, 0} + } + + for i, r := range redelOut.Response { + Expect(r.Entries).To(HaveLen(redOrder[i] + 1)) + } + }) + + It("should return all redelegations for delegator w/pagination", func() { + delegator := s.keyring.GetKey(0) + + // make 2 queries + // 1st one with pagination limit = 1 + // 2nd using the next page key + var nextPageKey []byte + for i := 0; i < 2; i++ { + var pagination query.PageRequest + if nextPageKey == nil { + pagination.Limit = 1 + pagination.CountTotal = true + } else { + pagination.Key = nextPageKey + } + callArgs.Args = []interface{}{ + delegator.Addr, + "", + "", + pagination, + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + var redelOut staking.RedelegationsOutput + err = s.precompile.UnpackIntoInterface(&redelOut, staking.RedelegationsMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) + + if nextPageKey == nil { + nextPageKey = redelOut.PageResponse.NextKey + Expect(redelOut.PageResponse.Total).To(Equal(redelTotalCount)) + } else { + Expect(redelOut.PageResponse.NextKey).To(BeEmpty()) + Expect(redelOut.PageResponse.Total).To(Equal(uint64(1))) + } + + Expect(redelOut.Response).To(HaveLen(1), "expected two redelegations to be returned") + // return order can change + redOrder := []int{0, 1} + if len(redelOut.Response[0].Entries) == 2 { + redOrder = []int{1, 0} + } + + for i, r := range redelOut.Response { + Expect(r.Entries).To(HaveLen(redOrder[i] + 1)) + } + } + }) + + It("should return an empty array if no redelegation is found for the given source validator", func() { + // NOTE: the way that the functionality is implemented in the Cosmos SDK, the following combinations are + // possible (see https://github.com/evmos/cosmos-sdk/blob/e773cf768844c87245d0c737cda1893a2819dd89/x/staking/keeper/querier.go#L361-L373): + // + // - delegator is NOT empty, source validator is empty, destination validator is empty + // --> filtering for all redelegations of the given delegator + // - delegator is empty, source validator is NOT empty, destination validator is empty + // --> filtering for all redelegations with the given source validator + // - delegator is NOT empty, source validator is NOT empty, destination validator is NOT empty + // --> filtering for all redelegations with the given combination of delegator, source and destination validator + callArgs.Args = []interface{}{ + common.Address{}, // passing in an empty address to filter for all redelegations from valAddr2 + valAddr2.String(), + "", + query.PageRequest{}, + } + + sender := s.keyring.GetKey(0) + _, ethRes, err := s.factory.CallContractAndCheckLogs( + sender.Priv, + txArgs, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "expected error while calling the smart contract") + + var redelOut staking.RedelegationsOutput + err = s.precompile.UnpackIntoInterface(&redelOut, staking.RedelegationsMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) + + Expect(redelOut.PageResponse.NextKey).To(BeEmpty()) + Expect(redelOut.PageResponse.Total).To(BeZero(), "expected no redelegations to be returned") + + Expect(redelOut.Response).To(HaveLen(0), "expected no redelegations to be returned") + }) + }) + + It("Should refund leftover gas", func() { + delegator := s.keyring.GetKey(0) + + resBal, err := s.grpcHandler.GetBalanceFromBank(delegator.AccAddr, s.bondDenom) + Expect(err).To(BeNil(), "error while getting balance") + balancePre := resBal.Balance + gasPrice := big.NewInt(1e9) + delAmt := big.NewInt(1e18) + + // Call the precompile with a lot of gas + callArgs.MethodName = staking.DelegateMethod + callArgs.Args = []interface{}{ + delegator.Addr, + valAddr.String(), + delAmt, + } + + txArgs.GasPrice = gasPrice + + logCheckArgs := passCheck. + WithExpEvents(staking.EventTypeDelegate) + + res, _, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + resBal, err = s.grpcHandler.GetBalanceFromBank(delegator.AccAddr, s.bondDenom) + Expect(err).To(BeNil(), "error while getting balance") + balancePost := resBal.Balance + difference := balancePre.Sub(*balancePost) + + // NOTE: the expected difference is the delegate amount plus the gas price multiplied by the gas used, because the rest should be refunded + expDifference := delAmt.Int64() + gasPrice.Int64()*res.GasUsed + Expect(difference.Amount.Int64()).To(Equal(expDifference), "expected different total transaction cost") + }) + }) + var _ = Describe("Calling staking precompile via Solidity", Ordered, func() { + var ( + // s is the precompile test suite to use for the tests + s *PrecompileTestSuite + // contractAddr is the address of the smart contract that will be deployed + contractAddr common.Address + contractTwoAddr common.Address + stkReverterAddr common.Address + + // stakingCallerContract is the contract instance calling into the staking precompile + stakingCallerContract evmtypes.CompiledContract + stakingCallerTwoContract evmtypes.CompiledContract + stakingReverterContract evmtypes.CompiledContract + + // execRevertedCheck defines the default log checking arguments which include the + // standard revert message + execRevertedCheck testutil.LogCheckArgs + // err is a basic error type + err error + + // nonExistingAddr is an address that does not exist in the state of the test suite + nonExistingAddr = testutiltx.GenerateAddress() + // nonExistingVal is a validator address that does not exist in the state of the test suite + nonExistingVal = sdk.ValAddress(nonExistingAddr.Bytes()) + testContractInitialBalance = math.NewInt(1e18) + ) + + BeforeAll(func() { + stakingCallerContract, err = testdata.LoadStakingCallerContract() + Expect(err).To(BeNil()) + stakingCallerTwoContract, err = testdata.LoadStakingCallerTwoContract() + Expect(err).To(BeNil(), "error while loading the StakingCallerTwo contract") + stakingReverterContract, err = contracts.LoadStakingReverterContract() + Expect(err).To(BeNil(), "error while loading the StakingReverter contract") + }) + + BeforeEach(func() { + s = NewPrecompileTestSuite(create, options...) + s.SetupTest() + delegator := s.keyring.GetKey(0) + + contractAddr, err = s.factory.DeployContract( + delegator.Priv, + evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values + testutiltypes.ContractDeploymentData{ + Contract: stakingCallerContract, + }, + ) + Expect(err).To(BeNil(), "error while deploying the smart contract: %v", err) + valAddr, err = sdk.ValAddressFromBech32(s.network.GetValidators()[0].GetOperator()) + Expect(err).To(BeNil()) + valAddr2, err = sdk.ValAddressFromBech32(s.network.GetValidators()[1].GetOperator()) + Expect(err).To(BeNil()) + + Expect(s.network.NextBlock()).To(BeNil()) + + // Deploy StakingCallerTwo contract + contractTwoAddr, err = s.factory.DeployContract( + delegator.Priv, + evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values + testutiltypes.ContractDeploymentData{ + Contract: stakingCallerTwoContract, + }, + ) + Expect(err).To(BeNil(), "error while deploying the StakingCallerTwo contract") + Expect(s.network.NextBlock()).To(BeNil()) + + // Deploy StakingReverter contract + stkReverterAddr, err = s.factory.DeployContract( + delegator.Priv, + evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values + testutiltypes.ContractDeploymentData{ + Contract: stakingReverterContract, + }, + ) + Expect(err).To(BeNil(), "error while deploying the StakingReverter contract") + Expect(s.network.NextBlock()).To(BeNil()) + + // send some funds to the StakingCallerTwo & StakingReverter contracts to transfer to the + // delegator during the tx + err := utils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), contractTwoAddr.Bytes(), testContractInitialBalance) + Expect(err).To(BeNil(), "error while funding the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + err = utils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), stkReverterAddr.Bytes(), testContractInitialBalance) + Expect(err).To(BeNil(), "error while funding the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + // check contract was correctly deployed + cAcc := s.network.App.GetEVMKeeper().GetAccount(s.network.GetContext(), contractAddr) + Expect(cAcc).ToNot(BeNil(), "contract account should exist") + Expect(cAcc.IsContract()).To(BeTrue(), "account should be a contract") + + // populate default TxArgs + txArgs.To = &contractAddr + // populate default call args + callArgs = testutiltypes.CallArgs{ + ContractABI: stakingCallerContract.ABI, + } + // populate default log check args + defaultLogCheck = testutil.LogCheckArgs{ + ABIEvents: s.precompile.Events, + } + execRevertedCheck = defaultLogCheck.WithErrContains(vm.ErrExecutionReverted.Error()) + passCheck = defaultLogCheck.WithExpPass(true) + }) + + Describe("when the precompile is not enabled in the EVM params", func() { + It("should return an error", func() { + delegator := s.keyring.GetKey(0) + + // disable the precompile + res, err := s.grpcHandler.GetEvmParams() + Expect(err).To(BeNil(), "error while setting params") + params := res.Params + var activePrecompiles []string + for _, precompile := range params.ActiveStaticPrecompiles { + if precompile != s.precompile.Address().String() { + activePrecompiles = append(activePrecompiles, precompile) + } + } + params.ActiveStaticPrecompiles = activePrecompiles + + err = utils.UpdateEvmParams(utils.UpdateParamsInput{ + Tf: s.factory, + Network: s.network, + Pk: delegator.Priv, + Params: params, + }) + Expect(err).To(BeNil(), "error while setting params") + + // try to call the precompile + callArgs.MethodName = "testDelegate" + callArgs.Args = []interface{}{ + valAddr.String(), + } + + txArgs.Amount = big.NewInt(1e9) + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + execRevertedCheck, + ) + Expect(err).To(BeNil(), "fails for other reason, I think general message like ") + }) + }) + + Context("create a validator", func() { + var ( + valPriv *ethsecp256k1.PrivKey + valAddr sdk.AccAddress + valHexAddr common.Address + + defaultDescription = staking.Description{ + Moniker: "new node", + Identity: "", + Website: "", + SecurityContact: "", + Details: "", + } + defaultCommission = staking.Commission{ + Rate: big.NewInt(100000000000000000), + MaxRate: big.NewInt(100000000000000000), + MaxChangeRate: big.NewInt(100000000000000000), + } + defaultMinSelfDelegation = big.NewInt(1) + defaultPubkeyBase64Str = GenerateBase64PubKey() + defaultValue = big.NewInt(1e8) + ) + + BeforeEach(func() { + callArgs.MethodName = "testCreateValidator" + valAddr, valPriv = testutiltx.NewAccAddressAndKey() + valHexAddr = common.BytesToAddress(valAddr.Bytes()) + err = utils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), valAddr.Bytes(), math.NewInt(1e18)) + Expect(err).To(BeNil(), "error while funding account: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + }) + + It("tx from validator operator - should NOT create a validator", func() { + callArgs.Args = []interface{}{ + defaultDescription, defaultCommission, defaultMinSelfDelegation, valHexAddr, defaultPubkeyBase64Str, defaultValue, + } + + _, _, err = s.factory.CallContractAndCheckLogs( + valPriv, + txArgs, callArgs, + execRevertedCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract") + Expect(s.network.NextBlock()).To(BeNil()) + + qc := s.network.GetStakingClient() + _, err := qc.Validator(s.network.GetContext(), &stakingtypes.QueryValidatorRequest{ValidatorAddr: sdk.ValAddress(valAddr).String()}) + Expect(err).NotTo(BeNil(), "expected validator NOT to be found") + Expect(err.Error()).To(ContainSubstring("not found"), "expected validator NOT to be found") + }) + + It("tx from another EOA - should create a validator fail", func() { + callArgs.Args = []interface{}{ + defaultDescription, defaultCommission, defaultMinSelfDelegation, valHexAddr, defaultPubkeyBase64Str, defaultValue, + } + + _, _, err = s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, callArgs, + execRevertedCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract") + Expect(s.network.NextBlock()).To(BeNil()) + + qc := s.network.GetStakingClient() + _, err := qc.Validator(s.network.GetContext(), &stakingtypes.QueryValidatorRequest{ValidatorAddr: sdk.ValAddress(valAddr).String()}) + Expect(err).NotTo(BeNil(), "expected validator NOT to be found") + Expect(err.Error()).To(ContainSubstring("not found"), "expected validator NOT to be found") + }) + }) + + Context("to edit a validator", func() { + var ( + valPriv *ethsecp256k1.PrivKey + valAddr sdk.AccAddress + valHexAddr common.Address + + defaultDescription = staking.Description{ + Moniker: "edit node", + Identity: "[do-not-modify]", + Website: "[do-not-modify]", + SecurityContact: "[do-not-modify]", + Details: "[do-not-modify]", + } + defaultCommissionRate = big.NewInt(staking.DoNotModifyCommissionRate) + defaultMinSelfDelegation = big.NewInt(staking.DoNotModifyMinSelfDelegation) + + minSelfDelegation = big.NewInt(1) + + description = staking.Description{} + commission = staking.Commission{} + ) + + BeforeEach(func() { + callArgs.MethodName = "testEditValidator" + + // create a new validator + valAddr, valPriv = testutiltx.NewAccAddressAndKey() + valHexAddr = common.BytesToAddress(valAddr.Bytes()) + err = utils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), valAddr.Bytes(), math.NewInt(2e18)) + Expect(err).To(BeNil(), "error while funding account: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + description = staking.Description{ + Moniker: "original moniker", + Identity: "", + Website: "", + SecurityContact: "", + Details: "", + } + commission = staking.Commission{ + Rate: big.NewInt(100000000000000000), + MaxRate: big.NewInt(100000000000000000), + MaxChangeRate: big.NewInt(100000000000000000), + } + pubkeyBase64Str := "UuhHQmkUh2cPBA6Rg4ei0M2B04cVYGNn/F8SAUsYIb4=" + value := big.NewInt(1e18) + + createValidatorArgs := testutiltypes.CallArgs{ + ContractABI: s.precompile.ABI, + MethodName: staking.CreateValidatorMethod, + Args: []interface{}{description, commission, minSelfDelegation, valHexAddr, pubkeyBase64Str, value}, + } + + logCheckArgs := passCheck.WithExpEvents(staking.EventTypeCreateValidator) + + toAddr := s.precompile.Address() + _, _, err = s.factory.CallContractAndCheckLogs( + valPriv, + evmtypes.EvmTxArgs{ + To: &toAddr, + }, + createValidatorArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract") + Expect(s.network.NextBlock()).To(BeNil()) + }) + + It("with tx from validator operator - should NOT edit a validator", func() { + callArgs.Args = []interface{}{ + defaultDescription, valHexAddr, + defaultCommissionRate, defaultMinSelfDelegation, + } + + _, _, err = s.factory.CallContractAndCheckLogs( + valPriv, + txArgs, + callArgs, + execRevertedCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract") + Expect(s.network.NextBlock()).To(BeNil()) + + qc := s.network.GetStakingClient() + qRes, err := qc.Validator(s.network.GetContext(), &stakingtypes.QueryValidatorRequest{ValidatorAddr: sdk.ValAddress(valAddr).String()}) + Expect(err).To(BeNil()) + Expect(qRes).NotTo(BeNil()) + validator := qRes.Validator + Expect(validator.Description.Moniker).NotTo(Equal(defaultDescription.Moniker), "expected validator moniker NOT to be updated") + }) + + It("with tx from another EOA - should fail", func() { + callArgs.Args = []interface{}{ + defaultDescription, valHexAddr, + defaultCommissionRate, defaultMinSelfDelegation, + } + + _, _, err = s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + callArgs, + execRevertedCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract") + Expect(s.network.NextBlock()).To(BeNil()) + + // validator should remain unchanged + qc := s.network.GetStakingClient() + qRes, err := qc.Validator(s.network.GetContext(), &stakingtypes.QueryValidatorRequest{ValidatorAddr: sdk.ValAddress(valAddr).String()}) + Expect(err).To(BeNil()) + Expect(qRes).NotTo(BeNil()) + + validator := qRes.Validator + Expect(validator.Description.Moniker).To(Equal("original moniker"), "expected validator moniker is updated") + Expect(validator.Commission.Rate.BigInt().String()).To(Equal("100000000000000000"), "expected validator commission rate remain unchanged") + }) + }) + + Context("delegating", func() { + // prevDelegation is the delegation that is available prior to the test (an initial delegation is + // added in the test suite setup). + var prevDelegation stakingtypes.Delegation + + BeforeEach(func() { + delegator := s.keyring.GetKey(0) + + txArgs.Amount = big.NewInt(1e18) + txArgs.GasLimit = 500_000 + + // initial delegation via contract + callArgs.MethodName = "testDelegate" + callArgs.Args = []interface{}{ + valAddr.String(), + } + + logCheckArgs := passCheck. + WithExpEvents(staking.EventTypeDelegate) + + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, + callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract") + Expect(s.network.NextBlock()).To(BeNil()) + + // get the delegation that is available prior to the test + contractAccAddr := sdk.AccAddress(contractAddr.Bytes()) + Expect(err).To(BeNil()) + res, err := s.grpcHandler.GetDelegation(contractAccAddr.String(), valAddr.String()) + Expect(err).To(BeNil()) + Expect(res.DelegationResponse).NotTo(BeNil()) + + prevDelegation = res.DelegationResponse.Delegation + }) + + Context("with native coin transfer", func() { + It("should delegate", func() { + delegator := s.keyring.GetKey(0) + + txArgs.Amount = big.NewInt(1e18) + + callArgs.Args = []interface{}{ + valAddr.String(), + } + + logCheckArgs := passCheck. + WithExpEvents(staking.EventTypeDelegate) + + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + contractAccAddr := sdk.AccAddress(contractAddr.Bytes()) + res, err := s.grpcHandler.GetDelegation(contractAccAddr.String(), valAddr.String()) + Expect(err).To(BeNil()) + Expect(res.DelegationResponse).NotTo(BeNil()) + delegation := res.DelegationResponse.Delegation + + expShares := prevDelegation.GetShares().Add(math.LegacyNewDec(1)) + Expect(delegation.GetShares()).To(Equal(expShares), "expected delegation shares to be 2") + }) + + Context("Calling the precompile from the StakingReverter contract", func() { + var ( + txSenderInitialBal *sdk.Coin + contractInitialBalance *sdk.Coin + gasPrice = math.NewInt(1e9) + ) + + BeforeEach(func() { + balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + txSenderInitialBal = balRes.Balance + balRes, err = s.grpcHandler.GetBalanceFromBank(stkReverterAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + contractInitialBalance = balRes.Balance + }) + + It("should revert the changes and NOT delegate - successful tx", func() { + callArgs := testutiltypes.CallArgs{ + ContractABI: stakingReverterContract.ABI, + MethodName: "run", + Args: []interface{}{ + big.NewInt(5), s.network.GetValidators()[0].OperatorAddress, + }, + } + + // Tx should be successful, but no state changes happened + res, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{ + To: &stkReverterAddr, + GasPrice: gasPrice.BigInt(), + }, + callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + fees := gasPrice.MulRaw(res.GasUsed) + + // contract balance should remain unchanged + balRes, err := s.grpcHandler.GetBalanceFromBank(stkReverterAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + contractFinalBalance := balRes.Balance + Expect(contractFinalBalance.Amount).To(Equal(contractInitialBalance.Amount)) + + // No delegation should be created + _, err = s.grpcHandler.GetDelegation(sdk.AccAddress(stkReverterAddr.Bytes()).String(), s.network.GetValidators()[0].OperatorAddress) + Expect(err).NotTo(BeNil()) + Expect(err.Error()).To(ContainSubstring("not found"), "expected NO delegation created") + + // Only fees deducted on tx sender + balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + txSenderFinalBal := balRes.Balance + Expect(txSenderFinalBal.Amount).To(Equal(txSenderInitialBal.Amount.Sub(fees))) + }) + + It("should revert the changes and NOT delegate - failed tx - max precompile calls reached", func() { + callArgs := testutiltypes.CallArgs{ + ContractABI: stakingReverterContract.ABI, + MethodName: "multipleDelegations", + Args: []interface{}{ + big.NewInt(int64(evmtypes.MaxPrecompileCalls + 2)), s.network.GetValidators()[0].OperatorAddress, + }, + } + + // Tx should fail due to MaxPrecompileCalls + _, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{ + To: &stkReverterAddr, + GasPrice: gasPrice.BigInt(), + }, + callArgs, + execRevertedCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + // contract balance should remain unchanged + balRes, err := s.grpcHandler.GetBalanceFromBank(stkReverterAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + contractFinalBalance := balRes.Balance + Expect(contractFinalBalance.Amount).To(Equal(contractInitialBalance.Amount)) + + // No delegation should be created + _, err = s.grpcHandler.GetDelegation(sdk.AccAddress(stkReverterAddr.Bytes()).String(), s.network.GetValidators()[0].OperatorAddress) + Expect(err).NotTo(BeNil()) + Expect(err.Error()).To(ContainSubstring("not found"), "expected NO delegation created") + }) + }) + + Context("Table-driven tests for Delegate method", func() { + // testCase is a struct used for cases of contracts calls that have some operation + // performed before and/or after the precompile call + type testCase struct { + before bool + after bool + } + + var ( + args testutiltypes.CallArgs + delegatorInitialBal *sdk.Coin + contractInitialBalance *sdk.Coin + bondedTokensPoolInitialBalance *sdk.Coin + delAmt = math.NewInt(1e18) + gasPrice = math.NewInt(1e9) + bondedTokensPoolAccAddr = authtypes.NewModuleAddress("bonded_tokens_pool") + ) + + BeforeEach(func() { + balRes, err := s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + delegatorInitialBal = balRes.Balance + balRes, err = s.grpcHandler.GetBalanceFromBank(contractTwoAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + contractInitialBalance = balRes.Balance + balRes, err = s.grpcHandler.GetBalanceFromBank(bondedTokensPoolAccAddr, s.bondDenom) + Expect(err).To(BeNil()) + bondedTokensPoolInitialBalance = balRes.Balance + + args.ContractABI = stakingCallerTwoContract.ABI + args.MethodName = "testDelegateWithCounterAndTransfer" + }) + + DescribeTable("should delegate and update balances accordingly", func(tc testCase) { + args.Args = []interface{}{ + valAddr.String(), tc.before, tc.after, + } + + // This is the amount of tokens transferred from the contract to the delegator + // during the contract call + transferToDelAmt := math.ZeroInt() + for _, transferred := range []bool{tc.before, tc.after} { + if transferred { + transferToDelAmt = transferToDelAmt.AddRaw(15) + } + } + + logCheckArgs := passCheck. + WithExpEvents(staking.EventTypeDelegate) + + txArgs := evmtypes.EvmTxArgs{ + To: &contractTwoAddr, + GasPrice: gasPrice.BigInt(), + GasLimit: 500_000, + Amount: delAmt.BigInt(), + } + + res, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + args, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + fees := gasPrice.MulRaw(res.GasUsed) + + // check the contract's balance was deducted to fund the vesting account + balRes, err := s.grpcHandler.GetBalanceFromBank(contractTwoAddr.Bytes(), s.bondDenom) + contractFinalBal := balRes.Balance + Expect(err).To(BeNil()) + Expect(contractFinalBal.Amount).To(Equal(contractInitialBalance.Amount.Sub(transferToDelAmt))) + + contractTwoAccAddr := sdk.AccAddress(contractTwoAddr.Bytes()) + qRes, err := s.grpcHandler.GetDelegation(contractTwoAccAddr.String(), valAddr.String()) + Expect(err).To(BeNil()) + Expect(qRes).NotTo(BeNil(), "expected delegation to be found") + delegation := qRes.DelegationResponse.Delegation + expShares := math.LegacyZeroDec().Add(math.LegacyNewDec(1)) + Expect(delegation.GetShares()).To(Equal(expShares), "expected delegation shares to be 2") + + balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + delegatorFinalBal := balRes.Balance + Expect(delegatorFinalBal.Amount).To(Equal(delegatorInitialBal.Amount.Sub(fees).Sub(delAmt).Add(transferToDelAmt))) + + // check the bondedTokenPool is updated with the delegated tokens + balRes, err = s.grpcHandler.GetBalanceFromBank(bondedTokensPoolAccAddr, s.bondDenom) + bondedTokensPoolFinalBalance := balRes.Balance + Expect(err).To(BeNil()) + Expect(bondedTokensPoolFinalBalance.Amount).To(Equal(bondedTokensPoolInitialBalance.Amount.Add(delAmt))) + }, + Entry("contract tx with transfer to delegator before and after precompile call ", testCase{ + before: true, + after: true, + }), + Entry("contract tx with transfer to delegator before precompile call ", testCase{ + before: true, + after: false, + }), + Entry("contract tx with transfer to delegator after precompile call ", testCase{ + before: false, + after: true, + }), + ) + + It("should NOT delegate and update balances accordingly - internal transfer to tokens pool", func() { + args.MethodName = "testDelegateWithTransfer" + args.Args = []interface{}{ + common.BytesToAddress(bondedTokensPoolAccAddr), + s.keyring.GetAddr(0), valAddr.String(), true, true, + } + + txArgs.Amount = delAmt.BigInt() + _, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + txArgs, + args, + execRevertedCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + // contract balance should remain unchanged + balRes, err := s.grpcHandler.GetBalanceFromBank(contractTwoAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + contractFinalBal := balRes.Balance + Expect(contractFinalBal.Amount).To(Equal(contractInitialBalance.Amount)) + + // check the bondedTokenPool should remain unchanged + balRes, err = s.grpcHandler.GetBalanceFromBank(bondedTokensPoolAccAddr, s.bondDenom) + Expect(err).To(BeNil()) + bondedTokensPoolFinalBalance := balRes.Balance + Expect(bondedTokensPoolFinalBalance.Amount).To(Equal(bondedTokensPoolInitialBalance.Amount)) + }) + }) + + It("should not delegate when validator does not exist", func() { + delegator := s.keyring.GetKey(0) + + txArgs.Amount = big.NewInt(1e18) + + callArgs.Args = []interface{}{ + nonExistingVal.String(), + } + + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + execRevertedCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + contractAccAddr := sdk.AccAddress(contractAddr.Bytes()) + res, err := s.grpcHandler.GetDelegation(contractAccAddr.String(), nonExistingVal.String()) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("delegation with delegator %s not found for validator %s", contractAccAddr.String(), nonExistingVal.String()))) + Expect(res).To(BeNil()) + }) + }) + }) + + Context("unbonding", func() { + var contractAccAddr sdk.AccAddress + + BeforeEach(func() { + contractAccAddr = sdk.AccAddress(contractAddr.Bytes()) + + callArgs.MethodName = "testUndelegate" + + // delegate to undelegate + _, _, err = s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{ + To: &contractAddr, + Amount: big.NewInt(1e18), + GasPrice: big.NewInt(1e9), + GasLimit: 500_000, + }, + testutiltypes.CallArgs{ + ContractABI: stakingCallerContract.ABI, + MethodName: "testDelegate", + Args: []interface{}{ + valAddr.String(), + }, + }, + passCheck.WithExpEvents(staking.EventTypeDelegate), + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + txArgs.GasLimit = 500_000 + txArgs.Amount = big.NewInt(0) + }) + + It("should undelegate", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + valAddr.String(), big.NewInt(1e18), + } + + logCheckArgs := defaultLogCheck. + WithExpEvents(staking.EventTypeUnbond). + WithExpPass(true) + + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + logCheckArgs) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(contractAccAddr.String()) + Expect(err).To(BeNil()) + Expect(res.UnbondingResponses).To(HaveLen(1), "expected one undelegation") + Expect(res.UnbondingResponses[0].ValidatorAddress).To(Equal(valAddr.String()), "expected validator address to be %s", valAddr) + }) + + It("should not undelegate if the delegation does not exist", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + nonExistingVal.String(), big.NewInt(1e18), + } + + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + execRevertedCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(contractAccAddr.String()) + Expect(err).To(BeNil()) + Expect(res.UnbondingResponses).To(BeEmpty()) + }) + + It("should not undelegate when called from a different address", func() { + delegator := s.keyring.GetKey(0) + differentSender := s.keyring.GetKey(1) + + callArgs.Args = []interface{}{ + valAddr.String(), big.NewInt(1e18), + } + + _, _, err = s.factory.CallContractAndCheckLogs( + differentSender.Priv, + txArgs, callArgs, + execRevertedCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(delegator.AccAddr.String()) + Expect(err).To(BeNil()) + Expect(res.UnbondingResponses).To(BeEmpty()) + }) + }) + + Context("redelegating", func() { + var contractAccAddr sdk.AccAddress + + BeforeEach(func() { + contractAccAddr = sdk.AccAddress(contractAddr.Bytes()) + + callArgs.MethodName = "testRedelegate" + + // delegate to redelegate + _, _, err = s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{ + To: &contractAddr, + Amount: big.NewInt(1e18), + GasPrice: big.NewInt(1e9), + GasLimit: 500_000, + }, + testutiltypes.CallArgs{ + ContractABI: stakingCallerContract.ABI, + MethodName: "testDelegate", + Args: []interface{}{ + valAddr.String(), + }, + }, + passCheck.WithExpEvents(staking.EventTypeDelegate), + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + txArgs.GasLimit = 500_000 + txArgs.Amount = big.NewInt(0) + }) + + It("should redelegate", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + valAddr.String(), valAddr2.String(), big.NewInt(1e18), + } + + logCheckArgs := defaultLogCheck. + WithExpEvents(staking.EventTypeRedelegate). + WithExpPass(true) + + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + res, err := s.grpcHandler.GetRedelegations(contractAccAddr.String(), valAddr.String(), valAddr2.String()) + Expect(err).To(BeNil()) + Expect(res.RedelegationResponses).To(HaveLen(1), "expected one redelegation to be found") + Expect(res.RedelegationResponses[0].Redelegation.DelegatorAddress).To(Equal(contractAccAddr.String()), "expected delegator address to be %s", contractAccAddr) + Expect(res.RedelegationResponses[0].Redelegation.ValidatorSrcAddress).To(Equal(valAddr.String()), "expected source validator address to be %s", valAddr) + Expect(res.RedelegationResponses[0].Redelegation.ValidatorDstAddress).To(Equal(valAddr2.String()), "expected destination validator address to be %s", valAddr2) + }) + + It("should not redelegate if the delegation does not exist", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + nonExistingVal.String(), valAddr2.String(), big.NewInt(1e18), + } + + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + execRevertedCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + res, err := s.grpcHandler.GetRedelegations(contractAccAddr.String(), nonExistingVal.String(), valAddr2.String()) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("redelegation not found for delegator address %s from validator address %s", contractAccAddr, nonExistingVal))) + Expect(res).To(BeNil(), "expected no redelegations to be found") + }) + + It("should not redelegate when calling from a different address", func() { + differentSender := s.keyring.GetKey(1) + + callArgs.Args = []interface{}{ + valAddr.String(), valAddr2.String(), big.NewInt(1e18), + } + + _, _, err = s.factory.CallContractAndCheckLogs( + differentSender.Priv, + txArgs, callArgs, + execRevertedCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + res, err := s.grpcHandler.GetRedelegations(contractAccAddr.String(), valAddr.String(), valAddr2.String()) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("redelegation not found for delegator address %s from validator address %s", contractAccAddr, valAddr))) + Expect(res).To(BeNil(), "expected no redelegations to be found") + }) + + It("should not redelegate when the validator does not exist", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + valAddr.String(), nonExistingVal.String(), big.NewInt(1e18), + } + + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + execRevertedCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + res, err := s.grpcHandler.GetRedelegations(contractAccAddr.String(), valAddr.String(), nonExistingVal.String()) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("redelegation not found for delegator address %s from validator address %s", contractAccAddr, valAddr))) + Expect(res).To(BeNil()) + }) + }) + + Context("canceling unbonding delegations", func() { + // expCreationHeight is the expected creation height of the unbonding delegation + var expCreationHeight int64 + var contractAccAddr sdk.AccAddress + + BeforeEach(func() { + contractAccAddr = sdk.AccAddress(contractAddr.Bytes()) + + callArgs.MethodName = "testCancelUnbonding" + + // delegate to undelegate + _, _, err = s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{ + To: &contractAddr, + Amount: big.NewInt(1e18), + GasPrice: big.NewInt(1e9), + GasLimit: 500_000, + }, + testutiltypes.CallArgs{ + ContractABI: stakingCallerContract.ABI, + MethodName: "testDelegate", + Args: []interface{}{ + valAddr.String(), + }, + }, + passCheck.WithExpEvents(staking.EventTypeDelegate), + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil(), "failed to advance block") + + // undelegate to cancel unbonding + delegator := s.keyring.GetKey(0) + txArgs.Amount = big.NewInt(0) + undelegateArgs := testutiltypes.CallArgs{ + ContractABI: stakingCallerContract.ABI, + MethodName: "testUndelegate", + Args: []interface{}{valAddr.String(), big.NewInt(1e18)}, + } + + logCheckArgs := defaultLogCheck. + WithExpEvents(staking.EventTypeUnbond). + WithExpPass(true) + + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, undelegateArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while setting up an unbonding delegation: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + expCreationHeight = s.network.GetContext().BlockHeight() + // Check that the unbonding delegation was created + res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(contractAccAddr.String()) + Expect(err).To(BeNil()) + Expect(res.UnbondingResponses).To(HaveLen(1), "expected one unbonding delegation to be found") + Expect(res.UnbondingResponses[0].DelegatorAddress).To(Equal(contractAccAddr.String()), "expected delegator address to be %s", contractAccAddr) + Expect(res.UnbondingResponses[0].ValidatorAddress).To(Equal(valAddr.String()), "expected validator address to be %s", valAddr) + Expect(res.UnbondingResponses[0].Entries).To(HaveLen(1), "expected one unbonding delegation entry to be found") + Expect(res.UnbondingResponses[0].Entries[0].CreationHeight).To(Equal(expCreationHeight), "expected different creation height") + Expect(res.UnbondingResponses[0].Entries[0].Balance).To(Equal(math.NewInt(1e18)), "expected different balance") + }) + + It("should cancel unbonding delegations", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + valAddr.String(), big.NewInt(1e18), big.NewInt(expCreationHeight), + } + + txArgs.GasLimit = 1e9 + + logCheckArgs := passCheck. + WithExpEvents(staking.EventTypeCancelUnbondingDelegation) + + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + logCheckArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(contractAccAddr.String()) + Expect(err).To(BeNil()) + Expect(res.UnbondingResponses).To(BeEmpty(), "expected unbonding delegation to be canceled") + }) + + It("should not cancel unbonding any delegations when unbonding delegation does not exist", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + nonExistingVal.String(), + big.NewInt(1e18), + big.NewInt(expCreationHeight), + } + + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, + callArgs, + execRevertedCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(contractAccAddr.String()) + Expect(err).To(BeNil()) + Expect(res.UnbondingResponses).To(HaveLen(1), "expected unbonding delegation to not be canceled") + }) + }) + + Context("querying validator", func() { + BeforeEach(func() { + callArgs.MethodName = "getValidator" + }) + It("with non-existing address should return an empty validator", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + nonExistingAddr, + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var valOut staking.ValidatorOutput + err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) + Expect(valOut.Validator.OperatorAddress).To(Equal(""), "expected empty validator address") + Expect(valOut.Validator.Status).To(Equal(uint8(0)), "expected validator status to be 0 (unspecified)") + }) + + It("with existing address should return the validator", func() { + delegator := s.keyring.GetKey(0) + + valHexAddr := common.BytesToAddress(valAddr.Bytes()) + callArgs.Args = []interface{}{valHexAddr} + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var valOut staking.ValidatorOutput + err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) + Expect(valOut.Validator.OperatorAddress).To(Equal(valHexAddr.String()), "expected validator address to match") + Expect(valOut.Validator.DelegatorShares).To(Equal(big.NewInt(1e18)), "expected different delegator shares") + }) + + It("with status bonded and pagination", func() { + delegator := s.keyring.GetKey(0) + + callArgs.MethodName = "getValidators" + callArgs.Args = []interface{}{ + stakingtypes.Bonded.String(), + query.PageRequest{ + Limit: 1, + CountTotal: true, + }, + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var valOut staking.ValidatorsOutput + err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorsMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) + Expect(valOut.PageResponse.Total).To(Equal(uint64(len(s.network.GetValidators())))) + Expect(valOut.PageResponse.NextKey).NotTo(BeEmpty()) + Expect(valOut.Validators[0].DelegatorShares).To(Equal(big.NewInt(1e18)), "expected different delegator shares") + }) + }) + + Context("querying validators", func() { + BeforeEach(func() { + callArgs.MethodName = "getValidators" + }) + It("should return validators (default pagination)", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + stakingtypes.Bonded.String(), + query.PageRequest{}, + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var valOut staking.ValidatorsOutput + err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorsMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) + Expect(valOut.PageResponse.Total).To(Equal(uint64(len(s.network.GetValidators())))) + Expect(valOut.PageResponse.NextKey).To(BeEmpty()) + Expect(valOut.Validators).To(HaveLen(len(s.network.GetValidators())), "expected all validators to be returned") + // return order can change, that's why each validator is checked individually + for _, val := range valOut.Validators { + s.CheckValidatorOutput(val) + } + }) + + //nolint:dupl // this is a duplicate of the test for EOA calls to the precompile + It("should return validators with pagination limit = 1", func() { + const limit uint64 = 1 + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + stakingtypes.Bonded.String(), + query.PageRequest{ + Limit: limit, + CountTotal: true, + }, + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var valOut staking.ValidatorsOutput + err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorsMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) + + // no pagination, should return default values + Expect(valOut.PageResponse.NextKey).NotTo(BeEmpty()) + Expect(valOut.PageResponse.Total).To(Equal(uint64(len(s.network.GetValidators())))) + + Expect(valOut.Validators).To(HaveLen(int(limit)), "expected one validator to be returned") + + // return order can change, that's why each validator is checked individually + for _, val := range valOut.Validators { + s.CheckValidatorOutput(val) + } + }) + + It("should revert the execution if the bonding type is not known", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + "15", // invalid bonding type + query.PageRequest{}, + } + + _, _, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + execRevertedCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + }) + + It("should return an empty array if there are no validators with the given bonding type", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + stakingtypes.Unbonded.String(), + query.PageRequest{}, + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var valOut staking.ValidatorsOutput + err = s.precompile.UnpackIntoInterface(&valOut, staking.ValidatorsMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the validator output: %v", err) + + Expect(valOut.PageResponse.NextKey).To(BeEmpty()) + Expect(valOut.PageResponse.Total).To(Equal(uint64(0))) + Expect(valOut.Validators).To(HaveLen(0), "expected no validators to be returned") + }) + }) + + Context("querying delegation", func() { + BeforeEach(func() { + callArgs.MethodName = "getDelegation" + }) + It("which does not exist should return an empty delegation", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + nonExistingAddr, valAddr.String(), + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var delOut staking.DelegationOutput + err = s.precompile.UnpackIntoInterface(&delOut, staking.DelegationMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the delegation output: %v", err) + Expect(delOut.Balance.Amount.Int64()).To(Equal(int64(0)), "expected a different delegation balance") + Expect(delOut.Balance.Denom).To(Equal(cosmosevmutil.ExampleAttoDenom), "expected a different delegation balance") + }) + + It("which exists should return the delegation", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + delegator.Addr, valAddr.String(), + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var delOut staking.DelegationOutput + err = s.precompile.UnpackIntoInterface(&delOut, staking.DelegationMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the delegation output: %v", err) + Expect(delOut.Balance).To(Equal( + cmn.Coin{Denom: cosmosevmutil.ExampleAttoDenom, Amount: big.NewInt(1e18)}), + "expected a different delegation balance", + ) + }) + }) + + Context("querying redelegation", func() { + var contractAccAddr sdk.AccAddress + + BeforeEach(func() { + callArgs.MethodName = "getRedelegation" + contractAccAddr = sdk.AccAddress(contractAddr.Bytes()) + + // delegate to redelegate + _, _, err = s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{ + To: &contractAddr, + Amount: big.NewInt(1e18), + GasPrice: big.NewInt(1e9), + GasLimit: 500_000, + }, + testutiltypes.CallArgs{ + ContractABI: stakingCallerContract.ABI, + MethodName: "testDelegate", + Args: []interface{}{ + valAddr.String(), + }, + }, + passCheck.WithExpEvents(staking.EventTypeDelegate), + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil(), "failed to advance block") + }) + + It("which does not exist should return an empty redelegation", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + delegator.Addr, valAddr.String(), nonExistingVal.String(), + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var redOut staking.RedelegationOutput + err = s.precompile.UnpackIntoInterface(&redOut, staking.RedelegationMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the redelegation output: %v", err) + Expect(redOut.Redelegation.Entries).To(HaveLen(0), "expected no redelegation entries") + }) + + It("which exists should return the redelegation", func() { + delegator := s.keyring.GetKey(0) + + // set up redelegation + redelegateArgs := testutiltypes.CallArgs{ + ContractABI: stakingCallerContract.ABI, + MethodName: "testRedelegate", + Args: []interface{}{valAddr.String(), valAddr2.String(), big.NewInt(1)}, + } + + redelegateCheck := passCheck. + WithExpEvents(staking.EventTypeRedelegate) + + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, redelegateArgs, + redelegateCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + // check that the redelegation was created + res, err := s.grpcHandler.GetRedelegations(contractAccAddr.String(), valAddr.String(), valAddr2.String()) + Expect(err).To(BeNil()) + Expect(res.RedelegationResponses).To(HaveLen(1), "expected one redelegation to be found") + bech32Addr := contractAccAddr + Expect(res.RedelegationResponses[0].Redelegation.DelegatorAddress).To(Equal(bech32Addr.String()), "expected delegator address to be %s", contractAddr) + Expect(res.RedelegationResponses[0].Redelegation.ValidatorSrcAddress).To(Equal(valAddr.String()), "expected source validator address to be %s", valAddr) + Expect(res.RedelegationResponses[0].Redelegation.ValidatorDstAddress).To(Equal(valAddr2.String()), "expected destination validator address to be %s", valAddr2) + + // query redelegation + callArgs.Args = []interface{}{ + contractAddr, valAddr.String(), valAddr2.String(), + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var redOut staking.RedelegationOutput + err = s.precompile.UnpackIntoInterface(&redOut, staking.RedelegationMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the redelegation output: %v", err) + Expect(redOut.Redelegation.Entries).To(HaveLen(1), "expected one redelegation entry to be returned") + }) + }) + + Describe("query redelegations", func() { + var contractAccAddr sdk.AccAddress + + BeforeEach(func() { + contractAccAddr = sdk.AccAddress(contractAddr.Bytes()) + + callArgs.MethodName = "getRedelegations" + + // delegate to redelegate + _, _, err = s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{ + To: &contractAddr, + Amount: big.NewInt(1e18), + GasPrice: big.NewInt(1e9), + GasLimit: 500_000, + }, + testutiltypes.CallArgs{ + ContractABI: stakingCallerContract.ABI, + MethodName: "testDelegate", + Args: []interface{}{ + valAddr.String(), + }, + }, + passCheck.WithExpEvents(staking.EventTypeDelegate), + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil(), "failed to advance block") + }) + + It("which exists should return all the existing redelegations w/pagination", func() { + delegator := s.keyring.GetKey(0) + + // set up redelegation + redelegateArgs := testutiltypes.CallArgs{ + ContractABI: stakingCallerContract.ABI, + MethodName: "testRedelegate", + Args: []interface{}{valAddr.String(), valAddr2.String(), big.NewInt(1)}, + } + + redelegateCheck := passCheck. + WithExpEvents(staking.EventTypeRedelegate) + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, redelegateArgs, + redelegateCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + // check that the redelegation was created + res, err := s.grpcHandler.GetRedelegations(contractAccAddr.String(), valAddr.String(), valAddr2.String()) + Expect(err).To(BeNil()) + Expect(res.RedelegationResponses).To(HaveLen(1), "expected one redelegation to be found") + bech32Addr := contractAccAddr + Expect(res.RedelegationResponses[0].Redelegation.DelegatorAddress).To(Equal(bech32Addr.String()), "expected delegator address to be %s", contractAccAddr) + Expect(res.RedelegationResponses[0].Redelegation.ValidatorSrcAddress).To(Equal(valAddr.String()), "expected source validator address to be %s", valAddr) + Expect(res.RedelegationResponses[0].Redelegation.ValidatorDstAddress).To(Equal(valAddr2.String()), "expected destination validator address to be %s", valAddr2) + + // query redelegations by delegator address + callArgs.Args = []interface{}{ + contractAddr, "", "", query.PageRequest{Limit: 1, CountTotal: true}, + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + passCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + var redOut staking.RedelegationsOutput + err = s.precompile.UnpackIntoInterface(&redOut, staking.RedelegationsMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the redelegation output: %v", err) + Expect(redOut.Response).To(HaveLen(1), "expected one redelegation entry to be returned") + Expect(redOut.Response[0].Entries).To(HaveLen(1), "expected one redelegation entry to be returned") + Expect(redOut.PageResponse.Total).To(Equal(uint64(1))) + Expect(redOut.PageResponse.NextKey).To(BeEmpty()) + }) + }) + + Context("querying unbonding delegation", func() { + var contractAccAddr sdk.AccAddress + + BeforeEach(func() { + delegator := s.keyring.GetKey(0) + contractAccAddr = sdk.AccAddress(contractAddr.Bytes()) + + callArgs.MethodName = "getUnbondingDelegation" + + // delegate to redelegate + _, _, err = s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{ + To: &contractAddr, + Amount: big.NewInt(1e18), + GasPrice: big.NewInt(1e9), + GasLimit: 500_000, + }, + testutiltypes.CallArgs{ + ContractABI: stakingCallerContract.ABI, + MethodName: "testDelegate", + Args: []interface{}{ + valAddr.String(), + }, + }, + passCheck.WithExpEvents(staking.EventTypeDelegate), + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil(), "failed to advance block") + + // undelegate + undelegateArgs := testutiltypes.CallArgs{ + ContractABI: stakingCallerContract.ABI, + MethodName: "testUndelegate", + Args: []interface{}{valAddr.String(), big.NewInt(1e18)}, + } + + logCheckArgs := passCheck. + WithExpEvents(staking.EventTypeUnbond) + + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, undelegateArgs, logCheckArgs) + Expect(err).To(BeNil(), "error while setting up an unbonding delegation: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + // Check that the unbonding delegation was created + res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(contractAccAddr.String()) + Expect(err).To(BeNil()) + Expect(res.UnbondingResponses).To(HaveLen(1), "expected one unbonding delegation to be found") + Expect(res.UnbondingResponses[0].DelegatorAddress).To(Equal(contractAccAddr.String()), "expected delegator address to be %s", contractAddr) + Expect(res.UnbondingResponses[0].ValidatorAddress).To(Equal(valAddr.String()), "expected validator address to be %s", valAddr) + Expect(res.UnbondingResponses[0].Entries).To(HaveLen(1), "expected one unbonding delegation entry to be found") + Expect(res.UnbondingResponses[0].Entries[0].CreationHeight).To(Equal(s.network.GetContext().BlockHeight()), "expected different creation height") + Expect(res.UnbondingResponses[0].Entries[0].Balance).To(Equal(math.NewInt(1e18)), "expected different balance") + }) + + It("which does not exist should return an empty unbonding delegation", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + delegator.Addr, valAddr2.String(), + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, passCheck) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var unbondingDelegationOutput staking.UnbondingDelegationOutput + err = s.precompile.UnpackIntoInterface(&unbondingDelegationOutput, staking.UnbondingDelegationMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the unbonding delegation output: %v", err) + Expect(unbondingDelegationOutput.UnbondingDelegation.Entries).To(HaveLen(0), "expected one unbonding delegation entry") + }) + + It("which exists should return the unbonding delegation", func() { + delegator := s.keyring.GetKey(0) + + callArgs.Args = []interface{}{ + contractAddr, valAddr.String(), + } + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, passCheck) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + + var unbondOut staking.UnbondingDelegationOutput + err = s.precompile.UnpackIntoInterface(&unbondOut, staking.UnbondingDelegationMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the unbonding delegation output: %v", err) + Expect(unbondOut.UnbondingDelegation.Entries).To(HaveLen(1), "expected one unbonding delegation entry to be returned") + Expect(unbondOut.UnbondingDelegation.Entries[0].Balance).To(Equal(big.NewInt(1e18)), "expected different balance") + }) + }) + + Context("when using special call opcodes", func() { + var contractAccAddr sdk.AccAddress + + BeforeEach(func() { + contractAccAddr = sdk.AccAddress(contractAddr.Bytes()) + + // delegate to undelegate + _, _, err = s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{ + To: &contractAddr, + Amount: big.NewInt(1e18), + GasPrice: big.NewInt(1e9), + GasLimit: 500_000, + }, + testutiltypes.CallArgs{ + ContractABI: stakingCallerContract.ABI, + MethodName: "testDelegate", + Args: []interface{}{ + valAddr2.String(), + }, + }, + passCheck.WithExpEvents(staking.EventTypeDelegate), + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil(), "failed to advance block") + }) + + testcases := []struct { + // calltype is the opcode to use + calltype string + // expTxPass defines if executing transactions should be possible with the given opcode. + // Queries should work for all options. + expTxPass bool + }{ + {"call", true}, + // {"callcode", false}, //todo: fix this - stops working after bech32 prefix changes off of evmos - the validator being sent in as arg contains a wrong checksum + {"staticcall", false}, + {"delegatecall", false}, + } + + for _, tc := range testcases { + // NOTE: this is necessary because of Ginkgo behavior -- if not done, the value of tc + // inside the It block will always be the last entry in the testcases slice + testcase := tc + + It(fmt.Sprintf("should not execute transactions for calltype %q", testcase.calltype), func() { + delegator := s.keyring.GetKey(0) + + callArgs.MethodName = "testCallUndelegate" + callArgs.Args = []interface{}{ + valAddr2.String(), big.NewInt(1e18), testcase.calltype, + } + + checkArgs := execRevertedCheck + if testcase.expTxPass { + checkArgs = passCheck.WithExpEvents(staking.EventTypeUnbond) + } + + _, _, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + checkArgs, + ) + Expect(err).To(BeNil(), "error while calling the smart contract for calltype %s: %v", testcase.calltype, err) + Expect(s.network.NextBlock()).To(BeNil()) + + // check no delegations are unbonding + res, err := s.grpcHandler.GetDelegatorUnbondingDelegations(contractAccAddr.String()) + Expect(err).To(BeNil()) + + if testcase.expTxPass { + Expect(res.UnbondingResponses).To(HaveLen(1), "expected an unbonding delegation") + Expect(res.UnbondingResponses[0].ValidatorAddress).To(Equal(valAddr2.String()), "expected different validator address") + Expect(res.UnbondingResponses[0].DelegatorAddress).To(Equal(contractAccAddr.String()), "expected different delegator address") + } else { + Expect(res.UnbondingResponses).To(HaveLen(0), "expected no unbonding delegations for calltype %s", testcase.calltype) + } + }) + + It(fmt.Sprintf("should execute queries for calltype %q", testcase.calltype), func() { + delegator := s.keyring.GetKey(0) + + callArgs.MethodName = "testCallDelegation" + callArgs.Args = []interface{}{contractAddr, valAddr2.String(), testcase.calltype} + + _, ethRes, err := s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, passCheck) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + var delOut staking.DelegationOutput + err = s.precompile.UnpackIntoInterface(&delOut, staking.DelegationMethod, ethRes.Ret) + Expect(err).To(BeNil(), "error while unpacking the delegation output: %v", err) + Expect(delOut.Shares).To(Equal(math.LegacyNewDec(1).BigInt()), "expected different delegation shares") + Expect(delOut.Balance.Amount).To(Equal(big.NewInt(1e18)), "expected different delegation balance") + if testcase.calltype != "callcode" { // having some trouble with returning the denom from inline assembly but that's a very special edge case which might never be used + Expect(delOut.Balance.Denom).To(Equal(s.bondDenom), "expected different denomination") + } + }) + } + }) + + // NOTE: These tests were added to replicate a problematic behavior, that occurred when a contract + // adjusted the state in multiple subsequent function calls, which adjusted the EVM state as well as + // things from the Cosmos SDK state (e.g. a bank balance). + // The result was, that changes made to the Cosmos SDK state have been overwritten during the next function + // call, because the EVM state was not updated in between. + // + // This behavior was fixed by updating the EVM state after each function call. + Context("when triggering multiple state changes in one function", func() { + // delegationAmount is the amount to be delegated + delegationAmount := big.NewInt(1e18) + + BeforeEach(func() { + // Set up funding for the contract address. + // NOTE: we are first asserting that no balance exists and then check successful + // funding afterwards. + resBal, err := s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil(), "error while getting balance") + + balanceBefore := resBal.Balance + Expect(balanceBefore.Amount.Int64()).To(BeZero(), "expected contract balance to be 0 before funding") + + // Check no delegation exists from the contract to the validator + res, err := s.grpcHandler.GetDelegation(sdk.AccAddress(contractAddr.Bytes()).String(), valAddr.String()) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("delegation with delegator %s not found for validator %s", sdk.AccAddress(contractAddr.Bytes()), valAddr))) + Expect(res).To(BeNil()) + }) + + It("delegating and increasing counter should change the bank balance accordingly", func() { + delegator := s.keyring.GetKey(0) + + callArgs.MethodName = "testDelegateIncrementCounter" + callArgs.Args = []interface{}{valAddr.String()} + txArgs.GasLimit = 1e9 + txArgs.Amount = delegationAmount + + delegationCheck := passCheck.WithExpEvents( + staking.EventTypeDelegate, + ) + + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + delegationCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + res, err := s.grpcHandler.GetDelegation(sdk.AccAddress(contractAddr.Bytes()).String(), valAddr.String()) + Expect(err).To(BeNil()) + Expect(res.DelegationResponse).NotTo(BeNil()) + Expect(res.DelegationResponse.Delegation.GetShares().BigInt()).To(Equal(delegationAmount), "expected different delegation shares") + + resBal, err := s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil(), "error while getting balance") + + postBalance := resBal.Balance + Expect(postBalance.Amount.Int64()).To(BeZero(), "expected balance to be 0 after contract call") + }) + }) + + Context("when updating the stateDB prior to calling the precompile", func() { + It("should utilize the same contract balance to delegate", func() { + delegator := s.keyring.GetKey(0) + fundAmount := big.NewInt(1e18) + delegationAmount := big.NewInt(1e18) + + // fund the contract before calling the precompile + err = utils.FundAccountWithBaseDenom(s.factory, s.network, s.keyring.GetKey(0), contractAddr.Bytes(), math.NewIntFromBigInt(fundAmount)) + Expect(err).To(BeNil(), "error while funding account") + Expect(s.network.NextBlock()).To(BeNil()) + + resBal, err := s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil(), "error while getting balance") + + balanceAfterFunding := resBal.Balance + Expect(balanceAfterFunding.Amount.BigInt()).To(Equal(fundAmount), "expected different contract balance after funding") + + // delegate + callArgs.MethodName = "testDelegateAndFailCustomLogic" + callArgs.Args = []interface{}{valAddr.String()} + + txArgs.Amount = delegationAmount + txArgs.GasLimit = 1e9 + + delegationCheck := passCheck.WithExpEvents( + staking.EventTypeDelegate, + ) + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + delegationCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + resBal, err = s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil(), "error while getting balance") + balance := resBal.Balance + + Expect(balance.Amount.Int64()).To(BeZero(), "expected different contract balance after funding") + res, err := s.grpcHandler.GetDelegatorDelegations(sdk.AccAddress(contractAddr.Bytes()).String()) + Expect(err).To(BeNil()) + Expect(res.DelegationResponses).To(HaveLen(1), "expected one delegation") + Expect(res.DelegationResponses[0].Delegation.GetShares().BigInt()).To(Equal(big.NewInt(1e18)), "expected different delegation shares") + }) + + //nolint:dupl + It("should revert the contract balance to the original value when the custom logic after the precompile fails ", func() { + delegator := s.keyring.GetKey(0) + + callArgs.MethodName = "testDelegateAndFailCustomLogic" + callArgs.Args = []interface{}{valAddr.String()} + + txArgs.Amount = big.NewInt(2e18) + txArgs.GasLimit = 1e9 + + delegationCheck := defaultLogCheck.WithErrContains(vm.ErrExecutionReverted.Error()) + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + delegationCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + resBal, err := s.grpcHandler.GetBalanceFromBank(contractAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil(), "error while getting balance") + + balance := resBal.Balance + Expect(balance.Amount.Int64()).To(BeZero(), "expected different contract balance after funding") + res, err := s.grpcHandler.GetDelegatorDelegations(sdk.AccAddress(contractAddr.Bytes()).String()) + Expect(err).To(BeNil()) + Expect(res.DelegationResponses).To(HaveLen(0), "expected no delegations") + }) + }) + }) + + // These tests are used to check that when batching multiple state changing transactions + // in one block, both states (Cosmos and EVM) are updated or reverted correctly. + // + // For this purpose, we are deploying an ERC20 contract and updating StakingCaller.sol + // to include a method where an ERC20 balance is sent between accounts as well as + // an interaction with the staking precompile is made. + // + // There are ERC20 tokens minted to the address of the deployed StakingCaller contract, + // which will transfer these to the message sender when successfully executed. + var _ = Describe("Batching cosmos and eth interactions", func() { + const ( + erc20Name = "Test" + erc20Token = "TTT" + erc20Decimals = uint8(18) + ) + + var ( + // s is the precompile test suite to use for the tests + s *PrecompileTestSuite + // contractAddr is the address of the deployed StakingCaller contract + contractAddr common.Address + // contractAccAddr is the bech32 encoded account address of the deployed StakingCaller contract + contractAccAddr sdk.AccAddress + // stakingCallerContract is the contract instance calling into the staking precompile + stakingCallerContract evmtypes.CompiledContract + // erc20ContractAddr is the address of the deployed ERC20 contract + erc20ContractAddr common.Address + // erc20Contract is the compiled ERC20 contract + erc20Contract = compiledcontracts.ERC20MinterBurnerDecimalsContract + + // err is a standard error + err error + // execRevertedCheck is a standard log check for a reverted transaction + execRevertedCheck = defaultLogCheck.WithErrContains(vm.ErrExecutionReverted.Error()) + + // mintAmount is the amount of ERC20 tokens minted to the StakingCaller contract + mintAmount = big.NewInt(1e18) + // transferredAmount is the amount of ERC20 tokens to transfer during the tests + transferredAmount = big.NewInt(1234e9) + ) + + BeforeEach(func() { + s = NewPrecompileTestSuite(create, options...) + s.SetupTest() + delegator := s.keyring.GetKey(0) + + stakingCallerContract, err = testdata.LoadStakingCallerContract() + Expect(err).To(BeNil(), "error while loading the StakingCaller contract") + + // Deploy StakingCaller contract + contractAddr, err = s.factory.DeployContract( + delegator.Priv, + evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values + testutiltypes.ContractDeploymentData{ + Contract: stakingCallerContract, + }, + ) + Expect(err).To(BeNil(), "error while deploying the StakingCaller contract") + Expect(s.network.NextBlock()).To(BeNil()) + + contractAccAddr = sdk.AccAddress(contractAddr.Bytes()) + Expect(err).To(BeNil()) + + // Deploy ERC20 contract + erc20ContractAddr, err = s.factory.DeployContract( + delegator.Priv, + evmtypes.EvmTxArgs{}, // NOTE: passing empty struct to use default values + testutiltypes.ContractDeploymentData{ + Contract: erc20Contract, + ConstructorArgs: []interface{}{erc20Name, erc20Token, erc20Decimals}, + }, + ) + Expect(err).To(BeNil(), "error while deploying the ERC20 contract") + Expect(s.network.NextBlock()).To(BeNil()) + + // Mint tokens to the StakingCaller contract + mintArgs := testutiltypes.CallArgs{ + ContractABI: erc20Contract.ABI, + MethodName: "mint", + Args: []interface{}{contractAddr, mintAmount}, + } + + txArgs = evmtypes.EvmTxArgs{ + To: &erc20ContractAddr, + } + + mintCheck := testutil.LogCheckArgs{ + ABIEvents: erc20Contract.ABI.Events, + ExpEvents: []string{"Transfer"}, // minting produces a Transfer event + ExpPass: true, + } + + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, mintArgs, mintCheck) + Expect(err).To(BeNil(), "error while minting tokens to the StakingCaller contract") + Expect(s.network.NextBlock()).To(BeNil()) + + // Check that the StakingCaller contract has the correct balance + erc20Balance := s.network.App.GetErc20Keeper().BalanceOf(s.network.GetContext(), erc20Contract.ABI, erc20ContractAddr, contractAddr) + Expect(erc20Balance).To(Equal(mintAmount), "expected different ERC20 balance for the StakingCaller contract") + + // populate default call args + callArgs = testutiltypes.CallArgs{ + ContractABI: stakingCallerContract.ABI, + MethodName: "callERC20AndDelegate", + } + + txArgs.To = &contractAddr + + // populate default log check args + defaultLogCheck = testutil.LogCheckArgs{ + ABIEvents: s.precompile.Events, + } + execRevertedCheck = defaultLogCheck.WithErrContains(vm.ErrExecutionReverted.Error()) + passCheck = defaultLogCheck.WithExpPass(true) + }) + + Describe("when batching multiple transactions", func() { + // validator is the validator address used for testing + var validator sdk.ValAddress + + BeforeEach(func() { + delegator := s.keyring.GetKey(0) + + res, err := s.grpcHandler.GetDelegatorDelegations(delegator.AccAddr.String()) + Expect(err).To(BeNil()) + Expect(res.DelegationResponses).ToNot(HaveLen(0), "expected address to have delegations") + + validator, err = sdk.ValAddressFromBech32(res.DelegationResponses[0].Delegation.ValidatorAddress) + Expect(err).To(BeNil()) + + _ = erc20ContractAddr + + // delegate + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + evmtypes.EvmTxArgs{ + To: &contractAddr, + Amount: big.NewInt(1e18), + GasPrice: big.NewInt(1e9), + GasLimit: 500_000, + }, + testutiltypes.CallArgs{ + ContractABI: stakingCallerContract.ABI, + MethodName: "testDelegate", + Args: []interface{}{ + validator.String(), + }, + }, + passCheck.WithExpEvents(staking.EventTypeDelegate), + ) + Expect(err).To(BeNil(), "error while calling the StakingCaller contract") + Expect(s.network.NextBlock()).To(BeNil()) + }) + + It("should revert both states if a staking transaction fails", func() { + delegator := s.keyring.GetKey(0) + + res, err := s.grpcHandler.GetDelegation(contractAccAddr.String(), validator.String()) + Expect(err).To(BeNil()) + Expect(res.DelegationResponse).NotTo(BeNil()) + + delegationPre := res.DelegationResponse.Delegation + sharesPre := delegationPre.GetShares() + + // NOTE: passing an invalid validator address here should fail AFTER the erc20 transfer was made in the smart contract. + // Therefore this can be used to check that both EVM and Cosmos states are reverted correctly. + callArgs.Args = []interface{}{erc20ContractAddr, "invalid validator", transferredAmount} + + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + execRevertedCheck) + Expect(err).To(BeNil(), "expected error while calling the smart contract") + Expect(s.network.NextBlock()).To(BeNil()) + + res, err = s.grpcHandler.GetDelegation(contractAccAddr.String(), validator.String()) + Expect(err).To(BeNil()) + Expect(res.DelegationResponse).NotTo(BeNil()) + delegationPost := res.DelegationResponse.Delegation + sharesPost := delegationPost.GetShares() + erc20BalancePost := s.network.App.GetErc20Keeper().BalanceOf(s.network.GetContext(), erc20Contract.ABI, erc20ContractAddr, delegator.Addr) + + Expect(sharesPost).To(Equal(sharesPre), "expected shares to be equal when reverting state") + Expect(erc20BalancePost.Int64()).To(BeZero(), "expected erc20 balance of target address to be zero when reverting state") + }) + + It("should revert both states if an ERC20 transaction fails", func() { + delegator := s.keyring.GetKey(0) + + res, err := s.grpcHandler.GetDelegation(contractAccAddr.String(), validator.String()) + Expect(err).To(BeNil()) + Expect(res.DelegationResponse).NotTo(BeNil()) + + delegationPre := res.DelegationResponse.Delegation + sharesPre := delegationPre.GetShares() + + // NOTE: trying to transfer more than the balance of the contract should fail in the smart contract. + // Therefore this can be used to check that both EVM and Cosmos states are reverted correctly. + moreThanMintedAmount := new(big.Int).Add(mintAmount, big.NewInt(1)) + callArgs.Args = []interface{}{erc20ContractAddr, s.network.GetValidators()[0].OperatorAddress, moreThanMintedAmount} + + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + execRevertedCheck) + Expect(err).To(BeNil(), "expected error while calling the smart contract") + Expect(s.network.NextBlock()).To(BeNil()) + + res, err = s.grpcHandler.GetDelegation(contractAccAddr.String(), validator.String()) + Expect(err).To(BeNil()) + Expect(res.DelegationResponse).NotTo(BeNil()) + delegationPost := res.DelegationResponse.Delegation + sharesPost := delegationPost.GetShares() + erc20BalancePost := s.network.App.GetErc20Keeper().BalanceOf(s.network.GetContext(), erc20Contract.ABI, erc20ContractAddr, delegator.Addr) + + Expect(sharesPost).To(Equal(sharesPre), "expected shares to be equal when reverting state") + Expect(erc20BalancePost.Int64()).To(BeZero(), "expected erc20 balance of target address to be zero when reverting state") + }) + + It("should persist changes in both the cosmos and eth states", func() { + delegator := s.keyring.GetKey(0) + + res, err := s.grpcHandler.GetDelegation(contractAccAddr.String(), validator.String()) + Expect(err).To(BeNil()) + Expect(res.DelegationResponse).NotTo(BeNil()) + + delegationPre := res.DelegationResponse.Delegation + sharesPre := delegationPre.GetShares() + + // NOTE: trying to transfer more than the balance of the contract should fail in the smart contract. + // Therefore this can be used to check that both EVM and Cosmos states are reverted correctly. + callArgs.Args = []interface{}{erc20ContractAddr, s.network.GetValidators()[0].OperatorAddress, transferredAmount} + + // Build combined map of ABI events to check for both ERC20 Transfer event as well as precompile events + combinedABIEvents := s.precompile.Events + combinedABIEvents["Transfer"] = erc20Contract.ABI.Events["Transfer"] + + successCheck := passCheck. + WithABIEvents(combinedABIEvents). + WithExpEvents( + "Transfer", staking.EventTypeDelegate, + ) + + txArgs.Amount = big.NewInt(1e18) + txArgs.GasPrice = big.NewInt(1e9) + txArgs.GasLimit = 500_000 + _, _, err = s.factory.CallContractAndCheckLogs( + delegator.Priv, + txArgs, callArgs, + successCheck) + Expect(err).ToNot(HaveOccurred(), "error while calling the smart contract") + Expect(s.network.NextBlock()).To(BeNil()) + + res, err = s.grpcHandler.GetDelegation(contractAccAddr.String(), validator.String()) + Expect(err).To(BeNil()) + Expect(res.DelegationResponse).NotTo(BeNil(), + "expected delegation from %s to validator %s to be found after calling the smart contract", + delegator.AccAddr.String(), validator.String(), + ) + delegationPost := res.DelegationResponse.Delegation + sharesPost := delegationPost.GetShares() + erc20BalancePost := s.network.App.GetErc20Keeper().BalanceOf(s.network.GetContext(), erc20Contract.ABI, erc20ContractAddr, delegator.Addr) + + Expect(sharesPost.GT(sharesPre)).To(BeTrue(), "expected shares to be more than before") + Expect(erc20BalancePost).To(Equal(transferredAmount), "expected different erc20 balance of target address") + }) + }) + }) + + // Run Ginkgo integration tests + RegisterFailHandler(Fail) + RunSpecs(t, "Distribution Precompile Suite") +} diff --git a/precompiles/staking/query_test.go b/tests/integration/precompiles/staking/test_query.go similarity index 99% rename from precompiles/staking/query_test.go rename to tests/integration/precompiles/staking/test_query.go index d6b72d97f..f25ab74a9 100644 --- a/precompiles/staking/query_test.go +++ b/tests/integration/precompiles/staking/test_query.go @@ -1,4 +1,4 @@ -package staking_test +package staking import ( "fmt" @@ -206,7 +206,7 @@ func (s *PrecompileTestSuite) TestUnbondingDelegation() { valAddr, err := sdk.ValAddressFromBech32(s.network.GetValidators()[0].GetOperator()) s.Require().NoError(err) - _, _, err = s.network.App.StakingKeeper.Undelegate(s.network.GetContext(), s.keyring.GetAddr(0).Bytes(), valAddr, math.LegacyNewDec(1)) + _, _, err = s.network.App.GetStakingKeeper().Undelegate(s.network.GetContext(), s.keyring.GetAddr(0).Bytes(), valAddr, math.LegacyNewDec(1)) s.Require().NoError(err) bz, err := s.precompile.UnbondingDelegation(s.network.GetContext(), contract, &method, tc.malleate(s.network.GetValidators()[0].OperatorAddress)) diff --git a/precompiles/staking/setup_test.go b/tests/integration/precompiles/staking/test_setup.go similarity index 72% rename from precompiles/staking/setup_test.go rename to tests/integration/precompiles/staking/test_setup.go index b0f940639..522a7a71f 100644 --- a/precompiles/staking/setup_test.go +++ b/tests/integration/precompiles/staking/test_setup.go @@ -1,16 +1,14 @@ -package staking_test +package staking import ( - "testing" - "github.com/stretchr/testify/suite" "github.com/cosmos/evm/precompiles/staking" testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + testkeyring "github.com/cosmos/evm/testutil/keyring" sdkmath "cosmossdk.io/math" @@ -22,6 +20,8 @@ import ( type PrecompileTestSuite struct { suite.Suite + create network.CreateEvmApp + options []network.ConfigOption network *network.UnitTestNetwork factory factory.TxFactory grpcHandler grpc.Handler @@ -32,8 +32,11 @@ type PrecompileTestSuite struct { customGenesis bool } -func TestPrecompileUnitTestSuite(t *testing.T) { - suite.Run(t, new(PrecompileTestSuite)) +func NewPrecompileTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *PrecompileTestSuite { + return &PrecompileTestSuite{ + create: create, + options: options, + } } func (s *PrecompileTestSuite) SetupTest() { @@ -56,14 +59,13 @@ func (s *PrecompileTestSuite) SetupTest() { if s.customGenesis { cfgOpts = append(cfgOpts, network.WithCustomGenesis(customGenesis)) } - nw := network.NewUnitTestNetwork( - cfgOpts..., - ) + options := append(s.options, cfgOpts...) + nw := network.NewUnitTestNetwork(s.create, options...) grpcHandler := grpc.NewIntegrationHandler(nw) txFactory := factory.New(nw, grpcHandler) ctx := nw.GetContext() - sk := nw.App.StakingKeeper + sk := nw.App.GetStakingKeeper() bondDenom, err := sk.BondDenom(ctx) if err != nil { panic(err) @@ -76,7 +78,7 @@ func (s *PrecompileTestSuite) SetupTest() { s.network = nw if s.precompile, err = staking.NewPrecompile( - *s.network.App.StakingKeeper, + *s.network.App.GetStakingKeeper(), ); err != nil { panic(err) } diff --git a/precompiles/staking/staking_test.go b/tests/integration/precompiles/staking/test_staking.go similarity index 85% rename from precompiles/staking/staking_test.go rename to tests/integration/precompiles/staking/test_staking.go index 5d4706f74..ce665c4e2 100644 --- a/precompiles/staking/staking_test.go +++ b/tests/integration/precompiles/staking/test_staking.go @@ -1,4 +1,4 @@ -package staking_test +package staking import ( "math/big" @@ -10,11 +10,11 @@ import ( "github.com/ethereum/go-ethereum/core/vm" "github.com/holiman/uint256" - chainutil "github.com/cosmos/evm/evmd/testutil" "github.com/cosmos/evm/precompiles/staking" "github.com/cosmos/evm/precompiles/testutil" + chainutil "github.com/cosmos/evm/testutil" testconstants "github.com/cosmos/evm/testutil/constants" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" + "github.com/cosmos/evm/testutil/keyring" "github.com/cosmos/evm/x/vm/statedb" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -128,7 +128,7 @@ func (s *PrecompileTestSuite) TestRun() { var ctx sdk.Context testcases := []struct { name string - malleate func(delegator testkeyring.Key) []byte + malleate func(delegator keyring.Key) []byte gas uint64 readOnly bool expPass bool @@ -136,7 +136,7 @@ func (s *PrecompileTestSuite) TestRun() { }{ { "fail - contract gas limit is < gas cost to run a query / tx", - func(delegator testkeyring.Key) []byte { + func(delegator keyring.Key) []byte { input, err := s.precompile.Pack( staking.DelegateMethod, delegator.Addr, @@ -153,7 +153,7 @@ func (s *PrecompileTestSuite) TestRun() { }, { "pass - delegate transaction", - func(delegator testkeyring.Key) []byte { + func(delegator keyring.Key) []byte { input, err := s.precompile.Pack( staking.DelegateMethod, delegator.Addr, @@ -170,7 +170,7 @@ func (s *PrecompileTestSuite) TestRun() { }, { "pass - undelegate transaction", - func(delegator testkeyring.Key) []byte { + func(delegator keyring.Key) []byte { input, err := s.precompile.Pack( staking.UndelegateMethod, delegator.Addr, @@ -187,7 +187,7 @@ func (s *PrecompileTestSuite) TestRun() { }, { "pass - redelegate transaction", - func(delegator testkeyring.Key) []byte { + func(delegator keyring.Key) []byte { input, err := s.precompile.Pack( staking.RedelegateMethod, delegator.Addr, @@ -205,7 +205,7 @@ func (s *PrecompileTestSuite) TestRun() { }, { "pass - cancel unbonding delegation transaction", - func(delegator testkeyring.Key) []byte { + func(delegator keyring.Key) []byte { valAddr, err := sdk.ValAddressFromBech32(s.network.GetValidators()[0].GetOperator()) s.Require().NoError(err) // add unbonding delegation to staking keeper @@ -216,16 +216,16 @@ func (s *PrecompileTestSuite) TestRun() { time.Now().Add(time.Hour), math.NewInt(1000), 0, - s.network.App.StakingKeeper.ValidatorAddressCodec(), - s.network.App.AccountKeeper.AddressCodec(), + s.network.App.GetStakingKeeper().ValidatorAddressCodec(), + s.network.App.GetAccountKeeper().AddressCodec(), ) - err = s.network.App.StakingKeeper.SetUnbondingDelegation(ctx, ubd) + err = s.network.App.GetStakingKeeper().SetUnbondingDelegation(ctx, ubd) s.Require().NoError(err, "failed to set unbonding delegation") // Needs to be called after setting unbonding delegation // In order to mimic the coins being added to the unboding pool coin := sdk.NewCoin(testconstants.ExampleAttoDenom, math.NewInt(1000)) - err = s.network.App.BankKeeper.SendCoinsFromModuleToModule(ctx, stakingtypes.BondedPoolName, stakingtypes.NotBondedPoolName, sdk.Coins{coin}) + err = s.network.App.GetBankKeeper().SendCoinsFromModuleToModule(ctx, stakingtypes.BondedPoolName, stakingtypes.NotBondedPoolName, sdk.Coins{coin}) s.Require().NoError(err, "failed to send coins from module to module") input, err := s.precompile.Pack( @@ -245,7 +245,7 @@ func (s *PrecompileTestSuite) TestRun() { }, { "pass - delegation query", - func(delegator testkeyring.Key) []byte { + func(delegator keyring.Key) []byte { input, err := s.precompile.Pack( staking.DelegationMethod, delegator.Addr, @@ -261,7 +261,7 @@ func (s *PrecompileTestSuite) TestRun() { }, { "pass - validator query", - func(_ testkeyring.Key) []byte { + func(_ keyring.Key) []byte { valAddr, err := sdk.ValAddressFromBech32(s.network.GetValidators()[0].OperatorAddress) s.Require().NoError(err) @@ -279,7 +279,7 @@ func (s *PrecompileTestSuite) TestRun() { }, { "pass - redelgation query", - func(delegator testkeyring.Key) []byte { + func(delegator keyring.Key) []byte { valAddr1, err := sdk.ValAddressFromBech32(s.network.GetValidators()[0].GetOperator()) s.Require().NoError(err) valAddr2, err := sdk.ValAddressFromBech32(s.network.GetValidators()[1].GetOperator()) @@ -294,11 +294,11 @@ func (s *PrecompileTestSuite) TestRun() { math.NewInt(1000), math.LegacyNewDec(1), 0, - s.network.App.StakingKeeper.ValidatorAddressCodec(), - s.network.App.AccountKeeper.AddressCodec(), + s.network.App.GetStakingKeeper().ValidatorAddressCodec(), + s.network.App.GetAccountKeeper().AddressCodec(), ) - err = s.network.App.StakingKeeper.SetRedelegation(ctx, redelegation) + err = s.network.App.GetStakingKeeper().SetRedelegation(ctx, redelegation) s.Require().NoError(err, "failed to set redelegation") input, err := s.precompile.Pack( @@ -317,7 +317,7 @@ func (s *PrecompileTestSuite) TestRun() { }, { "pass - delegation query - read only", - func(delegator testkeyring.Key) []byte { + func(delegator keyring.Key) []byte { input, err := s.precompile.Pack( staking.DelegationMethod, delegator.Addr, @@ -333,7 +333,7 @@ func (s *PrecompileTestSuite) TestRun() { }, { "pass - unbonding delegation query", - func(delegator testkeyring.Key) []byte { + func(delegator keyring.Key) []byte { valAddr, err := sdk.ValAddressFromBech32(s.network.GetValidators()[0].GetOperator()) s.Require().NoError(err) // add unbonding delegation to staking keeper @@ -344,16 +344,16 @@ func (s *PrecompileTestSuite) TestRun() { time.Now().Add(time.Hour), math.NewInt(1000), 0, - s.network.App.StakingKeeper.ValidatorAddressCodec(), - s.network.App.AccountKeeper.AddressCodec(), + s.network.App.GetStakingKeeper().ValidatorAddressCodec(), + s.network.App.GetAccountKeeper().AddressCodec(), ) - err = s.network.App.StakingKeeper.SetUnbondingDelegation(ctx, ubd) + err = s.network.App.GetStakingKeeper().SetUnbondingDelegation(ctx, ubd) s.Require().NoError(err, "failed to set unbonding delegation") // Needs to be called after setting unbonding delegation // In order to mimic the coins being added to the unboding pool coin := sdk.NewCoin(testconstants.ExampleAttoDenom, math.NewInt(1000)) - err = s.network.App.BankKeeper.SendCoinsFromModuleToModule(ctx, stakingtypes.BondedPoolName, stakingtypes.NotBondedPoolName, sdk.Coins{coin}) + err = s.network.App.GetBankKeeper().SendCoinsFromModuleToModule(ctx, stakingtypes.BondedPoolName, stakingtypes.NotBondedPoolName, sdk.Coins{coin}) s.Require().NoError(err, "failed to send coins from module to module") input, err := s.precompile.Pack( @@ -371,7 +371,7 @@ func (s *PrecompileTestSuite) TestRun() { }, { "fail - delegate method - read only", - func(delegator testkeyring.Key) []byte { + func(delegator keyring.Key) []byte { input, err := s.precompile.Pack( staking.DelegateMethod, delegator.Addr, @@ -388,7 +388,7 @@ func (s *PrecompileTestSuite) TestRun() { }, { "fail - invalid method", - func(_ testkeyring.Key) []byte { + func(_ keyring.Key) []byte { return []byte("invalid") }, 1, // use gas > 0 to avoid doing gas estimation @@ -404,7 +404,7 @@ func (s *PrecompileTestSuite) TestRun() { s.SetupTest() ctx = s.network.GetContext().WithBlockTime(time.Now()) - baseFee := s.network.App.EVMKeeper.GetBaseFee(ctx) + baseFee := s.network.App.GetEVMKeeper().GetBaseFee(ctx) delegator := s.keyring.GetKey(0) @@ -432,21 +432,21 @@ func (s *PrecompileTestSuite) TestRun() { // Instantiate config proposerAddress := ctx.BlockHeader().ProposerAddress - cfg, err := s.network.App.EVMKeeper.EVMConfig(ctx, proposerAddress) + cfg, err := s.network.App.GetEVMKeeper().EVMConfig(ctx, proposerAddress) s.Require().NoError(err, "failed to instantiate EVM config") // Instantiate EVM headerHash := ctx.HeaderHash() stDB := statedb.New( ctx, - s.network.App.EVMKeeper, + s.network.App.GetEVMKeeper(), statedb.NewEmptyTxConfig(common.BytesToHash(headerHash)), ) - evm := s.network.App.EVMKeeper.NewEVM( + evm := s.network.App.GetEVMKeeper().NewEVM( ctx, *msg, cfg, nil, stDB, ) - precompiles, found, err := s.network.App.EVMKeeper.GetPrecompileInstance(ctx, contractAddr) + precompiles, found, err := s.network.App.GetEVMKeeper().GetPrecompileInstance(ctx, contractAddr) s.Require().NoError(err, "failed to instantiate precompile") s.Require().True(found, "not found precompile") evm.WithPrecompiles(precompiles.Map) @@ -477,7 +477,7 @@ func (s *PrecompileTestSuite) TestCMS() { var ctx sdk.Context testcases := []struct { name string - malleate func(delegator testkeyring.Key) []byte + malleate func(delegator keyring.Key) []byte gas uint64 expPass bool expKeeperPass bool @@ -485,7 +485,7 @@ func (s *PrecompileTestSuite) TestCMS() { }{ { "fail - contract gas limit is < gas cost to run a query / tx", - func(delegator testkeyring.Key) []byte { + func(delegator keyring.Key) []byte { input, err := s.precompile.Pack( staking.DelegateMethod, delegator.Addr, @@ -502,7 +502,7 @@ func (s *PrecompileTestSuite) TestCMS() { }, { "pass - delegate transaction", - func(delegator testkeyring.Key) []byte { + func(delegator keyring.Key) []byte { input, err := s.precompile.Pack( staking.DelegateMethod, delegator.Addr, @@ -519,7 +519,7 @@ func (s *PrecompileTestSuite) TestCMS() { }, { "pass - undelegate transaction", - func(delegator testkeyring.Key) []byte { + func(delegator keyring.Key) []byte { input, err := s.precompile.Pack( staking.UndelegateMethod, delegator.Addr, @@ -536,7 +536,7 @@ func (s *PrecompileTestSuite) TestCMS() { }, { "pass - redelegate transaction", - func(delegator testkeyring.Key) []byte { + func(delegator keyring.Key) []byte { input, err := s.precompile.Pack( staking.RedelegateMethod, delegator.Addr, @@ -554,7 +554,7 @@ func (s *PrecompileTestSuite) TestCMS() { }, { "pass - cancel unbonding delegation transaction", - func(delegator testkeyring.Key) []byte { + func(delegator keyring.Key) []byte { valAddr, err := sdk.ValAddressFromBech32(s.network.GetValidators()[0].GetOperator()) s.Require().NoError(err) // add unbonding delegation to staking keeper @@ -565,16 +565,16 @@ func (s *PrecompileTestSuite) TestCMS() { time.Now().Add(time.Hour), math.NewInt(1000), 0, - s.network.App.StakingKeeper.ValidatorAddressCodec(), - s.network.App.AccountKeeper.AddressCodec(), + s.network.App.GetStakingKeeper().ValidatorAddressCodec(), + s.network.App.GetAccountKeeper().AddressCodec(), ) - err = s.network.App.StakingKeeper.SetUnbondingDelegation(ctx, ubd) + err = s.network.App.GetStakingKeeper().SetUnbondingDelegation(ctx, ubd) s.Require().NoError(err, "failed to set unbonding delegation") // Needs to be called after setting unbonding delegation // In order to mimic the coins being added to the unboding pool coin := sdk.NewCoin(testconstants.ExampleAttoDenom, math.NewInt(1000)) - err = s.network.App.BankKeeper.SendCoinsFromModuleToModule(ctx, stakingtypes.BondedPoolName, stakingtypes.NotBondedPoolName, sdk.Coins{coin}) + err = s.network.App.GetBankKeeper().SendCoinsFromModuleToModule(ctx, stakingtypes.BondedPoolName, stakingtypes.NotBondedPoolName, sdk.Coins{coin}) s.Require().NoError(err, "failed to send coins from module to module") input, err := s.precompile.Pack( @@ -594,7 +594,7 @@ func (s *PrecompileTestSuite) TestCMS() { }, { "pass - delegation query", - func(delegator testkeyring.Key) []byte { + func(delegator keyring.Key) []byte { input, err := s.precompile.Pack( staking.DelegationMethod, delegator.Addr, @@ -610,7 +610,7 @@ func (s *PrecompileTestSuite) TestCMS() { }, { "pass - validator query", - func(_ testkeyring.Key) []byte { + func(_ keyring.Key) []byte { valAddr, err := sdk.ValAddressFromBech32(s.network.GetValidators()[0].OperatorAddress) s.Require().NoError(err) @@ -628,7 +628,7 @@ func (s *PrecompileTestSuite) TestCMS() { }, { "pass - redelgation query", - func(delegator testkeyring.Key) []byte { + func(delegator keyring.Key) []byte { valAddr1, err := sdk.ValAddressFromBech32(s.network.GetValidators()[0].GetOperator()) s.Require().NoError(err) valAddr2, err := sdk.ValAddressFromBech32(s.network.GetValidators()[1].GetOperator()) @@ -643,11 +643,11 @@ func (s *PrecompileTestSuite) TestCMS() { math.NewInt(1000), math.LegacyNewDec(1), 0, - s.network.App.StakingKeeper.ValidatorAddressCodec(), - s.network.App.AccountKeeper.AddressCodec(), + s.network.App.GetStakingKeeper().ValidatorAddressCodec(), + s.network.App.GetAccountKeeper().AddressCodec(), ) - err = s.network.App.StakingKeeper.SetRedelegation(ctx, redelegation) + err = s.network.App.GetStakingKeeper().SetRedelegation(ctx, redelegation) s.Require().NoError(err, "failed to set redelegation") input, err := s.precompile.Pack( @@ -666,7 +666,7 @@ func (s *PrecompileTestSuite) TestCMS() { }, { "pass - delegation query - read only", - func(delegator testkeyring.Key) []byte { + func(delegator keyring.Key) []byte { input, err := s.precompile.Pack( staking.DelegationMethod, delegator.Addr, @@ -682,7 +682,7 @@ func (s *PrecompileTestSuite) TestCMS() { }, { "pass - unbonding delegation query", - func(delegator testkeyring.Key) []byte { + func(delegator keyring.Key) []byte { valAddr, err := sdk.ValAddressFromBech32(s.network.GetValidators()[0].GetOperator()) s.Require().NoError(err) // add unbonding delegation to staking keeper @@ -693,16 +693,16 @@ func (s *PrecompileTestSuite) TestCMS() { time.Now().Add(time.Hour), math.NewInt(1000), 0, - s.network.App.StakingKeeper.ValidatorAddressCodec(), - s.network.App.AccountKeeper.AddressCodec(), + s.network.App.GetStakingKeeper().ValidatorAddressCodec(), + s.network.App.GetAccountKeeper().AddressCodec(), ) - err = s.network.App.StakingKeeper.SetUnbondingDelegation(ctx, ubd) + err = s.network.App.GetStakingKeeper().SetUnbondingDelegation(ctx, ubd) s.Require().NoError(err, "failed to set unbonding delegation") // Needs to be called after setting unbonding delegation // In order to mimic the coins being added to the unboding pool coin := sdk.NewCoin(testconstants.ExampleAttoDenom, math.NewInt(1000)) - err = s.network.App.BankKeeper.SendCoinsFromModuleToModule(ctx, stakingtypes.BondedPoolName, stakingtypes.NotBondedPoolName, sdk.Coins{coin}) + err = s.network.App.GetBankKeeper().SendCoinsFromModuleToModule(ctx, stakingtypes.BondedPoolName, stakingtypes.NotBondedPoolName, sdk.Coins{coin}) s.Require().NoError(err, "failed to send coins from module to module") input, err := s.precompile.Pack( @@ -720,7 +720,7 @@ func (s *PrecompileTestSuite) TestCMS() { }, { "fail - invalid method", - func(_ testkeyring.Key) []byte { + func(_ keyring.Key) []byte { return []byte("invalid") }, 100000, // use gas > 0 to avoid doing gas estimation @@ -737,12 +737,12 @@ func (s *PrecompileTestSuite) TestCMS() { ctx = s.network.GetContext().WithBlockTime(time.Now()) cms := &testutil.TrackingMultiStore{ - Store: s.network.App.BaseApp.CommitMultiStore().CacheMultiStore(), + Store: s.network.App.GetBaseApp().CommitMultiStore().CacheMultiStore(), Writes: 0, HistoricalStores: nil, } ctx = ctx.WithMultiStore(cms) - baseFee := s.network.App.EVMKeeper.GetBaseFee(ctx) + baseFee := s.network.App.GetEVMKeeper().GetBaseFee(ctx) delegator := s.keyring.GetKey(0) @@ -771,7 +771,7 @@ func (s *PrecompileTestSuite) TestCMS() { signedMsg, err := s.factory.SignMsgEthereumTx(s.keyring.GetPrivKey(0), msgEthereumTx) s.Require().NoError(err, "failed to sign Ethereum message") - resp, err := s.network.App.EVMKeeper.EthereumTx(ctx, &signedMsg) + resp, err := s.network.App.GetEVMKeeper().EthereumTx(ctx, &signedMsg) // Check results if tc.expPass { diff --git a/precompiles/staking/tx_test.go b/tests/integration/precompiles/staking/test_tx.go similarity index 97% rename from precompiles/staking/tx_test.go rename to tests/integration/precompiles/staking/test_tx.go index 345168354..2a85f739b 100644 --- a/precompiles/staking/tx_test.go +++ b/tests/integration/precompiles/staking/test_tx.go @@ -1,4 +1,4 @@ -package staking_test +package staking import ( "encoding/base64" @@ -12,7 +12,7 @@ import ( cmn "github.com/cosmos/evm/precompiles/common" "github.com/cosmos/evm/precompiles/staking" "github.com/cosmos/evm/precompiles/testutil" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" + testkeyring "github.com/cosmos/evm/testutil/keyring" cosmosevmutiltx "github.com/cosmos/evm/testutil/tx" "github.com/cosmos/evm/x/vm/statedb" @@ -280,7 +280,7 @@ func (s *PrecompileTestSuite) TestCreateValidator() { s.Require().Equal(value, createValidatorEvent.Value) // check the validator state - validator, err := s.network.App.StakingKeeper.GetValidator(s.network.GetContext(), validatorAddress.Bytes()) + validator, err := s.network.App.GetStakingKeeper().GetValidator(s.network.GetContext(), validatorAddress.Bytes()) s.Require().NoError(err) s.Require().NotNil(validator, "expected validator not to be nil") expRate := math.LegacyNewDecFromBigIntWithPrec(commission.Rate, math.LegacyPrecision) @@ -322,7 +322,7 @@ func (s *PrecompileTestSuite) TestCreateValidator() { } else { s.Require().NoError(err) // query the validator in the staking keeper - validator, err := s.network.App.StakingKeeper.Validator(ctx, validator.AccAddr.Bytes()) + validator, err := s.network.App.GetStakingKeeper().Validator(ctx, validator.AccAddr.Bytes()) s.Require().NoError(err) s.Require().NotNil(validator, "expected validator not to be nil") @@ -681,7 +681,7 @@ func (s *PrecompileTestSuite) TestEditValidator() { s.Require().NoError(err) // query the validator in the staking keeper - validator, err := s.network.App.StakingKeeper.Validator(ctx, valAddr.Bytes()) + validator, err := s.network.App.GetStakingKeeper().Validator(ctx, valAddr.Bytes()) s.Require().NoError(err) s.Require().NotNil(validator, "expected validator not to be nil") @@ -844,7 +844,7 @@ func (s *PrecompileTestSuite) TestDelegate() { // query the delegation in the staking keeper valAddr, valErr := sdk.ValAddressFromBech32(s.network.GetValidators()[0].OperatorAddress) s.Require().NoError(valErr) - delegation, delErr := s.network.App.StakingKeeper.Delegation(ctx, delegator.AccAddr, valAddr) + delegation, delErr := s.network.App.GetStakingKeeper().Delegation(ctx, delegator.AccAddr, valAddr) s.Require().NoError(delErr) if tc.expError { s.Require().ErrorContains(err, tc.errContains) @@ -950,7 +950,7 @@ func (s *PrecompileTestSuite) TestUndelegate() { s.Require().Len(args, 1) completionTime, ok := args[0].(int64) s.Require().True(ok, "completion time type %T", args[0]) - params, err := s.network.App.StakingKeeper.GetParams(ctx) + params, err := s.network.App.GetStakingKeeper().GetParams(ctx) s.Require().NoError(err) expCompletionTime := ctx.BlockTime().Add(params.UnbondingTime).UTC().Unix() s.Require().Equal(expCompletionTime, completionTime) @@ -980,7 +980,7 @@ func (s *PrecompileTestSuite) TestUndelegate() { bz, err := s.precompile.Undelegate(ctx, contract, stDB, &method, undelegateArgs) // query the unbonding delegations in the staking keeper - undelegations, _ := s.network.App.StakingKeeper.GetAllUnbondingDelegations(ctx, delegator.AccAddr) + undelegations, _ := s.network.App.GetStakingKeeper().GetAllUnbondingDelegations(ctx, delegator.AccAddr) if tc.expError { s.Require().ErrorContains(err, tc.errContains) @@ -1101,7 +1101,7 @@ func (s *PrecompileTestSuite) TestRedelegate() { s.Require().Len(args, 1) completionTime, ok := args[0].(int64) s.Require().True(ok, "completion time type %T", args[0]) - params, err := s.network.App.StakingKeeper.GetParams(ctx) + params, err := s.network.App.GetStakingKeeper().GetParams(ctx) s.Require().NoError(err) expCompletionTime := ctx.BlockTime().Add(params.UnbondingTime).UTC().Unix() s.Require().Equal(expCompletionTime, completionTime) @@ -1129,7 +1129,7 @@ func (s *PrecompileTestSuite) TestRedelegate() { bz, err := s.precompile.Redelegate(ctx, contract, s.network.GetStateDB(), &method, redelegateArgs) // query the redelegations in the staking keeper - redelegations, redelErr := s.network.App.StakingKeeper.GetRedelegations(ctx, delegator.AccAddr, 5) + redelegations, redelErr := s.network.App.GetStakingKeeper().GetRedelegations(ctx, delegator.AccAddr, 5) s.Require().NoError(redelErr) if tc.expError { @@ -1303,7 +1303,7 @@ func (s *PrecompileTestSuite) TestCancelUnbondingDelegation() { valAddr, err := sdk.ValAddressFromBech32(s.network.GetValidators()[0].GetOperator()) s.Require().NoError(err) - _, err = s.network.App.StakingKeeper.GetDelegation(ctx, delegator.AccAddr, valAddr) + _, err = s.network.App.GetStakingKeeper().GetDelegation(ctx, delegator.AccAddr, valAddr) s.Require().Error(err) s.Require().Contains("no delegation for (address, validator) tuple", err.Error()) @@ -1311,7 +1311,7 @@ func (s *PrecompileTestSuite) TestCancelUnbondingDelegation() { s.Require().NoError(err) tc.postCheck(bz) - delegation, err := s.network.App.StakingKeeper.GetDelegation(ctx, delegator.AccAddr, valAddr) + delegation, err := s.network.App.GetStakingKeeper().GetDelegation(ctx, delegator.AccAddr, valAddr) s.Require().NoError(err) s.Require().Equal(delegation.DelegatorAddress, delegator.AccAddr.String()) diff --git a/precompiles/staking/utils_test.go b/tests/integration/precompiles/staking/test_utils.go similarity index 98% rename from precompiles/staking/utils_test.go rename to tests/integration/precompiles/staking/test_utils.go index 4861c53f3..9ed5a34e5 100644 --- a/precompiles/staking/utils_test.go +++ b/tests/integration/precompiles/staking/test_utils.go @@ -1,4 +1,4 @@ -package staking_test +package staking import ( "encoding/base64" @@ -118,7 +118,7 @@ func (s *PrecompileTestSuite) setupRedelegations(ctx sdk.Context, redelAmt *big. Amount: sdk.NewCoin(s.bondDenom, math.NewIntFromBigInt(redelAmt)), } - msgSrv := stakingkeeper.NewMsgServerImpl(s.network.App.StakingKeeper) + msgSrv := stakingkeeper.NewMsgServerImpl(s.network.App.GetStakingKeeper()) // create 2 entries for same redelegation for i := 0; i < 2; i++ { if _, err := msgSrv.BeginRedelegate(ctx, &msg); err != nil { diff --git a/precompiles/werc20/events_test.go b/tests/integration/precompiles/werc20/test_events.go similarity index 83% rename from precompiles/werc20/events_test.go rename to tests/integration/precompiles/werc20/test_events.go index 3512dc4ca..0f175830c 100644 --- a/precompiles/werc20/events_test.go +++ b/tests/integration/precompiles/werc20/test_events.go @@ -1,8 +1,7 @@ -package werc20_test +package werc20 import ( "math/big" - "testing" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -11,15 +10,17 @@ import ( cmn "github.com/cosmos/evm/precompiles/common" "github.com/cosmos/evm/precompiles/werc20" testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/keyring" ) type PrecompileUnitTestSuite struct { suite.Suite + create network.CreateEvmApp + options []network.ConfigOption network *network.UnitTestNetwork factory factory.TxFactory grpcHandler grpc.Handler @@ -30,8 +31,14 @@ type PrecompileUnitTestSuite struct { precompileAddrHex string } -func TestPrecompileUnitTestSuite(t *testing.T) { - suite.Run(t, new(PrecompileUnitTestSuite)) +func NewPrecompileUnitTestSuite( + create network.CreateEvmApp, + options ...network.ConfigOption, +) *PrecompileUnitTestSuite { + return &PrecompileUnitTestSuite{ + create: create, + options: options, + } } // SetupTest allows to configure the testing suite embedding a network with a @@ -40,10 +47,12 @@ func TestPrecompileUnitTestSuite(t *testing.T) { func (s *PrecompileUnitTestSuite) SetupTest(chainID testconstants.ChainID) { keyring := keyring.New(2) - integrationNetwork := network.NewUnitTestNetwork( + options := []network.ConfigOption{ network.WithChainID(chainID), network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), - ) + } + options = append(options, s.options...) + integrationNetwork := network.NewUnitTestNetwork(s.create, options...) grpcHandler := grpc.NewIntegrationHandler(integrationNetwork) txFactory := factory.New(integrationNetwork, grpcHandler) @@ -56,18 +65,18 @@ func (s *PrecompileUnitTestSuite) SetupTest(chainID testconstants.ChainID) { ctx := integrationNetwork.GetContext() - tokenDenom, err := s.network.App.Erc20Keeper.GetTokenDenom(ctx, common.HexToAddress(s.precompileAddrHex)) + tokenDenom, err := s.network.App.GetErc20Keeper().GetTokenDenom(ctx, common.HexToAddress(s.precompileAddrHex)) s.Require().NoError(err, "failed to get token denom") - tokenPairID := s.network.App.Erc20Keeper.GetTokenPairID(ctx, tokenDenom) - tokenPair, found := s.network.App.Erc20Keeper.GetTokenPair(ctx, tokenPairID) + tokenPairID := s.network.App.GetErc20Keeper().GetTokenPairID(ctx, tokenDenom) + tokenPair, found := s.network.App.GetErc20Keeper().GetTokenPair(ctx, tokenPairID) s.Require().True(found, "expected wevmos precompile to be registered in the tokens map") s.Require().Equal(s.precompileAddrHex, tokenPair.Erc20Address, "expected a different address of the contract") precompile, err := werc20.NewPrecompile( tokenPair, - s.network.App.BankKeeper, - s.network.App.Erc20Keeper, - s.network.App.TransferKeeper, + s.network.App.GetBankKeeper(), + s.network.App.GetErc20Keeper(), + s.network.App.GetTransferKeeper(), ) s.Require().NoError(err, "failed to instantiate the werc20 precompile") s.Require().NotNil(precompile) diff --git a/tests/integration/precompiles/werc20/test_integration.go b/tests/integration/precompiles/werc20/test_integration.go new file mode 100644 index 000000000..bf0285cc9 --- /dev/null +++ b/tests/integration/precompiles/werc20/test_integration.go @@ -0,0 +1,605 @@ +package werc20 + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + + //nolint:revive // dot imports are fine for Ginkgo + . "github.com/onsi/ginkgo/v2" + //nolint:revive // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" + + "github.com/cosmos/evm/precompiles/erc20" + "github.com/cosmos/evm/precompiles/testutil" + "github.com/cosmos/evm/precompiles/werc20" + "github.com/cosmos/evm/precompiles/werc20/testdata" + testconstants "github.com/cosmos/evm/testutil/constants" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/keyring" + utiltx "github.com/cosmos/evm/testutil/tx" + testutiltypes "github.com/cosmos/evm/testutil/types" + erc20types "github.com/cosmos/evm/x/erc20/types" + feemarkettypes "github.com/cosmos/evm/x/feemarket/types" + evmtypes "github.com/cosmos/evm/x/vm/types" + + "cosmossdk.io/math" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// ------------------------------------------------------------------------------------------------- +// Integration test suite +// ------------------------------------------------------------------------------------------------- + +type PrecompileIntegrationTestSuite struct { + create network.CreateEvmApp + network *network.UnitTestNetwork + factory factory.TxFactory + grpcHandler grpc.Handler + keyring keyring.Keyring + + wrappedCoinDenom string + + // WEVMOS related fields + precompile *werc20.Precompile + precompileAddrHex string +} + +func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmApp, options ...network.ConfigOption) { + var _ = When("a user interact with the WEVMOS precompiled contract", func() { + var ( + is *PrecompileIntegrationTestSuite + passCheck, failCheck testutil.LogCheckArgs + transferCheck, depositCheck, withdrawCheck testutil.LogCheckArgs + + callsData CallsData + + txSender, user keyring.Key + + revertContractAddr common.Address + ) + + depositAmount := big.NewInt(1e18) + withdrawAmount := depositAmount + transferAmount := depositAmount + + BeforeEach(func() { + is = new(PrecompileIntegrationTestSuite) + keyring := keyring.New(2) + + txSender = keyring.GetKey(0) + user = keyring.GetKey(1) + + // Set the base fee to zero to allow for zero cost tx. The final gas cost is + // not part of the logic tested here so this makes testing more easy. + customGenesis := network.CustomGenesisState{} + feemarketGenesis := feemarkettypes.DefaultGenesisState() + feemarketGenesis.Params.NoBaseFee = true + customGenesis[feemarkettypes.ModuleName] = feemarketGenesis + + // Reset evm config here for the standard case + configurator := evmtypes.NewEVMConfigurator() + configurator.ResetTestConfig() + Expect(configurator. + WithEVMCoinInfo(testconstants.ExampleChainCoinInfo[testconstants.ExampleChainID]). + Configure()).To(BeNil(), "expected no error setting the evm configurator") + + opts := []network.ConfigOption{ + network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), + network.WithCustomGenesis(customGenesis), + } + opts = append(opts, options...) + integrationNetwork := network.NewUnitTestNetwork(create, opts...) + grpcHandler := grpc.NewIntegrationHandler(integrationNetwork) + txFactory := factory.New(integrationNetwork, grpcHandler) + + is.network = integrationNetwork + is.factory = txFactory + is.grpcHandler = grpcHandler + is.keyring = keyring + + is.wrappedCoinDenom = evmtypes.GetEVMCoinDenom() + is.precompileAddrHex = network.GetWEVMOSContractHex(testconstants.ChainID{ + ChainID: is.network.GetChainID(), + EVMChainID: is.network.GetEIP155ChainID().Uint64(), + }) + + ctx := integrationNetwork.GetContext() + + // Perform some check before adding the precompile to the suite. + + // Check that WEVMOS is part of the native precompiles. + erc20Params := is.network.App.GetErc20Keeper().GetParams(ctx) + Expect(erc20Params.NativePrecompiles).To( + ContainElement(is.precompileAddrHex), + "expected wevmos to be in the native precompiles", + ) + _, found := is.network.App.GetBankKeeper().GetDenomMetaData(ctx, evmtypes.GetEVMCoinDenom()) + Expect(found).To(BeTrue(), "expected native token metadata to be registered") + + // Check that WEVMOS is registered in the token pairs map. + tokenPairID := is.network.App.GetErc20Keeper().GetTokenPairID(ctx, is.wrappedCoinDenom) + tokenPair, found := is.network.App.GetErc20Keeper().GetTokenPair(ctx, tokenPairID) + Expect(found).To(BeTrue(), "expected wevmos precompile to be registered in the tokens map") + Expect(tokenPair.Erc20Address).To(Equal(is.precompileAddrHex)) + + precompileAddr := common.HexToAddress(is.precompileAddrHex) + tokenPair = erc20types.NewTokenPair( + precompileAddr, + evmtypes.GetEVMCoinDenom(), + erc20types.OWNER_MODULE, + ) + precompile, err := werc20.NewPrecompile( + tokenPair, + is.network.App.GetBankKeeper(), + is.network.App.GetErc20Keeper(), + is.network.App.GetTransferKeeper(), + ) + Expect(err).ToNot(HaveOccurred(), "failed to instantiate the werc20 precompile") + is.precompile = precompile + + // Setup of the contract calling into the precompile to tests revert + // edge cases and proper handling of snapshots. + revertCallerContract, err := testdata.LoadWEVMOS9TestCaller() + Expect(err).ToNot(HaveOccurred(), "failed to load werc20 reverter caller contract") + + txArgs := evmtypes.EvmTxArgs{} + txArgs.GasTipCap = new(big.Int).SetInt64(0) + txArgs.GasLimit = 1_000_000_000_000 + revertContractAddr, err = is.factory.DeployContract( + txSender.Priv, + txArgs, + testutiltypes.ContractDeploymentData{ + Contract: revertCallerContract, + ConstructorArgs: []interface{}{ + common.HexToAddress(is.precompileAddrHex), + }, + }, + ) + Expect(err).ToNot(HaveOccurred(), "failed to deploy werc20 reverter contract") + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + // Support struct used to simplify transactions creation. + callsData = CallsData{ + sender: txSender, + + precompileAddr: precompileAddr, + precompileABI: precompile.ABI, + + precompileReverterAddr: revertContractAddr, + precompileReverterABI: revertCallerContract.ABI, + } + + // Utility types used to check the different events emitted. + failCheck = testutil.LogCheckArgs{ABIEvents: is.precompile.Events} + passCheck = failCheck.WithExpPass(true) + withdrawCheck = passCheck.WithExpEvents(werc20.EventTypeWithdrawal) + depositCheck = passCheck.WithExpEvents(werc20.EventTypeDeposit) + transferCheck = passCheck.WithExpEvents(erc20.EventTypeTransfer) + }) + Context("calling a specific wrapped coin method", func() { + Context("and funds are part of the transaction", func() { + When("the method is deposit", func() { + It("it should return funds to sender and emit the event", func() { + // Store initial balance to verify that sender + // balance remains the same after the contract call. + initBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + txArgs, callArgs := callsData.getTxAndCallArgs(directCall, werc20.DepositMethod) + txArgs.Amount = depositAmount + + _, _, err := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected error calling the precompile") + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + finalBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) + Expect(finalBalance.String()).To(Equal(initBalance.String())) + }) + It("it should consume at least the deposit requested gas", func() { + txArgs, callArgs := callsData.getTxAndCallArgs(directCall, werc20.DepositMethod) + txArgs.Amount = depositAmount + + _, ethRes, _ := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + Expect(ethRes.GasUsed).To(BeNumerically(">=", werc20.DepositRequiredGas), "expected different gas used for deposit") + }) + }) + //nolint:dupl + When("no calldata is provided", func() { + It("it should call the receive which behave like deposit", func() { + initBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + txArgs, callArgs := callsData.getTxAndCallArgs(directCall, "") + txArgs.Amount = depositAmount + + _, _, err := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected error calling the precompile") + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + finalBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) + Expect(finalBalance).To(Equal(initBalance)) + }) + It("it should consume at least the deposit requested gas", func() { + txArgs, callArgs := callsData.getTxAndCallArgs(directCall, werc20.DepositMethod) + txArgs.Amount = depositAmount + + _, ethRes, _ := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + Expect(ethRes.GasUsed).To(BeNumerically(">=", werc20.DepositRequiredGas), "expected different gas used for receive") + }) + }) + When("the specified method is too short", func() { + It("it should call the fallback which behave like deposit", func() { + initBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + txArgs, callArgs := callsData.getTxAndCallArgs(directCall, "") + txArgs.Amount = depositAmount + // Short method is directly set in the input to skip ABI validation + txArgs.Input = []byte{1, 2, 3} + + _, _, err := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected error calling the precompile") + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + finalBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) + Expect(finalBalance).To(Equal(initBalance)) + }) + It("it should consume at least the deposit requested gas", func() { + txArgs, callArgs := callsData.getTxAndCallArgs(directCall, "") + txArgs.Amount = depositAmount + // Short method is directly set in the input to skip ABI validation + txArgs.Input = []byte{1, 2, 3} + + _, ethRes, _ := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + Expect(ethRes.GasUsed).To(BeNumerically(">=", werc20.DepositRequiredGas), "expected different gas used for fallback") + }) + }) + When("the specified method does not exist", func() { + It("it should call the fallback which behave like deposit", func() { + initBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + txArgs, callArgs := callsData.getTxAndCallArgs(directCall, "") + txArgs.Amount = depositAmount + // Wrong method is directly set in the input to skip ABI validation + txArgs.Input = []byte("nonExistingMethod") + + _, _, err := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected error calling the precompile") + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + finalBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) + Expect(finalBalance).To(Equal(initBalance)) + }) + It("it should consume at least the deposit requested gas", func() { + txArgs, callArgs := callsData.getTxAndCallArgs(directCall, "") + txArgs.Amount = depositAmount + // Wrong method is directly set in the input to skip ABI validation + txArgs.Input = []byte("nonExistingMethod") + + _, ethRes, _ := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + Expect(ethRes.GasUsed).To(BeNumerically(">=", werc20.DepositRequiredGas), "expected different gas used for fallback") + }) + }) + }) + Context("and funds are NOT part of the transaction", func() { + When("the method is withdraw", func() { + It("it should fail if user doesn't have enough funds", func() { + // Store initial balance to verify withdraw is a no-op and sender + // balance remains the same after the contract call. + initBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + newUserAcc, newUserPriv := utiltx.NewAccAddressAndKey() + newUserBalance := sdk.Coins{sdk.Coin{ + Denom: evmtypes.GetEVMCoinDenom(), + Amount: math.NewIntFromBigInt(withdrawAmount).SubRaw(1), + }} + err := is.network.App.GetBankKeeper().SendCoins(is.network.GetContext(), user.AccAddr, newUserAcc, newUserBalance) + Expect(err).ToNot(HaveOccurred(), "expected no error sending tokens") + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + txArgs, callArgs := callsData.getTxAndCallArgs(directCall, werc20.WithdrawMethod, withdrawAmount) + + _, _, err = is.factory.CallContractAndCheckLogs(newUserPriv, txArgs, callArgs, withdrawCheck) + Expect(err).To(HaveOccurred(), "expected an error because not enough funds") + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + finalBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) + Expect(finalBalance).To(Equal(initBalance)) + }) + It("it should be a no-op and emit the event", func() { + initBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + txArgs, callArgs := callsData.getTxAndCallArgs(directCall, werc20.WithdrawMethod, withdrawAmount) + + _, _, err := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, withdrawCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected error calling the precompile") + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + finalBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) + Expect(finalBalance).To(Equal(initBalance)) + }) + It("it should consume at least the withdraw requested gas", func() { + txArgs, callArgs := callsData.getTxAndCallArgs(directCall, werc20.WithdrawMethod, withdrawAmount) + + _, ethRes, _ := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, withdrawCheck) + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + Expect(ethRes.GasUsed).To(BeNumerically(">=", werc20.WithdrawRequiredGas), "expected different gas used for withdraw") + }) + }) + //nolint:dupl + When("no calldata is provided", func() { + It("it should call the fallback which behave like deposit", func() { + initBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + txArgs, callArgs := callsData.getTxAndCallArgs(directCall, "") + txArgs.Amount = depositAmount + + _, _, err := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected error calling the precompile") + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + finalBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) + Expect(finalBalance).To(Equal(initBalance)) + }) + It("it should consume at least the deposit requested gas", func() { + txArgs, callArgs := callsData.getTxAndCallArgs(directCall, werc20.DepositMethod) + txArgs.Amount = depositAmount + + _, ethRes, _ := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + Expect(ethRes.GasUsed).To(BeNumerically(">=", werc20.DepositRequiredGas), "expected different gas used for receive") + }) + }) + When("the specified method is too short", func() { + It("it should call the fallback which behave like deposit", func() { + initBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + txArgs, callArgs := callsData.getTxAndCallArgs(directCall, "") + txArgs.Amount = depositAmount + // Short method is directly set in the input to skip ABI validation + txArgs.Input = []byte{1, 2, 3} + + _, _, err := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected error calling the precompile") + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + finalBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) + Expect(finalBalance).To(Equal(initBalance)) + }) + It("it should consume at least the deposit requested gas", func() { + txArgs, callArgs := callsData.getTxAndCallArgs(directCall, "") + txArgs.Amount = depositAmount + // Short method is directly set in the input to skip ABI validation + txArgs.Input = []byte{1, 2, 3} + + _, ethRes, _ := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + Expect(ethRes.GasUsed).To(BeNumerically(">=", werc20.DepositRequiredGas), "expected different gas used for fallback") + }) + }) + When("the specified method does not exist", func() { + It("it should call the fallback which behave like deposit", func() { + initBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + txArgs, callArgs := callsData.getTxAndCallArgs(directCall, "") + txArgs.Amount = depositAmount + // Wrong method is directly set in the input to skip ABI validation + txArgs.Input = []byte("nonExistingMethod") + + _, _, err := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected error calling the precompile") + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + finalBalance := is.checkAndReturnBalance(passCheck, callsData, user.Addr) + Expect(finalBalance).To(Equal(initBalance)) + }) + It("it should consume at least the deposit requested gas", func() { + txArgs, callArgs := callsData.getTxAndCallArgs(directCall, "") + txArgs.Amount = depositAmount + // Wrong method is directly set in the input to skip ABI validation + txArgs.Input = []byte("nonExistingMethod") + + _, ethRes, _ := is.factory.CallContractAndCheckLogs(user.Priv, txArgs, callArgs, depositCheck) + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + Expect(ethRes.GasUsed).To(BeNumerically(">=", werc20.DepositRequiredGas), "expected different gas used for fallback") + }) + }) + }) + }) + Context("calling a reverter contract", func() { + When("to call the deposit", func() { + It("it should return funds to the last sender and emit the event", func() { + ctx := is.network.GetContext() + + txArgs, callArgs := callsData.getTxAndCallArgs(contractCall, "depositWithRevert", false, false) + txArgs.Amount = depositAmount + + _, _, err := is.factory.CallContractAndCheckLogs(txSender.Priv, txArgs, callArgs, depositCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected error calling the precompile") + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + finalBalance := is.network.App.GetBankKeeper().GetAllBalances(ctx, revertContractAddr.Bytes()) + Expect(finalBalance.AmountOf(evmtypes.GetEVMCoinDenom()).String()).To(Equal(depositAmount.String()), "expected final balance equal to deposit") + }) + }) + DescribeTable("to call the deposit", func(before, after bool) { + ctx := is.network.GetContext() + + initBalance := is.network.App.GetBankKeeper().GetAllBalances(ctx, txSender.AccAddr) + + txArgs, callArgs := callsData.getTxAndCallArgs(contractCall, "depositWithRevert", before, after) + txArgs.Amount = depositAmount + + _, _, err := is.factory.CallContractAndCheckLogs(txSender.Priv, txArgs, callArgs, depositCheck) + Expect(err).To(HaveOccurred(), "execution should have reverted") + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "error on NextBlock") + + finalBalance := is.network.App.GetBankKeeper().GetAllBalances(ctx, txSender.AccAddr) + Expect(finalBalance.String()).To(Equal(initBalance.String()), "expected final balance equal to initial") + }, + Entry("it should not move funds and dont emit the event reverting before changing state", true, false), + Entry("it should not move funds and dont emit the event reverting after changing state", false, true), + ) + }) + Context("calling an erc20 method", func() { + When("transferring tokens", func() { + It("it should transfer tokens to a receiver using `transfer`", func() { + ctx := is.network.GetContext() + + senderBalance := is.network.App.GetBankKeeper().GetAllBalances(ctx, txSender.AccAddr) + receiverBalance := is.network.App.GetBankKeeper().GetAllBalances(ctx, user.AccAddr) + + txArgs, transferArgs := callsData.getTxAndCallArgs(directCall, erc20.TransferMethod, user.Addr, transferAmount) + transferCoins := sdk.Coins{sdk.NewInt64Coin(is.wrappedCoinDenom, transferAmount.Int64())} + + _, _, err := is.factory.CallContractAndCheckLogs(txSender.Priv, txArgs, transferArgs, transferCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + senderBalanceAfter := is.network.App.GetBankKeeper().GetAllBalances(ctx, txSender.AccAddr) + receiverBalanceAfter := is.network.App.GetBankKeeper().GetAllBalances(ctx, user.AccAddr) + Expect(senderBalanceAfter).To(Equal(senderBalance.Sub(transferCoins...))) + Expect(receiverBalanceAfter).To(Equal(receiverBalance.Add(transferCoins...))) + }) + It("it should fail to transfer tokens to a receiver using `transferFrom`", func() { + ctx := is.network.GetContext() + + senderBalance := is.network.App.GetBankKeeper().GetAllBalances(ctx, txSender.AccAddr) + receiverBalance := is.network.App.GetBankKeeper().GetAllBalances(ctx, user.AccAddr) + + txArgs, transferArgs := callsData.getTxAndCallArgs(directCall, erc20.TransferFromMethod, txSender.Addr, user.Addr, transferAmount) + + insufficientAllowanceCheck := failCheck.WithErrContains(erc20.ErrInsufficientAllowance.Error()) + _, _, err := is.factory.CallContractAndCheckLogs(txSender.Priv, txArgs, transferArgs, insufficientAllowanceCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + senderBalanceAfter := is.network.App.GetBankKeeper().GetAllBalances(ctx, txSender.AccAddr) + receiverBalanceAfter := is.network.App.GetBankKeeper().GetAllBalances(ctx, user.AccAddr) + Expect(senderBalanceAfter).To(Equal(senderBalance)) + Expect(receiverBalanceAfter).To(Equal(receiverBalance)) + }) + }) + When("querying information", func() { + Context("to retrieve a balance", func() { + It("should return the correct balance for an existing account", func() { + // Query the balance + txArgs, balancesArgs := callsData.getTxAndCallArgs(directCall, erc20.BalanceOfMethod, txSender.Addr) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(txSender.Priv, txArgs, balancesArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + expBalance := is.network.App.GetBankKeeper().GetBalance(is.network.GetContext(), txSender.AccAddr, is.wrappedCoinDenom) + + var balance *big.Int + err = is.precompile.UnpackIntoInterface(&balance, erc20.BalanceOfMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack result") + Expect(balance).To(Equal(expBalance.Amount.BigInt()), "expected different balance") + }) + It("should return 0 for a new account", func() { + // Query the balance + txArgs, balancesArgs := callsData.getTxAndCallArgs(directCall, erc20.BalanceOfMethod, utiltx.GenerateAddress()) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(txSender.Priv, txArgs, balancesArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + var balance *big.Int + err = is.precompile.UnpackIntoInterface(&balance, erc20.BalanceOfMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack result") + Expect(balance.Int64()).To(Equal(int64(0)), "expected different balance") + }) + }) + It("should return the correct name", func() { + txArgs, nameArgs := callsData.getTxAndCallArgs(directCall, erc20.NameMethod) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(txSender.Priv, txArgs, nameArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + var name string + err = is.precompile.UnpackIntoInterface(&name, erc20.NameMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack result") + Expect(name).To(ContainSubstring("Cosmos EVM"), "expected different name") + }) + + It("should return the correct symbol", func() { + txArgs, symbolArgs := callsData.getTxAndCallArgs(directCall, erc20.SymbolMethod) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(txSender.Priv, txArgs, symbolArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + var symbol string + err = is.precompile.UnpackIntoInterface(&symbol, erc20.SymbolMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack result") + Expect(symbol).To(ContainSubstring("ATOM"), "expected different symbol") + }) + + It("should return the decimals", func() { + txArgs, decimalsArgs := callsData.getTxAndCallArgs(directCall, erc20.DecimalsMethod) + + _, ethRes, err := is.factory.CallContractAndCheckLogs(txSender.Priv, txArgs, decimalsArgs, passCheck) + Expect(err).ToNot(HaveOccurred(), "unexpected result calling contract") + + var decimals uint8 + err = is.precompile.UnpackIntoInterface(&decimals, erc20.DecimalsMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack result") + + coinInfo := testconstants.ExampleChainCoinInfo[testconstants.ChainID{ + ChainID: is.network.GetChainID(), + EVMChainID: is.network.GetEIP155ChainID().Uint64(), + }] + Expect(decimals).To(Equal(uint8(coinInfo.Decimals)), "expected different decimals") + }, + ) + }) + }) + }) + + // Run Ginkgo integration tests + RegisterFailHandler(Fail) + RunSpecs(t, "WEVMOS precompile test suite") +} + +// checkAndReturnBalance check that the balance of the address is the same in +// the smart contract and in the balance and returns the amount. +func (is *PrecompileIntegrationTestSuite) checkAndReturnBalance( + balanceCheck testutil.LogCheckArgs, + callsData CallsData, + address common.Address, +) *big.Int { + txArgs, balancesArgs := callsData.getTxAndCallArgs(directCall, erc20.BalanceOfMethod, address) + txArgs.GasLimit = 1_000_000_000_000 + + _, ethRes, err := is.factory.CallContractAndCheckLogs(callsData.sender.Priv, txArgs, balancesArgs, balanceCheck) + Expect(err).ToNot(HaveOccurred(), "failed to execute balanceOf") + var erc20Balance *big.Int + err = is.precompile.UnpackIntoInterface(&erc20Balance, erc20.BalanceOfMethod, ethRes.Ret) + Expect(err).ToNot(HaveOccurred(), "failed to unpack result") + + addressAcc := sdk.AccAddress(address.Bytes()) + balanceAfter, err := is.grpcHandler.GetBalanceFromBank(addressAcc, is.wrappedCoinDenom) + Expect(err).ToNot(HaveOccurred(), "expected no error getting balance") + + Expect(erc20Balance.String()).To(Equal(balanceAfter.Balance.Amount.BigInt().String()), "expected return balance from contract equal to bank") + return erc20Balance +} diff --git a/precompiles/werc20/utils_test.go b/tests/integration/precompiles/werc20/test_utils.go similarity index 88% rename from precompiles/werc20/utils_test.go rename to tests/integration/precompiles/werc20/test_utils.go index 696a9617e..82eccfc29 100644 --- a/precompiles/werc20/utils_test.go +++ b/tests/integration/precompiles/werc20/test_utils.go @@ -1,4 +1,4 @@ -package werc20_test +package werc20 import ( "math/big" @@ -6,8 +6,8 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/keyring" + "github.com/cosmos/evm/testutil/keyring" + testutiltypes "github.com/cosmos/evm/testutil/types" evmtypes "github.com/cosmos/evm/x/vm/types" ) @@ -41,9 +41,9 @@ func (cd CallsData) getTxAndCallArgs( callType callType, methodName string, args ...interface{}, -) (evmtypes.EvmTxArgs, factory.CallArgs) { +) (evmtypes.EvmTxArgs, testutiltypes.CallArgs) { txArgs := evmtypes.EvmTxArgs{} - callArgs := factory.CallArgs{} + callArgs := testutiltypes.CallArgs{} switch callType { case directCall: diff --git a/rpc/backend/account_info_test.go b/tests/integration/rpc/backend/test_account_info.go similarity index 67% rename from rpc/backend/account_info_test.go rename to tests/integration/rpc/backend/test_account_info.go index 4309f08b8..52d948829 100644 --- a/rpc/backend/account_info_test.go +++ b/tests/integration/rpc/backend/test_account_info.go @@ -19,7 +19,7 @@ import ( authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) -func (suite *BackendTestSuite) TestGetCode() { +func (s *BackendTestSuite) TestGetCode() { blockNr := rpctypes.NewBlockNumber(big.NewInt(1)) contractCode := []byte("0xef616c92f3cfc9e92dc270d6acff9cea213cecc7020a76ee4395af09bdceb4837a1ebdb5735e11e7d3adb6104e0c3ac55180b4ddf5e54d022cc5e8837f6a4f971b") @@ -44,8 +44,8 @@ func (suite *BackendTestSuite) TestGetCode() { utiltx.GenerateAddress(), rpctypes.BlockNumberOrHash{BlockNumber: &blockNr}, func(addr common.Address) { - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterCodeError(queryClient, addr) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterCodeError(QueryClient, addr) }, false, nil, @@ -55,30 +55,30 @@ func (suite *BackendTestSuite) TestGetCode() { utiltx.GenerateAddress(), rpctypes.BlockNumberOrHash{BlockNumber: &blockNr}, func(addr common.Address) { - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterCode(queryClient, addr, contractCode) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterCode(QueryClient, addr, contractCode) }, true, contractCode, }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() // reset + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // reset tc.registerMock(tc.addr) - code, err := suite.backend.GetCode(tc.addr, tc.blockNrOrHash) + code, err := s.backend.GetCode(tc.addr, tc.blockNrOrHash) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(tc.expCode, code) + s.Require().NoError(err) + s.Require().Equal(tc.expCode, code) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestGetProof() { +func (s *BackendTestSuite) TestGetProof() { blockNrInvalid := rpctypes.NewBlockNumber(big.NewInt(1)) blockNr := rpctypes.NewBlockNumber(big.NewInt(4)) address1 := utiltx.GenerateAddress() @@ -98,11 +98,11 @@ func (suite *BackendTestSuite) TestGetProof() { []string{}, rpctypes.BlockNumberOrHash{BlockNumber: &blockNrInvalid}, func(bn rpctypes.BlockNumber, addr common.Address) { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlock(client, bn.Int64(), nil) - suite.Require().NoError(err) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterAccount(queryClient, addr, blockNrInvalid.Int64()) + s.Require().NoError(err) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterAccount(QueryClient, addr, blockNrInvalid.Int64()) }, false, &rpctypes.AccountResult{}, @@ -113,7 +113,7 @@ func (suite *BackendTestSuite) TestGetProof() { []string{}, rpctypes.BlockNumberOrHash{BlockNumber: &blockNrInvalid}, func(bn rpctypes.BlockNumber, _ common.Address) { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterBlockError(client, bn.Int64()) }, false, @@ -125,13 +125,13 @@ func (suite *BackendTestSuite) TestGetProof() { []string{"0x0"}, rpctypes.BlockNumberOrHash{BlockNumber: &blockNr}, func(bn rpctypes.BlockNumber, addr common.Address) { - suite.backend.ctx = rpctypes.ContextWithHeight(bn.Int64()) + s.backend.Ctx = rpctypes.ContextWithHeight(bn.Int64()) - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlock(client, bn.Int64(), nil) - suite.Require().NoError(err) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterAccount(queryClient, addr, bn.Int64()) + s.Require().NoError(err) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterAccount(QueryClient, addr, bn.Int64()) // Use the IAVL height if a valid tendermint height is passed in. iavlHeight := bn.Int64() @@ -169,23 +169,23 @@ func (suite *BackendTestSuite) TestGetProof() { }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() tc.registerMock(*tc.blockNrOrHash.BlockNumber, tc.addr) - accRes, err := suite.backend.GetProof(tc.addr, tc.storageKeys, tc.blockNrOrHash) + accRes, err := s.backend.GetProof(tc.addr, tc.storageKeys, tc.blockNrOrHash) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(tc.expAccRes, accRes) + s.Require().NoError(err) + s.Require().Equal(tc.expAccRes, accRes) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestGetStorageAt() { +func (s *BackendTestSuite) TestGetStorageAt() { blockNr := rpctypes.NewBlockNumber(big.NewInt(1)) testCases := []struct { @@ -212,8 +212,8 @@ func (suite *BackendTestSuite) TestGetStorageAt() { "0x0", rpctypes.BlockNumberOrHash{BlockNumber: &blockNr}, func(addr common.Address, key string, _ string) { - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterStorageAtError(queryClient, addr, key) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterStorageAtError(QueryClient, addr, key) }, false, nil, @@ -224,30 +224,30 @@ func (suite *BackendTestSuite) TestGetStorageAt() { "0x0", rpctypes.BlockNumberOrHash{BlockNumber: &blockNr}, func(addr common.Address, key string, storage string) { - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterStorageAt(queryClient, addr, key, storage) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterStorageAt(QueryClient, addr, key, storage) }, true, hexutil.Bytes{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() tc.registerMock(tc.addr, tc.key, tc.expStorage.String()) - storage, err := suite.backend.GetStorageAt(tc.addr, tc.key, tc.blockNrOrHash) + storage, err := s.backend.GetStorageAt(tc.addr, tc.key, tc.blockNrOrHash) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(tc.expStorage, storage) + s.Require().NoError(err) + s.Require().Equal(tc.expStorage, storage) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestGetBalance() { +func (s *BackendTestSuite) TestGetBalance() { blockNr := rpctypes.NewBlockNumber(big.NewInt(1)) testCases := []struct { @@ -272,7 +272,7 @@ func (suite *BackendTestSuite) TestGetBalance() { utiltx.GenerateAddress(), rpctypes.BlockNumberOrHash{BlockNumber: &blockNr}, func(bn rpctypes.BlockNumber, _ common.Address) { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterBlockError(client, bn.Int64()) }, false, @@ -283,11 +283,11 @@ func (suite *BackendTestSuite) TestGetBalance() { utiltx.GenerateAddress(), rpctypes.BlockNumberOrHash{BlockNumber: &blockNr}, func(bn rpctypes.BlockNumber, addr common.Address) { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlock(client, bn.Int64(), nil) - suite.Require().NoError(err) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBalanceError(queryClient, addr, bn.Int64()) + s.Require().NoError(err) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBalanceError(QueryClient, addr, bn.Int64()) }, false, nil, @@ -297,11 +297,11 @@ func (suite *BackendTestSuite) TestGetBalance() { utiltx.GenerateAddress(), rpctypes.BlockNumberOrHash{BlockNumber: &blockNr}, func(bn rpctypes.BlockNumber, addr common.Address) { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlock(client, bn.Int64(), nil) - suite.Require().NoError(err) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBalanceInvalid(queryClient, addr, bn.Int64()) + s.Require().NoError(err) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBalanceInvalid(QueryClient, addr, bn.Int64()) }, false, nil, @@ -311,11 +311,11 @@ func (suite *BackendTestSuite) TestGetBalance() { utiltx.GenerateAddress(), rpctypes.BlockNumberOrHash{BlockNumber: &blockNr}, func(bn rpctypes.BlockNumber, addr common.Address) { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlock(client, bn.Int64(), nil) - suite.Require().NoError(err) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBalanceNegative(queryClient, addr, bn.Int64()) + s.Require().NoError(err) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBalanceNegative(QueryClient, addr, bn.Int64()) }, false, nil, @@ -325,37 +325,37 @@ func (suite *BackendTestSuite) TestGetBalance() { utiltx.GenerateAddress(), rpctypes.BlockNumberOrHash{BlockNumber: &blockNr}, func(bn rpctypes.BlockNumber, addr common.Address) { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlock(client, bn.Int64(), nil) - suite.Require().NoError(err) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBalance(queryClient, addr, bn.Int64()) + s.Require().NoError(err) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBalance(QueryClient, addr, bn.Int64()) }, true, (*hexutil.Big)(big.NewInt(1)), }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // avoid nil pointer reference if tc.blockNrOrHash.BlockNumber != nil { tc.registerMock(*tc.blockNrOrHash.BlockNumber, tc.addr) } - balance, err := suite.backend.GetBalance(tc.addr, tc.blockNrOrHash) + balance, err := s.backend.GetBalance(tc.addr, tc.blockNrOrHash) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(tc.expBalance, balance) + s.Require().NoError(err) + s.Require().Equal(tc.expBalance, balance) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestGetTransactionCount() { +func (s *BackendTestSuite) TestGetTransactionCount() { testCases := []struct { name string accExists bool @@ -370,8 +370,8 @@ func (suite *BackendTestSuite) TestGetTransactionCount() { rpctypes.NewBlockNumber(big.NewInt(1)), func(common.Address, rpctypes.BlockNumber) { var header metadata.MD - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterParams(queryClient, &header, 1) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterParams(QueryClient, &header, 1) }, true, hexutil.Uint64(0), @@ -382,8 +382,8 @@ func (suite *BackendTestSuite) TestGetTransactionCount() { rpctypes.NewBlockNumber(big.NewInt(10000)), func(common.Address, rpctypes.BlockNumber) { var header metadata.MD - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterParams(queryClient, &header, 1) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterParams(QueryClient, &header, 1) }, false, hexutil.Uint64(0), @@ -394,10 +394,10 @@ func (suite *BackendTestSuite) TestGetTransactionCount() { // true, // rpctypes.NewBlockNumber(big.NewInt(1)), // func(addr common.Address, bn rpctypes.BlockNumber) { - // client := suite.backend.clientCtx.Client.(*mocks.Client) - // account, err := suite.backend.clientCtx.AccountRetriever.GetAccount(suite.backend.clientCtx, suite.acc) - // suite.Require().NoError(err) - // request := &authtypes.QueryAccountRequest{Address: sdk.AccAddress(suite.acc.Bytes()).String()} + // client := s.backend.ClientCtx.Client.(*mocks.Client) + // account, err := s.backend.ClientCtx.AccountRetriever.GetAccount(s.backend.ClientCtx, s.acc) + // s.Require().NoError(err) + // request := &authtypes.QueryAccountRequest{Address: sdk.AccAddress(s.acc.Bytes()).String()} // requestMarshal, _ := request.Marshal() // RegisterABCIQueryAccount( // client, @@ -411,22 +411,22 @@ func (suite *BackendTestSuite) TestGetTransactionCount() { // }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() addr := utiltx.GenerateAddress() if tc.accExists { - addr = common.BytesToAddress(suite.acc.Bytes()) + addr = common.BytesToAddress(s.acc.Bytes()) } tc.registerMock(addr, tc.blockNum) - txCount, err := suite.backend.GetTransactionCount(addr, tc.blockNum) + txCount, err := s.backend.GetTransactionCount(addr, tc.blockNum) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(tc.expTxCount, *txCount) + s.Require().NoError(err) + s.Require().Equal(tc.expTxCount, *txCount) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } diff --git a/rpc/backend/backend_suite_test.go b/tests/integration/rpc/backend/test_backend_suite.go similarity index 64% rename from rpc/backend/backend_suite_test.go rename to tests/integration/rpc/backend/test_backend_suite.go index 91c7f9d32..f5967b6ff 100644 --- a/rpc/backend/backend_suite_test.go +++ b/tests/integration/rpc/backend/test_backend_suite.go @@ -5,7 +5,6 @@ import ( "math/big" "os" "path/filepath" - "testing" "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" @@ -17,11 +16,12 @@ import ( "github.com/cosmos/evm/crypto/hd" "github.com/cosmos/evm/encoding" "github.com/cosmos/evm/indexer" + rpcbackend "github.com/cosmos/evm/rpc/backend" "github.com/cosmos/evm/rpc/backend/mocks" rpctypes "github.com/cosmos/evm/rpc/types" "github.com/cosmos/evm/server/config" "github.com/cosmos/evm/testutil/constants" - testnetwork "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/network" utiltx "github.com/cosmos/evm/testutil/tx" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -34,46 +34,51 @@ import ( type BackendTestSuite struct { suite.Suite - backend *Backend + create network.CreateEvmApp + options []network.ConfigOption + backend *rpcbackend.Backend from common.Address acc sdk.AccAddress signer keyring.Signer } -func TestBackendTestSuite(t *testing.T) { - suite.Run(t, new(BackendTestSuite)) +func NewBackendTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *BackendTestSuite { + return &BackendTestSuite{ + create: create, + options: options, + } } var ChainID = constants.ExampleChainID // SetupTest is executed before every BackendTestSuite test -func (suite *BackendTestSuite) SetupTest() { +func (s *BackendTestSuite) SetupTest() { ctx := server.NewDefaultContext() ctx.Viper.Set("telemetry.global-labels", []interface{}{}) - baseDir := suite.T().TempDir() + baseDir := s.T().TempDir() nodeDirName := "node" clientDir := filepath.Join(baseDir, nodeDirName, "evmoscli") - keyRing, err := suite.generateTestKeyring(clientDir) + keyRing, err := s.generateTestKeyring(clientDir) if err != nil { panic(err) } // Create Account with set sequence - suite.acc = sdk.AccAddress(utiltx.GenerateAddress().Bytes()) + s.acc = sdk.AccAddress(utiltx.GenerateAddress().Bytes()) accounts := map[string]client.TestAccount{} - accounts[suite.acc.String()] = client.TestAccount{ - Address: suite.acc, + accounts[s.acc.String()] = client.TestAccount{ + Address: s.acc, Num: uint64(1), Seq: uint64(1), } from, priv := utiltx.NewAddrKey() - suite.from = from - suite.signer = utiltx.NewSigner(priv) - suite.Require().NoError(err) + s.from = from + s.signer = utiltx.NewSigner(priv) + s.Require().NoError(err) - nw := testnetwork.New() + nw := network.New(s.create, s.options...) encodingConfig := nw.GetEncodingConfig() clientCtx := client.Context{}.WithChainID(ChainID.ChainID). WithHeight(1). @@ -81,28 +86,28 @@ func (suite *BackendTestSuite) SetupTest() { WithKeyringDir(clientDir). WithKeyring(keyRing). WithAccountRetriever(client.TestAccountRetriever{Accounts: accounts}). - WithClient(mocks.NewClient(suite.T())) + WithClient(mocks.NewClient(s.T())) allowUnprotectedTxs := false idxer := indexer.NewKVIndexer(dbm.NewMemDB(), ctx.Logger, clientCtx) - suite.backend = NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, idxer) - suite.backend.cfg.JSONRPC.GasCap = 0 - suite.backend.cfg.JSONRPC.EVMTimeout = 0 - suite.backend.cfg.JSONRPC.AllowInsecureUnlock = true - suite.backend.cfg.EVM.EVMChainID = 262144 - suite.backend.queryClient.QueryClient = mocks.NewEVMQueryClient(suite.T()) - suite.backend.queryClient.FeeMarket = mocks.NewFeeMarketQueryClient(suite.T()) - suite.backend.ctx = rpctypes.ContextWithHeight(1) + s.backend = rpcbackend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, idxer) + s.backend.Cfg.JSONRPC.GasCap = 0 + s.backend.Cfg.JSONRPC.EVMTimeout = 0 + s.backend.Cfg.JSONRPC.AllowInsecureUnlock = true + s.backend.Cfg.EVM.EVMChainID = 262144 + s.backend.QueryClient.QueryClient = mocks.NewEVMQueryClient(s.T()) + s.backend.QueryClient.FeeMarket = mocks.NewFeeMarketQueryClient(s.T()) + s.backend.Ctx = rpctypes.ContextWithHeight(1) // Add codec - suite.backend.clientCtx.Codec = encodingConfig.Codec + s.backend.ClientCtx.Codec = encodingConfig.Codec } // buildEthereumTx returns an example legacy Ethereum transaction -func (suite *BackendTestSuite) buildEthereumTx() (*evmtypes.MsgEthereumTx, []byte) { +func (s *BackendTestSuite) buildEthereumTx() (*evmtypes.MsgEthereumTx, []byte) { ethTxParams := evmtypes.EvmTxArgs{ - ChainID: suite.backend.chainID, + ChainID: s.backend.EvmChainID, Nonce: uint64(0), To: &common.Address{}, Amount: big.NewInt(0), @@ -112,19 +117,19 @@ func (suite *BackendTestSuite) buildEthereumTx() (*evmtypes.MsgEthereumTx, []byt msgEthereumTx := evmtypes.NewTx(ðTxParams) // A valid msg should have empty `From` - msgEthereumTx.From = suite.from.Hex() + msgEthereumTx.From = s.from.Hex() - txBuilder := suite.backend.clientCtx.TxConfig.NewTxBuilder() + txBuilder := s.backend.ClientCtx.TxConfig.NewTxBuilder() err := txBuilder.SetMsgs(msgEthereumTx) - suite.Require().NoError(err) + s.Require().NoError(err) - bz, err := suite.backend.clientCtx.TxConfig.TxEncoder()(txBuilder.GetTx()) - suite.Require().NoError(err) + bz, err := s.backend.ClientCtx.TxConfig.TxEncoder()(txBuilder.GetTx()) + s.Require().NoError(err) return msgEthereumTx, bz } // buildEthereumTx returns an example legacy Ethereum transaction -func (suite *BackendTestSuite) buildEthereumTxWithChainID(eip155ChainID *big.Int) *evmtypes.MsgEthereumTx { +func (s *BackendTestSuite) buildEthereumTxWithChainID(eip155ChainID *big.Int) *evmtypes.MsgEthereumTx { ethTxParams := evmtypes.EvmTxArgs{ ChainID: eip155ChainID, Nonce: uint64(0), @@ -136,17 +141,17 @@ func (suite *BackendTestSuite) buildEthereumTxWithChainID(eip155ChainID *big.Int msgEthereumTx := evmtypes.NewTx(ðTxParams) // A valid msg should have empty `From` - msgEthereumTx.From = suite.from.Hex() + msgEthereumTx.From = s.from.Hex() - txBuilder := suite.backend.clientCtx.TxConfig.NewTxBuilder() + txBuilder := s.backend.ClientCtx.TxConfig.NewTxBuilder() err := txBuilder.SetMsgs(msgEthereumTx) - suite.Require().NoError(err) + s.Require().NoError(err) return msgEthereumTx } // buildFormattedBlock returns a formatted block for testing -func (suite *BackendTestSuite) buildFormattedBlock( +func (s *BackendTestSuite) buildFormattedBlock( blockRes *cmtrpctypes.ResultBlockResults, resBlock *cmtrpctypes.ResultBlock, fullTx bool, @@ -171,9 +176,9 @@ func (suite *BackendTestSuite) buildFormattedBlock( uint64(header.Height), //nolint:gosec // G115 // won't exceed uint64 uint64(0), baseFee, - suite.backend.chainID, + s.backend.EvmChainID, ) - suite.Require().NoError(err) + s.Require().NoError(err) ethRPCTxs = []interface{}{rpcTx} } else { ethRPCTxs = []interface{}{common.HexToHash(tx.Hash)} @@ -192,28 +197,28 @@ func (suite *BackendTestSuite) buildFormattedBlock( ) } -func (suite *BackendTestSuite) generateTestKeyring(clientDir string) (keyring.Keyring, error) { +func (s *BackendTestSuite) generateTestKeyring(clientDir string) (keyring.Keyring, error) { buf := bufio.NewReader(os.Stdin) encCfg := encoding.MakeConfig(config.DefaultEVMChainID) return keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, clientDir, buf, encCfg.Codec, []keyring.Option{hd.EthSecp256k1Option()}...) } -func (suite *BackendTestSuite) signAndEncodeEthTx(msgEthereumTx *evmtypes.MsgEthereumTx) []byte { +func (s *BackendTestSuite) signAndEncodeEthTx(msgEthereumTx *evmtypes.MsgEthereumTx) []byte { from, priv := utiltx.NewAddrKey() signer := utiltx.NewSigner(priv) - ethSigner := ethtypes.LatestSigner(suite.backend.ChainConfig()) + ethSigner := ethtypes.LatestSigner(s.backend.ChainConfig()) msgEthereumTx.From = from.String() err := msgEthereumTx.Sign(ethSigner, signer) - suite.Require().NoError(err) + s.Require().NoError(err) evmDenom := evmtypes.GetEVMCoinDenom() - tx, err := msgEthereumTx.BuildTx(suite.backend.clientCtx.TxConfig.NewTxBuilder(), evmDenom) - suite.Require().NoError(err) + tx, err := msgEthereumTx.BuildTx(s.backend.ClientCtx.TxConfig.NewTxBuilder(), evmDenom) + s.Require().NoError(err) - txEncoder := suite.backend.clientCtx.TxConfig.TxEncoder() + txEncoder := s.backend.ClientCtx.TxConfig.TxEncoder() txBz, err := txEncoder(tx) - suite.Require().NoError(err) + s.Require().NoError(err) return txBz } diff --git a/rpc/backend/blocks_test.go b/tests/integration/rpc/backend/test_blocks.go similarity index 67% rename from rpc/backend/blocks_test.go rename to tests/integration/rpc/backend/test_blocks.go index dfc192b1f..ef6603bb7 100644 --- a/rpc/backend/blocks_test.go +++ b/tests/integration/rpc/backend/test_blocks.go @@ -24,7 +24,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -func (suite *BackendTestSuite) TestBlockNumber() { +func (s *BackendTestSuite) TestBlockNumber() { testCases := []struct { name string registerMock func() @@ -36,8 +36,8 @@ func (suite *BackendTestSuite) TestBlockNumber() { func() { var header metadata.MD height := int64(1) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterParamsInvalidHeight(queryClient, &header, height) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterParamsInvalidHeight(QueryClient, &header, height) }, 0x0, false, @@ -47,8 +47,8 @@ func (suite *BackendTestSuite) TestBlockNumber() { func() { var header metadata.MD height := int64(1) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterParamsInvalidHeader(queryClient, &header, height) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterParamsInvalidHeader(QueryClient, &header, height) }, 0x0, false, @@ -58,36 +58,36 @@ func (suite *BackendTestSuite) TestBlockNumber() { func() { var header metadata.MD height := int64(1) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterParams(queryClient, &header, height) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterParams(QueryClient, &header, height) }, 0x1, true, }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock() - blockNumber, err := suite.backend.BlockNumber() + blockNumber, err := s.backend.BlockNumber() if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(tc.expBlockNumber, blockNumber) + s.Require().NoError(err) + s.Require().Equal(tc.expBlockNumber, blockNumber) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestGetBlockByNumber() { +func (s *BackendTestSuite) TestGetBlockByNumber() { var ( blockRes *cmtrpctypes.ResultBlockResults resBlock *cmtrpctypes.ResultBlock ) - msgEthereumTx, bz := suite.buildEthereumTx() + msgEthereumTx, bz := s.buildEthereumTx() testCases := []struct { name string @@ -111,7 +111,7 @@ func (suite *BackendTestSuite) TestGetBlockByNumber() { nil, func(blockNum ethrpc.BlockNumber, _ math.Int, _ sdk.AccAddress, _ []byte) { height := blockNum.Int64() - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterBlockError(client, height) }, true, @@ -127,7 +127,7 @@ func (suite *BackendTestSuite) TestGetBlockByNumber() { nil, func(blockNum ethrpc.BlockNumber, _ math.Int, _ sdk.AccAddress, _ []byte) { height := blockNum.Int64() - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) resBlock, _ = RegisterBlockNotFound(client, height) }, true, @@ -143,7 +143,7 @@ func (suite *BackendTestSuite) TestGetBlockByNumber() { nil, func(blockNum ethrpc.BlockNumber, _ math.Int, _ sdk.AccAddress, txBz []byte) { height := blockNum.Int64() - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) resBlock, _ = RegisterBlock(client, height, txBz) RegisterBlockResultsError(client, blockNum.Int64()) }, @@ -160,14 +160,14 @@ func (suite *BackendTestSuite) TestGetBlockByNumber() { nil, func(blockNum ethrpc.BlockNumber, baseFee math.Int, validator sdk.AccAddress, txBz []byte) { height := blockNum.Int64() - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) resBlock, _ = RegisterBlock(client, height, txBz) blockRes, _ = RegisterBlockResults(client, blockNum.Int64()) RegisterConsensusParams(client, height) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFee(queryClient, baseFee) - RegisterValidatorAccount(queryClient, validator) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFee(QueryClient, baseFee) + RegisterValidatorAccount(QueryClient, validator) }, false, true, @@ -182,31 +182,31 @@ func (suite *BackendTestSuite) TestGetBlockByNumber() { bz, func(blockNum ethrpc.BlockNumber, baseFee math.Int, validator sdk.AccAddress, txBz []byte) { height := blockNum.Int64() - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) resBlock, _ = RegisterBlock(client, height, txBz) blockRes, _ = RegisterBlockResults(client, blockNum.Int64()) RegisterConsensusParams(client, height) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFee(queryClient, baseFee) - RegisterValidatorAccount(queryClient, validator) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFee(QueryClient, baseFee) + RegisterValidatorAccount(QueryClient, validator) }, false, true, }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock(tc.blockNumber, math.NewIntFromBigInt(tc.baseFee), tc.validator, tc.txBz) - block, err := suite.backend.GetBlockByNumber(tc.blockNumber, tc.fullTx) + block, err := s.backend.GetBlockByNumber(tc.blockNumber, tc.fullTx) if tc.expPass { if tc.expNoop { - suite.Require().Nil(block) + s.Require().Nil(block) } else { - expBlock := suite.buildFormattedBlock( + expBlock := s.buildFormattedBlock( blockRes, resBlock, tc.fullTx, @@ -214,23 +214,23 @@ func (suite *BackendTestSuite) TestGetBlockByNumber() { tc.validator, tc.baseFee, ) - suite.Require().Equal(expBlock, block) + s.Require().Equal(expBlock, block) } - suite.Require().NoError(err) + s.Require().NoError(err) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestGetBlockByHash() { +func (s *BackendTestSuite) TestGetBlockByHash() { var ( blockRes *cmtrpctypes.ResultBlockResults resBlock *cmtrpctypes.ResultBlock ) - msgEthereumTx, bz := suite.buildEthereumTx() + msgEthereumTx, bz := s.buildEthereumTx() block := cmttypes.MakeBlock(1, []cmttypes.Tx{bz}, nil, nil) @@ -255,7 +255,7 @@ func (suite *BackendTestSuite) TestGetBlockByHash() { nil, nil, func(hash common.Hash, _ math.Int, _ sdk.AccAddress, txBz []byte) { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterBlockByHashError(client, hash, txBz) }, false, @@ -270,7 +270,7 @@ func (suite *BackendTestSuite) TestGetBlockByHash() { nil, nil, func(hash common.Hash, _ math.Int, _ sdk.AccAddress, txBz []byte) { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterBlockByHashNotFound(client, hash, txBz) }, true, @@ -286,7 +286,7 @@ func (suite *BackendTestSuite) TestGetBlockByHash() { nil, func(hash common.Hash, _ math.Int, _ sdk.AccAddress, txBz []byte) { height := int64(1) - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) resBlock, _ = RegisterBlockByHash(client, hash, txBz) RegisterBlockResultsError(client, height) @@ -304,15 +304,15 @@ func (suite *BackendTestSuite) TestGetBlockByHash() { nil, func(hash common.Hash, baseFee math.Int, validator sdk.AccAddress, txBz []byte) { height := int64(1) - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) resBlock, _ = RegisterBlockByHash(client, hash, txBz) blockRes, _ = RegisterBlockResults(client, height) RegisterConsensusParams(client, height) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFee(queryClient, baseFee) - RegisterValidatorAccount(queryClient, validator) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFee(QueryClient, baseFee) + RegisterValidatorAccount(QueryClient, validator) }, false, true, @@ -327,32 +327,32 @@ func (suite *BackendTestSuite) TestGetBlockByHash() { bz, func(hash common.Hash, baseFee math.Int, validator sdk.AccAddress, txBz []byte) { height := int64(1) - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) resBlock, _ = RegisterBlockByHash(client, hash, txBz) blockRes, _ = RegisterBlockResults(client, height) RegisterConsensusParams(client, height) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFee(queryClient, baseFee) - RegisterValidatorAccount(queryClient, validator) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFee(QueryClient, baseFee) + RegisterValidatorAccount(QueryClient, validator) }, false, true, }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock(tc.hash, math.NewIntFromBigInt(tc.baseFee), tc.validator, tc.txBz) - block, err := suite.backend.GetBlockByHash(tc.hash, tc.fullTx) + block, err := s.backend.GetBlockByHash(tc.hash, tc.fullTx) if tc.expPass { if tc.expNoop { - suite.Require().Nil(block) + s.Require().Nil(block) } else { - expBlock := suite.buildFormattedBlock( + expBlock := s.buildFormattedBlock( blockRes, resBlock, tc.fullTx, @@ -360,19 +360,19 @@ func (suite *BackendTestSuite) TestGetBlockByHash() { tc.validator, tc.baseFee, ) - suite.Require().Equal(expBlock, block) + s.Require().Equal(expBlock, block) } - suite.Require().NoError(err) + s.Require().NoError(err) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestGetBlockTransactionCountByHash() { - _, bz := suite.buildEthereumTx() +func (s *BackendTestSuite) TestGetBlockTransactionCountByHash() { + _, bz := s.buildEthereumTx() block := cmttypes.MakeBlock(1, []cmttypes.Tx{bz}, nil, nil) emptyBlock := cmttypes.MakeBlock(1, []cmttypes.Tx{}, nil, nil) @@ -387,7 +387,7 @@ func (suite *BackendTestSuite) TestGetBlockTransactionCountByHash() { "fail - block not found", common.BytesToHash(emptyBlock.Hash()), func(hash common.Hash) { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterBlockByHashError(client, hash, nil) }, hexutil.Uint(0), @@ -398,9 +398,9 @@ func (suite *BackendTestSuite) TestGetBlockTransactionCountByHash() { common.BytesToHash(emptyBlock.Hash()), func(hash common.Hash) { height := int64(1) - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlockByHash(client, hash, nil) - suite.Require().NoError(err) + s.Require().NoError(err) RegisterBlockResultsError(client, height) }, hexutil.Uint(0), @@ -411,11 +411,11 @@ func (suite *BackendTestSuite) TestGetBlockTransactionCountByHash() { common.BytesToHash(emptyBlock.Hash()), func(hash common.Hash) { height := int64(1) - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlockByHash(client, hash, nil) - suite.Require().NoError(err) + s.Require().NoError(err) _, err = RegisterBlockResults(client, height) - suite.Require().NoError(err) + s.Require().NoError(err) }, hexutil.Uint(0), true, @@ -425,33 +425,33 @@ func (suite *BackendTestSuite) TestGetBlockTransactionCountByHash() { common.BytesToHash(block.Hash()), func(hash common.Hash) { height := int64(1) - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlockByHash(client, hash, bz) - suite.Require().NoError(err) + s.Require().NoError(err) _, err = RegisterBlockResults(client, height) - suite.Require().NoError(err) + s.Require().NoError(err) }, hexutil.Uint(1), true, }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock(tc.hash) - count := suite.backend.GetBlockTransactionCountByHash(tc.hash) + count := s.backend.GetBlockTransactionCountByHash(tc.hash) if tc.expPass { - suite.Require().Equal(tc.expCount, *count) + s.Require().Equal(tc.expCount, *count) } else { - suite.Require().Nil(count) + s.Require().Nil(count) } }) } } -func (suite *BackendTestSuite) TestGetBlockTransactionCountByNumber() { - _, bz := suite.buildEthereumTx() +func (s *BackendTestSuite) TestGetBlockTransactionCountByNumber() { + _, bz := s.buildEthereumTx() block := cmttypes.MakeBlock(1, []cmttypes.Tx{bz}, nil, nil) emptyBlock := cmttypes.MakeBlock(1, []cmttypes.Tx{}, nil, nil) @@ -467,7 +467,7 @@ func (suite *BackendTestSuite) TestGetBlockTransactionCountByNumber() { ethrpc.BlockNumber(emptyBlock.Height), func(blockNum ethrpc.BlockNumber) { height := blockNum.Int64() - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterBlockError(client, height) }, hexutil.Uint(0), @@ -478,9 +478,9 @@ func (suite *BackendTestSuite) TestGetBlockTransactionCountByNumber() { ethrpc.BlockNumber(emptyBlock.Height), func(blockNum ethrpc.BlockNumber) { height := blockNum.Int64() - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlock(client, height, nil) - suite.Require().NoError(err) + s.Require().NoError(err) RegisterBlockResultsError(client, height) }, hexutil.Uint(0), @@ -491,11 +491,11 @@ func (suite *BackendTestSuite) TestGetBlockTransactionCountByNumber() { ethrpc.BlockNumber(emptyBlock.Height), func(blockNum ethrpc.BlockNumber) { height := blockNum.Int64() - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlock(client, height, nil) - suite.Require().NoError(err) + s.Require().NoError(err) _, err = RegisterBlockResults(client, height) - suite.Require().NoError(err) + s.Require().NoError(err) }, hexutil.Uint(0), true, @@ -505,32 +505,32 @@ func (suite *BackendTestSuite) TestGetBlockTransactionCountByNumber() { ethrpc.BlockNumber(block.Height), func(blockNum ethrpc.BlockNumber) { height := blockNum.Int64() - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlock(client, height, bz) - suite.Require().NoError(err) + s.Require().NoError(err) _, err = RegisterBlockResults(client, height) - suite.Require().NoError(err) + s.Require().NoError(err) }, hexutil.Uint(1), true, }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock(tc.blockNum) - count := suite.backend.GetBlockTransactionCountByNumber(tc.blockNum) + count := s.backend.GetBlockTransactionCountByNumber(tc.blockNum) if tc.expPass { - suite.Require().Equal(tc.expCount, *count) + s.Require().Equal(tc.expCount, *count) } else { - suite.Require().Nil(count) + s.Require().Nil(count) } }) } } -func (suite *BackendTestSuite) TestTendermintBlockByNumber() { +func (s *BackendTestSuite) TestTendermintBlockByNumber() { var expResultBlock *cmtrpctypes.ResultBlock testCases := []struct { @@ -545,7 +545,7 @@ func (suite *BackendTestSuite) TestTendermintBlockByNumber() { ethrpc.BlockNumber(1), func(blockNum ethrpc.BlockNumber) { height := blockNum.Int64() - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterBlockError(client, height) }, false, @@ -556,9 +556,9 @@ func (suite *BackendTestSuite) TestTendermintBlockByNumber() { ethrpc.BlockNumber(1), func(blockNum ethrpc.BlockNumber) { height := blockNum.Int64() - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlockNotFound(client, height) - suite.Require().NoError(err) + s.Require().NoError(err) }, false, true, @@ -569,8 +569,8 @@ func (suite *BackendTestSuite) TestTendermintBlockByNumber() { func(_ ethrpc.BlockNumber) { var header metadata.MD appHeight := int64(1) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterParamsError(queryClient, &header, appHeight) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterParamsError(QueryClient, &header, appHeight) }, false, false, @@ -581,11 +581,11 @@ func (suite *BackendTestSuite) TestTendermintBlockByNumber() { func(ethrpc.BlockNumber) { var header metadata.MD appHeight := int64(1) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterParams(queryClient, &header, appHeight) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterParams(QueryClient, &header, appHeight) tmHeight := appHeight - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) expResultBlock, _ = RegisterBlock(client, tmHeight, nil) }, true, @@ -596,7 +596,7 @@ func (suite *BackendTestSuite) TestTendermintBlockByNumber() { ethrpc.BlockNumber(0), func(blockNum ethrpc.BlockNumber) { height := blockNum.Int64() - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) expResultBlock, _ = RegisterBlock(client, height, nil) }, true, @@ -607,7 +607,7 @@ func (suite *BackendTestSuite) TestTendermintBlockByNumber() { ethrpc.BlockNumber(1), func(blockNum ethrpc.BlockNumber) { height := blockNum.Int64() - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) expResultBlock, _ = RegisterBlock(client, height, nil) }, true, @@ -615,29 +615,29 @@ func (suite *BackendTestSuite) TestTendermintBlockByNumber() { }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock(tc.blockNumber) - resultBlock, err := suite.backend.TendermintBlockByNumber(tc.blockNumber) + resultBlock, err := s.backend.TendermintBlockByNumber(tc.blockNumber) if tc.expPass { - suite.Require().NoError(err) + s.Require().NoError(err) if !tc.found { - suite.Require().Nil(resultBlock) + s.Require().Nil(resultBlock) } else { - suite.Require().Equal(expResultBlock, resultBlock) - suite.Require().Equal(expResultBlock.Block.Header.Height, resultBlock.Block.Header.Height) + s.Require().Equal(expResultBlock, resultBlock) + s.Require().Equal(expResultBlock.Block.Header.Height, resultBlock.Block.Header.Height) } } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestTendermintBlockResultByNumber() { +func (s *BackendTestSuite) TestTendermintBlockResultByNumber() { var expBlockRes *cmtrpctypes.ResultBlockResults testCases := []struct { @@ -650,7 +650,7 @@ func (suite *BackendTestSuite) TestTendermintBlockResultByNumber() { "fail", 1, func(blockNum int64) { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterBlockResultsError(client, blockNum) }, false, @@ -659,9 +659,9 @@ func (suite *BackendTestSuite) TestTendermintBlockResultByNumber() { "pass", 1, func(blockNum int64) { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlockResults(client, blockNum) - suite.Require().NoError(err) + s.Require().NoError(err) expBlockRes = &cmtrpctypes.ResultBlockResults{ Height: blockNum, TxsResults: []*types.ExecTxResult{{Code: 0, GasUsed: 0}}, @@ -671,27 +671,27 @@ func (suite *BackendTestSuite) TestTendermintBlockResultByNumber() { }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock(tc.blockNumber) - client := suite.backend.clientCtx.Client.(*mocks.Client) - blockRes, err := client.BlockResults(suite.backend.ctx, &tc.blockNumber) //#nosec G601 -- fine for tests + client := s.backend.ClientCtx.Client.(*mocks.Client) + blockRes, err := client.BlockResults(s.backend.Ctx, &tc.blockNumber) //#nosec G601 -- fine for tests if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(expBlockRes, blockRes) + s.Require().NoError(err) + s.Require().Equal(expBlockRes, blockRes) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestBlockNumberFromTendermint() { +func (s *BackendTestSuite) TestBlockNumberFromTendermint() { var resHeader *cmtrpctypes.ResultHeader - _, bz := suite.buildEthereumTx() + _, bz := s.buildEthereumTx() block := cmttypes.MakeBlock(1, []cmttypes.Tx{bz}, nil, nil) blockNum := ethrpc.NewBlockNumber(big.NewInt(block.Height)) blockHash := common.BytesToHash(block.Hash()) @@ -715,7 +715,7 @@ func (suite *BackendTestSuite) TestBlockNumberFromTendermint() { nil, &blockHash, func(hash *common.Hash) { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterHeaderByHashError(client, *hash, bz) }, false, @@ -725,7 +725,7 @@ func (suite *BackendTestSuite) TestBlockNumberFromTendermint() { nil, &blockHash, func(hash *common.Hash) { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) resHeader, _ = RegisterHeaderByHash(client, *hash, bz) }, true, @@ -739,8 +739,8 @@ func (suite *BackendTestSuite) TestBlockNumberFromTendermint() { }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // reset test and queries blockNrOrHash := ethrpc.BlockNumberOrHash{ BlockNumber: tc.blockNum, @@ -748,27 +748,27 @@ func (suite *BackendTestSuite) TestBlockNumberFromTendermint() { } tc.registerMock(tc.hash) - blockNum, err := suite.backend.BlockNumberFromTendermint(blockNrOrHash) + blockNum, err := s.backend.BlockNumberFromTendermint(blockNrOrHash) if tc.expPass { - suite.Require().NoError(err) + s.Require().NoError(err) if tc.hash == nil { - suite.Require().Equal(*tc.blockNum, blockNum) + s.Require().Equal(*tc.blockNum, blockNum) } else { expHeight := ethrpc.NewBlockNumber(big.NewInt(resHeader.Header.Height)) - suite.Require().Equal(expHeight, blockNum) + s.Require().Equal(expHeight, blockNum) } } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestBlockNumberFromTendermintByHash() { +func (s *BackendTestSuite) TestBlockNumberFromTendermintByHash() { var resHeader *cmtrpctypes.ResultHeader - _, bz := suite.buildEthereumTx() + _, bz := s.buildEthereumTx() block := cmttypes.MakeBlock(1, []cmttypes.Tx{bz}, nil, nil) emptyBlock := cmttypes.MakeBlock(1, []cmttypes.Tx{}, nil, nil) @@ -782,7 +782,7 @@ func (suite *BackendTestSuite) TestBlockNumberFromTendermintByHash() { "fail - tendermint client failed to get block", common.BytesToHash(block.Hash()), func(hash common.Hash) { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterHeaderByHashError(client, hash, bz) }, false, @@ -791,7 +791,7 @@ func (suite *BackendTestSuite) TestBlockNumberFromTendermintByHash() { "pass - block without tx", common.BytesToHash(emptyBlock.Hash()), func(hash common.Hash) { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) resHeader, _ = RegisterHeaderByHash(client, hash, bz) }, true, @@ -800,30 +800,30 @@ func (suite *BackendTestSuite) TestBlockNumberFromTendermintByHash() { "pass - block with tx", common.BytesToHash(block.Hash()), func(hash common.Hash) { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) resHeader, _ = RegisterHeaderByHash(client, hash, bz) }, true, }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock(tc.hash) - blockNum, err := suite.backend.BlockNumberFromTendermintByHash(tc.hash) + blockNum, err := s.backend.BlockNumberFromTendermintByHash(tc.hash) if tc.expPass { expHeight := big.NewInt(resHeader.Header.Height) - suite.Require().NoError(err) - suite.Require().Equal(expHeight, blockNum) + s.Require().NoError(err) + s.Require().Equal(expHeight, blockNum) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestBlockBloom() { +func (s *BackendTestSuite) TestBlockBloom() { testCases := []struct { name string blockRes *cmtrpctypes.ResultBlockResults @@ -876,21 +876,21 @@ func (suite *BackendTestSuite) TestBlockBloom() { }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - blockBloom, err := suite.backend.BlockBloom(tc.blockRes) + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + blockBloom, err := s.backend.BlockBloom(tc.blockRes) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(tc.expBlockBloom, blockBloom) + s.Require().NoError(err) + s.Require().Equal(tc.expBlockBloom, blockBloom) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestGetEthBlockFromTendermint() { - msgEthereumTx, bz := suite.buildEthereumTx() +func (s *BackendTestSuite) TestGetEthBlockFromTendermint() { + msgEthereumTx, bz := s.buildEthereumTx() emptyBlock := cmttypes.MakeBlock(1, []cmttypes.Tx{}, nil, nil) testCases := []struct { @@ -917,11 +917,11 @@ func (suite *BackendTestSuite) TestGetEthBlockFromTendermint() { }, false, func(baseFee math.Int, validator sdk.AccAddress, height int64) { - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFee(queryClient, baseFee) - RegisterValidatorAccount(queryClient, validator) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFee(QueryClient, baseFee) + RegisterValidatorAccount(QueryClient, validator) - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterConsensusParams(client, height) }, false, @@ -941,11 +941,11 @@ func (suite *BackendTestSuite) TestGetEthBlockFromTendermint() { }, true, func(_ math.Int, validator sdk.AccAddress, height int64) { - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFeeError(queryClient) - RegisterValidatorAccount(queryClient, validator) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFeeError(QueryClient) + RegisterValidatorAccount(QueryClient, validator) - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterConsensusParams(client, height) }, true, @@ -965,11 +965,11 @@ func (suite *BackendTestSuite) TestGetEthBlockFromTendermint() { }, true, func(baseFee math.Int, _ sdk.AccAddress, height int64) { - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFee(queryClient, baseFee) - RegisterValidatorAccountError(queryClient) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFee(QueryClient, baseFee) + RegisterValidatorAccountError(QueryClient) - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterConsensusParams(client, height) }, true, @@ -989,11 +989,11 @@ func (suite *BackendTestSuite) TestGetEthBlockFromTendermint() { }, true, func(baseFee math.Int, validator sdk.AccAddress, height int64) { - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFee(queryClient, baseFee) - RegisterValidatorAccount(queryClient, validator) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFee(QueryClient, baseFee) + RegisterValidatorAccount(QueryClient, validator) - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterConsensusParamsError(client, height) }, true, @@ -1019,11 +1019,11 @@ func (suite *BackendTestSuite) TestGetEthBlockFromTendermint() { }, true, func(baseFee math.Int, validator sdk.AccAddress, height int64) { - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFee(queryClient, baseFee) - RegisterValidatorAccount(queryClient, validator) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFee(QueryClient, baseFee) + RegisterValidatorAccount(QueryClient, validator) - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterConsensusParams(client, height) }, false, @@ -1043,11 +1043,11 @@ func (suite *BackendTestSuite) TestGetEthBlockFromTendermint() { }, false, func(baseFee math.Int, validator sdk.AccAddress, height int64) { - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFee(queryClient, baseFee) - RegisterValidatorAccount(queryClient, validator) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFee(QueryClient, baseFee) + RegisterValidatorAccount(QueryClient, validator) - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterConsensusParams(client, height) }, true, @@ -1067,11 +1067,11 @@ func (suite *BackendTestSuite) TestGetEthBlockFromTendermint() { }, true, func(baseFee math.Int, validator sdk.AccAddress, height int64) { - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFee(queryClient, baseFee) - RegisterValidatorAccount(queryClient, validator) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFee(QueryClient, baseFee) + RegisterValidatorAccount(QueryClient, validator) - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterConsensusParams(client, height) }, true, @@ -1079,11 +1079,11 @@ func (suite *BackendTestSuite) TestGetEthBlockFromTendermint() { }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock(math.NewIntFromBigInt(tc.baseFee), tc.validator, tc.height) - block, err := suite.backend.RPCBlockFromTendermintBlock(tc.resBlock, tc.blockRes, tc.fullTx) + block, err := s.backend.RPCBlockFromTendermintBlock(tc.resBlock, tc.blockRes, tc.fullTx) var expBlock map[string]interface{} header := tc.resBlock.Block.Header @@ -1104,9 +1104,9 @@ func (suite *BackendTestSuite) TestGetEthBlockFromTendermint() { uint64(header.Height), //nolint:gosec // G115 // won't exceed uint64 uint64(0), tc.baseFee, - suite.backend.chainID, + s.backend.EvmChainID, ) - suite.Require().NoError(err) + s.Require().NoError(err) ethRPCTxs = []interface{}{rpcTx} } else { ethRPCTxs = []interface{}{common.HexToHash(msgEthereumTx.Hash)} @@ -1125,17 +1125,17 @@ func (suite *BackendTestSuite) TestGetEthBlockFromTendermint() { ) if tc.expPass { - suite.Require().Equal(expBlock, block) - suite.Require().NoError(err) + s.Require().Equal(expBlock, block) + s.Require().NoError(err) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestEthMsgsFromTendermintBlock() { - msgEthereumTx, bz := suite.buildEthereumTx() +func (s *BackendTestSuite) TestEthMsgsFromTendermintBlock() { + msgEthereumTx, bz := s.buildEthereumTx() testCases := []struct { name string @@ -1189,19 +1189,19 @@ func (suite *BackendTestSuite) TestEthMsgsFromTendermintBlock() { }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // reset test and queries - msgs := suite.backend.EthMsgsFromTendermintBlock(tc.resBlock, tc.blockRes) - suite.Require().Equal(tc.expMsgs, msgs) + msgs := s.backend.EthMsgsFromTendermintBlock(tc.resBlock, tc.blockRes) + s.Require().Equal(tc.expMsgs, msgs) }) } } -func (suite *BackendTestSuite) TestHeaderByNumber() { +func (s *BackendTestSuite) TestHeaderByNumber() { var expResultBlock *cmtrpctypes.ResultBlock - _, bz := suite.buildEthereumTx() + _, bz := s.buildEthereumTx() testCases := []struct { name string @@ -1216,7 +1216,7 @@ func (suite *BackendTestSuite) TestHeaderByNumber() { math.NewInt(1).BigInt(), func(blockNum ethrpc.BlockNumber, _ math.Int) { height := blockNum.Int64() - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterBlockError(client, height) }, false, @@ -1227,9 +1227,9 @@ func (suite *BackendTestSuite) TestHeaderByNumber() { math.NewInt(1).BigInt(), func(blockNum ethrpc.BlockNumber, _ math.Int) { height := blockNum.Int64() - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlockNotFound(client, height) - suite.Require().NoError(err) + s.Require().NoError(err) }, false, }, @@ -1239,9 +1239,9 @@ func (suite *BackendTestSuite) TestHeaderByNumber() { math.NewInt(1).BigInt(), func(blockNum ethrpc.BlockNumber, _ math.Int) { height := blockNum.Int64() - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlock(client, height, nil) - suite.Require().NoError(err) + s.Require().NoError(err) RegisterBlockResultsError(client, height) }, false, @@ -1252,12 +1252,12 @@ func (suite *BackendTestSuite) TestHeaderByNumber() { nil, func(blockNum ethrpc.BlockNumber, _ math.Int) { height := blockNum.Int64() - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) expResultBlock, _ = RegisterBlock(client, height, nil) _, err := RegisterBlockResults(client, height) - suite.Require().NoError(err) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFeeError(queryClient) + s.Require().NoError(err) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFeeError(QueryClient) }, true, }, @@ -1267,12 +1267,12 @@ func (suite *BackendTestSuite) TestHeaderByNumber() { math.NewInt(1).BigInt(), func(blockNum ethrpc.BlockNumber, baseFee math.Int) { height := blockNum.Int64() - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) expResultBlock, _ = RegisterBlock(client, height, nil) _, err := RegisterBlockResults(client, height) - suite.Require().NoError(err) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFee(queryClient, baseFee) + s.Require().NoError(err) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFee(QueryClient, baseFee) }, true, }, @@ -1282,38 +1282,38 @@ func (suite *BackendTestSuite) TestHeaderByNumber() { math.NewInt(1).BigInt(), func(blockNum ethrpc.BlockNumber, baseFee math.Int) { height := blockNum.Int64() - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) expResultBlock, _ = RegisterBlock(client, height, bz) _, err := RegisterBlockResults(client, height) - suite.Require().NoError(err) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFee(queryClient, baseFee) + s.Require().NoError(err) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFee(QueryClient, baseFee) }, true, }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock(tc.blockNumber, math.NewIntFromBigInt(tc.baseFee)) - header, err := suite.backend.HeaderByNumber(tc.blockNumber) + header, err := s.backend.HeaderByNumber(tc.blockNumber) if tc.expPass { expHeader := ethrpc.EthHeaderFromTendermint(expResultBlock.Block.Header, ethtypes.Bloom{}, tc.baseFee) - suite.Require().NoError(err) - suite.Require().Equal(expHeader, header) + s.Require().NoError(err) + s.Require().Equal(expHeader, header) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestHeaderByHash() { +func (s *BackendTestSuite) TestHeaderByHash() { var expResultHeader *cmtrpctypes.ResultHeader - _, bz := suite.buildEthereumTx() + _, bz := s.buildEthereumTx() block := cmttypes.MakeBlock(1, []cmttypes.Tx{bz}, nil, nil) emptyBlock := cmttypes.MakeBlock(1, []cmttypes.Tx{}, nil, nil) @@ -1329,7 +1329,7 @@ func (suite *BackendTestSuite) TestHeaderByHash() { common.BytesToHash(block.Hash()), math.NewInt(1).BigInt(), func(hash common.Hash, _ math.Int) { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterHeaderByHashError(client, hash, bz) }, false, @@ -1339,7 +1339,7 @@ func (suite *BackendTestSuite) TestHeaderByHash() { common.BytesToHash(block.Hash()), math.NewInt(1).BigInt(), func(hash common.Hash, _ math.Int) { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterHeaderByHashNotFound(client, hash, bz) }, false, @@ -1350,9 +1350,9 @@ func (suite *BackendTestSuite) TestHeaderByHash() { math.NewInt(1).BigInt(), func(hash common.Hash, _ math.Int) { height := int64(1) - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterHeaderByHash(client, hash, bz) - suite.Require().NoError(err) + s.Require().NoError(err) RegisterBlockResultsError(client, height) }, false, @@ -1363,12 +1363,12 @@ func (suite *BackendTestSuite) TestHeaderByHash() { nil, func(hash common.Hash, _ math.Int) { height := int64(1) - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) expResultHeader, _ = RegisterHeaderByHash(client, hash, bz) _, err := RegisterBlockResults(client, height) - suite.Require().NoError(err) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFeeError(queryClient) + s.Require().NoError(err) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFeeError(QueryClient) }, true, }, @@ -1378,12 +1378,12 @@ func (suite *BackendTestSuite) TestHeaderByHash() { math.NewInt(1).BigInt(), func(hash common.Hash, baseFee math.Int) { height := int64(1) - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) expResultHeader, _ = RegisterHeaderByHash(client, hash, nil) _, err := RegisterBlockResults(client, height) - suite.Require().NoError(err) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFee(queryClient, baseFee) + s.Require().NoError(err) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFee(QueryClient, baseFee) }, true, }, @@ -1393,36 +1393,36 @@ func (suite *BackendTestSuite) TestHeaderByHash() { math.NewInt(1).BigInt(), func(hash common.Hash, baseFee math.Int) { height := int64(1) - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) expResultHeader, _ = RegisterHeaderByHash(client, hash, bz) _, err := RegisterBlockResults(client, height) - suite.Require().NoError(err) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFee(queryClient, baseFee) + s.Require().NoError(err) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFee(QueryClient, baseFee) }, true, }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock(tc.hash, math.NewIntFromBigInt(tc.baseFee)) - header, err := suite.backend.HeaderByHash(tc.hash) + header, err := s.backend.HeaderByHash(tc.hash) if tc.expPass { expHeader := ethrpc.EthHeaderFromTendermint(*expResultHeader.Header, ethtypes.Bloom{}, tc.baseFee) - suite.Require().NoError(err) - suite.Require().Equal(expHeader, header) + s.Require().NoError(err) + s.Require().Equal(expHeader, header) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestEthBlockByNumber() { - msgEthereumTx, bz := suite.buildEthereumTx() +func (s *BackendTestSuite) TestEthBlockByNumber() { + msgEthereumTx, bz := s.buildEthereumTx() emptyBlock := cmttypes.MakeBlock(1, []cmttypes.Tx{}, nil, nil) testCases := []struct { @@ -1437,7 +1437,7 @@ func (suite *BackendTestSuite) TestEthBlockByNumber() { ethrpc.BlockNumber(1), func(blockNum ethrpc.BlockNumber) { height := blockNum.Int64() - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterBlockError(client, height) }, nil, @@ -1448,9 +1448,9 @@ func (suite *BackendTestSuite) TestEthBlockByNumber() { ethrpc.BlockNumber(1), func(blockNum ethrpc.BlockNumber) { height := blockNum.Int64() - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlock(client, height, nil) - suite.Require().NoError(err) + s.Require().NoError(err) RegisterBlockResultsError(client, blockNum.Int64()) }, nil, @@ -1461,14 +1461,14 @@ func (suite *BackendTestSuite) TestEthBlockByNumber() { ethrpc.BlockNumber(1), func(blockNum ethrpc.BlockNumber) { height := blockNum.Int64() - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlock(client, height, nil) - suite.Require().NoError(err) + s.Require().NoError(err) _, err = RegisterBlockResults(client, blockNum.Int64()) - suite.Require().NoError(err) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) + s.Require().NoError(err) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) baseFee := math.NewInt(1) - RegisterBaseFee(queryClient, baseFee) + RegisterBaseFee(QueryClient, baseFee) }, ethtypes.NewBlock( ethrpc.EthHeaderFromTendermint( @@ -1487,14 +1487,14 @@ func (suite *BackendTestSuite) TestEthBlockByNumber() { ethrpc.BlockNumber(1), func(blockNum ethrpc.BlockNumber) { height := blockNum.Int64() - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlock(client, height, bz) - suite.Require().NoError(err) + s.Require().NoError(err) _, err = RegisterBlockResults(client, blockNum.Int64()) - suite.Require().NoError(err) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) + s.Require().NoError(err) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) baseFee := math.NewInt(1) - RegisterBaseFee(queryClient, baseFee) + RegisterBaseFee(QueryClient, baseFee) }, ethtypes.NewBlock( ethrpc.EthHeaderFromTendermint( @@ -1512,30 +1512,30 @@ func (suite *BackendTestSuite) TestEthBlockByNumber() { }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock(tc.blockNumber) - ethBlock, err := suite.backend.EthBlockByNumber(tc.blockNumber) + ethBlock, err := s.backend.EthBlockByNumber(tc.blockNumber) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(tc.expEthBlock.Header(), ethBlock.Header()) - suite.Require().Equal(tc.expEthBlock.Uncles(), ethBlock.Uncles()) - suite.Require().Equal(tc.expEthBlock.ReceiptHash(), ethBlock.ReceiptHash()) + s.Require().NoError(err) + s.Require().Equal(tc.expEthBlock.Header(), ethBlock.Header()) + s.Require().Equal(tc.expEthBlock.Uncles(), ethBlock.Uncles()) + s.Require().Equal(tc.expEthBlock.ReceiptHash(), ethBlock.ReceiptHash()) for i, tx := range tc.expEthBlock.Transactions() { - suite.Require().Equal(tx.Data(), ethBlock.Transactions()[i].Data()) + s.Require().Equal(tx.Data(), ethBlock.Transactions()[i].Data()) } } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestEthBlockFromTendermintBlock() { - msgEthereumTx, bz := suite.buildEthereumTx() +func (s *BackendTestSuite) TestEthBlockFromTendermintBlock() { + msgEthereumTx, bz := s.buildEthereumTx() emptyBlock := cmttypes.MakeBlock(1, []cmttypes.Tx{}, nil, nil) testCases := []struct { @@ -1558,8 +1558,8 @@ func (suite *BackendTestSuite) TestEthBlockFromTendermintBlock() { TxsResults: []*types.ExecTxResult{{Code: 0, GasUsed: 0}}, }, func(baseFee math.Int, _ int64) { - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFee(queryClient, baseFee) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFee(QueryClient, baseFee) }, ethtypes.NewBlock( ethrpc.EthHeaderFromTendermint( @@ -1592,8 +1592,8 @@ func (suite *BackendTestSuite) TestEthBlockFromTendermintBlock() { }, }, func(baseFee math.Int, _ int64) { - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFee(queryClient, baseFee) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFee(QueryClient, baseFee) }, ethtypes.NewBlock( ethrpc.EthHeaderFromTendermint( @@ -1609,23 +1609,23 @@ func (suite *BackendTestSuite) TestEthBlockFromTendermintBlock() { }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock(math.NewIntFromBigInt(tc.baseFee), tc.blockRes.Height) - ethBlock, err := suite.backend.EthBlockFromTendermintBlock(tc.resBlock, tc.blockRes) + ethBlock, err := s.backend.EthBlockFromTendermintBlock(tc.resBlock, tc.blockRes) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(tc.expEthBlock.Header(), ethBlock.Header()) - suite.Require().Equal(tc.expEthBlock.Uncles(), ethBlock.Uncles()) - suite.Require().Equal(tc.expEthBlock.ReceiptHash(), ethBlock.ReceiptHash()) + s.Require().NoError(err) + s.Require().Equal(tc.expEthBlock.Header(), ethBlock.Header()) + s.Require().Equal(tc.expEthBlock.Uncles(), ethBlock.Uncles()) + s.Require().Equal(tc.expEthBlock.ReceiptHash(), ethBlock.ReceiptHash()) for i, tx := range tc.expEthBlock.Transactions() { - suite.Require().Equal(tx.Data(), ethBlock.Transactions()[i].Data()) + s.Require().Equal(tx.Data(), ethBlock.Transactions()[i].Data()) } } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } diff --git a/rpc/backend/call_tx_test.go b/tests/integration/rpc/backend/test_call_tx.go similarity index 57% rename from rpc/backend/call_tx_test.go rename to tests/integration/rpc/backend/test_call_tx.go index 3c0439398..e329d5c85 100644 --- a/rpc/backend/call_tx_test.go +++ b/tests/integration/rpc/backend/test_call_tx.go @@ -22,12 +22,12 @@ import ( errortypes "github.com/cosmos/cosmos-sdk/types/errors" ) -func (suite *BackendTestSuite) TestResend() { +func (s *BackendTestSuite) TestResend() { txNonce := (hexutil.Uint64)(1) baseFee := math.NewInt(1) gasPrice := new(hexutil.Big) toAddr := utiltx.GenerateAddress() - chainID := (*hexutil.Big)(suite.backend.chainID) + evmChainID := (*hexutil.Big)(s.backend.EvmChainID) callArgs := evmtypes.TransactionArgs{ From: nil, To: &toAddr, @@ -40,7 +40,7 @@ func (suite *BackendTestSuite) TestResend() { Input: nil, Data: nil, AccessList: nil, - ChainID: chainID, + ChainID: evmChainID, } testCases := []struct { @@ -67,14 +67,14 @@ func (suite *BackendTestSuite) TestResend() { "pass - Can't set Tx defaults BaseFee disabled", func() { var header metadata.MD - client := suite.backend.clientCtx.Client.(*mocks.Client) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterParams(queryClient, &header, 1) + client := s.backend.ClientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterParams(QueryClient, &header, 1) _, err := RegisterBlock(client, 1, nil) - suite.Require().NoError(err) + s.Require().NoError(err) _, err = RegisterBlockResults(client, 1) - suite.Require().NoError(err) - RegisterBaseFeeDisabled(queryClient) + s.Require().NoError(err) + RegisterBaseFeeDisabled(QueryClient) }, evmtypes.TransactionArgs{ Nonce: &txNonce, @@ -89,16 +89,16 @@ func (suite *BackendTestSuite) TestResend() { "pass - Can't set Tx defaults", func() { var header metadata.MD - client := suite.backend.clientCtx.Client.(*mocks.Client) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - feeMarketClient := suite.backend.queryClient.FeeMarket.(*mocks.FeeMarketQueryClient) - RegisterParams(queryClient, &header, 1) + client := s.backend.ClientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + feeMarketClient := s.backend.QueryClient.FeeMarket.(*mocks.FeeMarketQueryClient) + RegisterParams(QueryClient, &header, 1) RegisterFeeMarketParams(feeMarketClient, 1) _, err := RegisterBlock(client, 1, nil) - suite.Require().NoError(err) + s.Require().NoError(err) _, err = RegisterBlockResults(client, 1) - suite.Require().NoError(err) - RegisterBaseFee(queryClient, baseFee) + s.Require().NoError(err) + RegisterBaseFee(QueryClient, baseFee) }, evmtypes.TransactionArgs{ Nonce: &txNonce, @@ -112,14 +112,14 @@ func (suite *BackendTestSuite) TestResend() { "pass - MaxFeePerGas is nil", func() { var header metadata.MD - client := suite.backend.clientCtx.Client.(*mocks.Client) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterParams(queryClient, &header, 1) + client := s.backend.ClientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterParams(QueryClient, &header, 1) _, err := RegisterBlock(client, 1, nil) - suite.Require().NoError(err) + s.Require().NoError(err) _, err = RegisterBlockResults(client, 1) - suite.Require().NoError(err) - RegisterBaseFeeDisabled(queryClient) + s.Require().NoError(err) + RegisterBaseFeeDisabled(QueryClient) }, evmtypes.TransactionArgs{ Nonce: &txNonce, @@ -150,9 +150,9 @@ func (suite *BackendTestSuite) TestResend() { "fail - Block error", func() { var header metadata.MD - client := suite.backend.clientCtx.Client.(*mocks.Client) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterParams(queryClient, &header, 1) + client := s.backend.ClientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterParams(QueryClient, &header, 1) RegisterBlockError(client, 1) }, evmtypes.TransactionArgs{ @@ -167,14 +167,14 @@ func (suite *BackendTestSuite) TestResend() { "pass - MaxFeePerGas is nil", func() { var header metadata.MD - client := suite.backend.clientCtx.Client.(*mocks.Client) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterParams(queryClient, &header, 1) + client := s.backend.ClientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterParams(QueryClient, &header, 1) _, err := RegisterBlock(client, 1, nil) - suite.Require().NoError(err) + s.Require().NoError(err) _, err = RegisterBlockResults(client, 1) - suite.Require().NoError(err) - RegisterBaseFee(queryClient, baseFee) + s.Require().NoError(err) + RegisterBaseFee(QueryClient, baseFee) }, evmtypes.TransactionArgs{ Nonce: &txNonce, @@ -192,14 +192,14 @@ func (suite *BackendTestSuite) TestResend() { "pass - Chain Id is nil", func() { var header metadata.MD - client := suite.backend.clientCtx.Client.(*mocks.Client) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterParams(queryClient, &header, 1) + client := s.backend.ClientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterParams(QueryClient, &header, 1) _, err := RegisterBlock(client, 1, nil) - suite.Require().NoError(err) + s.Require().NoError(err) _, err = RegisterBlockResults(client, 1) - suite.Require().NoError(err) - RegisterBaseFee(queryClient, baseFee) + s.Require().NoError(err) + RegisterBaseFee(QueryClient, baseFee) }, evmtypes.TransactionArgs{ Nonce: &txNonce, @@ -215,15 +215,15 @@ func (suite *BackendTestSuite) TestResend() { "fail - Pending transactions error", func() { var header metadata.MD - client := suite.backend.clientCtx.Client.(*mocks.Client) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) + client := s.backend.ClientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) _, err := RegisterBlock(client, 1, nil) - suite.Require().NoError(err) + s.Require().NoError(err) _, err = RegisterBlockResults(client, 1) - suite.Require().NoError(err) - RegisterBaseFee(queryClient, baseFee) - RegisterEstimateGas(queryClient, callArgs) - RegisterParams(queryClient, &header, 1) + s.Require().NoError(err) + RegisterBaseFee(QueryClient, baseFee) + RegisterEstimateGas(QueryClient, callArgs) + RegisterParams(QueryClient, &header, 1) RegisterUnconfirmedTxsError(client, nil) }, evmtypes.TransactionArgs{ @@ -244,15 +244,15 @@ func (suite *BackendTestSuite) TestResend() { "fail - Not Ethereum txs", func() { var header metadata.MD - client := suite.backend.clientCtx.Client.(*mocks.Client) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) + client := s.backend.ClientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) _, err := RegisterBlock(client, 1, nil) - suite.Require().NoError(err) + s.Require().NoError(err) _, err = RegisterBlockResults(client, 1) - suite.Require().NoError(err) - RegisterBaseFee(queryClient, baseFee) - RegisterEstimateGas(queryClient, callArgs) - RegisterParams(queryClient, &header, 1) + s.Require().NoError(err) + RegisterBaseFee(QueryClient, baseFee) + RegisterEstimateGas(QueryClient, callArgs) + RegisterParams(QueryClient, &header, 1) RegisterUnconfirmedTxsEmpty(client, nil) }, @@ -273,31 +273,31 @@ func (suite *BackendTestSuite) TestResend() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock() - hash, err := suite.backend.Resend(tc.args, tc.gasPrice, tc.gasLimit) + hash, err := s.backend.Resend(tc.args, tc.gasPrice, tc.gasLimit) if tc.expPass { - suite.Require().Equal(tc.expHash, hash) + s.Require().Equal(tc.expHash, hash) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestSendRawTransaction() { - ethTx, bz := suite.buildEthereumTx() +func (s *BackendTestSuite) TestSendRawTransaction() { + ethTx, bz := s.buildEthereumTx() - emptyChainIDTx := suite.buildEthereumTxWithChainID(nil) - invalidChainIDTx := suite.buildEthereumTxWithChainID(big.NewInt(1)) + emptyEvmChainIDTx := s.buildEthereumTxWithChainID(nil) + invalidEvmChainIDTx := s.buildEthereumTxWithChainID(big.NewInt(1)) // Sign the ethTx - ethSigner := ethtypes.LatestSigner(suite.backend.ChainConfig()) - err := ethTx.Sign(ethSigner, suite.signer) - suite.Require().NoError(err) + ethSigner := ethtypes.LatestSigner(s.backend.ChainConfig()) + err := ethTx.Sign(ethSigner, s.signer) + s.Require().NoError(err) rlpEncodedBz, _ := rlp.EncodeToBytes(ethTx.AsTransaction()) evmDenom := evmtypes.GetEVMCoinDenom() @@ -329,15 +329,15 @@ func (suite *BackendTestSuite) TestSendRawTransaction() { { "fail - invalid chain-id", func() { - suite.backend.allowUnprotectedTxs = false + s.backend.AllowUnprotectedTxs = false }, func() []byte { from, priv := utiltx.NewAddrKey() signer := utiltx.NewSigner(priv) - invalidChainIDTx.From = from.String() - err := invalidChainIDTx.Sign(ethSigner, signer) - suite.Require().NoError(err) - bytes, _ := rlp.EncodeToBytes(invalidChainIDTx.AsTransaction()) + invalidEvmChainIDTx.From = from.String() + err := invalidEvmChainIDTx.Sign(ethSigner, signer) + s.Require().NoError(err) + bytes, _ := rlp.EncodeToBytes(invalidEvmChainIDTx.AsTransaction()) return bytes }, common.Hash{}, @@ -347,10 +347,10 @@ func (suite *BackendTestSuite) TestSendRawTransaction() { { "fail - unprotected tx", func() { - suite.backend.allowUnprotectedTxs = false + s.backend.AllowUnprotectedTxs = false }, func() []byte { - bytes, _ := rlp.EncodeToBytes(emptyChainIDTx.AsTransaction()) + bytes, _ := rlp.EncodeToBytes(emptyEvmChainIDTx.AsTransaction()) return bytes }, common.Hash{}, @@ -360,11 +360,11 @@ func (suite *BackendTestSuite) TestSendRawTransaction() { { "fail - failed to broadcast transaction", func() { - cosmosTx, _ := ethTx.BuildTx(suite.backend.clientCtx.TxConfig.NewTxBuilder(), evmDenom) - txBytes, _ := suite.backend.clientCtx.TxConfig.TxEncoder()(cosmosTx) + cosmosTx, _ := ethTx.BuildTx(s.backend.ClientCtx.TxConfig.NewTxBuilder(), evmDenom) + txBytes, _ := s.backend.ClientCtx.TxConfig.TxEncoder()(cosmosTx) - client := suite.backend.clientCtx.Client.(*mocks.Client) - suite.backend.allowUnprotectedTxs = true + client := s.backend.ClientCtx.Client.(*mocks.Client) + s.backend.AllowUnprotectedTxs = true RegisterBroadcastTxError(client, txBytes) }, func() []byte { @@ -378,11 +378,11 @@ func (suite *BackendTestSuite) TestSendRawTransaction() { { "pass - Gets the correct transaction hash of the eth transaction", func() { - cosmosTx, _ := ethTx.BuildTx(suite.backend.clientCtx.TxConfig.NewTxBuilder(), evmDenom) - txBytes, _ := suite.backend.clientCtx.TxConfig.TxEncoder()(cosmosTx) + cosmosTx, _ := ethTx.BuildTx(s.backend.ClientCtx.TxConfig.NewTxBuilder(), evmDenom) + txBytes, _ := s.backend.ClientCtx.TxConfig.TxEncoder()(cosmosTx) - client := suite.backend.clientCtx.Client.(*mocks.Client) - suite.backend.allowUnprotectedTxs = true + client := s.backend.ClientCtx.Client.(*mocks.Client) + s.backend.AllowUnprotectedTxs = true RegisterBroadcastTx(client, txBytes) }, func() []byte { return rlpEncodedBz }, @@ -393,26 +393,26 @@ func (suite *BackendTestSuite) TestSendRawTransaction() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock() - hash, err := suite.backend.SendRawTransaction(tc.rawTx()) + hash, err := s.backend.SendRawTransaction(tc.rawTx()) if tc.expPass { - suite.Require().Equal(tc.expHash, hash) + s.Require().Equal(tc.expHash, hash) } else { - suite.Require().Errorf(err, tc.expError) + s.Require().Errorf(err, tc.expError) } }) } } -func (suite *BackendTestSuite) TestDoCall() { - _, bz := suite.buildEthereumTx() +func (s *BackendTestSuite) TestDoCall() { + _, bz := s.buildEthereumTx() gasPrice := (*hexutil.Big)(big.NewInt(1)) toAddr := utiltx.GenerateAddress() - chainID := (*hexutil.Big)(suite.backend.chainID) + evmChainID := (*hexutil.Big)(s.backend.EvmChainID) callArgs := evmtypes.TransactionArgs{ From: nil, To: &toAddr, @@ -424,10 +424,10 @@ func (suite *BackendTestSuite) TestDoCall() { Input: nil, Data: nil, AccessList: nil, - ChainID: chainID, + ChainID: evmChainID, } argsBz, err := json.Marshal(callArgs) - suite.Require().NoError(err) + s.Require().NoError(err) testCases := []struct { name string @@ -440,11 +440,11 @@ func (suite *BackendTestSuite) TestDoCall() { { "fail - Invalid request", func() { - client := suite.backend.clientCtx.Client.(*mocks.Client) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) + client := s.backend.ClientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) _, err := RegisterBlock(client, 1, bz) - suite.Require().NoError(err) - RegisterEthCallError(queryClient, &evmtypes.EthCallRequest{Args: argsBz, ChainId: suite.backend.chainID.Int64()}) + s.Require().NoError(err) + RegisterEthCallError(QueryClient, &evmtypes.EthCallRequest{Args: argsBz, ChainId: s.backend.EvmChainID.Int64()}) }, rpctypes.BlockNumber(1), callArgs, @@ -454,11 +454,11 @@ func (suite *BackendTestSuite) TestDoCall() { { "pass - Returned transaction response", func() { - client := suite.backend.clientCtx.Client.(*mocks.Client) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) + client := s.backend.ClientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) _, err := RegisterBlock(client, 1, bz) - suite.Require().NoError(err) - RegisterEthCall(queryClient, &evmtypes.EthCallRequest{Args: argsBz, ChainId: suite.backend.chainID.Int64()}) + s.Require().NoError(err) + RegisterEthCall(QueryClient, &evmtypes.EthCallRequest{Args: argsBz, ChainId: s.backend.EvmChainID.Int64()}) }, rpctypes.BlockNumber(1), callArgs, @@ -468,22 +468,22 @@ func (suite *BackendTestSuite) TestDoCall() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock() - msgEthTx, err := suite.backend.DoCall(tc.callArgs, tc.blockNum) + msgEthTx, err := s.backend.DoCall(tc.callArgs, tc.blockNum) if tc.expPass { - suite.Require().Equal(tc.expEthTx, msgEthTx) + s.Require().Equal(tc.expEthTx, msgEthTx) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestGasPrice() { +func (s *BackendTestSuite) TestGasPrice() { defaultGasPrice := (*hexutil.Big)(big.NewInt(1)) testCases := []struct { @@ -496,17 +496,17 @@ func (suite *BackendTestSuite) TestGasPrice() { "pass - get the default gas price", func() { var header metadata.MD - client := suite.backend.clientCtx.Client.(*mocks.Client) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - feeMarketClient := suite.backend.queryClient.FeeMarket.(*mocks.FeeMarketQueryClient) + client := s.backend.ClientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + feeMarketClient := s.backend.QueryClient.FeeMarket.(*mocks.FeeMarketQueryClient) RegisterFeeMarketParams(feeMarketClient, 1) - RegisterParams(queryClient, &header, 1) - RegisterGlobalMinGasPrice(queryClient, 1) + RegisterParams(QueryClient, &header, 1) + RegisterGlobalMinGasPrice(QueryClient, 1) _, err := RegisterBlock(client, 1, nil) - suite.Require().NoError(err) + s.Require().NoError(err) _, err = RegisterBlockResults(client, 1) - suite.Require().NoError(err) - RegisterBaseFee(queryClient, math.NewInt(1)) + s.Require().NoError(err) + RegisterBaseFee(QueryClient, math.NewInt(1)) }, defaultGasPrice, true, @@ -515,16 +515,16 @@ func (suite *BackendTestSuite) TestGasPrice() { "fail - can't get gasFee, FeeMarketParams error", func() { var header metadata.MD - client := suite.backend.clientCtx.Client.(*mocks.Client) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - feeMarketClient := suite.backend.queryClient.FeeMarket.(*mocks.FeeMarketQueryClient) + client := s.backend.ClientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + feeMarketClient := s.backend.QueryClient.FeeMarket.(*mocks.FeeMarketQueryClient) RegisterFeeMarketParamsError(feeMarketClient, 1) - RegisterParams(queryClient, &header, 1) + RegisterParams(QueryClient, &header, 1) _, err := RegisterBlock(client, 1, nil) - suite.Require().NoError(err) + s.Require().NoError(err) _, err = RegisterBlockResults(client, 1) - suite.Require().NoError(err) - RegisterBaseFee(queryClient, math.NewInt(1)) + s.Require().NoError(err) + RegisterBaseFee(QueryClient, math.NewInt(1)) }, defaultGasPrice, false, @@ -532,15 +532,15 @@ func (suite *BackendTestSuite) TestGasPrice() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock() - gasPrice, err := suite.backend.GasPrice() + gasPrice, err := s.backend.GasPrice() if tc.expPass { - suite.Require().Equal(tc.expGas, gasPrice) + s.Require().Equal(tc.expGas, gasPrice) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } diff --git a/rpc/backend/chain_info_test.go b/tests/integration/rpc/backend/test_chain_info.go similarity index 58% rename from rpc/backend/chain_info_test.go rename to tests/integration/rpc/backend/test_chain_info.go index 3bba11bed..4cc3eb057 100644 --- a/rpc/backend/chain_info_test.go +++ b/tests/integration/rpc/backend/test_chain_info.go @@ -21,7 +21,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -func (suite *BackendTestSuite) TestBaseFee() { +func (s *BackendTestSuite) TestBaseFee() { baseFee := math.NewInt(1) testCases := []struct { @@ -35,8 +35,8 @@ func (suite *BackendTestSuite) TestBaseFee() { "fail - grpc BaseFee error", &tmrpctypes.ResultBlockResults{Height: 1}, func() { - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFeeError(queryClient) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFeeError(QueryClient) }, nil, false, @@ -52,8 +52,8 @@ func (suite *BackendTestSuite) TestBaseFee() { }, }, func() { - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFeeError(queryClient) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFeeError(QueryClient) }, nil, false, @@ -69,8 +69,8 @@ func (suite *BackendTestSuite) TestBaseFee() { }, }, func() { - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFeeError(queryClient) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFeeError(QueryClient) }, nil, false, @@ -89,8 +89,8 @@ func (suite *BackendTestSuite) TestBaseFee() { }, }, func() { - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFeeError(queryClient) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFeeError(QueryClient) }, nil, false, @@ -109,8 +109,8 @@ func (suite *BackendTestSuite) TestBaseFee() { }, }, func() { - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFeeError(queryClient) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFeeError(QueryClient) }, baseFee.BigInt(), true, @@ -119,8 +119,8 @@ func (suite *BackendTestSuite) TestBaseFee() { "fail - base fee or london fork not enabled", &tmrpctypes.ResultBlockResults{Height: 1}, func() { - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFeeDisabled(queryClient) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFeeDisabled(QueryClient) }, nil, true, @@ -129,31 +129,31 @@ func (suite *BackendTestSuite) TestBaseFee() { "pass", &tmrpctypes.ResultBlockResults{Height: 1}, func() { - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBaseFee(queryClient, baseFee) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBaseFee(QueryClient, baseFee) }, baseFee.BigInt(), true, }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock() - baseFee, err := suite.backend.BaseFee(tc.blockRes) + baseFee, err := s.backend.BaseFee(tc.blockRes) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(tc.expBaseFee, baseFee) + s.Require().NoError(err) + s.Require().Equal(tc.expBaseFee, baseFee) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestChainId() { +func (s *BackendTestSuite) TestChainId() { expChainID := (*hexutil.Big)(big.NewInt(262144)) testCases := []struct { name string @@ -165,8 +165,8 @@ func (suite *BackendTestSuite) TestChainId() { "pass - block is at or past the EIP-155 replay-protection fork block, return chainID from config ", func() { var header metadata.MD - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterParamsInvalidHeight(queryClient, &header, int64(1)) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterParamsInvalidHeight(QueryClient, &header, int64(1)) }, expChainID, true, @@ -174,22 +174,22 @@ func (suite *BackendTestSuite) TestChainId() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock() - chainID, err := suite.backend.ChainID() + chainID, err := s.backend.ChainID() if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(tc.expChainID, chainID) + s.Require().NoError(err) + s.Require().Equal(tc.expChainID, chainID) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestGetCoinbase() { +func (s *BackendTestSuite) TestGetCoinbase() { validatorAcc := sdk.AccAddress(utiltx.GenerateAddress().Bytes()) testCases := []struct { name string @@ -200,7 +200,7 @@ func (suite *BackendTestSuite) TestGetCoinbase() { { "fail - Can't retrieve status from node", func() { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterStatusError(client) }, validatorAcc, @@ -209,10 +209,10 @@ func (suite *BackendTestSuite) TestGetCoinbase() { { "fail - Can't query validator account", func() { - client := suite.backend.clientCtx.Client.(*mocks.Client) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) + client := s.backend.ClientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) RegisterStatus(client) - RegisterValidatorAccountError(queryClient) + RegisterValidatorAccountError(QueryClient) }, validatorAcc, false, @@ -220,10 +220,10 @@ func (suite *BackendTestSuite) TestGetCoinbase() { { "pass - Gets coinbase account", func() { - client := suite.backend.clientCtx.Client.(*mocks.Client) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) + client := s.backend.ClientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) RegisterStatus(client) - RegisterValidatorAccount(queryClient, validatorAcc) + RegisterValidatorAccount(QueryClient, validatorAcc) }, validatorAcc, true, @@ -231,22 +231,22 @@ func (suite *BackendTestSuite) TestGetCoinbase() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock() - accAddr, err := suite.backend.GetCoinbase() + accAddr, err := s.backend.GetCoinbase() if tc.expPass { - suite.Require().Equal(tc.accAddr, accAddr) + s.Require().Equal(tc.accAddr, accAddr) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestSuggestGasTipCap() { +func (s *BackendTestSuite) TestSuggestGasTipCap() { testCases := []struct { name string registerMock func() @@ -271,22 +271,22 @@ func (suite *BackendTestSuite) TestSuggestGasTipCap() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock() - maxDelta, err := suite.backend.SuggestGasTipCap(tc.baseFee) + maxDelta, err := s.backend.SuggestGasTipCap(tc.baseFee) if tc.expPass { - suite.Require().Equal(tc.expGasTipCap, maxDelta) + s.Require().Equal(tc.expGasTipCap, maxDelta) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestGlobalMinGasPrice() { +func (s *BackendTestSuite) TestGlobalMinGasPrice() { testCases := []struct { name string registerMock func() @@ -296,7 +296,7 @@ func (suite *BackendTestSuite) TestGlobalMinGasPrice() { { "pass - get GlobalMinGasPrice", func() { - qc := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) + qc := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) RegisterGlobalMinGasPrice(qc, 1) }, big.NewInt(1), @@ -305,22 +305,22 @@ func (suite *BackendTestSuite) TestGlobalMinGasPrice() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock() - globalMinGasPrice, err := suite.backend.GlobalMinGasPrice() + globalMinGasPrice, err := s.backend.GlobalMinGasPrice() if tc.expPass { - suite.Require().Equal(tc.expMinGasPrice, globalMinGasPrice) + s.Require().Equal(tc.expMinGasPrice, globalMinGasPrice) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestFeeHistory() { +func (s *BackendTestSuite) TestFeeHistory() { testCases := []struct { name string registerMock func(validator sdk.AccAddress) @@ -334,9 +334,9 @@ func (suite *BackendTestSuite) TestFeeHistory() { "fail - can't get params ", func(_ sdk.AccAddress) { var header metadata.MD - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - suite.backend.cfg.JSONRPC.FeeHistoryCap = 0 - RegisterParamsError(queryClient, &header, ethrpc.BlockNumber(1).Int64()) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + s.backend.Cfg.JSONRPC.FeeHistoryCap = 0 + RegisterParamsError(QueryClient, &header, ethrpc.BlockNumber(1).Int64()) }, 1, -1, @@ -348,9 +348,9 @@ func (suite *BackendTestSuite) TestFeeHistory() { "fail - user block count higher than max block count ", func(_ sdk.AccAddress) { var header metadata.MD - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - suite.backend.cfg.JSONRPC.FeeHistoryCap = 0 - RegisterParams(queryClient, &header, ethrpc.BlockNumber(1).Int64()) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + s.backend.Cfg.JSONRPC.FeeHistoryCap = 0 + RegisterParams(QueryClient, &header, ethrpc.BlockNumber(1).Int64()) }, 1, -1, @@ -361,8 +361,8 @@ func (suite *BackendTestSuite) TestFeeHistory() { { "fail - Tendermint block fetching error ", func(_ sdk.AccAddress) { - client := suite.backend.clientCtx.Client.(*mocks.Client) - suite.backend.cfg.JSONRPC.FeeHistoryCap = 2 + client := s.backend.ClientCtx.Client.(*mocks.Client) + s.backend.Cfg.JSONRPC.FeeHistoryCap = 2 RegisterBlockError(client, ethrpc.BlockNumber(1).Int64()) }, 1, @@ -374,10 +374,10 @@ func (suite *BackendTestSuite) TestFeeHistory() { { "fail - Eth block fetching error", func(sdk.AccAddress) { - client := suite.backend.clientCtx.Client.(*mocks.Client) - suite.backend.cfg.JSONRPC.FeeHistoryCap = 2 + client := s.backend.ClientCtx.Client.(*mocks.Client) + s.backend.Cfg.JSONRPC.FeeHistoryCap = 2 _, err := RegisterBlock(client, ethrpc.BlockNumber(1).Int64(), nil) - suite.Require().NoError(err) + s.Require().NoError(err) RegisterBlockResultsError(client, 1) }, 1, @@ -390,15 +390,15 @@ func (suite *BackendTestSuite) TestFeeHistory() { "fail - Invalid base fee", func(validator sdk.AccAddress) { // baseFee := math.NewInt(1) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - client := suite.backend.clientCtx.Client.(*mocks.Client) - suite.backend.cfg.JSONRPC.FeeHistoryCap = 2 + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + client := s.backend.ClientCtx.Client.(*mocks.Client) + s.backend.Cfg.JSONRPC.FeeHistoryCap = 2 _, err := RegisterBlock(client, ethrpc.BlockNumber(1).Int64(), nil) - suite.Require().NoError(err) + s.Require().NoError(err) _, err = RegisterBlockResults(client, 1) - suite.Require().NoError(err) - RegisterBaseFeeError(queryClient) - RegisterValidatorAccount(queryClient, validator) + s.Require().NoError(err) + RegisterBaseFeeError(QueryClient) + RegisterValidatorAccount(QueryClient, validator) RegisterConsensusParams(client, 1) }, 1, @@ -412,17 +412,17 @@ func (suite *BackendTestSuite) TestFeeHistory() { func(validator sdk.AccAddress) { var header metadata.MD baseFee := math.NewInt(1) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - client := suite.backend.clientCtx.Client.(*mocks.Client) - suite.backend.cfg.JSONRPC.FeeHistoryCap = 2 + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + client := s.backend.ClientCtx.Client.(*mocks.Client) + s.backend.Cfg.JSONRPC.FeeHistoryCap = 2 _, err := RegisterBlock(client, ethrpc.BlockNumber(1).Int64(), nil) - suite.Require().NoError(err) + s.Require().NoError(err) _, err = RegisterBlockResults(client, 1) - suite.Require().NoError(err) - RegisterBaseFee(queryClient, baseFee) - RegisterValidatorAccount(queryClient, validator) + s.Require().NoError(err) + RegisterBaseFee(QueryClient, baseFee) + RegisterValidatorAccount(QueryClient, validator) RegisterConsensusParams(client, 1) - RegisterParams(queryClient, &header, 1) + RegisterParams(QueryClient, &header, 1) }, 1, 1, @@ -438,16 +438,16 @@ func (suite *BackendTestSuite) TestFeeHistory() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock(tc.validator) - feeHistory, err := suite.backend.FeeHistory(tc.userBlockCount, tc.latestBlock, []float64{25, 50, 75, 100}) + feeHistory, err := s.backend.FeeHistory(tc.userBlockCount, tc.latestBlock, []float64{25, 50, 75, 100}) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(feeHistory, tc.expFeeHistory) + s.Require().NoError(err) + s.Require().Equal(feeHistory, tc.expFeeHistory) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } diff --git a/rpc/backend/client_test.go b/tests/integration/rpc/backend/test_client.go similarity index 100% rename from rpc/backend/client_test.go rename to tests/integration/rpc/backend/test_client.go diff --git a/rpc/backend/evm_query_client_test.go b/tests/integration/rpc/backend/test_evm_query_client.go similarity index 100% rename from rpc/backend/evm_query_client_test.go rename to tests/integration/rpc/backend/test_evm_query_client.go diff --git a/rpc/backend/feemarket_query_client_test.go b/tests/integration/rpc/backend/test_feemarket_query_client.go similarity index 100% rename from rpc/backend/feemarket_query_client_test.go rename to tests/integration/rpc/backend/test_feemarket_query_client.go diff --git a/rpc/backend/filters_test.go b/tests/integration/rpc/backend/test_filters.go similarity index 70% rename from rpc/backend/filters_test.go rename to tests/integration/rpc/backend/test_filters.go index 5d17e88a5..d6df8cd88 100644 --- a/rpc/backend/filters_test.go +++ b/tests/integration/rpc/backend/test_filters.go @@ -13,13 +13,13 @@ import ( evmtypes "github.com/cosmos/evm/x/vm/types" ) -func (suite *BackendTestSuite) TestGetLogs() { - _, bz := suite.buildEthereumTx() +func (s *BackendTestSuite) TestGetLogs() { + _, bz := s.buildEthereumTx() block := cmttypes.MakeBlock(1, []cmttypes.Tx{bz}, nil, nil) logs := make([]*evmtypes.Log, 0, 1) var log evmtypes.Log err := json.Unmarshal([]byte("{\"test\": \"hello\"}"), &log) // TODO refactor this to unmarshall to a log struct successfully - suite.Require().NoError(err) + s.Require().NoError(err) logs = append(logs, &log) @@ -33,7 +33,7 @@ func (suite *BackendTestSuite) TestGetLogs() { { "fail - no block with that hash", func(hash common.Hash) { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterBlockByHashNotFound(client, hash, bz) }, common.Hash{}, @@ -43,7 +43,7 @@ func (suite *BackendTestSuite) TestGetLogs() { { "fail - error fetching block by hash", func(hash common.Hash) { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterBlockByHashError(client, hash, bz) }, common.Hash{}, @@ -53,9 +53,9 @@ func (suite *BackendTestSuite) TestGetLogs() { { "fail - error getting block results", func(hash common.Hash) { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlockByHash(client, hash, bz) - suite.Require().NoError(err) + s.Require().NoError(err) RegisterBlockResultsError(client, 1) }, common.Hash{}, @@ -65,11 +65,11 @@ func (suite *BackendTestSuite) TestGetLogs() { { "success - getting logs with block hash", func(hash common.Hash) { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlockByHash(client, hash, bz) - suite.Require().NoError(err) + s.Require().NoError(err) _, err = RegisterBlockResultsWithEventLog(client, ethrpc.BlockNumber(1).Int64()) - suite.Require().NoError(err) + s.Require().NoError(err) }, common.BytesToHash(block.Hash()), [][]*ethtypes.Log{evmtypes.LogsToEthereum(logs)}, @@ -78,23 +78,23 @@ func (suite *BackendTestSuite) TestGetLogs() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() + s.Run(tc.name, func() { + s.SetupTest() tc.registerMock(tc.blockHash) - logs, err := suite.backend.GetLogs(tc.blockHash) + logs, err := s.backend.GetLogs(tc.blockHash) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(tc.expLogs, logs) + s.Require().NoError(err) + s.Require().Equal(tc.expLogs, logs) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestBloomStatus() { +func (s *BackendTestSuite) TestBloomStatus() { testCases := []struct { name string registerMock func() @@ -110,14 +110,14 @@ func (suite *BackendTestSuite) TestBloomStatus() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() + s.Run(tc.name, func() { + s.SetupTest() tc.registerMock() - bloom, _ := suite.backend.BloomStatus() + bloom, _ := s.backend.BloomStatus() if tc.expPass { - suite.Require().Equal(tc.expResult, bloom) + s.Require().Equal(tc.expResult, bloom) } }) } diff --git a/rpc/backend/node_info_test.go b/tests/integration/rpc/backend/test_node_info.go similarity index 61% rename from rpc/backend/node_info_test.go rename to tests/integration/rpc/backend/test_node_info.go index 055783536..faee2eed0 100644 --- a/rpc/backend/node_info_test.go +++ b/tests/integration/rpc/backend/test_node_info.go @@ -23,7 +23,7 @@ import ( authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) -func (suite *BackendTestSuite) TestRPCMinGasPrice() { +func (s *BackendTestSuite) TestRPCMinGasPrice() { testCases := []struct { name string registerMock func() @@ -45,21 +45,21 @@ func (suite *BackendTestSuite) TestRPCMinGasPrice() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock() - minPrice := suite.backend.RPCMinGasPrice() + minPrice := s.backend.RPCMinGasPrice() if tc.expPass { - suite.Require().Equal(tc.expMinGasPrice, minPrice) + s.Require().Equal(tc.expMinGasPrice, minPrice) } else { - suite.Require().NotEqual(tc.expMinGasPrice, minPrice) + s.Require().NotEqual(tc.expMinGasPrice, minPrice) } }) } } -func (suite *BackendTestSuite) TestGenerateMinGasCoin() { +func (s *BackendTestSuite) TestGenerateMinGasCoin() { defaultGasPrice := (*hexutil.Big)(big.NewInt(1)) testCases := []struct { name string @@ -88,21 +88,21 @@ func (suite *BackendTestSuite) TestGenerateMinGasCoin() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("case %s", tc.name), func() { - suite.SetupTest() // reset test and queries - suite.backend.clientCtx.Viper = viper.New() + s.Run(fmt.Sprintf("case %s", tc.name), func() { + s.SetupTest() // reset test and queries + s.backend.ClientCtx.Viper = viper.New() appConf := config.DefaultConfig() appConf.SetMinGasPrices(tc.minGas) - output := suite.backend.GenerateMinGasCoin(tc.gasPrice, *appConf) - suite.Require().Equal(tc.expectedOutput, output) + output := s.backend.GenerateMinGasCoin(tc.gasPrice, *appConf) + s.Require().Equal(tc.expectedOutput, output) }) } } // TODO: Combine these 2 into one test since the code is identical -func (suite *BackendTestSuite) TestListAccounts() { +func (s *BackendTestSuite) TestListAccounts() { testCases := []struct { name string registerMock func() @@ -118,23 +118,23 @@ func (suite *BackendTestSuite) TestListAccounts() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock() - output, err := suite.backend.ListAccounts() + output, err := s.backend.ListAccounts() if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(tc.expAddr, output) + s.Require().NoError(err) + s.Require().Equal(tc.expAddr, output) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestAccounts() { +func (s *BackendTestSuite) TestAccounts() { testCases := []struct { name string registerMock func() @@ -150,23 +150,23 @@ func (suite *BackendTestSuite) TestAccounts() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock() - output, err := suite.backend.Accounts() + output, err := s.backend.Accounts() if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(tc.expAddr, output) + s.Require().NoError(err) + s.Require().Equal(tc.expAddr, output) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestSyncing() { +func (s *BackendTestSuite) TestSyncing() { testCases := []struct { name string registerMock func() @@ -176,7 +176,7 @@ func (suite *BackendTestSuite) TestSyncing() { { "fail - Can't get status", func() { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterStatusError(client) }, false, @@ -185,7 +185,7 @@ func (suite *BackendTestSuite) TestSyncing() { { "pass - Node not catching up", func() { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterStatus(client) }, false, @@ -194,9 +194,9 @@ func (suite *BackendTestSuite) TestSyncing() { { "pass - Node is catching up", func() { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterStatus(client) - status, _ := client.Status(suite.backend.ctx) + status, _ := client.Status(s.backend.Ctx) status.SyncInfo.CatchingUp = true }, map[string]interface{}{ @@ -208,23 +208,23 @@ func (suite *BackendTestSuite) TestSyncing() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock() - output, err := suite.backend.Syncing() + output, err := s.backend.Syncing() if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(tc.expResponse, output) + s.Require().NoError(err) + s.Require().Equal(tc.expResponse, output) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestSetEtherbase() { +func (s *BackendTestSuite) TestSetEtherbase() { testCases := []struct { name string registerMock func() @@ -234,7 +234,7 @@ func (suite *BackendTestSuite) TestSetEtherbase() { { "pass - Failed to get coinbase address", func() { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterStatusError(client) }, common.Address{}, @@ -243,10 +243,10 @@ func (suite *BackendTestSuite) TestSetEtherbase() { { "pass - the minimum fee is not set", func() { - client := suite.backend.clientCtx.Client.(*mocks.Client) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) + client := s.backend.ClientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) RegisterStatus(client) - RegisterValidatorAccount(queryClient, suite.acc) + RegisterValidatorAccount(QueryClient, s.acc) }, common.Address{}, false, @@ -255,15 +255,15 @@ func (suite *BackendTestSuite) TestSetEtherbase() { "fail - error querying for account", func() { var header metadata.MD - client := suite.backend.clientCtx.Client.(*mocks.Client) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) + client := s.backend.ClientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) RegisterStatus(client) - RegisterValidatorAccount(queryClient, suite.acc) - RegisterParams(queryClient, &header, 1) + RegisterValidatorAccount(QueryClient, s.acc) + RegisterParams(QueryClient, &header, 1) c := sdk.NewDecCoin(constants.ExampleAttoDenom, math.NewIntFromBigInt(big.NewInt(1))) - suite.backend.cfg.SetMinGasPrices(sdk.DecCoins{c}) - delAddr, _ := suite.backend.GetCoinbase() - // account, _ := suite.backend.clientCtx.AccountRetriever.GetAccount(suite.backend.clientCtx, delAddr) + s.backend.Cfg.SetMinGasPrices(sdk.DecCoins{c}) + delAddr, _ := s.backend.GetCoinbase() + // account, _ := s.backend.ClientCtx.AccountRetriever.GetAccount(s.backend.ClientCtx, delAddr) delCommonAddr := common.BytesToAddress(delAddr.Bytes()) request := &authtypes.QueryAccountRequest{Address: sdk.AccAddress(delCommonAddr.Bytes()).String()} requestMarshal, _ := request.Marshal() @@ -281,14 +281,14 @@ func (suite *BackendTestSuite) TestSetEtherbase() { // { // "pass - set the etherbase for the miner", // func() { - // client := suite.backend.clientCtx.Client.(*mocks.Client) - // queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) + // client := s.backend.ClientCtx.Client.(*mocks.Client) + // QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) // RegisterStatus(client) - // RegisterValidatorAccount(queryClient, suite.acc) + // RegisterValidatorAccount(QueryClient, s.acc) // c := sdk.NewDecCoin(testconstants.ExampleAttoDenom, math.NewIntFromBigInt(big.NewInt(1))) - // suite.backend.cfg.SetMinGasPrices(sdk.DecCoins{c}) - // delAddr, _ := suite.backend.GetCoinbase() - // account, _ := suite.backend.clientCtx.AccountRetriever.GetAccount(suite.backend.clientCtx, delAddr) + // s.backend.Cfg.SetMinGasPrices(sdk.DecCoins{c}) + // delAddr, _ := s.backend.GetCoinbase() + // account, _ := s.backend.ClientCtx.AccountRetriever.GetAccount(s.backend.ClientCtx, delAddr) // delCommonAddr := common.BytesToAddress(delAddr.Bytes()) // request := &authtypes.QueryAccountRequest{Address: sdk.AccAddress(delCommonAddr.Bytes()).String()} // requestMarshal, _ := request.Marshal() @@ -305,18 +305,18 @@ func (suite *BackendTestSuite) TestSetEtherbase() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock() - output := suite.backend.SetEtherbase(tc.etherbase) + output := s.backend.SetEtherbase(tc.etherbase) - suite.Require().Equal(tc.expResult, output) + s.Require().Equal(tc.expResult, output) }) } } -func (suite *BackendTestSuite) TestImportRawKey() { +func (s *BackendTestSuite) TestImportRawKey() { priv, _ := ethsecp256k1.GenerateKey() privHex := common.Bytes2Hex(priv.Bytes()) pubAddr := common.BytesToAddress(priv.PubKey().Address().Bytes()) @@ -348,16 +348,16 @@ func (suite *BackendTestSuite) TestImportRawKey() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock() - output, err := suite.backend.ImportRawKey(tc.privKey, tc.password) + output, err := s.backend.ImportRawKey(tc.privKey, tc.password) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(tc.expAddr, output) + s.Require().NoError(err) + s.Require().Equal(tc.expAddr, output) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } diff --git a/rpc/backend/sign_tx_test.go b/tests/integration/rpc/backend/test_sign_tx.go similarity index 60% rename from rpc/backend/sign_tx_test.go rename to tests/integration/rpc/backend/test_sign_tx.go index 06b2b7934..59eb30239 100644 --- a/rpc/backend/sign_tx_test.go +++ b/tests/integration/rpc/backend/test_sign_tx.go @@ -22,7 +22,7 @@ import ( signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" ) -func (suite *BackendTestSuite) TestSendTransaction() { +func (s *BackendTestSuite) TestSendTransaction() { gasPrice := new(hexutil.Big) gas := hexutil.Uint64(1) zeroGas := hexutil.Uint64(0) @@ -59,12 +59,12 @@ func (suite *BackendTestSuite) TestSendTransaction() { "fail - Block error can't set Tx defaults", func() { var header metadata.MD - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - client := suite.backend.clientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + client := s.backend.ClientCtx.Client.(*mocks.Client) armor := crypto.EncryptArmorPrivKey(priv, "", "eth_secp256k1") - err := suite.backend.clientCtx.Keyring.ImportPrivKey("test_key", armor, "") - suite.Require().NoError(err) - RegisterParams(queryClient, &header, 1) + err := s.backend.ClientCtx.Keyring.ImportPrivKey("test_key", armor, "") + s.Require().NoError(err) + RegisterParams(QueryClient, &header, 1) RegisterBlockError(client, 1) }, callArgsDefault, @@ -75,17 +75,17 @@ func (suite *BackendTestSuite) TestSendTransaction() { "fail - Cannot validate transaction gas set to 0", func() { var header metadata.MD - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - client := suite.backend.clientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + client := s.backend.ClientCtx.Client.(*mocks.Client) armor := crypto.EncryptArmorPrivKey(priv, "", "eth_secp256k1") - err := suite.backend.clientCtx.Keyring.ImportPrivKey("test_key", armor, "") - suite.Require().NoError(err) - RegisterParams(queryClient, &header, 1) + err := s.backend.ClientCtx.Keyring.ImportPrivKey("test_key", armor, "") + s.Require().NoError(err) + RegisterParams(QueryClient, &header, 1) _, err = RegisterBlock(client, 1, nil) - suite.Require().NoError(err) + s.Require().NoError(err) _, err = RegisterBlockResults(client, 1) - suite.Require().NoError(err) - RegisterBaseFee(queryClient, baseFee) + s.Require().NoError(err) + RegisterBaseFee(QueryClient, baseFee) }, evmtypes.TransactionArgs{ From: &from, @@ -100,7 +100,7 @@ func (suite *BackendTestSuite) TestSendTransaction() { { "fail - Cannot broadcast transaction", func() { - client, txBytes := broadcastTx(suite, priv, baseFee, callArgsDefault) + client, txBytes := broadcastTx(s, priv, baseFee, callArgsDefault) RegisterBroadcastTxError(client, txBytes) }, callArgsDefault, @@ -110,7 +110,7 @@ func (suite *BackendTestSuite) TestSendTransaction() { { "pass - Return the transaction hash", func() { - client, txBytes := broadcastTx(suite, priv, baseFee, callArgsDefault) + client, txBytes := broadcastTx(s, priv, baseFee, callArgsDefault) RegisterBroadcastTx(client, txBytes) }, callArgsDefault, @@ -120,31 +120,31 @@ func (suite *BackendTestSuite) TestSendTransaction() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock() if tc.expPass { // Sign the transaction and get the hash - ethSigner := ethtypes.LatestSigner(suite.backend.ChainConfig()) + ethSigner := ethtypes.LatestSigner(s.backend.ChainConfig()) msg := callArgsDefault.ToTransaction() - err := msg.Sign(ethSigner, suite.backend.clientCtx.Keyring) - suite.Require().NoError(err) + err := msg.Sign(ethSigner, s.backend.ClientCtx.Keyring) + s.Require().NoError(err) tc.expHash = msg.AsTransaction().Hash() } - responseHash, err := suite.backend.SendTransaction(tc.args) + responseHash, err := s.backend.SendTransaction(tc.args) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(tc.expHash, responseHash) + s.Require().NoError(err) + s.Require().Equal(tc.expHash, responseHash) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestSign() { +func (s *BackendTestSuite) TestSign() { from, priv := utiltx.NewAddrKey() testCases := []struct { name string @@ -164,8 +164,8 @@ func (suite *BackendTestSuite) TestSign() { "pass - sign nil data", func() { armor := crypto.EncryptArmorPrivKey(priv, "", "eth_secp256k1") - err := suite.backend.clientCtx.Keyring.ImportPrivKey("test_key", armor, "") - suite.Require().NoError(err) + err := s.backend.ClientCtx.Keyring.ImportPrivKey("test_key", armor, "") + s.Require().NoError(err) }, from, nil, @@ -174,24 +174,24 @@ func (suite *BackendTestSuite) TestSign() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock() - responseBz, err := suite.backend.Sign(tc.fromAddr, tc.inputBz) + responseBz, err := s.backend.Sign(tc.fromAddr, tc.inputBz) if tc.expPass { - signature, _, err := suite.backend.clientCtx.Keyring.SignByAddress((sdk.AccAddress)(from.Bytes()), tc.inputBz, signingtypes.SignMode_SIGN_MODE_TEXTUAL) + signature, _, err := s.backend.ClientCtx.Keyring.SignByAddress((sdk.AccAddress)(from.Bytes()), tc.inputBz, signingtypes.SignMode_SIGN_MODE_TEXTUAL) signature[goethcrypto.RecoveryIDOffset] += 27 - suite.Require().NoError(err) - suite.Require().Equal((hexutil.Bytes)(signature), responseBz) + s.Require().NoError(err) + s.Require().Equal((hexutil.Bytes)(signature), responseBz) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestSignTypedData() { +func (s *BackendTestSuite) TestSignTypedData() { from, priv := utiltx.NewAddrKey() testCases := []struct { name string @@ -211,8 +211,8 @@ func (suite *BackendTestSuite) TestSignTypedData() { "fail - empty TypeData", func() { armor := crypto.EncryptArmorPrivKey(priv, "", "eth_secp256k1") - err := suite.backend.clientCtx.Keyring.ImportPrivKey("test_key", armor, "") - suite.Require().NoError(err) + err := s.backend.ClientCtx.Keyring.ImportPrivKey("test_key", armor, "") + s.Require().NoError(err) }, from, apitypes.TypedData{}, @@ -222,20 +222,20 @@ func (suite *BackendTestSuite) TestSignTypedData() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock() - responseBz, err := suite.backend.SignTypedData(tc.fromAddr, tc.inputTypedData) + responseBz, err := s.backend.SignTypedData(tc.fromAddr, tc.inputTypedData) if tc.expPass { sigHash, _, _ := apitypes.TypedDataAndHash(tc.inputTypedData) - signature, _, err := suite.backend.clientCtx.Keyring.SignByAddress((sdk.AccAddress)(from.Bytes()), sigHash, signingtypes.SignMode_SIGN_MODE_TEXTUAL) + signature, _, err := s.backend.ClientCtx.Keyring.SignByAddress((sdk.AccAddress)(from.Bytes()), sigHash, signingtypes.SignMode_SIGN_MODE_TEXTUAL) signature[goethcrypto.RecoveryIDOffset] += 27 - suite.Require().NoError(err) - suite.Require().Equal((hexutil.Bytes)(signature), responseBz) + s.Require().NoError(err) + s.Require().Equal((hexutil.Bytes)(signature), responseBz) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } @@ -243,23 +243,23 @@ func (suite *BackendTestSuite) TestSignTypedData() { func broadcastTx(suite *BackendTestSuite, priv *ethsecp256k1.PrivKey, baseFee math.Int, callArgsDefault evmtypes.TransactionArgs) (client *mocks.Client, txBytes []byte) { var header metadata.MD - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - client = suite.backend.clientCtx.Client.(*mocks.Client) + QueryClient := suite.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + client = suite.backend.ClientCtx.Client.(*mocks.Client) armor := crypto.EncryptArmorPrivKey(priv, "", "eth_secp256k1") - _ = suite.backend.clientCtx.Keyring.ImportPrivKey("test_key", armor, "") - RegisterParams(queryClient, &header, 1) + _ = suite.backend.ClientCtx.Keyring.ImportPrivKey("test_key", armor, "") + RegisterParams(QueryClient, &header, 1) _, err := RegisterBlock(client, 1, nil) suite.Require().NoError(err) _, err = RegisterBlockResults(client, 1) suite.Require().NoError(err) - RegisterBaseFee(queryClient, baseFee) + RegisterBaseFee(QueryClient, baseFee) ethSigner := ethtypes.LatestSigner(suite.backend.ChainConfig()) msg := callArgsDefault.ToTransaction() - err = msg.Sign(ethSigner, suite.backend.clientCtx.Keyring) + err = msg.Sign(ethSigner, suite.backend.ClientCtx.Keyring) suite.Require().NoError(err) baseDenom := evmtypes.GetEVMCoinDenom() - tx, _ := msg.BuildTx(suite.backend.clientCtx.TxConfig.NewTxBuilder(), baseDenom) - txEncoder := suite.backend.clientCtx.TxConfig.TxEncoder() + tx, _ := msg.BuildTx(suite.backend.ClientCtx.TxConfig.NewTxBuilder(), baseDenom) + txEncoder := suite.backend.ClientCtx.TxConfig.TxEncoder() txBytes, _ = txEncoder(tx) return client, txBytes } diff --git a/rpc/backend/tracing_test.go b/tests/integration/rpc/backend/test_tracing.go similarity index 72% rename from rpc/backend/tracing_test.go rename to tests/integration/rpc/backend/test_tracing.go index 12e62903e..58c1e56f7 100644 --- a/rpc/backend/tracing_test.go +++ b/tests/integration/rpc/backend/test_tracing.go @@ -21,9 +21,9 @@ import ( "github.com/cosmos/cosmos-sdk/crypto" ) -func (suite *BackendTestSuite) TestTraceTransaction() { - msgEthereumTx, _ := suite.buildEthereumTx() - msgEthereumTx2, _ := suite.buildEthereumTx() +func (s *BackendTestSuite) TestTraceTransaction() { + msgEthereumTx, _ := s.buildEthereumTx() + msgEthereumTx2, _ := s.buildEthereumTx() txHash := msgEthereumTx.AsTransaction().Hash() txHash2 := msgEthereumTx2.AsTransaction().Hash() @@ -31,24 +31,24 @@ func (suite *BackendTestSuite) TestTraceTransaction() { priv, _ := ethsecp256k1.GenerateKey() from := common.BytesToAddress(priv.PubKey().Address().Bytes()) armor := crypto.EncryptArmorPrivKey(priv, "", "eth_secp256k1") - _ = suite.backend.clientCtx.Keyring.ImportPrivKey("test_key", armor, "") + _ = s.backend.ClientCtx.Keyring.ImportPrivKey("test_key", armor, "") - ethSigner := ethtypes.LatestSigner(suite.backend.ChainConfig()) + ethSigner := ethtypes.LatestSigner(s.backend.ChainConfig()) - txEncoder := suite.backend.clientCtx.TxConfig.TxEncoder() + txEncoder := s.backend.ClientCtx.TxConfig.TxEncoder() msgEthereumTx.From = from.String() - _ = msgEthereumTx.Sign(ethSigner, suite.signer) + _ = msgEthereumTx.Sign(ethSigner, s.signer) baseDenom := evmtypes.GetEVMCoinDenom() - tx, _ := msgEthereumTx.BuildTx(suite.backend.clientCtx.TxConfig.NewTxBuilder(), baseDenom) + tx, _ := msgEthereumTx.BuildTx(s.backend.ClientCtx.TxConfig.NewTxBuilder(), baseDenom) txBz, _ := txEncoder(tx) msgEthereumTx2.From = from.String() - _ = msgEthereumTx2.Sign(ethSigner, suite.signer) + _ = msgEthereumTx2.Sign(ethSigner, s.signer) - tx2, _ := msgEthereumTx.BuildTx(suite.backend.clientCtx.TxConfig.NewTxBuilder(), baseDenom) + tx2, _ := msgEthereumTx.BuildTx(s.backend.ClientCtx.TxConfig.NewTxBuilder(), baseDenom) txBz2, _ := txEncoder(tx2) testCases := []struct { @@ -85,7 +85,7 @@ func (suite *BackendTestSuite) TestTraceTransaction() { "fail - block not found", func() { // var header metadata.MD - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterBlockError(client, 1) }, &types.Block{Header: types.Header{Height: 1}, Data: types.Data{Txs: []types.Tx{txBz}}}, @@ -111,13 +111,13 @@ func (suite *BackendTestSuite) TestTraceTransaction() { "pass - transaction found in a block with multiple transactions", func() { var ( - queryClient = suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - client = suite.backend.clientCtx.Client.(*mocks.Client) + QueryClient = s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + client = s.backend.ClientCtx.Client.(*mocks.Client) height int64 = 1 ) _, err := RegisterBlockMultipleTxs(client, height, []types.Tx{txBz, txBz2}) - suite.Require().NoError(err) - RegisterTraceTransactionWithPredecessors(queryClient, msgEthereumTx, []*evmtypes.MsgEthereumTx{msgEthereumTx}) + s.Require().NoError(err) + RegisterTraceTransactionWithPredecessors(QueryClient, msgEthereumTx, []*evmtypes.MsgEthereumTx{msgEthereumTx}) RegisterConsensusParams(client, height) }, &types.Block{Header: types.Header{Height: 1, ChainID: ChainID.ChainID}, Data: types.Data{Txs: []types.Tx{txBz, txBz2}}}, @@ -156,13 +156,13 @@ func (suite *BackendTestSuite) TestTraceTransaction() { "pass - transaction found", func() { var ( - queryClient = suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - client = suite.backend.clientCtx.Client.(*mocks.Client) + QueryClient = s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + client = s.backend.ClientCtx.Client.(*mocks.Client) height int64 = 1 ) _, err := RegisterBlock(client, height, txBz) - suite.Require().NoError(err) - RegisterTraceTransaction(queryClient, msgEthereumTx) + s.Require().NoError(err) + RegisterTraceTransaction(QueryClient, msgEthereumTx) RegisterConsensusParams(client, height) }, &types.Block{Header: types.Header{Height: 1}, Data: types.Data{Txs: []types.Tx{txBz}}}, @@ -187,29 +187,29 @@ func (suite *BackendTestSuite) TestTraceTransaction() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock() db := dbm.NewMemDB() - suite.backend.indexer = indexer.NewKVIndexer(db, log.NewNopLogger(), suite.backend.clientCtx) + s.backend.Indexer = indexer.NewKVIndexer(db, log.NewNopLogger(), s.backend.ClientCtx) - err := suite.backend.indexer.IndexBlock(tc.block, tc.responseBlock) - suite.Require().NoError(err) - txResult, err := suite.backend.TraceTransaction(txHash, nil) + err := s.backend.Indexer.IndexBlock(tc.block, tc.responseBlock) + s.Require().NoError(err) + txResult, err := s.backend.TraceTransaction(txHash, nil) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(tc.expResult, txResult) + s.Require().NoError(err) + s.Require().Equal(tc.expResult, txResult) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestTraceBlock() { - msgEthTx, bz := suite.buildEthereumTx() +func (s *BackendTestSuite) TestTraceBlock() { + msgEthTx, bz := s.buildEthereumTx() emptyBlock := types.MakeBlock(1, []types.Tx{}, nil, nil) emptyBlock.ChainID = ChainID.ChainID filledBlock := types.MakeBlock(1, []types.Tx{bz}, nil, nil) @@ -236,9 +236,9 @@ func (suite *BackendTestSuite) TestTraceBlock() { { "fail - cannot unmarshal data", func() { - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - client := suite.backend.clientCtx.Client.(*mocks.Client) - RegisterTraceBlock(queryClient, []*evmtypes.MsgEthereumTx{msgEthTx}) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + client := s.backend.ClientCtx.Client.(*mocks.Client) + RegisterTraceBlock(QueryClient, []*evmtypes.MsgEthereumTx{msgEthTx}) RegisterConsensusParams(client, 1) }, []*evmtypes.TxTraceResult{}, @@ -249,17 +249,17 @@ func (suite *BackendTestSuite) TestTraceBlock() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("case %s", tc.name), func() { - suite.SetupTest() // reset test and queries + s.Run(fmt.Sprintf("case %s", tc.name), func() { + s.SetupTest() // reset test and queries tc.registerMock() - traceResults, err := suite.backend.TraceBlock(1, tc.config, tc.resBlock) + traceResults, err := s.backend.TraceBlock(1, tc.config, tc.resBlock) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(tc.expTraceResults, traceResults) + s.Require().NoError(err) + s.Require().Equal(tc.expTraceResults, traceResults) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } diff --git a/rpc/backend/tx_info_test.go b/tests/integration/rpc/backend/test_tx_info.go similarity index 58% rename from rpc/backend/tx_info_test.go rename to tests/integration/rpc/backend/test_tx_info.go index 8652c48f4..57db91d9d 100644 --- a/rpc/backend/tx_info_test.go +++ b/tests/integration/rpc/backend/test_tx_info.go @@ -23,11 +23,11 @@ import ( "cosmossdk.io/math" ) -func (suite *BackendTestSuite) TestGetTransactionByHash() { - msgEthereumTx, _ := suite.buildEthereumTx() +func (s *BackendTestSuite) TestGetTransactionByHash() { + msgEthereumTx, _ := s.buildEthereumTx() txHash := msgEthereumTx.AsTransaction().Hash() - txBz := suite.signAndEncodeEthTx(msgEthereumTx) + txBz := s.signAndEncodeEthTx(msgEthereumTx) block := &types.Block{Header: types.Header{Height: 1, ChainID: "test"}, Data: types.Data{Txs: []types.Tx{txBz}}} responseDeliver := []*abci.ExecTxResult{ { @@ -45,7 +45,7 @@ func (suite *BackendTestSuite) TestGetTransactionByHash() { }, } - rpcTransaction, _ := rpctypes.NewRPCTransaction(msgEthereumTx.AsTransaction(), common.Hash{}, 0, 0, big.NewInt(1), suite.backend.chainID) + rpcTransaction, _ := rpctypes.NewRPCTransaction(msgEthereumTx.AsTransaction(), common.Hash{}, 0, 0, big.NewInt(1), s.backend.EvmChainID) testCases := []struct { name string @@ -57,7 +57,7 @@ func (suite *BackendTestSuite) TestGetTransactionByHash() { { "fail - Block error", func() { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterBlockError(client, 1) }, msgEthereumTx, @@ -67,9 +67,9 @@ func (suite *BackendTestSuite) TestGetTransactionByHash() { { "fail - Block Result error", func() { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlock(client, 1, txBz) - suite.Require().NoError(err) + s.Require().NoError(err) RegisterBlockResultsError(client, 1) }, msgEthereumTx, @@ -79,13 +79,13 @@ func (suite *BackendTestSuite) TestGetTransactionByHash() { { "pass - Base fee error", func() { - client := suite.backend.clientCtx.Client.(*mocks.Client) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) + client := s.backend.ClientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) _, err := RegisterBlock(client, 1, txBz) - suite.Require().NoError(err) + s.Require().NoError(err) _, err = RegisterBlockResults(client, 1) - suite.Require().NoError(err) - RegisterBaseFeeError(queryClient) + s.Require().NoError(err) + RegisterBaseFeeError(QueryClient) }, msgEthereumTx, rpcTransaction, @@ -94,13 +94,13 @@ func (suite *BackendTestSuite) TestGetTransactionByHash() { { "pass - Transaction found and returned", func() { - client := suite.backend.clientCtx.Client.(*mocks.Client) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) + client := s.backend.ClientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) _, err := RegisterBlock(client, 1, txBz) - suite.Require().NoError(err) + s.Require().NoError(err) _, err = RegisterBlockResults(client, 1) - suite.Require().NoError(err) - RegisterBaseFee(queryClient, math.NewInt(1)) + s.Require().NoError(err) + RegisterBaseFee(QueryClient, math.NewInt(1)) }, msgEthereumTx, rpcTransaction, @@ -109,30 +109,30 @@ func (suite *BackendTestSuite) TestGetTransactionByHash() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() // reset + s.Run(tc.name, func() { + s.SetupTest() // reset tc.registerMock() db := dbm.NewMemDB() - suite.backend.indexer = indexer.NewKVIndexer(db, log.NewNopLogger(), suite.backend.clientCtx) - err := suite.backend.indexer.IndexBlock(block, responseDeliver) - suite.Require().NoError(err) + s.backend.Indexer = indexer.NewKVIndexer(db, log.NewNopLogger(), s.backend.ClientCtx) + err := s.backend.Indexer.IndexBlock(block, responseDeliver) + s.Require().NoError(err) - rpcTx, err := suite.backend.GetTransactionByHash(common.HexToHash(tc.tx.Hash)) + rpcTx, err := s.backend.GetTransactionByHash(common.HexToHash(tc.tx.Hash)) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(rpcTx, tc.expRPCTx) + s.Require().NoError(err) + s.Require().Equal(rpcTx, tc.expRPCTx) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestGetTransactionsByHashPending() { - msgEthereumTx, bz := suite.buildEthereumTx() - rpcTransaction, _ := rpctypes.NewRPCTransaction(msgEthereumTx.AsTransaction(), common.Hash{}, 0, 0, big.NewInt(1), suite.backend.chainID) +func (s *BackendTestSuite) TestGetTransactionsByHashPending() { + msgEthereumTx, bz := s.buildEthereumTx() + rpcTransaction, _ := rpctypes.NewRPCTransaction(msgEthereumTx.AsTransaction(), common.Hash{}, 0, 0, big.NewInt(1), s.backend.EvmChainID) testCases := []struct { name string @@ -144,7 +144,7 @@ func (suite *BackendTestSuite) TestGetTransactionsByHashPending() { { "fail - Pending transactions returns error", func() { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterUnconfirmedTxsError(client, nil) }, msgEthereumTx, @@ -154,7 +154,7 @@ func (suite *BackendTestSuite) TestGetTransactionsByHashPending() { { "fail - Tx not found return nil", func() { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterUnconfirmedTxs(client, nil, nil) }, msgEthereumTx, @@ -164,7 +164,7 @@ func (suite *BackendTestSuite) TestGetTransactionsByHashPending() { { "pass - Tx found and returned", func() { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterUnconfirmedTxs(client, nil, types.Txs{bz}) }, msgEthereumTx, @@ -174,25 +174,25 @@ func (suite *BackendTestSuite) TestGetTransactionsByHashPending() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() // reset + s.Run(tc.name, func() { + s.SetupTest() // reset tc.registerMock() - rpcTx, err := suite.backend.getTransactionByHashPending(common.HexToHash(tc.tx.Hash)) + rpcTx, err := s.backend.GetTransactionByHashPending(common.HexToHash(tc.tx.Hash)) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(rpcTx, tc.expRPCTx) + s.Require().NoError(err) + s.Require().Equal(rpcTx, tc.expRPCTx) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestGetTxByEthHash() { - msgEthereumTx, bz := suite.buildEthereumTx() - rpcTransaction, _ := rpctypes.NewRPCTransaction(msgEthereumTx.AsTransaction(), common.Hash{}, 0, 0, big.NewInt(1), suite.backend.chainID) +func (s *BackendTestSuite) TestGetTxByEthHash() { + msgEthereumTx, bz := s.buildEthereumTx() + rpcTransaction, _ := rpctypes.NewRPCTransaction(msgEthereumTx.AsTransaction(), common.Hash{}, 0, 0, big.NewInt(1), s.backend.EvmChainID) testCases := []struct { name string @@ -204,8 +204,8 @@ func (suite *BackendTestSuite) TestGetTxByEthHash() { { "fail - Indexer disabled can't find transaction", func() { - suite.backend.indexer = nil - client := suite.backend.clientCtx.Client.(*mocks.Client) + s.backend.Indexer = nil + client := s.backend.ClientCtx.Client.(*mocks.Client) query := fmt.Sprintf("%s.%s='%s'", evmtypes.TypeMsgEthereumTx, evmtypes.AttributeKeyEthereumTxHash, common.HexToHash(msgEthereumTx.Hash).Hex()) RegisterTxSearch(client, query, bz) }, @@ -216,24 +216,24 @@ func (suite *BackendTestSuite) TestGetTxByEthHash() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() // reset + s.Run(tc.name, func() { + s.SetupTest() // reset tc.registerMock() - rpcTx, err := suite.backend.GetTxByEthHash(common.HexToHash(tc.tx.Hash)) + rpcTx, err := s.backend.GetTxByEthHash(common.HexToHash(tc.tx.Hash)) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(rpcTx, tc.expRPCTx) + s.Require().NoError(err) + s.Require().Equal(rpcTx, tc.expRPCTx) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestGetTransactionByBlockHashAndIndex() { - _, bz := suite.buildEthereumTx() +func (s *BackendTestSuite) TestGetTransactionByBlockHashAndIndex() { + _, bz := s.buildEthereumTx() testCases := []struct { name string @@ -245,7 +245,7 @@ func (suite *BackendTestSuite) TestGetTransactionByBlockHashAndIndex() { { "pass - block not found", func() { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterBlockByHashError(client, common.Hash{}, bz) }, common.Hash{}, @@ -255,9 +255,9 @@ func (suite *BackendTestSuite) TestGetTransactionByBlockHashAndIndex() { { "pass - Block results error", func() { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlockByHash(client, common.Hash{}, bz) - suite.Require().NoError(err) + s.Require().NoError(err) RegisterBlockResultsError(client, 1) }, common.Hash{}, @@ -267,24 +267,24 @@ func (suite *BackendTestSuite) TestGetTransactionByBlockHashAndIndex() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() // reset + s.Run(tc.name, func() { + s.SetupTest() // reset tc.registerMock() - rpcTx, err := suite.backend.GetTransactionByBlockHashAndIndex(tc.blockHash, 1) + rpcTx, err := s.backend.GetTransactionByBlockHashAndIndex(tc.blockHash, 1) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(rpcTx, tc.expRPCTx) + s.Require().NoError(err) + s.Require().Equal(rpcTx, tc.expRPCTx) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestGetTransactionByBlockAndIndex() { - msgEthTx, bz := suite.buildEthereumTx() +func (s *BackendTestSuite) TestGetTransactionByBlockAndIndex() { + msgEthTx, bz := s.buildEthereumTx() defaultBlock := types.MakeBlock(1, []types.Tx{bz}, nil, nil) defaultExecTxResult := []*abci.ExecTxResult{ @@ -309,7 +309,7 @@ func (suite *BackendTestSuite) TestGetTransactionByBlockAndIndex() { 1, 0, big.NewInt(1), - suite.backend.chainID, + s.backend.EvmChainID, ) testCases := []struct { name string @@ -322,9 +322,9 @@ func (suite *BackendTestSuite) TestGetTransactionByBlockAndIndex() { { "pass - block txs index out of bound", func() { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlockResults(client, 1) - suite.Require().NoError(err) + s.Require().NoError(err) }, &tmrpctypes.ResultBlock{Block: types.MakeBlock(1, []types.Tx{bz}, nil, nil)}, 1, @@ -334,11 +334,11 @@ func (suite *BackendTestSuite) TestGetTransactionByBlockAndIndex() { { "pass - Can't fetch base fee", func() { - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - client := suite.backend.clientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlockResults(client, 1) - suite.Require().NoError(err) - RegisterBaseFeeError(queryClient) + s.Require().NoError(err) + RegisterBaseFeeError(QueryClient) }, &tmrpctypes.ResultBlock{Block: defaultBlock}, 0, @@ -348,17 +348,17 @@ func (suite *BackendTestSuite) TestGetTransactionByBlockAndIndex() { { "pass - Gets Tx by transaction index", func() { - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - client := suite.backend.clientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + client := s.backend.ClientCtx.Client.(*mocks.Client) db := dbm.NewMemDB() - suite.backend.indexer = indexer.NewKVIndexer(db, log.NewNopLogger(), suite.backend.clientCtx) - txBz := suite.signAndEncodeEthTx(msgEthTx) + s.backend.Indexer = indexer.NewKVIndexer(db, log.NewNopLogger(), s.backend.ClientCtx) + txBz := s.signAndEncodeEthTx(msgEthTx) block := &types.Block{Header: types.Header{Height: 1, ChainID: "test"}, Data: types.Data{Txs: []types.Tx{txBz}}} - err := suite.backend.indexer.IndexBlock(block, defaultExecTxResult) - suite.Require().NoError(err) + err := s.backend.Indexer.IndexBlock(block, defaultExecTxResult) + s.Require().NoError(err) _, err = RegisterBlockResults(client, 1) - suite.Require().NoError(err) - RegisterBaseFee(queryClient, math.NewInt(1)) + s.Require().NoError(err) + RegisterBaseFee(QueryClient, math.NewInt(1)) }, &tmrpctypes.ResultBlock{Block: defaultBlock}, 0, @@ -368,11 +368,11 @@ func (suite *BackendTestSuite) TestGetTransactionByBlockAndIndex() { { "pass - returns the Ethereum format transaction by the Ethereum hash", func() { - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - client := suite.backend.clientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + client := s.backend.ClientCtx.Client.(*mocks.Client) _, err := RegisterBlockResults(client, 1) - suite.Require().NoError(err) - RegisterBaseFee(queryClient, math.NewInt(1)) + s.Require().NoError(err) + RegisterBaseFee(QueryClient, math.NewInt(1)) }, &tmrpctypes.ResultBlock{Block: defaultBlock}, 0, @@ -382,24 +382,24 @@ func (suite *BackendTestSuite) TestGetTransactionByBlockAndIndex() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() // reset + s.Run(tc.name, func() { + s.SetupTest() // reset tc.registerMock() - rpcTx, err := suite.backend.GetTransactionByBlockAndIndex(tc.block, tc.idx) + rpcTx, err := s.backend.GetTransactionByBlockAndIndex(tc.block, tc.idx) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(rpcTx, tc.expRPCTx) + s.Require().NoError(err) + s.Require().Equal(rpcTx, tc.expRPCTx) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestGetTransactionByBlockNumberAndIndex() { - msgEthTx, bz := suite.buildEthereumTx() +func (s *BackendTestSuite) TestGetTransactionByBlockNumberAndIndex() { + msgEthTx, bz := s.buildEthereumTx() defaultBlock := types.MakeBlock(1, []types.Tx{bz}, nil, nil) txFromMsg, _ := rpctypes.NewTransactionFromMsg( msgEthTx, @@ -407,7 +407,7 @@ func (suite *BackendTestSuite) TestGetTransactionByBlockNumberAndIndex() { 1, 0, big.NewInt(1), - suite.backend.chainID, + s.backend.EvmChainID, ) testCases := []struct { name string @@ -420,7 +420,7 @@ func (suite *BackendTestSuite) TestGetTransactionByBlockNumberAndIndex() { { "fail - block not found return nil", func() { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterBlockError(client, 1) }, 0, @@ -431,13 +431,13 @@ func (suite *BackendTestSuite) TestGetTransactionByBlockNumberAndIndex() { { "pass - returns the transaction identified by block number and index", func() { - client := suite.backend.clientCtx.Client.(*mocks.Client) - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) + client := s.backend.ClientCtx.Client.(*mocks.Client) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) _, err := RegisterBlock(client, 1, bz) - suite.Require().NoError(err) + s.Require().NoError(err) _, err = RegisterBlockResults(client, 1) - suite.Require().NoError(err) - RegisterBaseFee(queryClient, math.NewInt(1)) + s.Require().NoError(err) + RegisterBaseFee(QueryClient, math.NewInt(1)) }, 0, 0, @@ -447,23 +447,23 @@ func (suite *BackendTestSuite) TestGetTransactionByBlockNumberAndIndex() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() // reset + s.Run(tc.name, func() { + s.SetupTest() // reset tc.registerMock() - rpcTx, err := suite.backend.GetTransactionByBlockNumberAndIndex(tc.blockNum, tc.idx) + rpcTx, err := s.backend.GetTransactionByBlockNumberAndIndex(tc.blockNum, tc.idx) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(rpcTx, tc.expRPCTx) + s.Require().NoError(err) + s.Require().Equal(rpcTx, tc.expRPCTx) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestGetTransactionByTxIndex() { - _, bz := suite.buildEthereumTx() +func (s *BackendTestSuite) TestGetTransactionByTxIndex() { + _, bz := s.buildEthereumTx() testCases := []struct { name string @@ -476,8 +476,8 @@ func (suite *BackendTestSuite) TestGetTransactionByTxIndex() { { "fail - Ethereum tx with query not found", func() { - client := suite.backend.clientCtx.Client.(*mocks.Client) - suite.backend.indexer = nil + client := s.backend.ClientCtx.Client.(*mocks.Client) + s.backend.Indexer = nil RegisterTxSearch(client, "tx.height=0 AND ethereum_tx.txIndex=0", bz) }, 0, @@ -488,23 +488,23 @@ func (suite *BackendTestSuite) TestGetTransactionByTxIndex() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() // reset + s.Run(tc.name, func() { + s.SetupTest() // reset tc.registerMock() - txResults, err := suite.backend.GetTxByTxIndex(tc.height, tc.index) + txResults, err := s.backend.GetTxByTxIndex(tc.height, tc.index) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(txResults, tc.expTxResult) + s.Require().NoError(err) + s.Require().Equal(txResults, tc.expTxResult) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestQueryTendermintTxIndexer() { +func (s *BackendTestSuite) TestQueryTendermintTxIndexer() { testCases := []struct { name string registerMock func() @@ -516,7 +516,7 @@ func (suite *BackendTestSuite) TestQueryTendermintTxIndexer() { { "fail - Ethereum tx with query not found", func() { - client := suite.backend.clientCtx.Client.(*mocks.Client) + client := s.backend.ClientCtx.Client.(*mocks.Client) RegisterTxSearchEmpty(client, "") }, func(_ *rpctypes.ParsedTxs) *rpctypes.ParsedTx { @@ -529,27 +529,27 @@ func (suite *BackendTestSuite) TestQueryTendermintTxIndexer() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() // reset + s.Run(tc.name, func() { + s.SetupTest() // reset tc.registerMock() - txResults, err := suite.backend.queryTendermintTxIndexer(tc.query, tc.txGetter) + txResults, err := s.backend.QueryTendermintTxIndexer(tc.query, tc.txGetter) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(txResults, tc.expTxResult) + s.Require().NoError(err) + s.Require().Equal(txResults, tc.expTxResult) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *BackendTestSuite) TestGetTransactionReceipt() { - msgEthereumTx, _ := suite.buildEthereumTx() +func (s *BackendTestSuite) TestGetTransactionReceipt() { + msgEthereumTx, _ := s.buildEthereumTx() txHash := msgEthereumTx.AsTransaction().Hash() - txBz := suite.signAndEncodeEthTx(msgEthereumTx) + txBz := s.signAndEncodeEthTx(msgEthereumTx) testCases := []struct { name string @@ -564,13 +564,13 @@ func (suite *BackendTestSuite) TestGetTransactionReceipt() { "fail - Receipts do not match", func() { var header metadata.MD - queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - client := suite.backend.clientCtx.Client.(*mocks.Client) - RegisterParams(queryClient, &header, 1) + QueryClient := s.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) + client := s.backend.ClientCtx.Client.(*mocks.Client) + RegisterParams(QueryClient, &header, 1) _, err := RegisterBlock(client, 1, txBz) - suite.Require().NoError(err) + s.Require().NoError(err) _, err = RegisterBlockResults(client, 1) - suite.Require().NoError(err) + s.Require().NoError(err) }, msgEthereumTx, &types.Block{Header: types.Header{Height: 1}, Data: types.Data{Txs: []types.Tx{txBz}}}, @@ -595,28 +595,28 @@ func (suite *BackendTestSuite) TestGetTransactionReceipt() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() // reset + s.Run(tc.name, func() { + s.SetupTest() // reset tc.registerMock() db := dbm.NewMemDB() - suite.backend.indexer = indexer.NewKVIndexer(db, log.NewNopLogger(), suite.backend.clientCtx) - err := suite.backend.indexer.IndexBlock(tc.block, tc.blockResult) - suite.Require().NoError(err) + s.backend.Indexer = indexer.NewKVIndexer(db, log.NewNopLogger(), s.backend.ClientCtx) + err := s.backend.Indexer.IndexBlock(tc.block, tc.blockResult) + s.Require().NoError(err) - txReceipt, err := suite.backend.GetTransactionReceipt(common.HexToHash(tc.tx.Hash)) + txReceipt, err := s.backend.GetTransactionReceipt(common.HexToHash(tc.tx.Hash)) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(txReceipt, tc.expTxReceipt) + s.Require().NoError(err) + s.Require().Equal(txReceipt, tc.expTxReceipt) } else { - suite.Require().NotEqual(txReceipt, tc.expTxReceipt) + s.Require().NotEqual(txReceipt, tc.expTxReceipt) } }) } } -func (suite *BackendTestSuite) TestGetGasUsed() { - origin := suite.backend.cfg.JSONRPC.FixRevertGasRefundHeight +func (s *BackendTestSuite) TestGetGasUsed() { + origin := s.backend.Cfg.JSONRPC.FixRevertGasRefundHeight testCases := []struct { name string fixRevertGasRefundHeight int64 @@ -663,10 +663,10 @@ func (suite *BackendTestSuite) TestGetGasUsed() { }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.backend.cfg.JSONRPC.FixRevertGasRefundHeight = tc.fixRevertGasRefundHeight - suite.Require().Equal(tc.exp, suite.backend.GetGasUsed(tc.txResult, tc.price, tc.gas)) - suite.backend.cfg.JSONRPC.FixRevertGasRefundHeight = origin + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.backend.Cfg.JSONRPC.FixRevertGasRefundHeight = tc.fixRevertGasRefundHeight + s.Require().Equal(tc.exp, s.backend.GetGasUsed(tc.txResult, tc.price, tc.gas)) + s.backend.Cfg.JSONRPC.FixRevertGasRefundHeight = origin }) } } diff --git a/rpc/backend/utils_test.go b/tests/integration/rpc/backend/test_utils.go similarity index 81% rename from rpc/backend/utils_test.go rename to tests/integration/rpc/backend/test_utils.go index e62bffe28..418633534 100644 --- a/rpc/backend/utils_test.go +++ b/tests/integration/rpc/backend/test_utils.go @@ -4,6 +4,8 @@ import ( "fmt" "github.com/cometbft/cometbft/proto/tendermint/crypto" + + backend2 "github.com/cosmos/evm/rpc/backend" ) func mookProofs(num int, withData bool) *crypto.ProofOps { @@ -21,7 +23,7 @@ func mookProofs(num int, withData bool) *crypto.ProofOps { return proofOps } -func (suite *BackendTestSuite) TestGetHexProofs() { +func (s *BackendTestSuite) TestGetHexProofs() { defaultRes := []string{""} testCases := []struct { name string @@ -45,8 +47,8 @@ func (suite *BackendTestSuite) TestGetHexProofs() { }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.Require().Equal(tc.exp, GetHexProofs(tc.proof)) + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.Require().Equal(tc.exp, backend2.GetHexProofs(tc.proof)) }) } } diff --git a/tests/integration/testutil/test_bank.go b/tests/integration/testutil/test_bank.go new file mode 100644 index 000000000..0f3c90b17 --- /dev/null +++ b/tests/integration/testutil/test_bank.go @@ -0,0 +1,71 @@ +//go:build test + +package testutil + +import ( + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/integration/evm/utils" + testkeyring "github.com/cosmos/evm/testutil/keyring" + evmtypes "github.com/cosmos/evm/x/vm/types" + + "cosmossdk.io/math" + + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +func (s *TestSuite) TestCheckBalances() { + testDenom := "atest" + keyring := testkeyring.New(1) + address := keyring.GetAccAddr(0).String() + + testcases := []struct { + name string + decimals uint8 + expAmount math.Int + expPass bool + errContains string + }{ + { + name: "pass - eighteen decimals", + decimals: 18, + expAmount: network.GetInitialAmount(evmtypes.EighteenDecimals), + expPass: true, + }, + { + name: "pass - six decimals", + decimals: 6, + expAmount: network.GetInitialAmount(evmtypes.SixDecimals), + expPass: true, + }, + { + name: "fail - wrong amount", + decimals: 18, + expAmount: math.NewInt(1), + errContains: "expected balance", + }, + } + + for _, tc := range testcases { + balances := []banktypes.Balance{{ + Address: address, + Coins: sdk.NewCoins( + sdk.NewCoin(testDenom, tc.expAmount), + ), + }} + + options := []network.ConfigOption{ + network.WithBaseCoin(testDenom, tc.decimals), + network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), + } + options = append(options, s.options...) + nw := network.New(s.create, options...) + err := utils.CheckBalances(nw.GetContext(), nw.GetBankClient(), balances) + if tc.expPass { + s.NoError(err, "unexpected error checking balances") + } else { + s.Error(err, "expected error checking balances") + s.ErrorContains(err, tc.errContains, "expected different error checking balances") + } + } +} diff --git a/tests/integration/testutil/test_config.go b/tests/integration/testutil/test_config.go new file mode 100644 index 000000000..dac835b44 --- /dev/null +++ b/tests/integration/testutil/test_config.go @@ -0,0 +1,135 @@ +//go:build test + +package testutil + +import ( + testconstants "github.com/cosmos/evm/testutil/constants" + grpchandler "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + testkeyring "github.com/cosmos/evm/testutil/keyring" + evmtypes "github.com/cosmos/evm/x/vm/types" + + "cosmossdk.io/math" + + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +func (s *TestSuite) TestWithChainID() { + eighteenDecimalsCoinInfo := testconstants.ExampleChainCoinInfo[testconstants.ExampleChainID] + sixDecimalsCoinInfo := testconstants.ExampleChainCoinInfo[testconstants.SixDecimalsChainID] + + testCases := []struct { + name string + chainID testconstants.ChainID + evmChainID uint64 + coinInfo evmtypes.EvmCoinInfo + expBaseFee math.LegacyDec + expCosmosAmount math.Int + }{ + { + name: "18 decimals", + chainID: testconstants.ExampleChainID, + coinInfo: eighteenDecimalsCoinInfo, + expBaseFee: math.LegacyNewDec(875_000_000), + expCosmosAmount: network.GetInitialAmount(evmtypes.EighteenDecimals), + }, + { + name: "6 decimals", + chainID: testconstants.SixDecimalsChainID, + coinInfo: sixDecimalsCoinInfo, + expBaseFee: math.LegacyNewDecWithPrec(875, 6), + expCosmosAmount: network.GetInitialAmount(evmtypes.SixDecimals), + }, + } + + for _, tc := range testCases { + // create a new network with 2 pre-funded accounts + keyring := testkeyring.New(1) + + options := []network.ConfigOption{ + network.WithChainID(tc.chainID), + network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), + } + options = append(options, s.options...) + + nw := network.New(s.create, options...) + + handler := grpchandler.NewIntegrationHandler(nw) + + // ------------------------------------------------------------------------------------ + // Checks on initial balances. + // ------------------------------------------------------------------------------------ + + // Evm balance should always be in 18 decimals regardless of the + // chain ID. + + // Evm balance should always be in 18 decimals + req, err := handler.GetBalanceFromEVM(keyring.GetAccAddr(0)) + s.NoError(err, "error getting balances") + s.Equal( + network.GetInitialAmount(evmtypes.EighteenDecimals).String(), + req.Balance, + "expected amount to be in 18 decimals", + ) + + // Bank balance should always be in the original amount. + cReq, err := handler.GetBalanceFromBank(keyring.GetAccAddr(0), tc.coinInfo.Denom) + s.NoError(err, "error getting balances") + s.Equal( + tc.expCosmosAmount.String(), + cReq.Balance.Amount.String(), + "expected amount to be in original decimals", + ) + + // ------------------------------------------------------------------------------------ + // Checks on the base fee. + // ------------------------------------------------------------------------------------ + // Base fee should always be represented with the decimal + // representation of the EVM denom coin. + bfResp, err := handler.GetBaseFee() + s.NoError(err, "error getting base fee") + s.Equal( + tc.expBaseFee.String(), + bfResp.BaseFee.String(), + "expected amount to be in 18 decimals", + ) + } +} + +func (s *TestSuite) TestWithBalances() { + key1Balance := sdk.NewCoins(sdk.NewInt64Coin(testconstants.ExampleAttoDenom, 1e18)) + key2Balance := sdk.NewCoins( + sdk.NewInt64Coin(testconstants.ExampleAttoDenom, 2e18), + sdk.NewInt64Coin("other", 3e18), + ) + + // create a new network with 2 pre-funded accounts + keyring := testkeyring.New(2) + balances := []banktypes.Balance{ + { + Address: keyring.GetAccAddr(0).String(), + Coins: key1Balance, + }, + { + Address: keyring.GetAccAddr(1).String(), + Coins: key2Balance, + }, + } + options := []network.ConfigOption{ + network.WithBalances(balances...), + } + options = append(options, s.options...) + nw := network.New(s.create, options...) + handler := grpchandler.NewIntegrationHandler(nw) + + req, err := handler.GetAllBalances(keyring.GetAccAddr(0)) + s.NoError(err, "error getting balances") + s.Len(req.Balances, 1, "wrong number of balances") + s.Equal(balances[0].Coins, req.Balances, "wrong balances") + + req, err = handler.GetAllBalances(keyring.GetAccAddr(1)) + s.NoError(err, "error getting balances") + s.Len(req.Balances, 2, "wrong number of balances") + s.Equal(balances[1].Coins, req.Balances, "wrong balances") +} diff --git a/tests/integration/testutil/test_evm.go b/tests/integration/testutil/test_evm.go new file mode 100644 index 000000000..1bb4d8d85 --- /dev/null +++ b/tests/integration/testutil/test_evm.go @@ -0,0 +1,69 @@ +//go:build test + +package testutil + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + + "github.com/cosmos/evm/contracts" + testfactory "github.com/cosmos/evm/testutil/integration/evm/factory" + testhandler "github.com/cosmos/evm/testutil/integration/evm/grpc" + testnetwork "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/integration/evm/utils" + testkeyring "github.com/cosmos/evm/testutil/keyring" + testutiltypes "github.com/cosmos/evm/testutil/types" + evmtypes "github.com/cosmos/evm/x/vm/types" +) + +func (s *TestSuite) TestGetERC20Balance() { + keyring := testkeyring.New(1) + options := []testnetwork.ConfigOption{ + testnetwork.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), + } + + options = append(options, s.options...) + network := testnetwork.NewUnitTestNetwork(s.create, options...) + handler := testhandler.NewIntegrationHandler(network) + factory := testfactory.New(network, handler) + + sender := keyring.GetKey(0) + mintAmount := big.NewInt(100) + + // Deploy an ERC-20 contract + erc20Addr, err := factory.DeployContract( + sender.Priv, + evmtypes.EvmTxArgs{}, + testutiltypes.ContractDeploymentData{ + Contract: contracts.ERC20MinterBurnerDecimalsContract, + ConstructorArgs: []interface{}{"TestToken", "TT", uint8(18)}, + }, + ) + s.NoError(err, "failed to deploy contract") + s.NoError(network.NextBlock(), "failed to advance block") + + balance, err := utils.GetERC20Balance(network, erc20Addr, sender.Addr) + s.NoError(err, "failed to get ERC20 balance") + s.Equal(common.Big0.Int64(), balance.Int64(), "expected no balance before minting") + + // Mint some tokens + _, err = factory.ExecuteContractCall( + sender.Priv, + evmtypes.EvmTxArgs{ + To: &erc20Addr, + }, + testutiltypes.CallArgs{ + ContractABI: contracts.ERC20MinterBurnerDecimalsContract.ABI, + MethodName: "mint", + Args: []interface{}{sender.Addr, mintAmount}, + }, + ) + s.NoError(err, "failed to mint tokens") + + s.NoError(network.NextBlock(), "failed to advance block") + + balance, err = utils.GetERC20Balance(network, erc20Addr, sender.Addr) + s.NoError(err, "failed to get ERC20 balance") + s.Equal(mintAmount.Int64(), balance.Int64(), "expected different balance after minting") +} diff --git a/tests/integration/testutil/test_suite.go b/tests/integration/testutil/test_suite.go new file mode 100644 index 000000000..2473a6d72 --- /dev/null +++ b/tests/integration/testutil/test_suite.go @@ -0,0 +1,23 @@ +//go:build test + +package testutil + +import ( + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/testutil/integration/evm/network" +) + +type TestSuite struct { + suite.Suite + + create network.CreateEvmApp + options []network.ConfigOption +} + +func NewTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *TestSuite { + return &TestSuite{ + create: create, + options: options, + } +} diff --git a/wallets/ledger/ledger_suite_test.go b/tests/integration/wallets/test_ledger_suite.go similarity index 77% rename from wallets/ledger/ledger_suite_test.go rename to tests/integration/wallets/test_ledger_suite.go index 54f75e4fc..2f16fc395 100644 --- a/wallets/ledger/ledger_suite_test.go +++ b/tests/integration/wallets/test_ledger_suite.go @@ -1,15 +1,14 @@ -package ledger_test +package wallets import ( "encoding/hex" "fmt" "regexp" - "testing" "github.com/stretchr/testify/suite" "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/network" "github.com/cosmos/evm/wallets/ledger" "github.com/cosmos/evm/wallets/ledger/mocks" "github.com/cosmos/evm/wallets/usbwallet" @@ -17,14 +16,14 @@ import ( "cosmossdk.io/math" "github.com/cosmos/cosmos-sdk/codec" - codecTypes "github.com/cosmos/cosmos-sdk/codec/types" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" - cryptoTypes "github.com/cosmos/cosmos-sdk/crypto/types" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" txTypes "github.com/cosmos/cosmos-sdk/types/tx" "github.com/cosmos/cosmos-sdk/types/tx/signing" - auxTx "github.com/cosmos/cosmos-sdk/x/auth/tx" - bankTypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/cosmos-sdk/x/auth/tx" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) type LedgerTestSuite struct { @@ -34,20 +33,28 @@ type LedgerTestSuite struct { ledger ledger.CosmosEVMSECP256K1 mockWallet *mocks.Wallet hrp string + + create network.CreateEvmApp + options []network.ConfigOption +} + +func NewLedgerTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *LedgerTestSuite { + return &LedgerTestSuite{ + create: create, + options: options, + } } // Load encoding config for sign doc encoding/decoding // This is done on app instantiation. // We use the testutil network to load the encoding config -func init() { - network.New() -} - -func TestLedgerTestSuite(t *testing.T) { - suite.Run(t, new(LedgerTestSuite)) -} +//func init() { +// network.New() +//} func (suite *LedgerTestSuite) SetupTest() { + network.New(suite.create, suite.options...) + suite.hrp = "cosmos" suite.txAmino = suite.getMockTxAmino() @@ -61,7 +68,7 @@ func (suite *LedgerTestSuite) SetupTest() { suite.ledger = ledger.CosmosEVMSECP256K1{Hub: hub, PrimaryWallet: mockWallet} } -func (suite *LedgerTestSuite) newPubKey(pk string) (res cryptoTypes.PubKey) { +func (suite *LedgerTestSuite) newPubKey(pk string) (res cryptotypes.PubKey) { pkBytes, err := hex.DecodeString(pk) suite.Require().NoError(err) @@ -98,10 +105,10 @@ func (suite *LedgerTestSuite) getMockTxAmino() []byte { } func (suite *LedgerTestSuite) getMockTxProtobuf() []byte { - marshaler := codec.NewProtoCodec(codecTypes.NewInterfaceRegistry()) + marshaler := codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) memo := "memo" - msg := bankTypes.NewMsgSend( + msg := banktypes.NewMsgSend( sdk.MustAccAddressFromBech32("cosmos1r5sckdd808qvg7p8d0auaw896zcluqfd7djffp"), sdk.MustAccAddressFromBech32("cosmos10t8ca2w09ykd6ph0agdz5stvgau47whhaggl9a"), []sdk.Coin{ @@ -112,11 +119,11 @@ func (suite *LedgerTestSuite) getMockTxProtobuf() []byte { }, ) - msgAsAny, err := codecTypes.NewAnyWithValue(msg) + msgAsAny, err := codectypes.NewAnyWithValue(msg) suite.Require().NoError(err) body := &txTypes.TxBody{ - Messages: []*codecTypes.Any{ + Messages: []*codectypes.Any{ msgAsAny, }, Memo: memo, @@ -124,7 +131,7 @@ func (suite *LedgerTestSuite) getMockTxProtobuf() []byte { pubKey := suite.newPubKey("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AFB50") - pubKeyAsAny, err := codecTypes.NewAnyWithValue(pubKey) + pubKeyAsAny, err := codectypes.NewAnyWithValue(pubKey) suite.Require().NoError(err) signingMode := txTypes.ModeInfo_Single_{ @@ -151,7 +158,7 @@ func (suite *LedgerTestSuite) getMockTxProtobuf() []byte { bodyBytes := marshaler.MustMarshal(body) authInfoBytes := marshaler.MustMarshal(authInfo) - signBytes, err := auxTx.DirectSignBytes( + signBytes, err := tx.DirectSignBytes( bodyBytes, authInfoBytes, constants.ExampleChainID.ChainID, diff --git a/wallets/ledger/ledger_test.go b/tests/integration/wallets/test_legder.go similarity index 99% rename from wallets/ledger/ledger_test.go rename to tests/integration/wallets/test_legder.go index 635b8a4d2..8f8a915c6 100644 --- a/wallets/ledger/ledger_test.go +++ b/tests/integration/wallets/test_legder.go @@ -1,4 +1,4 @@ -package ledger_test +package wallets import ( gethaccounts "github.com/ethereum/go-ethereum/accounts" diff --git a/wallets/ledger/wallet_test.go b/tests/integration/wallets/test_wallet.go similarity index 98% rename from wallets/ledger/wallet_test.go rename to tests/integration/wallets/test_wallet.go index 27503fe0c..b76771311 100644 --- a/wallets/ledger/wallet_test.go +++ b/tests/integration/wallets/test_wallet.go @@ -1,4 +1,4 @@ -package ledger_test +package wallets import ( "crypto/ecdsa" diff --git a/x/erc20/keeper/allowance_test.go b/tests/integration/x/erc20/test_allowance.go similarity index 70% rename from x/erc20/keeper/allowance_test.go rename to tests/integration/x/erc20/test_allowance.go index 43dd9d751..7a0eeb536 100644 --- a/x/erc20/keeper/allowance_test.go +++ b/tests/integration/x/erc20/test_allowance.go @@ -1,4 +1,4 @@ -package keeper_test +package erc20 import ( "math/big" @@ -14,7 +14,7 @@ import ( errortypes "github.com/cosmos/cosmos-sdk/types/errors" ) -func (suite *KeeperTestSuite) TestGetAllowance() { +func (s *KeeperTestSuite) TestGetAllowance() { var ( ctx sdk.Context expRes *big.Int @@ -43,7 +43,7 @@ func (suite *KeeperTestSuite) TestGetAllowance() { func() { pair := types.NewTokenPair(erc20Addr, "coin", types.OWNER_MODULE) pair.Enabled = false - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) expRes = common.Big0 }, true, @@ -53,7 +53,7 @@ func (suite *KeeperTestSuite) TestGetAllowance() { "pass - allowance does not exist", func() { pair := types.NewTokenPair(erc20Addr, "coin", types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) expRes = common.Big0 }, true, @@ -64,11 +64,11 @@ func (suite *KeeperTestSuite) TestGetAllowance() { func() { // Set TokenPair pair := types.NewTokenPair(erc20Addr, "coin", types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) // Set Allowance - err := suite.network.App.Erc20Keeper.SetAllowance(ctx, erc20Addr, owner, spender, value) - suite.Require().NoError(err) + err := s.network.App.GetErc20Keeper().SetAllowance(ctx, erc20Addr, owner, spender, value) + s.Require().NoError(err) expRes = value }, true, @@ -76,27 +76,27 @@ func (suite *KeeperTestSuite) TestGetAllowance() { }, } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() - ctx = suite.network.GetContext() + s.Run(tc.name, func() { + s.SetupTest() + ctx = s.network.GetContext() tc.malleate() // Get Allowance - res, err := suite.network.App.Erc20Keeper.GetAllowance(ctx, erc20Addr, owner, spender) + res, err := s.network.App.GetErc20Keeper().GetAllowance(ctx, erc20Addr, owner, spender) if tc.expectPass { - suite.Require().NoError(err) - suite.Require().Equal(expRes, res) + s.Require().NoError(err) + s.Require().Equal(expRes, res) } else { - suite.Require().Error(err) - suite.Require().ErrorContains(err, tc.errContains) - suite.Require().Equal(common.Big0, res) + s.Require().Error(err) + s.Require().ErrorContains(err, tc.errContains) + s.Require().Equal(common.Big0, res) } }) } } -func (suite *KeeperTestSuite) TestSetAllowance() { +func (s *KeeperTestSuite) TestSetAllowance() { var ( ctx sdk.Context erc20Addr common.Address @@ -129,7 +129,7 @@ func (suite *KeeperTestSuite) TestSetAllowance() { func() { pair := types.NewTokenPair(erc20Addr, "coin", types.OWNER_MODULE) pair.Enabled = false - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) }, false, types.ErrERC20TokenPairDisabled.Error(), @@ -138,7 +138,7 @@ func (suite *KeeperTestSuite) TestSetAllowance() { "fail - zero owner address", func() { pair := types.NewTokenPair(erc20Addr, "coin", types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) owner = common.HexToAddress("0x0") }, false, @@ -148,7 +148,7 @@ func (suite *KeeperTestSuite) TestSetAllowance() { "fail - zero spender address", func() { pair := types.NewTokenPair(erc20Addr, "coin", types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) spender = common.HexToAddress("0x0") }, false, @@ -158,7 +158,7 @@ func (suite *KeeperTestSuite) TestSetAllowance() { "fail - negative value", func() { pair := types.NewTokenPair(erc20Addr, "coin", types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) value = big.NewInt(-100) }, false, @@ -168,7 +168,7 @@ func (suite *KeeperTestSuite) TestSetAllowance() { "pass - zero value", func() { pair := types.NewTokenPair(erc20Addr, "coin", types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) value = big.NewInt(0) }, true, @@ -178,7 +178,7 @@ func (suite *KeeperTestSuite) TestSetAllowance() { "pass - positive value", func() { pair := types.NewTokenPair(erc20Addr, "coin", types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) value = big.NewInt(100) }, true, @@ -186,26 +186,26 @@ func (suite *KeeperTestSuite) TestSetAllowance() { }, } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() - ctx = suite.network.GetContext() + s.Run(tc.name, func() { + s.SetupTest() + ctx = s.network.GetContext() initArgs() tc.malleate() // Set Allowance - err := suite.network.App.Erc20Keeper.SetAllowance(ctx, erc20Addr, owner, spender, value) + err := s.network.App.GetErc20Keeper().SetAllowance(ctx, erc20Addr, owner, spender, value) if tc.expectPass { - suite.Require().NoError(err) + s.Require().NoError(err) } else { - suite.Require().Error(err) - suite.Require().ErrorContains(err, tc.errContains) + s.Require().Error(err) + s.Require().ErrorContains(err, tc.errContains) } }) } } -func (suite *KeeperTestSuite) TestUnsafeSetAllowance() { +func (s *KeeperTestSuite) TestUnsafeSetAllowance() { var ( ctx sdk.Context erc20Addr common.Address @@ -238,7 +238,7 @@ func (suite *KeeperTestSuite) TestUnsafeSetAllowance() { func() { pair := types.NewTokenPair(erc20Addr, "coin", types.OWNER_MODULE) pair.Enabled = false - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) }, true, "", @@ -247,7 +247,7 @@ func (suite *KeeperTestSuite) TestUnsafeSetAllowance() { "fail - zero owner address", func() { pair := types.NewTokenPair(erc20Addr, "coin", types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) owner = common.HexToAddress("0x0") }, false, @@ -257,7 +257,7 @@ func (suite *KeeperTestSuite) TestUnsafeSetAllowance() { "fail - zero spender address", func() { pair := types.NewTokenPair(erc20Addr, "coin", types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) spender = common.HexToAddress("0x0") }, false, @@ -267,7 +267,7 @@ func (suite *KeeperTestSuite) TestUnsafeSetAllowance() { "fail - negative value", func() { pair := types.NewTokenPair(erc20Addr, "coin", types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) value = big.NewInt(-100) }, false, @@ -277,7 +277,7 @@ func (suite *KeeperTestSuite) TestUnsafeSetAllowance() { "pass - zero value", func() { pair := types.NewTokenPair(erc20Addr, "coin", types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) value = big.NewInt(0) }, true, @@ -287,7 +287,7 @@ func (suite *KeeperTestSuite) TestUnsafeSetAllowance() { "pass - positive value", func() { pair := types.NewTokenPair(erc20Addr, "coin", types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) value = big.NewInt(100) }, true, @@ -295,26 +295,26 @@ func (suite *KeeperTestSuite) TestUnsafeSetAllowance() { }, } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() - ctx = suite.network.GetContext() + s.Run(tc.name, func() { + s.SetupTest() + ctx = s.network.GetContext() initArgs() tc.malleate() // Set Allowance - err := suite.network.App.Erc20Keeper.UnsafeSetAllowance(ctx, erc20Addr, owner, spender, value) + err := s.network.App.GetErc20Keeper().UnsafeSetAllowance(ctx, erc20Addr, owner, spender, value) if tc.expectPass { - suite.Require().NoError(err) + s.Require().NoError(err) } else { - suite.Require().Error(err) - suite.Require().ErrorContains(err, tc.errContains) + s.Require().Error(err) + s.Require().ErrorContains(err, tc.errContains) } }) } } -func (suite *KeeperTestSuite) TestDeleteAllowance() { +func (s *KeeperTestSuite) TestDeleteAllowance() { var ( ctx sdk.Context erc20Addr common.Address @@ -345,7 +345,7 @@ func (suite *KeeperTestSuite) TestDeleteAllowance() { func() { pair := types.NewTokenPair(erc20Addr, "coin", types.OWNER_MODULE) pair.Enabled = false - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) }, false, types.ErrERC20TokenPairDisabled.Error(), @@ -354,7 +354,7 @@ func (suite *KeeperTestSuite) TestDeleteAllowance() { "fail - zero owner address", func() { pair := types.NewTokenPair(erc20Addr, "coin", types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) owner = common.HexToAddress("0x0") }, false, @@ -364,7 +364,7 @@ func (suite *KeeperTestSuite) TestDeleteAllowance() { "fail - zero spender address", func() { pair := types.NewTokenPair(erc20Addr, "coin", types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) spender = common.HexToAddress("0x0") }, false, @@ -374,33 +374,33 @@ func (suite *KeeperTestSuite) TestDeleteAllowance() { "pass - for non-existing allowance", func() { pair := types.NewTokenPair(erc20Addr, "coin", types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) }, true, "", }, } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() - ctx = suite.network.GetContext() + s.Run(tc.name, func() { + s.SetupTest() + ctx = s.network.GetContext() initArgs() tc.malleate() // Delete Allowance - err := suite.network.App.Erc20Keeper.DeleteAllowance(ctx, erc20Addr, owner, spender) + err := s.network.App.GetErc20Keeper().DeleteAllowance(ctx, erc20Addr, owner, spender) if tc.expectPass { - suite.Require().NoError(err) + s.Require().NoError(err) } else { - suite.Require().Error(err) - suite.Require().ErrorContains(err, tc.errContains) + s.Require().Error(err) + s.Require().ErrorContains(err, tc.errContains) } }) } } -func (suite *KeeperTestSuite) TestGetAllowances() { +func (s *KeeperTestSuite) TestGetAllowances() { var ( ctx sdk.Context expRes []types.Allowance @@ -421,13 +421,13 @@ func (suite *KeeperTestSuite) TestGetAllowances() { "pass - even if token pair were deleted, allowances are deleted together and returns empty allowances", func() { pair := types.NewTokenPair(erc20Addr, "coin", types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) - err := suite.network.App.Erc20Keeper.SetAllowance(ctx, erc20Addr, owner, spender, value) - suite.Require().NoError(err) + err := s.network.App.GetErc20Keeper().SetAllowance(ctx, erc20Addr, owner, spender, value) + s.Require().NoError(err) // Delete TokenPair - suite.network.App.Erc20Keeper.DeleteTokenPair(ctx, pair) + s.network.App.GetErc20Keeper().DeleteTokenPair(ctx, pair) expRes = []types.Allowance{} }, @@ -439,13 +439,13 @@ func (suite *KeeperTestSuite) TestGetAllowances() { "pass - even if token pair is disabled, return allowances", func() { pair := types.NewTokenPair(erc20Addr, "coin", types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) - err := suite.network.App.Erc20Keeper.SetAllowance(ctx, erc20Addr, owner, spender, value) - suite.Require().NoError(err) + err := s.network.App.GetErc20Keeper().SetAllowance(ctx, erc20Addr, owner, spender, value) + s.Require().NoError(err) pair.Enabled = false - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) expRes = []types.Allowance{ { @@ -467,10 +467,10 @@ func (suite *KeeperTestSuite) TestGetAllowances() { "pass", func() { pair := types.NewTokenPair(erc20Addr, "coin", types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) - err := suite.network.App.Erc20Keeper.SetAllowance(ctx, erc20Addr, owner, spender, value) - suite.Require().NoError(err) + err := s.network.App.GetErc20Keeper().SetAllowance(ctx, erc20Addr, owner, spender, value) + s.Require().NoError(err) expRes = []types.Allowance{ { @@ -484,15 +484,15 @@ func (suite *KeeperTestSuite) TestGetAllowances() { }, } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() - ctx = suite.network.GetContext() + s.Run(tc.name, func() { + s.SetupTest() + ctx = s.network.GetContext() tc.malleate() // Get Allowance - res := suite.network.App.Erc20Keeper.GetAllowances(ctx) - suite.Require().Equal(expRes, res) + res := s.network.App.GetErc20Keeper().GetAllowances(ctx) + s.Require().Equal(expRes, res) }) } } diff --git a/x/erc20/keeper/dynamic_precompiles_test.go b/tests/integration/x/erc20/test_dynamic_precompiles.go similarity index 50% rename from x/erc20/keeper/dynamic_precompiles_test.go rename to tests/integration/x/erc20/test_dynamic_precompiles.go index 20530dd64..66b4a147d 100644 --- a/x/erc20/keeper/dynamic_precompiles_test.go +++ b/tests/integration/x/erc20/test_dynamic_precompiles.go @@ -1,4 +1,4 @@ -package keeper_test +package erc20 import ( "github.com/ethereum/go-ethereum/common" @@ -12,7 +12,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -func (suite *KeeperTestSuite) TestRegisterERC20CodeHash() { +func (s *KeeperTestSuite) TestRegisterERC20CodeHash() { var ( ctx sdk.Context // bytecode and codeHash is the same for all IBC coins @@ -40,45 +40,45 @@ func (suite *KeeperTestSuite) TestRegisterERC20CodeHash() { { "existent account", func() { - err := suite.network.App.EVMKeeper.SetAccount(ctx, account, statedb.Account{ + err := s.network.App.GetEVMKeeper().SetAccount(ctx, account, statedb.Account{ CodeHash: codeHash, Nonce: nonce, Balance: balance, }) - suite.Require().NoError(err) + s.Require().NoError(err) }, true, }, } for _, tc := range testCases { - suite.SetupTest() // reset - ctx = suite.network.GetContext() + s.SetupTest() // reset + ctx = s.network.GetContext() tc.malleate() - err := suite.network.App.Erc20Keeper.RegisterERC20CodeHash(ctx, account) - suite.Require().NoError(err) + err := s.network.App.GetErc20Keeper().RegisterERC20CodeHash(ctx, account) + s.Require().NoError(err) - acc := suite.network.App.EVMKeeper.GetAccount(ctx, account) - suite.Require().Equal(codeHash, acc.CodeHash) + acc := s.network.App.GetEVMKeeper().GetAccount(ctx, account) + s.Require().Equal(codeHash, acc.CodeHash) if tc.existent { - suite.Require().Equal(balance, acc.Balance) - suite.Require().Equal(nonce, acc.Nonce) + s.Require().Equal(balance, acc.Balance) + s.Require().Equal(nonce, acc.Nonce) } else { - suite.Require().Equal(common.U2560, acc.Balance) - suite.Require().Equal(uint64(0), acc.Nonce) + s.Require().Equal(common.U2560, acc.Balance) + s.Require().Equal(uint64(0), acc.Nonce) } - err = suite.network.App.Erc20Keeper.UnRegisterERC20CodeHash(ctx, account) - suite.Require().NoError(err) + err = s.network.App.GetErc20Keeper().UnRegisterERC20CodeHash(ctx, account) + s.Require().NoError(err) - acc = suite.network.App.EVMKeeper.GetAccount(ctx, account) - suite.Require().Equal(emptyCodeHash, acc.CodeHash) + acc = s.network.App.GetEVMKeeper().GetAccount(ctx, account) + s.Require().Equal(emptyCodeHash, acc.CodeHash) if tc.existent { - suite.Require().Equal(balance, acc.Balance) - suite.Require().Equal(nonce, acc.Nonce) + s.Require().Equal(balance, acc.Balance) + s.Require().Equal(nonce, acc.Nonce) } else { - suite.Require().Equal(common.U2560, acc.Balance) - suite.Require().Equal(uint64(0), acc.Nonce) + s.Require().Equal(common.U2560, acc.Balance) + s.Require().Equal(uint64(0), acc.Nonce) } } diff --git a/x/erc20/keeper/erc20_utils_test.go b/tests/integration/x/erc20/test_erc20_utils.go similarity index 53% rename from x/erc20/keeper/erc20_utils_test.go rename to tests/integration/x/erc20/test_erc20_utils.go index c040a7148..7d92d6333 100644 --- a/x/erc20/keeper/erc20_utils_test.go +++ b/tests/integration/x/erc20/test_erc20_utils.go @@ -1,4 +1,4 @@ -package keeper_test +package erc20 import ( "errors" @@ -9,17 +9,17 @@ import ( abcitypes "github.com/cometbft/cometbft/abci/types" "github.com/cosmos/evm/contracts" - "github.com/cosmos/evm/testutil/integration/os/factory" - evm "github.com/cosmos/evm/x/vm/types" + testutiltypes "github.com/cosmos/evm/testutil/types" + evmtypes "github.com/cosmos/evm/x/vm/types" ) -func (suite *KeeperTestSuite) MintERC20Token(contractAddr, to common.Address, amount *big.Int) (abcitypes.ExecTxResult, error) { - res, err := suite.factory.ExecuteContractCall( - suite.keyring.GetPrivKey(0), - evm.EvmTxArgs{ +func (s *KeeperTestSuite) MintERC20Token(contractAddr, to common.Address, amount *big.Int) (abcitypes.ExecTxResult, error) { + res, err := s.factory.ExecuteContractCall( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{ To: &contractAddr, }, - factory.CallArgs{ + testutiltypes.CallArgs{ ContractABI: contracts.ERC20MinterBurnerDecimalsContract.ABI, MethodName: "mint", Args: []interface{}{to, amount}, @@ -29,18 +29,18 @@ func (suite *KeeperTestSuite) MintERC20Token(contractAddr, to common.Address, am return res, err } - return res, suite.network.NextBlock() + return res, s.network.NextBlock() } -func (suite *KeeperTestSuite) BalanceOf(contract, account common.Address) (interface{}, error) { +func (s *KeeperTestSuite) BalanceOf(contract, account common.Address) (interface{}, error) { erc20 := contracts.ERC20MinterBurnerDecimalsContract.ABI - res, err := suite.factory.ExecuteContractCall( - suite.keyring.GetPrivKey(0), - evm.EvmTxArgs{ + res, err := s.factory.ExecuteContractCall( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{ To: &contract, }, - factory.CallArgs{ + testutiltypes.CallArgs{ ContractABI: erc20, MethodName: "balanceOf", Args: []interface{}{account}, @@ -50,7 +50,7 @@ func (suite *KeeperTestSuite) BalanceOf(contract, account common.Address) (inter return nil, err } - ethRes, err := evm.DecodeTxResponse(res.Data) + ethRes, err := evmtypes.DecodeTxResponse(res.Data) if err != nil { return nil, err } @@ -63,5 +63,5 @@ func (suite *KeeperTestSuite) BalanceOf(contract, account common.Address) (inter return nil, errors.New("nothing unpacked from response") } - return unpacked[0], suite.network.NextBlock() + return unpacked[0], s.network.NextBlock() } diff --git a/x/erc20/keeper/evm_test.go b/tests/integration/x/erc20/test_evm.go similarity index 80% rename from x/erc20/keeper/evm_test.go rename to tests/integration/x/erc20/test_evm.go index ec6a116a7..1ece254d1 100644 --- a/x/erc20/keeper/evm_test.go +++ b/tests/integration/x/erc20/test_evm.go @@ -1,4 +1,4 @@ -package keeper_test +package erc20 import ( "fmt" @@ -7,8 +7,8 @@ import ( "github.com/stretchr/testify/mock" "github.com/cosmos/evm/contracts" - testfactory "github.com/cosmos/evm/testutil/integration/os/factory" utiltx "github.com/cosmos/evm/testutil/tx" + testutiltypes "github.com/cosmos/evm/testutil/types" "github.com/cosmos/evm/x/erc20/keeper" "github.com/cosmos/evm/x/erc20/types" erc20mocks "github.com/cosmos/evm/x/erc20/types/mocks" @@ -19,7 +19,7 @@ import ( govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) -func (suite *KeeperTestSuite) TestQueryERC20() { +func (s *KeeperTestSuite) TestQueryERC20() { var ( contract common.Address ctx sdk.Context @@ -38,41 +38,41 @@ func (suite *KeeperTestSuite) TestQueryERC20() { "ok", func() { var err error - contract, err = suite.factory.DeployContract( - suite.keyring.GetPrivKey(0), + contract, err = s.factory.DeployContract( + s.keyring.GetPrivKey(0), evmtypes.EvmTxArgs{}, - testfactory.ContractDeploymentData{ + testutiltypes.ContractDeploymentData{ Contract: contracts.ERC20MinterBurnerDecimalsContract, ConstructorArgs: []interface{}{"coin", "token", erc20Decimals}, }, ) - suite.Require().NoError(err) - suite.Require().NoError(suite.network.NextBlock()) - ctx = suite.network.GetContext() + s.Require().NoError(err) + s.Require().NoError(s.network.NextBlock()) + ctx = s.network.GetContext() }, true, }, } for _, tc := range testCases { - suite.SetupTest() // reset - ctx = suite.network.GetContext() + s.SetupTest() // reset + ctx = s.network.GetContext() tc.malleate() - res, err := suite.network.App.Erc20Keeper.QueryERC20(ctx, contract) + res, err := s.network.App.GetErc20Keeper().QueryERC20(ctx, contract) if tc.res { - suite.Require().NoError(err) - suite.Require().Equal( + s.Require().NoError(err) + s.Require().Equal( types.ERC20Data{Name: "coin", Symbol: "token", Decimals: erc20Decimals}, res, ) } else { - suite.Require().Error(err) + s.Require().Error(err) } } } -func (suite *KeeperTestSuite) TestBalanceOf() { +func (s *KeeperTestSuite) TestBalanceOf() { var mockEVMKeeper *erc20mocks.EVMKeeper contract := utiltx.GenerateAddress() testCases := []struct { @@ -112,29 +112,30 @@ func (suite *KeeperTestSuite) TestBalanceOf() { }, } for _, tc := range testCases { - suite.SetupTest() // reset + s.SetupTest() // reset mockEVMKeeper = &erc20mocks.EVMKeeper{} - suite.network.App.Erc20Keeper = keeper.NewKeeper( - suite.network.App.GetKey("erc20"), suite.network.App.AppCodec(), + transferKeeper := s.network.App.GetTransferKeeper() + erc20Keeper := keeper.NewKeeper( + s.network.App.GetKey("erc20"), s.network.App.AppCodec(), authtypes.NewModuleAddress(govtypes.ModuleName), - suite.network.App.AccountKeeper, suite.network.App.BankKeeper, - mockEVMKeeper, suite.network.App.StakingKeeper, - &suite.network.App.TransferKeeper, - ) + s.network.App.GetAccountKeeper(), s.network.App.GetBankKeeper(), + mockEVMKeeper, s.network.App.GetStakingKeeper(), + &transferKeeper) + s.network.App.SetErc20Keeper(&erc20Keeper) tc.malleate() abi := contracts.ERC20MinterBurnerDecimalsContract.ABI - balance := suite.network.App.Erc20Keeper.BalanceOf(suite.network.GetContext(), abi, contract, utiltx.GenerateAddress()) + balance := s.network.App.GetErc20Keeper().BalanceOf(s.network.GetContext(), abi, contract, utiltx.GenerateAddress()) if tc.res { - suite.Require().Equal(balance.Int64(), tc.expBalance) + s.Require().Equal(balance.Int64(), tc.expBalance) } else { - suite.Require().Nil(balance) + s.Require().Nil(balance) } } } -func (suite *KeeperTestSuite) TestQueryERC20ForceFail() { +func (s *KeeperTestSuite) TestQueryERC20ForceFail() { var mockEVMKeeper *erc20mocks.EVMKeeper contract := utiltx.GenerateAddress() testCases := []struct { @@ -209,28 +210,30 @@ func (suite *KeeperTestSuite) TestQueryERC20ForceFail() { }, } for _, tc := range testCases { - suite.SetupTest() // reset + s.SetupTest() // reset - // TODO: what's the reason we are using mockEVMKeeper here? Instead of just passing the suite.app.EVMKeeper? + // TODO: what's the reason we are using mockEVMKeeper here? Instead of just passing the s.app.EVMKeeper? mockEVMKeeper = &erc20mocks.EVMKeeper{} - suite.network.App.Erc20Keeper = keeper.NewKeeper( - suite.network.App.GetKey("erc20"), suite.network.App.AppCodec(), - authtypes.NewModuleAddress(govtypes.ModuleName), suite.network.App.AccountKeeper, - suite.network.App.BankKeeper, mockEVMKeeper, suite.network.App.StakingKeeper, - &suite.network.App.TransferKeeper, - ) + transferKeeper := s.network.App.GetTransferKeeper() + erc20Keeper := keeper.NewKeeper( + s.network.App.GetKey("erc20"), s.network.App.AppCodec(), + authtypes.NewModuleAddress(govtypes.ModuleName), + s.network.App.GetAccountKeeper(), s.network.App.GetBankKeeper(), + mockEVMKeeper, s.network.App.GetStakingKeeper(), + &transferKeeper) + s.network.App.SetErc20Keeper(&erc20Keeper) tc.malleate() - res, err := suite.network.App.Erc20Keeper.QueryERC20(suite.network.GetContext(), contract) + res, err := s.network.App.GetErc20Keeper().QueryERC20(s.network.GetContext(), contract) if tc.res { - suite.Require().NoError(err) - suite.Require().Equal( + s.Require().NoError(err) + s.Require().Equal( types.ERC20Data{Name: "coin", Symbol: "token", Decimals: erc20Decimals}, res, ) } else { - suite.Require().Error(err) + s.Require().Error(err) } } } diff --git a/x/erc20/genesis_test.go b/tests/integration/x/erc20/test_genesis.go similarity index 58% rename from x/erc20/genesis_test.go rename to tests/integration/x/erc20/test_genesis.go index 30b31c327..4b419da0f 100644 --- a/x/erc20/genesis_test.go +++ b/tests/integration/x/erc20/test_genesis.go @@ -1,33 +1,23 @@ -package erc20_test +package erc20 import ( - "testing" - "time" - "github.com/stretchr/testify/suite" - "github.com/cometbft/cometbft/crypto/tmhash" - tmproto "github.com/cometbft/cometbft/proto/tendermint/types" - tmversion "github.com/cometbft/cometbft/proto/tendermint/version" - "github.com/cometbft/cometbft/version" - - exampleapp "github.com/cosmos/evm/evmd" - "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/network" utiltx "github.com/cosmos/evm/testutil/tx" "github.com/cosmos/evm/x/erc20" + "github.com/cosmos/evm/x/erc20/keeper" "github.com/cosmos/evm/x/erc20/types" transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" "cosmossdk.io/math" - - sdk "github.com/cosmos/cosmos-sdk/types" ) type GenesisTestSuite struct { suite.Suite - ctx sdk.Context - app *exampleapp.EVMD + network *network.UnitTestNetwork + create network.CreateEvmApp + options []network.ConfigOption genesis types.GenesisState } @@ -35,45 +25,19 @@ const osmoERC20ContractAddr = "0x5D87876250185593977a6F94aF98877a5E7eD60E" var osmoDenom = transfertypes.NewDenom("uosmo", transfertypes.NewHop(transfertypes.PortID, "channel-0")) -func TestGenesisTestSuite(t *testing.T) { - suite.Run(t, new(GenesisTestSuite)) +func NewGenesisTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *GenesisTestSuite { + return &GenesisTestSuite{ + create: create, + options: options, + } } -func (suite *GenesisTestSuite) SetupTest() { - // consensus key - consAddress := sdk.ConsAddress(utiltx.GenerateAddress().Bytes()) - - chainID := constants.ExampleChainID - suite.app = exampleapp.Setup(suite.T(), chainID.ChainID, chainID.EVMChainID) - suite.ctx = suite.app.BaseApp.NewContextLegacy(false, tmproto.Header{ - Height: 1, - ChainID: chainID.ChainID, - Time: time.Now().UTC(), - ProposerAddress: consAddress.Bytes(), - - Version: tmversion.Consensus{ - Block: version.BlockProtocol, - }, - LastBlockId: tmproto.BlockID{ - Hash: tmhash.Sum([]byte("block_id")), - PartSetHeader: tmproto.PartSetHeader{ - Total: 11, - Hash: tmhash.Sum([]byte("partset_header")), - }, - }, - AppHash: tmhash.Sum([]byte("app")), - DataHash: tmhash.Sum([]byte("data")), - EvidenceHash: tmhash.Sum([]byte("evidence")), - ValidatorsHash: tmhash.Sum([]byte("validators")), - NextValidatorsHash: tmhash.Sum([]byte("next_validators")), - ConsensusHash: tmhash.Sum([]byte("consensus")), - LastResultsHash: tmhash.Sum([]byte("last_result")), - }) - - suite.genesis = *types.DefaultGenesisState() +func (s *GenesisTestSuite) SetupTest() { + s.network = network.NewUnitTestNetwork(s.create, s.options...) + s.genesis = *types.DefaultGenesisState() } -func (suite *GenesisTestSuite) TestERC20InitGenesis() { +func (s *GenesisTestSuite) TestERC20InitGenesis() { testCases := []struct { name string genesisState types.GenesisState @@ -151,30 +115,32 @@ func (suite *GenesisTestSuite) TestERC20InitGenesis() { gen := network.CustomGenesisState{ types.ModuleName: &tc.genesisState, // #nosec G601 } - nw := network.NewUnitTestNetwork( + options := []network.ConfigOption{ network.WithCustomGenesis(gen), - ) + } + options = append(options, s.options...) + nw := network.NewUnitTestNetwork(s.create, options...) - params := nw.App.Erc20Keeper.GetParams(nw.GetContext()) + params := nw.App.GetErc20Keeper().GetParams(nw.GetContext()) - tokenPairs := nw.App.Erc20Keeper.GetTokenPairs(nw.GetContext()) - suite.Require().Equal(tc.genesisState.Params, params) + tokenPairs := nw.App.GetErc20Keeper().GetTokenPairs(nw.GetContext()) + s.Require().Equal(tc.genesisState.Params, params) if len(tokenPairs) > 0 { - suite.Require().Equal(tc.genesisState.TokenPairs, tokenPairs, tc.name) + s.Require().Equal(tc.genesisState.TokenPairs, tokenPairs, tc.name) } else { - suite.Require().Len(tc.genesisState.TokenPairs, 0, tc.name) + s.Require().Len(tc.genesisState.TokenPairs, 0, tc.name) } - allowances := nw.App.Erc20Keeper.GetAllowances(nw.GetContext()) + allowances := nw.App.GetErc20Keeper().GetAllowances(nw.GetContext()) if len(allowances) > 0 { - suite.Require().Equal(tc.genesisState.Allowances, allowances, tc.name) + s.Require().Equal(tc.genesisState.Allowances, allowances, tc.name) } else { - suite.Require().Len(tc.genesisState.Allowances, 0, tc.name) + s.Require().Len(tc.genesisState.Allowances, 0, tc.name) } } } -func (suite *GenesisTestSuite) TestErc20ExportGenesis() { +func (s *GenesisTestSuite) TestErc20ExportGenesis() { testGenCases := []struct { name string genesisState types.GenesisState @@ -233,17 +199,20 @@ func (suite *GenesisTestSuite) TestErc20ExportGenesis() { } for _, tc := range testGenCases { - erc20.InitGenesis(suite.ctx, suite.app.Erc20Keeper, suite.app.AccountKeeper, tc.genesisState) - suite.Require().NotPanics(func() { - genesisExported := erc20.ExportGenesis(suite.ctx, suite.app.Erc20Keeper) - params := suite.app.Erc20Keeper.GetParams(suite.ctx) - suite.Require().Equal(genesisExported.Params, params) - - tokenPairs := suite.app.Erc20Keeper.GetTokenPairs(suite.ctx) + erc20Keeper := s.network.App.GetErc20Keeper() + impl, ok := erc20Keeper.(*keeper.Keeper) + s.Require().True(ok, "Erc20Keeper should implement Keeper interface") + erc20.InitGenesis(s.network.GetContext(), *impl, s.network.App.GetAccountKeeper(), tc.genesisState) + s.Require().NotPanics(func() { + genesisExported := erc20.ExportGenesis(s.network.GetContext(), *impl) + params := s.network.App.GetErc20Keeper().GetParams(s.network.GetContext()) + s.Require().Equal(genesisExported.Params, params) + + tokenPairs := s.network.App.GetErc20Keeper().GetTokenPairs(s.network.GetContext()) if len(tokenPairs) > 0 { - suite.Require().Equal(genesisExported.TokenPairs, tokenPairs) + s.Require().Equal(genesisExported.TokenPairs, tokenPairs) } else { - suite.Require().Len(genesisExported.TokenPairs, 0) + s.Require().Len(genesisExported.TokenPairs, 0) } }) } diff --git a/x/erc20/keeper/grpc_query_test.go b/tests/integration/x/erc20/test_grpc_query.go similarity index 68% rename from x/erc20/keeper/grpc_query_test.go rename to tests/integration/x/erc20/test_grpc_query.go index c07ac2c41..a78348c31 100644 --- a/x/erc20/keeper/grpc_query_test.go +++ b/tests/integration/x/erc20/test_grpc_query.go @@ -1,9 +1,10 @@ -package keeper_test +package erc20 import ( "fmt" - exampleapp "github.com/cosmos/evm/evmd" + exampleapp "cosmosevm.io/evmd" + testconstants "github.com/cosmos/evm/testutil/constants" utiltx "github.com/cosmos/evm/testutil/tx" "github.com/cosmos/evm/x/erc20/types" @@ -12,7 +13,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/query" ) -func (suite *KeeperTestSuite) TestTokenPairs() { +func (s *KeeperTestSuite) TestTokenPairs() { var ( ctx sdk.Context req *types.QueryTokenPairsRequest @@ -45,7 +46,7 @@ func (suite *KeeperTestSuite) TestTokenPairs() { } pairs := testconstants.ExampleTokenPairs pair := types.NewTokenPair(utiltx.GenerateAddress(), "coin", types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetTokenPair(ctx, pair) + s.network.App.GetErc20Keeper().SetTokenPair(ctx, pair) pairs = append(pairs, pair) expRes = &types.QueryTokenPairsResponse{ @@ -63,8 +64,8 @@ func (suite *KeeperTestSuite) TestTokenPairs() { pair := types.NewTokenPair(utiltx.GenerateAddress(), "coin", types.OWNER_MODULE) pair2 := types.NewTokenPair(utiltx.GenerateAddress(), "coin2", types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetTokenPair(ctx, pair) - suite.network.App.Erc20Keeper.SetTokenPair(ctx, pair2) + s.network.App.GetErc20Keeper().SetTokenPair(ctx, pair) + s.network.App.GetErc20Keeper().SetTokenPair(ctx, pair2) pairs = append(pairs, pair, pair2) expRes = &types.QueryTokenPairsResponse{ @@ -76,25 +77,25 @@ func (suite *KeeperTestSuite) TestTokenPairs() { }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() // reset - ctx = suite.network.GetContext() + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // reset + ctx = s.network.GetContext() tc.malleate() - res, err := suite.queryClient.TokenPairs(ctx, req) + res, err := s.queryClient.TokenPairs(ctx, req) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(expRes.Pagination, res.Pagination) - suite.Require().ElementsMatch(expRes.TokenPairs, res.TokenPairs) + s.Require().NoError(err) + s.Require().Equal(expRes.Pagination, res.Pagination) + s.Require().ElementsMatch(expRes.TokenPairs, res.TokenPairs) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *KeeperTestSuite) TestTokenPair() { +func (s *KeeperTestSuite) TestTokenPair() { var ( ctx sdk.Context req *types.QueryTokenPairRequest @@ -129,7 +130,7 @@ func (suite *KeeperTestSuite) TestTokenPair() { func() { addr := utiltx.GenerateAddress() pair := types.NewTokenPair(addr, "coin", types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) req = &types.QueryTokenPairRequest{ Token: pair.Erc20Address, } @@ -142,8 +143,8 @@ func (suite *KeeperTestSuite) TestTokenPair() { func() { addr := utiltx.GenerateAddress() pair := types.NewTokenPair(addr, "coin", types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetERC20Map(ctx, addr, pair.GetID()) - suite.network.App.Erc20Keeper.SetDenomMap(ctx, pair.Denom, pair.GetID()) + s.network.App.GetErc20Keeper().SetERC20Map(ctx, addr, pair.GetID()) + s.network.App.GetErc20Keeper().SetDenomMap(ctx, pair.Denom, pair.GetID()) req = &types.QueryTokenPairRequest{ Token: pair.Erc20Address, @@ -154,29 +155,29 @@ func (suite *KeeperTestSuite) TestTokenPair() { }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() // reset - ctx = suite.network.GetContext() + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // reset + ctx = s.network.GetContext() tc.malleate() - res, err := suite.queryClient.TokenPair(ctx, req) + res, err := s.queryClient.TokenPair(ctx, req) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(expRes, res) + s.Require().NoError(err) + s.Require().Equal(expRes, res) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *KeeperTestSuite) TestQueryParams() { - suite.SetupTest() - ctx := suite.network.GetContext() +func (s *KeeperTestSuite) TestQueryParams() { + s.SetupTest() + ctx := s.network.GetContext() expParams := exampleapp.NewErc20GenesisState().Params - res, err := suite.queryClient.Params(ctx, &types.QueryParamsRequest{}) - suite.Require().NoError(err) - suite.Require().Equal(expParams, res.Params) + res, err := s.queryClient.Params(ctx, &types.QueryParamsRequest{}) + s.Require().NoError(err) + s.Require().Equal(expParams, res.Params) } diff --git a/x/erc20/keeper/ibc_callbacks_test.go b/tests/integration/x/erc20/test_ibc_callback.go similarity index 70% rename from x/erc20/keeper/ibc_callbacks_test.go rename to tests/integration/x/erc20/test_ibc_callback.go index 0a2d97e1f..e49490bf2 100644 --- a/x/erc20/keeper/ibc_callbacks_test.go +++ b/tests/integration/x/erc20/test_ibc_callback.go @@ -1,4 +1,4 @@ -package keeper_test +package erc20 import ( "errors" @@ -29,7 +29,7 @@ import ( var erc20Denom = "erc20:0xdac17f958d2ee523a2206206994597c13d831ec7" -func (suite *KeeperTestSuite) TestOnRecvPacket() { +func (s *KeeperTestSuite) TestOnRecvPacket() { var ctx sdk.Context // secp256k1 account secpPk := secp256k1.GenPrivKey() @@ -38,7 +38,7 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() { // ethsecp256k1 account ethPk, err := ethsecp256k1.GenerateKey() - suite.Require().Nil(err) + s.Require().Nil(err) ethsecpAddr := sdk.AccAddress(ethPk.PubKey().Address()) ethsecpAddrEvmos := sdk.AccAddress(ethPk.PubKey().Address()).String() ethsecpAddrCosmos := sdk.MustBech32ifyAddressBytes(sdk.Bech32MainPrefix, ethsecpAddr) @@ -55,7 +55,7 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() { expAck := ibcmock.MockAcknowledgement baseDenom, err := sdk.GetBaseDenom() - suite.Require().NoError(err, "failed to get base denom") + s.Require().NoError(err, "failed to get base denom") registeredDenom := cosmosTokenBase coins := sdk.NewCoins( sdk.NewCoin(baseDenom, math.NewInt(1000)), @@ -154,7 +154,7 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() { { name: "no-op - receiver is module account", malleate: func() { - secpAddr = suite.network.App.AccountKeeper.GetModuleAccount(ctx, "erc20").GetAddress() + secpAddr = s.network.App.GetAccountKeeper().GetModuleAccount(ctx, "erc20").GetAddress() transfer := transfertypes.NewFungibleTokenPacketData(registeredDenom, "100", secpAddrCosmos, secpAddr.String(), "") bz := transfertypes.ModuleCdc.MustMarshalJSON(&transfer) packet = channeltypes.NewPacket(bz, 100, transfertypes.PortID, sourceChannel, transfertypes.PortID, cosmosEVMChannel, timeoutHeight, 0) @@ -170,8 +170,8 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() { malleate: func() { // base denom should be prefixed hop := transfertypes.NewHop(transfertypes.PortID, sourceChannel) - bondDenom, err := suite.network.App.StakingKeeper.BondDenom(ctx) - suite.Require().NoError(err) + bondDenom, err := s.network.App.GetStakingKeeper().BondDenom(ctx) + s.Require().NoError(err) prefixedDenom := transfertypes.NewDenom(bondDenom, hop).Path() transfer := transfertypes.NewFungibleTokenPacketData(prefixedDenom, "100", secpAddrCosmos, ethsecpAddrEvmos, "") bz := transfertypes.ModuleCdc.MustMarshalJSON(&transfer) @@ -220,22 +220,22 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() { }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.mintFeeCollector = true - suite.SetupTest() // reset - ctx = suite.network.GetContext() + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.mintFeeCollector = true + s.SetupTest() // reset + ctx = s.network.GetContext() tc.malleate() // Register Token Pair for testing - contractAddr, err := suite.setupRegisterERC20Pair(contractMinterBurner) - suite.Require().NoError(err, "failed to register pair") + contractAddr, err := s.setupRegisterERC20Pair(contractMinterBurner) + s.Require().NoError(err, "failed to register pair") // get updated context after registering ERC20 pair - ctx = suite.network.GetContext() + ctx = s.network.GetContext() // Set Denom denom := transfertypes.NewDenom(registeredDenom, hop) - suite.network.App.TransferKeeper.SetDenom(ctx, denom) + s.network.App.GetTransferKeeper().SetDenom(ctx, denom) // Set Cosmos Channel channel := channeltypes.Channel{ @@ -244,74 +244,76 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() { Counterparty: channeltypes.NewCounterparty(transfertypes.PortID, sourceChannel), ConnectionHops: []string{sourceChannel}, } - suite.network.App.IBCKeeper.ChannelKeeper.SetChannel(ctx, transfertypes.PortID, cosmosEVMChannel, channel) + s.network.App.GetIBCKeeper().ChannelKeeper.SetChannel(ctx, transfertypes.PortID, cosmosEVMChannel, channel) // Set Next Sequence Send - suite.network.App.IBCKeeper.ChannelKeeper.SetNextSequenceSend(ctx, transfertypes.PortID, cosmosEVMChannel, 1) + s.network.App.GetIBCKeeper().ChannelKeeper.SetNextSequenceSend(ctx, transfertypes.PortID, cosmosEVMChannel, 1) - suite.network.App.Erc20Keeper = keeper.NewKeeper( - suite.network.App.GetKey(types.StoreKey), - suite.network.App.AppCodec(), + tranasferKeeper := s.network.App.GetTransferKeeper() + erc20Keeper := keeper.NewKeeper( + s.network.App.GetKey(types.StoreKey), + s.network.App.AppCodec(), authtypes.NewModuleAddress(govtypes.ModuleName), - suite.network.App.AccountKeeper, - suite.network.App.BankKeeper, - suite.network.App.EVMKeeper, - suite.network.App.StakingKeeper, - &suite.network.App.TransferKeeper, + s.network.App.GetAccountKeeper(), + s.network.App.GetBankKeeper(), + s.network.App.GetEVMKeeper(), + s.network.App.GetStakingKeeper(), + &tranasferKeeper, ) + s.network.App.SetErc20Keeper(&erc20Keeper) // Fund receiver account with ATOM, ERC20 coins and IBC vouchers // We do this since we are interested in the conversion portion w/ OnRecvPacket - err = testutil.FundAccount(ctx, suite.network.App.BankKeeper, tc.receiver, coins) - suite.Require().NoError(err) + err = testutil.FundAccount(ctx, s.network.App.GetBankKeeper(), tc.receiver, coins) + s.Require().NoError(err) - id := suite.network.App.Erc20Keeper.GetTokenPairID(ctx, contractAddr.String()) - pair, _ := suite.network.App.Erc20Keeper.GetTokenPair(ctx, id) - suite.Require().NotNil(pair) + id := s.network.App.GetErc20Keeper().GetTokenPairID(ctx, contractAddr.String()) + pair, _ := s.network.App.GetErc20Keeper().GetTokenPair(ctx, id) + s.Require().NotNil(pair) if tc.disableERC20 { - params := suite.network.App.Erc20Keeper.GetParams(ctx) + params := s.network.App.GetErc20Keeper().GetParams(ctx) params.EnableErc20 = false - suite.network.App.Erc20Keeper.SetParams(ctx, params) //nolint:errcheck + s.network.App.GetErc20Keeper().SetParams(ctx, params) //nolint:errcheck } if tc.disableTokenPair { - _, err := suite.network.App.Erc20Keeper.ToggleConversion(ctx, &types.MsgToggleConversion{ + _, err := s.network.App.GetErc20Keeper().ToggleConversion(ctx, &types.MsgToggleConversion{ Authority: authtypes.NewModuleAddress("gov").String(), Token: pair.Denom, }) - suite.Require().NoError(err) + s.Require().NoError(err) } // Perform IBC callback - ack := suite.network.App.Erc20Keeper.OnRecvPacket(ctx, packet, expAck) + ack := s.network.App.GetErc20Keeper().OnRecvPacket(ctx, packet, expAck) // Check acknowledgement if tc.ackSuccess { - suite.Require().True(ack.Success(), string(ack.Acknowledgement())) - suite.Require().Equal(expAck, ack) + s.Require().True(ack.Success(), string(ack.Acknowledgement())) + s.Require().Equal(expAck, ack) } else { - suite.Require().False(ack.Success(), string(ack.Acknowledgement())) + s.Require().False(ack.Success(), string(ack.Acknowledgement())) } if tc.checkBalances { // Check ERC20 balances - balanceTokenAfter := suite.network.App.Erc20Keeper.BalanceOf(ctx, contracts.ERC20MinterBurnerDecimalsContract.ABI, pair.GetERC20Contract(), common.BytesToAddress(tc.receiver.Bytes())) - suite.Require().Equal(tc.expErc20s.Int64(), balanceTokenAfter.Int64()) + balanceTokenAfter := s.network.App.GetErc20Keeper().BalanceOf(ctx, contracts.ERC20MinterBurnerDecimalsContract.ABI, pair.GetERC20Contract(), common.BytesToAddress(tc.receiver.Bytes())) + s.Require().Equal(tc.expErc20s.Int64(), balanceTokenAfter.Int64()) // Check Cosmos Coin Balances - balances := suite.network.App.BankKeeper.GetAllBalances(ctx, tc.receiver) - suite.Require().Equal(tc.expCoins, balances) + balances := s.network.App.GetBankKeeper().GetAllBalances(ctx, tc.receiver) + s.Require().Equal(tc.expCoins, balances) } }) } } -func (suite *KeeperTestSuite) TestConvertCoinToERC20FromPacket() { +func (s *KeeperTestSuite) TestConvertCoinToERC20FromPacket() { var ctx sdk.Context senderAddr := "cosmos1x2w87cvt5mqjncav4lxy8yfreynn273x34qlwy" baseDenom, err := sdk.GetBaseDenom() - suite.Require().NoError(err) + s.Require().NoError(err) testCases := []struct { name string @@ -337,16 +339,16 @@ func (suite *KeeperTestSuite) TestConvertCoinToERC20FromPacket() { name: "pass - erc20 is disabled", malleate: func() transfertypes.FungibleTokenPacketData { // Register Token Pair for testing - contractAddr, err := suite.setupRegisterERC20Pair(contractMinterBurner) - suite.Require().NoError(err, "failed to register pair") - ctx = suite.network.GetContext() - id := suite.network.App.Erc20Keeper.GetTokenPairID(ctx, contractAddr.String()) - pair, _ := suite.network.App.Erc20Keeper.GetTokenPair(ctx, id) - suite.Require().NotNil(pair) - - params := suite.network.App.Erc20Keeper.GetParams(ctx) + contractAddr, err := s.setupRegisterERC20Pair(contractMinterBurner) + s.Require().NoError(err, "failed to register pair") + ctx = s.network.GetContext() + id := s.network.App.GetErc20Keeper().GetTokenPairID(ctx, contractAddr.String()) + pair, _ := s.network.App.GetErc20Keeper().GetTokenPair(ctx, id) + s.Require().NotNil(pair) + + params := s.network.App.GetErc20Keeper().GetParams(ctx) params.EnableErc20 = false - _ = suite.network.App.Erc20Keeper.SetParams(ctx, params) + _ = s.network.App.GetErc20Keeper().SetParams(ctx, params) return transfertypes.NewFungibleTokenPacketData(pair.Denom, "10", senderAddr, "", "") }, expPass: true, @@ -362,25 +364,25 @@ func (suite *KeeperTestSuite) TestConvertCoinToERC20FromPacket() { name: "pass - erc20 is disabled", malleate: func() transfertypes.FungibleTokenPacketData { // Register Token Pair for testing - contractAddr, err := suite.setupRegisterERC20Pair(contractMinterBurner) - suite.Require().NoError(err, "failed to register pair") - ctx = suite.network.GetContext() - id := suite.network.App.Erc20Keeper.GetTokenPairID(ctx, contractAddr.String()) - pair, _ := suite.network.App.Erc20Keeper.GetTokenPair(ctx, id) - suite.Require().NotNil(pair) + contractAddr, err := s.setupRegisterERC20Pair(contractMinterBurner) + s.Require().NoError(err, "failed to register pair") + ctx = s.network.GetContext() + id := s.network.App.GetErc20Keeper().GetTokenPairID(ctx, contractAddr.String()) + pair, _ := s.network.App.GetErc20Keeper().GetTokenPair(ctx, id) + s.Require().NotNil(pair) err = testutil.FundAccount( ctx, - suite.network.App.BankKeeper, + s.network.App.GetBankKeeper(), sdk.MustAccAddressFromBech32(senderAddr), sdk.NewCoins( sdk.NewCoin(pair.Denom, math.NewInt(100)), ), ) - suite.Require().NoError(err) + s.Require().NoError(err) - _, err = suite.network.App.EVMKeeper.CallEVM(ctx, contracts.ERC20MinterBurnerDecimalsContract.ABI, suite.keyring.GetAddr(0), contractAddr, true, "mint", types.ModuleAddress, big.NewInt(10)) - suite.Require().NoError(err) + _, err = s.network.App.GetEVMKeeper().CallEVM(ctx, contracts.ERC20MinterBurnerDecimalsContract.ABI, s.keyring.GetAddr(0), contractAddr, true, "mint", types.ModuleAddress, big.NewInt(10)) + s.Require().NoError(err) return transfertypes.NewFungibleTokenPacketData(pair.Denom, "10", senderAddr, "", "") }, @@ -388,26 +390,26 @@ func (suite *KeeperTestSuite) TestConvertCoinToERC20FromPacket() { }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.mintFeeCollector = true - defer func() { suite.mintFeeCollector = false }() + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.mintFeeCollector = true + defer func() { s.mintFeeCollector = false }() - suite.SetupTest() // reset - ctx = suite.network.GetContext() + s.SetupTest() // reset + ctx = s.network.GetContext() transfer := tc.malleate() - err := suite.network.App.Erc20Keeper.ConvertCoinToERC20FromPacket(ctx, transfer) + err := s.network.App.GetErc20Keeper().ConvertCoinToERC20FromPacket(ctx, transfer) if tc.expPass { - suite.Require().NoError(err) + s.Require().NoError(err) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *KeeperTestSuite) TestOnAcknowledgementPacket() { +func (s *KeeperTestSuite) TestOnAcknowledgementPacket() { var ( ctx sdk.Context data transfertypes.FungibleTokenPacketData @@ -431,25 +433,25 @@ func (suite *KeeperTestSuite) TestOnAcknowledgementPacket() { name: "no-op - ack error sender is module account", malleate: func() { // Register Token Pair for testing - contractAddr, err := suite.setupRegisterERC20Pair(contractMinterBurner) - suite.Require().NoError(err, "failed to register pair") - ctx = suite.network.GetContext() - id := suite.network.App.Erc20Keeper.GetTokenPairID(ctx, contractAddr.String()) - pair, _ = suite.network.App.Erc20Keeper.GetTokenPair(ctx, id) - suite.Require().NotNil(pair) + contractAddr, err := s.setupRegisterERC20Pair(contractMinterBurner) + s.Require().NoError(err, "failed to register pair") + ctx = s.network.GetContext() + id := s.network.App.GetErc20Keeper().GetTokenPairID(ctx, contractAddr.String()) + pair, _ = s.network.App.GetErc20Keeper().GetTokenPair(ctx, id) + s.Require().NotNil(pair) // for testing purposes we can only fund is not allowed to receive funds - moduleAcc := suite.network.App.AccountKeeper.GetModuleAccount(ctx, "erc20") + moduleAcc := s.network.App.GetAccountKeeper().GetModuleAccount(ctx, "erc20") sender = moduleAcc.GetAddress() err = testutil.FundModuleAccount( ctx, - suite.network.App.BankKeeper, + s.network.App.GetBankKeeper(), moduleAcc.GetName(), sdk.NewCoins( sdk.NewCoin(pair.Denom, math.NewInt(100)), ), ) - suite.Require().NoError(err) + s.Require().NoError(err) ack = channeltypes.NewErrorAcknowledgement(errors.New("")) data = transfertypes.NewFungibleTokenPacketData(pair.Denom, "100", sender.String(), receiver.String(), "") @@ -461,12 +463,12 @@ func (suite *KeeperTestSuite) TestOnAcknowledgementPacket() { name: "no-op - positive ack", malleate: func() { // Register Token Pair for testing - contractAddr, err := suite.setupRegisterERC20Pair(contractMinterBurner) - suite.Require().NoError(err, "failed to register pair") - ctx = suite.network.GetContext() - id := suite.network.App.Erc20Keeper.GetTokenPairID(ctx, contractAddr.String()) - pair, _ = suite.network.App.Erc20Keeper.GetTokenPair(ctx, id) - suite.Require().NotNil(pair) + contractAddr, err := s.setupRegisterERC20Pair(contractMinterBurner) + s.Require().NoError(err, "failed to register pair") + ctx = s.network.GetContext() + id := s.network.App.GetErc20Keeper().GetTokenPairID(ctx, contractAddr.String()) + pair, _ = s.network.App.GetErc20Keeper().GetTokenPair(ctx, id) + s.Require().NotNil(pair) sender = sdk.AccAddress(senderPk.PubKey().Address()) @@ -474,13 +476,13 @@ func (suite *KeeperTestSuite) TestOnAcknowledgementPacket() { // We do this since we are interested in the conversion portion w/ OnRecvPacket err = testutil.FundAccount( ctx, - suite.network.App.BankKeeper, + s.network.App.GetBankKeeper(), sender, sdk.NewCoins( sdk.NewCoin(pair.Denom, math.NewInt(100)), ), ) - suite.Require().NoError(err) + s.Require().NoError(err) ack = channeltypes.NewResultAcknowledgement([]byte{1}) }, @@ -489,35 +491,35 @@ func (suite *KeeperTestSuite) TestOnAcknowledgementPacket() { }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() // reset - ctx = suite.network.GetContext() + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // reset + ctx = s.network.GetContext() tc.malleate() - err := suite.network.App.Erc20Keeper.OnAcknowledgementPacket( + err := s.network.App.GetErc20Keeper().OnAcknowledgementPacket( ctx, channeltypes.Packet{}, data, ack, ) - suite.Require().NoError(err) + s.Require().NoError(err) if tc.expPass { - suite.Require().NoError(err) + s.Require().NoError(err) } else { - suite.Require().Error(err) + s.Require().Error(err) } // check balance is the same as expected - balance := suite.network.App.Erc20Keeper.BalanceOf( + balance := s.network.App.GetErc20Keeper().BalanceOf( ctx, contracts.ERC20MinterBurnerDecimalsContract.ABI, pair.GetERC20Contract(), common.BytesToAddress(sender.Bytes()), ) - suite.Require().Equal(tc.expERC20.Int64(), balance.Int64()) + s.Require().Equal(tc.expERC20.Int64(), balance.Int64()) }) } } -func (suite *KeeperTestSuite) TestOnTimeoutPacket() { +func (s *KeeperTestSuite) TestOnTimeoutPacket() { var ctx sdk.Context testCases := []struct { name string @@ -529,7 +531,7 @@ func (suite *KeeperTestSuite) TestOnTimeoutPacket() { name: "no-op - sender is module account", malleate: func() transfertypes.FungibleTokenPacketData { // any module account can be passed here - moduleAcc := suite.network.App.AccountKeeper.GetModuleAccount(ctx, evmtypes.ModuleName) + moduleAcc := s.network.App.GetAccountKeeper().GetModuleAccount(ctx, evmtypes.ModuleName) return transfertypes.NewFungibleTokenPacketData("", "10", moduleAcc.GetAddress().String(), "", "") }, @@ -537,17 +539,17 @@ func (suite *KeeperTestSuite) TestOnTimeoutPacket() { }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() - ctx = suite.network.GetContext() + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() + ctx = s.network.GetContext() data := tc.malleate() - err := suite.network.App.Erc20Keeper.OnTimeoutPacket(ctx, channeltypes.Packet{}, data) + err := s.network.App.GetErc20Keeper().OnTimeoutPacket(ctx, channeltypes.Packet{}, data) if tc.expPass { - suite.Require().NoError(err) + s.Require().NoError(err) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } diff --git a/tests/integration/x/erc20/test_integration.go b/tests/integration/x/erc20/test_integration.go new file mode 100644 index 000000000..fcbef69b5 --- /dev/null +++ b/tests/integration/x/erc20/test_integration.go @@ -0,0 +1,194 @@ +package erc20 + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + + //nolint:revive // dot imports are fine for Ginkgo + . "github.com/onsi/ginkgo/v2" + //nolint:revive // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" + + "github.com/cosmos/evm/testutil/integration/base/factory" + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/integration/evm/utils" + "github.com/cosmos/evm/x/erc20/types" + + "cosmossdk.io/math" + + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmApp, options ...network.ConfigOption) { + var _ = Describe("Performing EVM transactions", Ordered, func() { + var s *KeeperTestSuite + BeforeEach(func() { + s = NewKeeperTestSuite(create, options...) + s.SetupTest() + }) + + Context("with the ERC20 module disabled", func() { + BeforeEach(func() { + params := types.DefaultParams() + params.EnableErc20 = false + err := utils.UpdateERC20Params(utils.UpdateParamsInput{ + Tf: s.factory, + Network: s.network, + Pk: s.keyring.GetPrivKey(0), + Params: params, + }) + Expect(err).To(BeNil()) + }) + It("should be successful", func() { + _, err := s.DeployContract("coin", "token", erc20Decimals) + Expect(err).To(BeNil()) + }) + }) + + Context("with the ERC20 module and EVM Hook enabled", func() { + It("should be successful", func() { + _, err := s.DeployContract("coin", "token", erc20Decimals) + Expect(err).To(BeNil()) + }) + }) + }) + + var _ = Describe("ERC20:", Ordered, func() { + var ( + s *KeeperTestSuite + contract common.Address + contract2 common.Address + + // moduleAcc is the address of the ERC-20 module account + moduleAcc = authtypes.NewModuleAddress(types.ModuleName) + amt = math.NewInt(100) + ) + + BeforeEach(func() { + s = NewKeeperTestSuite(create, options...) + s.SetupTest() + }) + + Describe("Submitting a token pair proposal through governance", func() { + Context("with deployed contracts", func() { + BeforeEach(func() { + var err error + contract, err = s.DeployContract(erc20Name, erc20Symbol, erc20Decimals) + Expect(err).To(BeNil()) + contract2, err = s.DeployContract(erc20Name, erc20Symbol, erc20Decimals) + Expect(err).To(BeNil()) + }) + + Describe("for a single ERC20 token", func() { + BeforeEach(func() { + // register erc20 + _, err := utils.RegisterERC20( + s.factory, + s.network, + utils.ERC20RegistrationData{ + Addresses: []string{contract.Hex()}, + ProposerPriv: s.keyring.GetPrivKey(0), + }, + ) + Expect(err).To(BeNil()) + }) + + It("should create a token pair owned by the contract deployer", func() { + qc := s.network.GetERC20Client() + + res, err := qc.TokenPairs(s.network.GetContext(), &types.QueryTokenPairsRequest{}) + Expect(err).To(BeNil()) + + tokenPairs := res.TokenPairs + Expect(tokenPairs).To(HaveLen(2)) + for i, tokenPair := range tokenPairs { + if tokenPair.Erc20Address == contract.Hex() { + Expect(tokenPairs[i].ContractOwner).To(Equal(types.OWNER_EXTERNAL)) + } + } + }) + }) + + Describe("for multiple ERC20 tokens", func() { + BeforeEach(func() { + // register erc20 tokens + _, err := utils.RegisterERC20( + s.factory, + s.network, + utils.ERC20RegistrationData{ + Addresses: []string{contract.Hex(), contract2.Hex()}, + ProposerPriv: s.keyring.GetPrivKey(0), + }, + ) + Expect(err).To(BeNil()) + }) + + It("should create a token pairs owned by the contract deployer", func() { + qc := s.network.GetERC20Client() + res, err := qc.TokenPairs(s.network.GetContext(), &types.QueryTokenPairsRequest{}) + Expect(err).To(BeNil()) + + tokenPairs := res.TokenPairs + Expect(tokenPairs).To(HaveLen(3)) + for i, tokenPair := range tokenPairs { + if tokenPair.Erc20Address == contract2.Hex() { + Expect(tokenPairs[i].ContractOwner).To(Equal(types.OWNER_EXTERNAL)) + } + } + }) + }) + }) + }) + + Describe("Converting", func() { + Context("with a registered ERC20", func() { + BeforeEach(func() { + var err error + contract, err = s.setupRegisterERC20Pair(contractMinterBurner) + Expect(err).To(BeNil()) + + res, err := s.MintERC20Token(contract, s.keyring.GetAddr(0), big.NewInt(amt.Int64())) + Expect(err).To(BeNil()) + Expect(res.IsOK()).To(BeTrue()) + }) + + Describe("an ERC20 token into a Cosmos coin", func() { + BeforeEach(func() { + // convert ERC20 to cosmos coin + msg := types.NewMsgConvertERC20(amt, s.keyring.GetAccAddr(0), contract, s.keyring.GetAddr(0)) + res, err := s.factory.CommitCosmosTx(s.keyring.GetPrivKey(0), factory.CosmosTxArgs{Msgs: []sdk.Msg{msg}}) + Expect(err).To(BeNil()) + Expect(res.IsOK()).To(BeTrue()) + }) + + It("should decrease tokens on the sender account", func() { + balanceERC20, err := s.BalanceOf(contract, s.keyring.GetAddr(0)) + Expect(err).To(BeNil()) + Expect(balanceERC20.(*big.Int).Int64()).To(Equal(int64(0))) + }) + + It("should escrow tokens on the module account", func() { + moduleAddr := common.BytesToAddress(moduleAcc.Bytes()) + balanceERC20, err := s.BalanceOf(contract, moduleAddr) + Expect(err).To(BeNil()) + Expect(balanceERC20.(*big.Int).Int64()).To(Equal(amt.Int64())) + }) + + It("should send coins to the receiver account", func() { + balRes, err := s.handler.GetBalanceFromBank(s.keyring.GetAccAddr(0), types.CreateDenom(contract.Hex())) + Expect(err).To(BeNil()) + balanceCoin := balRes.Balance + Expect(balanceCoin.Amount).To(Equal(amt)) + }) + }) + }) + }) + }) + + // Run Ginkgo integration tests + RegisterFailHandler(Fail) + RunSpecs(t, "ERC20 Module Integration Tests") +} diff --git a/tests/integration/x/erc20/test_mint.go b/tests/integration/x/erc20/test_mint.go new file mode 100644 index 000000000..9a9a151ce --- /dev/null +++ b/tests/integration/x/erc20/test_mint.go @@ -0,0 +1,109 @@ +package erc20 + +import ( + "fmt" + + utiltx "github.com/cosmos/evm/testutil/tx" + "github.com/cosmos/evm/x/erc20/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func (s *KeeperTestSuite) TestMintingEnabled() { + var ctx sdk.Context + sender := sdk.AccAddress(utiltx.GenerateAddress().Bytes()) + receiver := sdk.AccAddress(utiltx.GenerateAddress().Bytes()) + expPair := types.NewTokenPair(utiltx.GenerateAddress(), "coin", types.OWNER_MODULE) + id := expPair.GetID() + + testCases := []struct { + name string + malleate func() + expPass bool + }{ + { + "conversion is disabled globally", + func() { + params := types.DefaultParams() + params.EnableErc20 = false + s.network.App.GetErc20Keeper().SetParams(ctx, params) //nolint:errcheck + }, + false, + }, + { + "token pair not found", + func() {}, + false, + }, + { + "conversion is disabled for the given pair", + func() { + expPair.Enabled = false + s.network.App.GetErc20Keeper().SetTokenPair(ctx, expPair) + s.network.App.GetErc20Keeper().SetDenomMap(ctx, expPair.Denom, id) + s.network.App.GetErc20Keeper().SetERC20Map(ctx, expPair.GetERC20Contract(), id) + }, + false, + }, + { + "token transfers are disabled", + func() { + expPair.Enabled = true + s.network.App.GetErc20Keeper().SetTokenPair(ctx, expPair) + s.network.App.GetErc20Keeper().SetDenomMap(ctx, expPair.Denom, id) + s.network.App.GetErc20Keeper().SetERC20Map(ctx, expPair.GetERC20Contract(), id) + + s.network.App.GetBankKeeper().SetSendEnabled(ctx, expPair.Denom, false) + }, + false, + }, + { + "token not registered", + func() { + s.network.App.GetErc20Keeper().SetDenomMap(ctx, expPair.Denom, id) + s.network.App.GetErc20Keeper().SetERC20Map(ctx, expPair.GetERC20Contract(), id) + }, + false, + }, + { + "receiver address is blocked (module account)", + func() { + s.network.App.GetErc20Keeper().SetTokenPair(ctx, expPair) + s.network.App.GetErc20Keeper().SetDenomMap(ctx, expPair.Denom, id) + s.network.App.GetErc20Keeper().SetERC20Map(ctx, expPair.GetERC20Contract(), id) + + acc := s.network.App.GetAccountKeeper().GetModuleAccount(ctx, types.ModuleName) + receiver = acc.GetAddress() + }, + false, + }, + { + "ok", + func() { + s.network.App.GetErc20Keeper().SetTokenPair(ctx, expPair) + s.network.App.GetErc20Keeper().SetDenomMap(ctx, expPair.Denom, id) + s.network.App.GetErc20Keeper().SetERC20Map(ctx, expPair.GetERC20Contract(), id) + + receiver = sdk.AccAddress(utiltx.GenerateAddress().Bytes()) + }, + true, + }, + } + + for _, tc := range testCases { + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // reset + ctx = s.network.GetContext() + + tc.malleate() + + pair, err := s.network.App.GetErc20Keeper().MintingEnabled(ctx, sender, receiver, expPair.Erc20Address) + if tc.expPass { + s.Require().NoError(err) + s.Require().Equal(expPair, pair) + } else { + s.Require().Error(err) + } + }) + } +} diff --git a/x/erc20/keeper/msg_server_test.go b/tests/integration/x/erc20/test_msg_server.go similarity index 62% rename from x/erc20/keeper/msg_server_test.go rename to tests/integration/x/erc20/test_msg_server.go index ec6b77bbb..f98b9c4ae 100644 --- a/x/erc20/keeper/msg_server_test.go +++ b/tests/integration/x/erc20/test_msg_server.go @@ -1,4 +1,4 @@ -package keeper_test +package erc20 import ( "fmt" @@ -7,10 +7,10 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/holiman/uint256" "github.com/stretchr/testify/mock" - gomock "go.uber.org/mock/gomock" + "go.uber.org/mock/gomock" - "github.com/cosmos/evm/testutil/integration/common/factory" - testutils "github.com/cosmos/evm/testutil/integration/os/utils" + "github.com/cosmos/evm/testutil/integration/base/factory" + "github.com/cosmos/evm/testutil/integration/evm/utils" "github.com/cosmos/evm/x/erc20/keeper" "github.com/cosmos/evm/x/erc20/types" erc20mocks "github.com/cosmos/evm/x/erc20/types/mocks" @@ -24,7 +24,7 @@ import ( govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) -func (suite *KeeperTestSuite) TestConvertERC20NativeERC20() { +func (s *KeeperTestSuite) TestConvertERC20NativeERC20() { var ( contractAddr common.Address coinName string @@ -76,15 +76,15 @@ func (suite *KeeperTestSuite) TestConvertERC20NativeERC20() { func(common.Address) { params := types.DefaultParams() params.EnableErc20 = false - err := testutils.UpdateERC20Params( - testutils.UpdateParamsInput{ - Tf: suite.factory, - Network: suite.network, - Pk: suite.keyring.GetPrivKey(0), + err := utils.UpdateERC20Params( + utils.UpdateParamsInput{ + Tf: s.factory, + Network: s.network, + Pk: s.keyring.GetPrivKey(0), Params: params, }, ) - suite.Require().NoError(err) + s.Require().NoError(err) }, func() {}, contractMinterBurner, @@ -128,12 +128,14 @@ func (suite *KeeperTestSuite) TestConvertERC20NativeERC20() { func(common.Address) {}, func() { mockEVMKeeper := &erc20mocks.EVMKeeper{} - suite.network.App.Erc20Keeper = keeper.NewKeeper( - suite.network.App.GetKey("erc20"), suite.network.App.AppCodec(), - authtypes.NewModuleAddress(govtypes.ModuleName), suite.network.App.AccountKeeper, - suite.network.App.BankKeeper, mockEVMKeeper, suite.network.App.StakingKeeper, - &suite.network.App.TransferKeeper, + transferKeeper := s.network.App.GetTransferKeeper() + erc20Keeper := keeper.NewKeeper( + s.network.App.GetKey("erc20"), s.network.App.AppCodec(), + authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), + s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), + &transferKeeper, ) + s.network.App.SetErc20Keeper(&erc20Keeper) existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} balance := make([]uint8, 32) @@ -155,12 +157,14 @@ func (suite *KeeperTestSuite) TestConvertERC20NativeERC20() { func(common.Address) {}, func() { mockEVMKeeper := &erc20mocks.EVMKeeper{} - suite.network.App.Erc20Keeper = keeper.NewKeeper( - suite.network.App.GetKey("erc20"), suite.network.App.AppCodec(), - authtypes.NewModuleAddress(govtypes.ModuleName), suite.network.App.AccountKeeper, - suite.network.App.BankKeeper, mockEVMKeeper, suite.network.App.StakingKeeper, - &suite.network.App.TransferKeeper, + transferKeeper := s.network.App.GetTransferKeeper() + erc20Keeper := keeper.NewKeeper( + s.network.App.GetKey("erc20"), s.network.App.AppCodec(), + authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), + s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), + &transferKeeper, ) + s.network.App.SetErc20Keeper(&erc20Keeper) existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} balance := make([]uint8, 32) @@ -181,12 +185,14 @@ func (suite *KeeperTestSuite) TestConvertERC20NativeERC20() { func(common.Address) {}, func() { mockEVMKeeper := &erc20mocks.EVMKeeper{} - suite.network.App.Erc20Keeper = keeper.NewKeeper( - suite.network.App.GetKey("erc20"), suite.network.App.AppCodec(), - authtypes.NewModuleAddress(govtypes.ModuleName), suite.network.App.AccountKeeper, - suite.network.App.BankKeeper, mockEVMKeeper, suite.network.App.StakingKeeper, - &suite.network.App.TransferKeeper, + transferKeeper := s.network.App.GetTransferKeeper() + erc20Keeper := keeper.NewKeeper( + s.network.App.GetKey("erc20"), s.network.App.AppCodec(), + authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), + s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), + &transferKeeper, ) + s.network.App.SetErc20Keeper(&erc20Keeper) existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} balance := make([]uint8, 32) @@ -208,12 +214,14 @@ func (suite *KeeperTestSuite) TestConvertERC20NativeERC20() { func(common.Address) {}, func() { mockEVMKeeper := &erc20mocks.EVMKeeper{} - suite.network.App.Erc20Keeper = keeper.NewKeeper( - suite.network.App.GetKey("erc20"), suite.network.App.AppCodec(), - authtypes.NewModuleAddress(govtypes.ModuleName), suite.network.App.AccountKeeper, - suite.network.App.BankKeeper, mockEVMKeeper, suite.network.App.StakingKeeper, - &suite.network.App.TransferKeeper, + transferKeeper := s.network.App.GetTransferKeeper() + erc20Keeper := keeper.NewKeeper( + s.network.App.GetKey("erc20"), s.network.App.AppCodec(), + authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), + s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), + &transferKeeper, ) + s.network.App.SetErc20Keeper(&erc20Keeper) existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} balance := make([]uint8, 32) @@ -234,15 +242,15 @@ func (suite *KeeperTestSuite) TestConvertERC20NativeERC20() { 10, func(common.Address) {}, func() { - ctrl := gomock.NewController(suite.T()) + ctrl := gomock.NewController(s.T()) mockBankKeeper := erc20mocks.NewMockBankKeeper(ctrl) - - suite.network.App.Erc20Keeper = keeper.NewKeeper( - suite.network.App.GetKey("erc20"), suite.network.App.AppCodec(), - authtypes.NewModuleAddress(govtypes.ModuleName), suite.network.App.AccountKeeper, - mockBankKeeper, suite.network.App.EVMKeeper, suite.network.App.StakingKeeper, - &suite.network.App.TransferKeeper, - ) + transferKeeper := s.network.App.GetTransferKeeper() + erc20Keeper := keeper.NewKeeper( + s.network.App.GetKey("erc20"), s.network.App.AppCodec(), + authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), + mockBankKeeper, s.network.App.GetEVMKeeper(), s.network.App.GetStakingKeeper(), + &transferKeeper) + s.network.App.SetErc20Keeper(&erc20Keeper) mockBankKeeper.EXPECT().MintCoins(gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("failed to mint")).AnyTimes() mockBankKeeper.EXPECT().SendCoinsFromModuleToAccount(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("failed to unescrow")).AnyTimes() @@ -259,15 +267,15 @@ func (suite *KeeperTestSuite) TestConvertERC20NativeERC20() { 10, func(common.Address) {}, func() { - ctrl := gomock.NewController(suite.T()) + ctrl := gomock.NewController(s.T()) mockBankKeeper := erc20mocks.NewMockBankKeeper(ctrl) - - suite.network.App.Erc20Keeper = keeper.NewKeeper( - suite.network.App.GetKey("erc20"), suite.network.App.AppCodec(), - authtypes.NewModuleAddress(govtypes.ModuleName), suite.network.App.AccountKeeper, - mockBankKeeper, suite.network.App.EVMKeeper, suite.network.App.StakingKeeper, - &suite.network.App.TransferKeeper, - ) + transferKeeper := s.network.App.GetTransferKeeper() + erc20Keeper := keeper.NewKeeper( + s.network.App.GetKey("erc20"), s.network.App.AppCodec(), + authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), + mockBankKeeper, s.network.App.GetEVMKeeper(), s.network.App.GetStakingKeeper(), + &transferKeeper) + s.network.App.SetErc20Keeper(&erc20Keeper) mockBankKeeper.EXPECT().MintCoins(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) mockBankKeeper.EXPECT().SendCoinsFromModuleToAccount(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("failed to unescrow")) @@ -284,15 +292,15 @@ func (suite *KeeperTestSuite) TestConvertERC20NativeERC20() { 10, func(common.Address) {}, func() { - ctrl := gomock.NewController(suite.T()) + ctrl := gomock.NewController(s.T()) mockBankKeeper := erc20mocks.NewMockBankKeeper(ctrl) - - suite.network.App.Erc20Keeper = keeper.NewKeeper( - suite.network.App.GetKey("erc20"), suite.network.App.AppCodec(), - authtypes.NewModuleAddress(govtypes.ModuleName), suite.network.App.AccountKeeper, - mockBankKeeper, suite.network.App.EVMKeeper, suite.network.App.StakingKeeper, - &suite.network.App.TransferKeeper, - ) + transferKeeper := s.network.App.GetTransferKeeper() + erc20Keeper := keeper.NewKeeper( + s.network.App.GetKey("erc20"), s.network.App.AppCodec(), + authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), + mockBankKeeper, s.network.App.GetEVMKeeper(), s.network.App.GetStakingKeeper(), + &transferKeeper) + s.network.App.SetErc20Keeper(&erc20Keeper) mockBankKeeper.EXPECT().MintCoins(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) mockBankKeeper.EXPECT().SendCoinsFromModuleToAccount(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) @@ -305,26 +313,26 @@ func (suite *KeeperTestSuite) TestConvertERC20NativeERC20() { }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.Run(fmt.Sprintf("Case %s", tc.name), func() { var err error - suite.mintFeeCollector = true + s.mintFeeCollector = true defer func() { - suite.mintFeeCollector = false + s.mintFeeCollector = false }() - suite.SetupTest() + s.SetupTest() - contractAddr, err = suite.setupRegisterERC20Pair(tc.contractType) - suite.Require().NoError(err) + contractAddr, err = s.setupRegisterERC20Pair(tc.contractType) + s.Require().NoError(err) tc.malleate(contractAddr) - suite.Require().NotNil(contractAddr) + s.Require().NotNil(contractAddr) coinName = types.CreateDenom(contractAddr.String()) - sender := suite.keyring.GetAccAddr(0) + sender := s.keyring.GetAccAddr(0) - _, err = suite.MintERC20Token(contractAddr, suite.keyring.GetAddr(0), big.NewInt(tc.mint)) - suite.Require().NoError(err) + _, err = s.MintERC20Token(contractAddr, s.keyring.GetAddr(0), big.NewInt(tc.mint)) + s.Require().NoError(err) // update context with latest committed changes tc.extra() @@ -333,41 +341,41 @@ func (suite *KeeperTestSuite) TestConvertERC20NativeERC20() { math.NewInt(tc.transfer), sender, contractAddr, - suite.keyring.GetAddr(0), + s.keyring.GetAddr(0), ) - ctx := suite.network.GetContext() + ctx := s.network.GetContext() if tc.expPass { - _, err = suite.factory.CommitCosmosTx(suite.keyring.GetPrivKey(0), factory.CosmosTxArgs{Msgs: []sdk.Msg{convertERC20Msg}}) - suite.Require().NoError(err, tc.name) + _, err = s.factory.CommitCosmosTx(s.keyring.GetPrivKey(0), factory.CosmosTxArgs{Msgs: []sdk.Msg{convertERC20Msg}}) + s.Require().NoError(err, tc.name) - cosmosBalance := suite.network.App.BankKeeper.GetBalance(ctx, sender, coinName) + cosmosBalance := s.network.App.GetBankKeeper().GetBalance(ctx, sender, coinName) - acc := suite.network.App.EVMKeeper.GetAccountWithoutBalance(ctx, contractAddr) + acc := s.network.App.GetEVMKeeper().GetAccountWithoutBalance(ctx, contractAddr) if tc.selfdestructed { - suite.Require().Nil(acc, "expected contract to be destroyed") + s.Require().Nil(acc, "expected contract to be destroyed") } else { - suite.Require().NotNil(acc) + s.Require().NotNil(acc) } if tc.selfdestructed || !acc.IsContract() { - id := suite.network.App.Erc20Keeper.GetTokenPairID(ctx, contractAddr.String()) - _, found := suite.network.App.Erc20Keeper.GetTokenPair(ctx, id) - suite.Require().False(found) + id := s.network.App.GetErc20Keeper().GetTokenPairID(ctx, contractAddr.String()) + _, found := s.network.App.GetErc20Keeper().GetTokenPair(ctx, id) + s.Require().False(found) } else { - suite.Require().Equal(cosmosBalance.Amount, math.NewInt(tc.transfer)) + s.Require().Equal(cosmosBalance.Amount, math.NewInt(tc.transfer)) } } else { - _, err = suite.network.App.Erc20Keeper.ConvertERC20(ctx, convertERC20Msg) - suite.Require().Error(err, tc.name) + _, err = s.network.App.GetErc20Keeper().ConvertERC20(ctx, convertERC20Msg) + s.Require().Error(err, tc.name) } }) } - suite.mintFeeCollector = false + s.mintFeeCollector = false } -func (suite *KeeperTestSuite) TestConvertNativeERC20ToEVMERC20() { +func (s *KeeperTestSuite) TestConvertNativeERC20ToEVMERC20() { var ( contractAddr common.Address coinName string @@ -419,11 +427,14 @@ func (suite *KeeperTestSuite) TestConvertNativeERC20ToEVMERC20() { func(common.Address) {}, func() { mockEVMKeeper := &erc20mocks.EVMKeeper{} - suite.network.App.Erc20Keeper = keeper.NewKeeper( - suite.network.App.GetKey("erc20"), suite.network.App.AppCodec(), - authtypes.NewModuleAddress(govtypes.ModuleName), suite.network.App.AccountKeeper, - suite.network.App.BankKeeper, mockEVMKeeper, suite.network.App.StakingKeeper, &suite.network.App.TransferKeeper, + transferKeeper := s.network.App.GetTransferKeeper() + erc20Keeper := keeper.NewKeeper( + s.network.App.GetKey("erc20"), s.network.App.AppCodec(), + authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), + s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), + &transferKeeper, ) + s.network.App.SetErc20Keeper(&erc20Keeper) existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} balance := make([]uint8, 32) @@ -445,12 +456,14 @@ func (suite *KeeperTestSuite) TestConvertNativeERC20ToEVMERC20() { func(common.Address) {}, func() { mockEVMKeeper := &erc20mocks.EVMKeeper{} - suite.network.App.Erc20Keeper = keeper.NewKeeper( - suite.network.App.GetKey("erc20"), suite.network.App.AppCodec(), - authtypes.NewModuleAddress(govtypes.ModuleName), suite.network.App.AccountKeeper, - suite.network.App.BankKeeper, mockEVMKeeper, suite.network.App.StakingKeeper, - &suite.network.App.TransferKeeper, + transferKeeper := s.network.App.GetTransferKeeper() + erc20Keeper := keeper.NewKeeper( + s.network.App.GetKey("erc20"), s.network.App.AppCodec(), + authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), + s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), + &transferKeeper, ) + s.network.App.SetErc20Keeper(&erc20Keeper) existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} balance := make([]uint8, 32) @@ -471,12 +484,14 @@ func (suite *KeeperTestSuite) TestConvertNativeERC20ToEVMERC20() { func(common.Address) {}, func() { mockEVMKeeper := &erc20mocks.EVMKeeper{} - suite.network.App.Erc20Keeper = keeper.NewKeeper( - suite.network.App.GetKey("erc20"), suite.network.App.AppCodec(), - authtypes.NewModuleAddress(govtypes.ModuleName), suite.network.App.AccountKeeper, - suite.network.App.BankKeeper, mockEVMKeeper, suite.network.App.StakingKeeper, - &suite.network.App.TransferKeeper, + transferKeeper := s.network.App.GetTransferKeeper() + erc20Keeper := keeper.NewKeeper( + s.network.App.GetKey("erc20"), s.network.App.AppCodec(), + authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), + s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), + &transferKeeper, ) + s.network.App.SetErc20Keeper(&erc20Keeper) existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} balance := make([]uint8, 32) @@ -498,12 +513,14 @@ func (suite *KeeperTestSuite) TestConvertNativeERC20ToEVMERC20() { func(common.Address) {}, func() { mockEVMKeeper := &erc20mocks.EVMKeeper{} - suite.network.App.Erc20Keeper = keeper.NewKeeper( - suite.network.App.GetKey("erc20"), suite.network.App.AppCodec(), - authtypes.NewModuleAddress(govtypes.ModuleName), suite.network.App.AccountKeeper, - suite.network.App.BankKeeper, mockEVMKeeper, suite.network.App.StakingKeeper, - &suite.network.App.TransferKeeper, + transferKeeper := s.network.App.GetTransferKeeper() + erc20Keeper := keeper.NewKeeper( + s.network.App.GetKey("erc20"), s.network.App.AppCodec(), + authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), + s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), + &transferKeeper, ) + s.network.App.SetErc20Keeper(&erc20Keeper) existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} balance := make([]uint8, 32) @@ -524,15 +541,16 @@ func (suite *KeeperTestSuite) TestConvertNativeERC20ToEVMERC20() { 10, func(common.Address) {}, func() { - ctrl := gomock.NewController(suite.T()) + ctrl := gomock.NewController(s.T()) mockBankKeeper := erc20mocks.NewMockBankKeeper(ctrl) - - suite.network.App.Erc20Keeper = keeper.NewKeeper( - suite.network.App.GetKey("erc20"), suite.network.App.AppCodec(), - authtypes.NewModuleAddress(govtypes.ModuleName), suite.network.App.AccountKeeper, - mockBankKeeper, suite.network.App.EVMKeeper, suite.network.App.StakingKeeper, - &suite.network.App.TransferKeeper, + transferKeeper := s.network.App.GetTransferKeeper() + erc20Keeper := keeper.NewKeeper( + s.network.App.GetKey("erc20"), s.network.App.AppCodec(), + authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), + mockBankKeeper, s.network.App.GetEVMKeeper(), s.network.App.GetStakingKeeper(), + &transferKeeper, ) + s.network.App.SetErc20Keeper(&erc20Keeper) mockBankKeeper.EXPECT().MintCoins(gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("failed to mint")).AnyTimes() mockBankKeeper.EXPECT().SendCoinsFromAccountToModule(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("failed to unescrow")).AnyTimes() @@ -549,15 +567,16 @@ func (suite *KeeperTestSuite) TestConvertNativeERC20ToEVMERC20() { 10, func(common.Address) {}, func() { - ctrl := gomock.NewController(suite.T()) + ctrl := gomock.NewController(s.T()) mockBankKeeper := erc20mocks.NewMockBankKeeper(ctrl) - - suite.network.App.Erc20Keeper = keeper.NewKeeper( - suite.network.App.GetKey("erc20"), suite.network.App.AppCodec(), - authtypes.NewModuleAddress(govtypes.ModuleName), suite.network.App.AccountKeeper, - mockBankKeeper, suite.network.App.EVMKeeper, suite.network.App.StakingKeeper, - &suite.network.App.TransferKeeper, + transferKeeper := s.network.App.GetTransferKeeper() + erc20Keeper := keeper.NewKeeper( + s.network.App.GetKey("erc20"), s.network.App.AppCodec(), + authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), + mockBankKeeper, s.network.App.GetEVMKeeper(), s.network.App.GetStakingKeeper(), + &transferKeeper, ) + s.network.App.SetErc20Keeper(&erc20Keeper) mockBankKeeper.EXPECT().SendCoinsFromAccountToModule(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) mockBankKeeper.EXPECT().BurnCoins(gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("failed to burn")).AnyTimes() @@ -569,26 +588,26 @@ func (suite *KeeperTestSuite) TestConvertNativeERC20ToEVMERC20() { }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.Run(fmt.Sprintf("Case %s", tc.name), func() { var err error - suite.mintFeeCollector = true + s.mintFeeCollector = true defer func() { - suite.mintFeeCollector = false + s.mintFeeCollector = false }() - suite.SetupTest() + s.SetupTest() - contractAddr, err = suite.setupRegisterERC20Pair(tc.contractType) - suite.Require().NoError(err) + contractAddr, err = s.setupRegisterERC20Pair(tc.contractType) + s.Require().NoError(err) tc.malleate(contractAddr) - suite.Require().NotNil(contractAddr) + s.Require().NotNil(contractAddr) // update context with latest committed changes - sender := suite.keyring.GetAccAddr(0) - senderHex := suite.keyring.GetAddr(0) + sender := s.keyring.GetAccAddr(0) + senderHex := s.keyring.GetAddr(0) // mint tokens to sender - _, err = suite.MintERC20Token(contractAddr, senderHex, big.NewInt(tc.mint)) - suite.Require().NoError(err) + _, err = s.MintERC20Token(contractAddr, senderHex, big.NewInt(tc.mint)) + s.Require().NoError(err) // convert tokens to native first convertERC20Msg := types.NewMsgConvertERC20( @@ -597,52 +616,52 @@ func (suite *KeeperTestSuite) TestConvertNativeERC20ToEVMERC20() { contractAddr, senderHex, ) - _, err = suite.factory.CommitCosmosTx(suite.keyring.GetPrivKey(0), factory.CosmosTxArgs{Msgs: []sdk.Msg{convertERC20Msg}}) - suite.Require().NoError(err) + _, err = s.factory.CommitCosmosTx(s.keyring.GetPrivKey(0), factory.CosmosTxArgs{Msgs: []sdk.Msg{convertERC20Msg}}) + s.Require().NoError(err) tc.extra() coinName = types.CreateDenom(contractAddr.String()) - evmTokenBalanceBefore, err := suite.BalanceOf(contractAddr, senderHex) // actual: 100, expected: 0 - suite.Require().NoError(err) - suite.Require().Equal(big.NewInt(0).Int64(), evmTokenBalanceBefore.(*big.Int).Int64()) + evmTokenBalanceBefore, err := s.BalanceOf(contractAddr, senderHex) // actual: 100, expected: 0 + s.Require().NoError(err) + s.Require().Equal(big.NewInt(0).Int64(), evmTokenBalanceBefore.(*big.Int).Int64()) // then convert native tokens back into EVM tokens convertNativeMsg := types.NewMsgConvertCoin(sdk.Coin{Denom: coinName, Amount: math.NewInt(tc.transfer)}, senderHex, sender) if tc.expPass { - _, err = suite.factory.CommitCosmosTx(suite.keyring.GetPrivKey(0), factory.CosmosTxArgs{Msgs: []sdk.Msg{convertNativeMsg}}) - suite.Require().NoError(err, tc.name) - cosmosBalance := suite.network.App.BankKeeper.GetBalance(suite.network.GetContext(), sender, coinName) - evmTokenBalanceAfter, err := suite.BalanceOf(contractAddr, senderHex) - suite.Require().NoError(err) + _, err = s.factory.CommitCosmosTx(s.keyring.GetPrivKey(0), factory.CosmosTxArgs{Msgs: []sdk.Msg{convertNativeMsg}}) + s.Require().NoError(err, tc.name) + cosmosBalance := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), sender, coinName) + evmTokenBalanceAfter, err := s.BalanceOf(contractAddr, senderHex) + s.Require().NoError(err) - acc := suite.network.App.EVMKeeper.GetAccountWithoutBalance(suite.network.GetContext(), contractAddr) + acc := s.network.App.GetEVMKeeper().GetAccountWithoutBalance(s.network.GetContext(), contractAddr) if tc.selfdestructed { - suite.Require().Nil(acc, "expected contract to be destroyed") + s.Require().Nil(acc, "expected contract to be destroyed") } else { - suite.Require().NotNil(acc) + s.Require().NotNil(acc) } if tc.selfdestructed || !acc.IsContract() { - id := suite.network.App.Erc20Keeper.GetTokenPairID(suite.network.GetContext(), contractAddr.String()) - _, found := suite.network.App.Erc20Keeper.GetTokenPair(suite.network.GetContext(), id) - suite.Require().False(found) + id := s.network.App.GetErc20Keeper().GetTokenPairID(s.network.GetContext(), contractAddr.String()) + _, found := s.network.App.GetErc20Keeper().GetTokenPair(s.network.GetContext(), id) + s.Require().False(found) } else { - suite.Require().Equal(cosmosBalance.Amount, math.NewInt(tc.mint-tc.transfer)) - suite.Require().Equal(evmTokenBalanceAfter.(*big.Int).Int64(), math.NewInt(tc.transfer).Int64()) + s.Require().Equal(cosmosBalance.Amount, math.NewInt(tc.mint-tc.transfer)) + s.Require().Equal(evmTokenBalanceAfter.(*big.Int).Int64(), math.NewInt(tc.transfer).Int64()) } } else { - _, err = suite.network.App.Erc20Keeper.ConvertCoin(suite.network.GetContext(), convertNativeMsg) - suite.Require().Error(err, tc.name) + _, err = s.network.App.GetErc20Keeper().ConvertCoin(s.network.GetContext(), convertNativeMsg) + s.Require().Error(err, tc.name) } }) } - suite.mintFeeCollector = false + s.mintFeeCollector = false } -func (suite *KeeperTestSuite) TestUpdateParams() { +func (s *KeeperTestSuite) TestUpdateParams() { testCases := []struct { name string request *types.MsgUpdateParams @@ -664,13 +683,13 @@ func (suite *KeeperTestSuite) TestUpdateParams() { } for _, tc := range testCases { - suite.Run("MsgUpdateParams", func() { - suite.SetupTest() - _, err := suite.network.App.Erc20Keeper.UpdateParams(suite.network.GetContext(), tc.request) + s.Run("MsgUpdateParams", func() { + s.SetupTest() + _, err := s.network.App.GetErc20Keeper().UpdateParams(s.network.GetContext(), tc.request) if tc.expectErr { - suite.Require().Error(err) + s.Require().Error(err) } else { - suite.Require().NoError(err) + s.Require().NoError(err) } }) } diff --git a/x/erc20/keeper/params_test.go b/tests/integration/x/erc20/test_params.go similarity index 68% rename from x/erc20/keeper/params_test.go rename to tests/integration/x/erc20/test_params.go index 7e21e0188..482d18987 100644 --- a/x/erc20/keeper/params_test.go +++ b/tests/integration/x/erc20/test_params.go @@ -1,4 +1,4 @@ -package keeper_test +package erc20 import ( testconstants "github.com/cosmos/evm/testutil/constants" @@ -7,7 +7,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -func (suite *KeeperTestSuite) TestParams() { +func (s *KeeperTestSuite) TestParams() { var ctx sdk.Context testCases := []struct { @@ -21,13 +21,13 @@ func (suite *KeeperTestSuite) TestParams() { func() interface{} { erc20Params := types.DefaultParams() // NOTE: we need to add the example token pair address which is not in the default params but in the genesis state - // of the test suite app and therefore is returned by the query client. + // of the test s app and therefore is returned by the query client. erc20Params.NativePrecompiles = append(erc20Params.NativePrecompiles, testconstants.WEVMOSContractMainnet) return erc20Params }, func() interface{} { - return suite.network.App.Erc20Keeper.GetParams(ctx) + return s.network.App.GetErc20Keeper().GetParams(ctx) }, true, }, @@ -36,12 +36,12 @@ func (suite *KeeperTestSuite) TestParams() { func() interface{} { params := types.DefaultParams() params.DynamicPrecompiles = []string{"0xB5124FA2b2cF92B2D469b249433BA1c96BDF536D", "0xC4CcDf91b810a61cCB48b35ccCc066C63bf94B4F"} - err := suite.network.App.Erc20Keeper.SetParams(ctx, params) - suite.Require().NoError(err) + err := s.network.App.GetErc20Keeper().SetParams(ctx, params) + s.Require().NoError(err) return params.DynamicPrecompiles }, func() interface{} { - return suite.network.App.Erc20Keeper.GetParams(ctx).DynamicPrecompiles + return s.network.App.GetErc20Keeper().GetParams(ctx).DynamicPrecompiles }, true, }, @@ -50,23 +50,23 @@ func (suite *KeeperTestSuite) TestParams() { func() interface{} { params := types.DefaultParams() params.NativePrecompiles = []string{"0x205CF44075E77A3543abC690437F3b2819bc450a", "0x8FA78CEB7F04118Ec6d06AaC37Ca854691d8e963"} - err := suite.network.App.Erc20Keeper.SetParams(ctx, params) - suite.Require().NoError(err) + err := s.network.App.GetErc20Keeper().SetParams(ctx, params) + s.Require().NoError(err) return params.NativePrecompiles }, func() interface{} { - return suite.network.App.Erc20Keeper.GetParams(ctx).NativePrecompiles + return s.network.App.GetErc20Keeper().GetParams(ctx).NativePrecompiles }, true, }, } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() - ctx = suite.network.GetContext() + s.Run(tc.name, func() { + s.SetupTest() + ctx = s.network.GetContext() - suite.Require().Equal(tc.paramsFun(), tc.getFun()) + s.Require().Equal(tc.paramsFun(), tc.getFun()) }) } } diff --git a/x/erc20/keeper/precompiles_test.go b/tests/integration/x/erc20/test_precompiles.go similarity index 66% rename from x/erc20/keeper/precompiles_test.go rename to tests/integration/x/erc20/test_precompiles.go index 32b233e6d..0a76d29ba 100644 --- a/x/erc20/keeper/precompiles_test.go +++ b/tests/integration/x/erc20/test_precompiles.go @@ -1,4 +1,4 @@ -package keeper_test +package erc20 import ( "github.com/ethereum/go-ethereum/common" @@ -8,7 +8,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -func (suite *KeeperTestSuite) TestGetERC20PrecompileInstance() { +func (s *KeeperTestSuite) TestGetERC20PrecompileInstance() { var ( ctx sdk.Context tokenPairs []types.TokenPair @@ -30,8 +30,8 @@ func (suite *KeeperTestSuite) TestGetERC20PrecompileInstance() { "fail - precompile not on params", func() { params := types.DefaultParams() - err := suite.network.App.Erc20Keeper.SetParams(ctx, params) - suite.Require().NoError(err) + err := s.network.App.GetErc20Keeper().SetParams(ctx, params) + s.Require().NoError(err) }, common.HexToAddress(nonExistendTokenHexAddr), false, @@ -43,8 +43,8 @@ func (suite *KeeperTestSuite) TestGetERC20PrecompileInstance() { func() { params := types.DefaultParams() params.NativePrecompiles = []string{newTokenHexAddr, nonExistendTokenHexAddr} - err := suite.network.App.Erc20Keeper.SetParams(ctx, params) - suite.Require().NoError(err) + err := s.network.App.GetErc20Keeper().SetParams(ctx, params) + s.Require().NoError(err) }, common.HexToAddress(nonExistendTokenHexAddr), false, @@ -56,8 +56,8 @@ func (suite *KeeperTestSuite) TestGetERC20PrecompileInstance() { func() { params := types.DefaultParams() params.NativePrecompiles = []string{tokenPair.Erc20Address} - err := suite.network.App.Erc20Keeper.SetParams(ctx, params) - suite.Require().NoError(err) + err := s.network.App.GetErc20Keeper().SetParams(ctx, params) + s.Require().NoError(err) }, common.HexToAddress(tokenPair.Erc20Address), true, @@ -66,23 +66,23 @@ func (suite *KeeperTestSuite) TestGetERC20PrecompileInstance() { }, } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() - ctx = suite.network.GetContext() + s.Run(tc.name, func() { + s.SetupTest() + ctx = s.network.GetContext() - suite.network.App.Erc20Keeper.SetToken(ctx, tokenPair) - tokenPairs = suite.network.App.Erc20Keeper.GetTokenPairs(ctx) - suite.Require().True(len(tokenPairs) > 1, + s.network.App.GetErc20Keeper().SetToken(ctx, tokenPair) + tokenPairs = s.network.App.GetErc20Keeper().GetTokenPairs(ctx) + s.Require().True(len(tokenPairs) > 1, "expected more than 1 token pair to be set; got %d", len(tokenPairs), ) tc.paramsFun() - _, found, err := suite.network.App.Erc20Keeper.GetERC20PrecompileInstance(ctx, tc.precompile) - suite.Require().Equal(found, tc.expectedFound) + _, found, err := s.network.App.GetErc20Keeper().GetERC20PrecompileInstance(ctx, tc.precompile) + s.Require().Equal(found, tc.expectedFound) if tc.expectedError { - suite.Require().ErrorContains(err, tc.err) + s.Require().ErrorContains(err, tc.err) } }) } diff --git a/x/erc20/keeper/proposals_test.go b/tests/integration/x/erc20/test_proposals.go similarity index 50% rename from x/erc20/keeper/proposals_test.go rename to tests/integration/x/erc20/test_proposals.go index fd065d6bb..5e3a6de5c 100644 --- a/x/erc20/keeper/proposals_test.go +++ b/tests/integration/x/erc20/test_proposals.go @@ -1,4 +1,4 @@ -package keeper_test +package erc20 import ( "fmt" @@ -7,8 +7,8 @@ import ( "github.com/stretchr/testify/mock" "github.com/cosmos/evm/contracts" - testfactory "github.com/cosmos/evm/testutil/integration/os/factory" - testutils "github.com/cosmos/evm/testutil/integration/os/utils" + "github.com/cosmos/evm/testutil/integration/evm/utils" + testutiltypes "github.com/cosmos/evm/testutil/types" "github.com/cosmos/evm/x/erc20/keeper" "github.com/cosmos/evm/x/erc20/types" erc20mocks "github.com/cosmos/evm/x/erc20/types/mocks" @@ -55,7 +55,7 @@ var metadataIbc = banktypes.Metadata{ // setupRegisterERC20Pair deploys an ERC20 smart contract and // registers it as ERC20. -func (suite *KeeperTestSuite) setupRegisterERC20Pair(contractType int) (common.Address, error) { +func (s *KeeperTestSuite) setupRegisterERC20Pair(contractType int) (common.Address, error) { var ( contract common.Address err error @@ -63,30 +63,30 @@ func (suite *KeeperTestSuite) setupRegisterERC20Pair(contractType int) (common.A // Deploy contract switch contractType { case contractDirectBalanceManipulation: - contract, err = suite.DeployContractDirectBalanceManipulation() + contract, err = s.DeployContractDirectBalanceManipulation() case contractMaliciousDelayed: - contract, err = suite.DeployContractMaliciousDelayed() + contract, err = s.DeployContractMaliciousDelayed() default: - contract, err = suite.DeployContract(erc20Name, erc20Symbol, erc20Decimals) + contract, err = s.DeployContract(erc20Name, erc20Symbol, erc20Decimals) } if err != nil { return common.Address{}, err } - if err := suite.network.NextBlock(); err != nil { + if err := s.network.NextBlock(); err != nil { return common.Address{}, err } // submit gov proposal to register ERC20 token pair - _, err = testutils.RegisterERC20(suite.factory, suite.network, testutils.ERC20RegistrationData{ + _, err = utils.RegisterERC20(s.factory, s.network, utils.ERC20RegistrationData{ Addresses: []string{contract.Hex()}, - ProposerPriv: suite.keyring.GetPrivKey(0), + ProposerPriv: s.keyring.GetPrivKey(0), }) return contract, err } -func (suite *KeeperTestSuite) TestRegisterERC20() { +func (s *KeeperTestSuite) TestRegisterERC20() { var ( ctx sdk.Context contractAddr common.Address @@ -101,31 +101,31 @@ func (suite *KeeperTestSuite) TestRegisterERC20() { { "token ERC20 already registered", func() { - suite.network.App.Erc20Keeper.SetERC20Map(ctx, pair.GetERC20Contract(), pair.GetID()) + s.network.App.GetErc20Keeper().SetERC20Map(ctx, pair.GetERC20Contract(), pair.GetID()) }, - suite.keyring.GetAccAddr(0).String(), + s.keyring.GetAccAddr(0).String(), false, }, { "denom already registered", func() { - suite.network.App.Erc20Keeper.SetDenomMap(ctx, pair.Denom, pair.GetID()) + s.network.App.GetErc20Keeper().SetDenomMap(ctx, pair.Denom, pair.GetID()) }, - suite.keyring.GetAccAddr(0).String(), + s.keyring.GetAccAddr(0).String(), false, }, { "meta data already stored", func() { - suite.network.App.Erc20Keeper.CreateCoinMetadata(ctx, contractAddr) //nolint:errcheck + s.network.App.GetErc20Keeper().CreateCoinMetadata(ctx, contractAddr) //nolint:errcheck }, - suite.keyring.GetAccAddr(0).String(), + s.keyring.GetAccAddr(0).String(), false, }, { "ok - governance, permissionless false", func() { - suite.network.App.Erc20Keeper.SetPermissionlessRegistration(ctx, false) + s.network.App.GetErc20Keeper().SetPermissionlessRegistration(ctx, false) }, authtypes.NewModuleAddress(govtypes.ModuleName).String(), true, @@ -139,15 +139,15 @@ func (suite *KeeperTestSuite) TestRegisterERC20() { { "fail - non-governance, permissionless false", func() { - suite.network.App.Erc20Keeper.SetPermissionlessRegistration(ctx, false) + s.network.App.GetErc20Keeper().SetPermissionlessRegistration(ctx, false) }, - suite.keyring.GetAccAddr(0).String(), + s.keyring.GetAccAddr(0).String(), false, }, { "ok - non-governance, permissionless true", func() {}, - suite.keyring.GetAccAddr(0).String(), + s.keyring.GetAccAddr(0).String(), true, }, { @@ -155,72 +155,74 @@ func (suite *KeeperTestSuite) TestRegisterERC20() { func() { mockEVMKeeper := &erc20mocks.EVMKeeper{} - suite.network.App.Erc20Keeper = keeper.NewKeeper( - suite.network.App.GetKey("erc20"), suite.network.App.AppCodec(), - authtypes.NewModuleAddress(govtypes.ModuleName), suite.network.App.AccountKeeper, - suite.network.App.BankKeeper, mockEVMKeeper, suite.network.App.StakingKeeper, - &suite.network.App.TransferKeeper, + transferKeeper := s.network.App.GetTransferKeeper() + erc20Keeper := keeper.NewKeeper( + s.network.App.GetKey("erc20"), s.network.App.AppCodec(), + authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), + s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), + &transferKeeper, ) + s.network.App.SetErc20Keeper(&erc20Keeper) mockEVMKeeper.On("EstimateGasInternal", mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.EstimateGasResponse{Gas: uint64(200)}, nil) mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("forced CallEVM error")) mockEVMKeeper.On("ApplyMessage", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("forced ApplyMessage error")) }, - suite.keyring.GetAccAddr(0).String(), + s.keyring.GetAccAddr(0).String(), false, }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.Run(fmt.Sprintf("Case %s", tc.name), func() { var err error - suite.SetupTest() // reset + s.SetupTest() // reset - contractAddr, err = suite.factory.DeployContract( - suite.keyring.GetPrivKey(0), + contractAddr, err = s.factory.DeployContract( + s.keyring.GetPrivKey(0), evmtypes.EvmTxArgs{}, - testfactory.ContractDeploymentData{ + testutiltypes.ContractDeploymentData{ Contract: contracts.ERC20MinterBurnerDecimalsContract, ConstructorArgs: []interface{}{erc20Name, erc20Symbol, cosmosDecimals}, }, ) - suite.Require().NoError(err, "failed to deploy contract") - suite.Require().NoError(suite.network.NextBlock(), "failed to advance block") + s.Require().NoError(err, "failed to deploy contract") + s.Require().NoError(s.network.NextBlock(), "failed to advance block") coinName := types.CreateDenom(contractAddr.String()) pair = types.NewTokenPair(contractAddr, coinName, types.OWNER_EXTERNAL) - ctx = suite.network.GetContext() + ctx = s.network.GetContext() tc.malleate() - _, err = suite.network.App.Erc20Keeper.RegisterERC20(ctx, &types.MsgRegisterERC20{ + _, err = s.network.App.GetErc20Keeper().RegisterERC20(ctx, &types.MsgRegisterERC20{ Signer: tc.signer, Erc20Addresses: []string{contractAddr.Hex()}, }) - metadata, found := suite.network.App.BankKeeper.GetDenomMetaData(ctx, coinName) + metadata, found := s.network.App.GetBankKeeper().GetDenomMetaData(ctx, coinName) if tc.expPass { - suite.Require().NoError(err, tc.name) + s.Require().NoError(err, tc.name) // Metadata variables - suite.Require().True(found) - suite.Require().Equal(coinName, metadata.Base) - suite.Require().Equal(coinName, metadata.Name) - suite.Require().Equal(types.SanitizeERC20Name(erc20Name), metadata.Display) - suite.Require().Equal(erc20Symbol, metadata.Symbol) + s.Require().True(found) + s.Require().Equal(coinName, metadata.Base) + s.Require().Equal(coinName, metadata.Name) + s.Require().Equal(types.SanitizeERC20Name(erc20Name), metadata.Display) + s.Require().Equal(erc20Symbol, metadata.Symbol) // Denom units - suite.Require().Equal(len(metadata.DenomUnits), 2) - suite.Require().Equal(coinName, metadata.DenomUnits[0].Denom) - suite.Require().Equal(zeroExponent, metadata.DenomUnits[0].Exponent) - suite.Require().Equal(types.SanitizeERC20Name(erc20Name), metadata.DenomUnits[1].Denom) + s.Require().Equal(len(metadata.DenomUnits), 2) + s.Require().Equal(coinName, metadata.DenomUnits[0].Denom) + s.Require().Equal(zeroExponent, metadata.DenomUnits[0].Exponent) + s.Require().Equal(types.SanitizeERC20Name(erc20Name), metadata.DenomUnits[1].Denom) // Custom exponent at contract creation matches coin with token - suite.Require().Equal(metadata.DenomUnits[1].Exponent, uint32(cosmosDecimals)) + s.Require().Equal(metadata.DenomUnits[1].Exponent, uint32(cosmosDecimals)) } else { - suite.Require().Error(err, tc.name) + s.Require().Error(err, tc.name) } }) } } -func (suite *KeeperTestSuite) TestToggleConverision() { +func (s *KeeperTestSuite) TestToggleConverision() { var ( ctx sdk.Context err error @@ -238,16 +240,16 @@ func (suite *KeeperTestSuite) TestToggleConverision() { { "token not registered", func() { - contractAddr, err = suite.factory.DeployContract( - suite.keyring.GetPrivKey(0), + contractAddr, err = s.factory.DeployContract( + s.keyring.GetPrivKey(0), evmtypes.EvmTxArgs{}, - testfactory.ContractDeploymentData{ + testutiltypes.ContractDeploymentData{ Contract: contracts.ERC20MinterBurnerDecimalsContract, ConstructorArgs: []interface{}{erc20Name, erc20Symbol, erc20Decimals}, }, ) - suite.Require().NoError(err, "failed to deploy contract") - suite.Require().NoError(suite.network.NextBlock(), "failed to advance block") + s.Require().NoError(err, "failed to deploy contract") + s.Require().NoError(s.network.NextBlock(), "failed to advance block") pair = types.NewTokenPair(contractAddr, cosmosTokenBase, types.OWNER_MODULE) }, @@ -257,19 +259,19 @@ func (suite *KeeperTestSuite) TestToggleConverision() { { "token not registered - pair not found", func() { - contractAddr, err = suite.factory.DeployContract( - suite.keyring.GetPrivKey(0), + contractAddr, err = s.factory.DeployContract( + s.keyring.GetPrivKey(0), evmtypes.EvmTxArgs{}, - testfactory.ContractDeploymentData{ + testutiltypes.ContractDeploymentData{ Contract: contracts.ERC20MinterBurnerDecimalsContract, ConstructorArgs: []interface{}{erc20Name, erc20Symbol, erc20Decimals}, }, ) - suite.Require().NoError(err, "failed to deploy contract") - suite.Require().NoError(suite.network.NextBlock(), "failed to advance block") + s.Require().NoError(err, "failed to deploy contract") + s.Require().NoError(s.network.NextBlock(), "failed to advance block") pair = types.NewTokenPair(contractAddr, cosmosTokenBase, types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetERC20Map(ctx, common.HexToAddress(pair.Erc20Address), pair.GetID()) + s.network.App.GetErc20Keeper().SetERC20Map(ctx, common.HexToAddress(pair.Erc20Address), pair.GetID()) }, false, false, @@ -277,11 +279,11 @@ func (suite *KeeperTestSuite) TestToggleConverision() { { "disable conversion", func() { - contractAddr, err = suite.setupRegisterERC20Pair(contractMinterBurner) - suite.Require().NoError(err, "failed to register pair") - ctx = suite.network.GetContext() - id = suite.network.App.Erc20Keeper.GetTokenPairID(ctx, contractAddr.String()) - pair, _ = suite.network.App.Erc20Keeper.GetTokenPair(ctx, id) + contractAddr, err = s.setupRegisterERC20Pair(contractMinterBurner) + s.Require().NoError(err, "failed to register pair") + ctx = s.network.GetContext() + id = s.network.App.GetErc20Keeper().GetTokenPairID(ctx, contractAddr.String()) + pair, _ = s.network.App.GetErc20Keeper().GetTokenPair(ctx, id) }, true, false, @@ -289,39 +291,39 @@ func (suite *KeeperTestSuite) TestToggleConverision() { { "disable and enable conversion", func() { - contractAddr, err = suite.setupRegisterERC20Pair(contractMinterBurner) - suite.Require().NoError(err, "failed to register pair") - ctx = suite.network.GetContext() - id = suite.network.App.Erc20Keeper.GetTokenPairID(ctx, contractAddr.String()) - pair, _ = suite.network.App.Erc20Keeper.GetTokenPair(ctx, id) - res, err := suite.network.App.Erc20Keeper.ToggleConversion(ctx, &types.MsgToggleConversion{Authority: authtypes.NewModuleAddress("gov").String(), Token: contractAddr.String()}) - suite.Require().NoError(err) - suite.Require().NotNil(res) - pair, _ = suite.network.App.Erc20Keeper.GetTokenPair(ctx, id) + contractAddr, err = s.setupRegisterERC20Pair(contractMinterBurner) + s.Require().NoError(err, "failed to register pair") + ctx = s.network.GetContext() + id = s.network.App.GetErc20Keeper().GetTokenPairID(ctx, contractAddr.String()) + pair, _ = s.network.App.GetErc20Keeper().GetTokenPair(ctx, id) + res, err := s.network.App.GetErc20Keeper().ToggleConversion(ctx, &types.MsgToggleConversion{Authority: authtypes.NewModuleAddress("gov").String(), Token: contractAddr.String()}) + s.Require().NoError(err) + s.Require().NotNil(res) + pair, _ = s.network.App.GetErc20Keeper().GetTokenPair(ctx, id) }, true, true, }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() // reset - ctx = suite.network.GetContext() + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // reset + ctx = s.network.GetContext() tc.malleate() - _, err = suite.network.App.Erc20Keeper.ToggleConversion(ctx, &types.MsgToggleConversion{Authority: authtypes.NewModuleAddress("gov").String(), Token: contractAddr.String()}) + _, err = s.network.App.GetErc20Keeper().ToggleConversion(ctx, &types.MsgToggleConversion{Authority: authtypes.NewModuleAddress("gov").String(), Token: contractAddr.String()}) // Request the pair using the GetPairToken func to make sure that is updated on the db - pair, _ = suite.network.App.Erc20Keeper.GetTokenPair(ctx, id) + pair, _ = s.network.App.GetErc20Keeper().GetTokenPair(ctx, id) if tc.expPass { - suite.Require().NoError(err, tc.name) + s.Require().NoError(err, tc.name) if tc.conversionEnabled { - suite.Require().True(pair.Enabled) + s.Require().True(pair.Enabled) } else { - suite.Require().False(pair.Enabled) + s.Require().False(pair.Enabled) } } else { - suite.Require().Error(err, tc.name) + s.Require().Error(err, tc.name) } }) } diff --git a/x/erc20/keeper/setup_test.go b/tests/integration/x/erc20/test_setup.go similarity index 60% rename from x/erc20/keeper/setup_test.go rename to tests/integration/x/erc20/test_setup.go index 30616e011..90ea9c5a0 100644 --- a/x/erc20/keeper/setup_test.go +++ b/tests/integration/x/erc20/test_setup.go @@ -1,15 +1,13 @@ -package keeper_test +package erc20 import ( - "testing" - "github.com/ethereum/go-ethereum/params" "github.com/stretchr/testify/suite" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/keyring" "github.com/cosmos/evm/x/erc20/types" sdkmath "cosmossdk.io/math" @@ -22,6 +20,8 @@ import ( type KeeperTestSuite struct { suite.Suite + create network.CreateEvmApp + options []network.ConfigOption network *network.UnitTestNetwork handler grpc.Handler keyring keyring.Keyring @@ -32,18 +32,21 @@ type KeeperTestSuite struct { mintFeeCollector bool } -func TestKeeperUnitTestSuite(t *testing.T) { - suite.Run(t, new(KeeperTestSuite)) +func NewKeeperTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *KeeperTestSuite { + return &KeeperTestSuite{ + create: create, + options: options, + } } -func (suite *KeeperTestSuite) SetupTest() { +func (s *KeeperTestSuite) SetupTest() { keys := keyring.New(2) // Set custom balance based on test params customGenesis := network.CustomGenesisState{} - if suite.mintFeeCollector { + if s.mintFeeCollector { baseDenom, err := sdk.GetBaseDenom() - suite.Require().NoError(err, "failed to get base denom") + s.Require().NoError(err, "failed to get base denom") // mint some coin to fee collector coins := sdk.NewCoins(sdk.NewCoin(baseDenom, sdkmath.NewInt(int64(params.TxGas)-1))) @@ -58,16 +61,18 @@ func (suite *KeeperTestSuite) SetupTest() { customGenesis[banktypes.ModuleName] = bankGenesis } - nw := network.NewUnitTestNetwork( + options := []network.ConfigOption{ network.WithPreFundedAccounts(keys.GetAllAccAddrs()...), network.WithCustomGenesis(customGenesis), - ) + } + options = append(options, s.options...) + nw := network.NewUnitTestNetwork(s.create, options...) gh := grpc.NewIntegrationHandler(nw) tf := factory.New(nw, gh) - suite.network = nw - suite.factory = tf - suite.handler = gh - suite.keyring = keys - suite.queryClient = nw.GetERC20Client() + s.network = nw + s.factory = tf + s.handler = gh + s.keyring = keys + s.queryClient = nw.GetERC20Client() } diff --git a/x/erc20/keeper/token_pairs_test.go b/tests/integration/x/erc20/test_token_pairs.go similarity index 55% rename from x/erc20/keeper/token_pairs_test.go rename to tests/integration/x/erc20/test_token_pairs.go index 2cfa68442..d87a37a01 100644 --- a/x/erc20/keeper/token_pairs_test.go +++ b/tests/integration/x/erc20/test_token_pairs.go @@ -1,4 +1,4 @@ -package keeper_test +package erc20 import ( "fmt" @@ -12,7 +12,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -func (suite *KeeperTestSuite) TestGetTokenPairs() { +func (s *KeeperTestSuite) TestGetTokenPairs() { var ( ctx sdk.Context expRes []types.TokenPair @@ -29,7 +29,7 @@ func (suite *KeeperTestSuite) TestGetTokenPairs() { "1 pair registered", func() { pair := types.NewTokenPair(utiltx.GenerateAddress(), "coin", types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetTokenPair(ctx, pair) + s.network.App.GetErc20Keeper().SetTokenPair(ctx, pair) expRes = testconstants.ExampleTokenPairs expRes = append(expRes, pair) }, @@ -39,29 +39,29 @@ func (suite *KeeperTestSuite) TestGetTokenPairs() { func() { pair := types.NewTokenPair(utiltx.GenerateAddress(), "coin", types.OWNER_MODULE) pair2 := types.NewTokenPair(utiltx.GenerateAddress(), "coin2", types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetTokenPair(ctx, pair) - suite.network.App.Erc20Keeper.SetTokenPair(ctx, pair2) + s.network.App.GetErc20Keeper().SetTokenPair(ctx, pair) + s.network.App.GetErc20Keeper().SetTokenPair(ctx, pair2) expRes = testconstants.ExampleTokenPairs expRes = append(expRes, []types.TokenPair{pair, pair2}...) }, }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() // reset - ctx = suite.network.GetContext() + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // reset + ctx = s.network.GetContext() tc.malleate() - res := suite.network.App.Erc20Keeper.GetTokenPairs(ctx) + res := s.network.App.GetErc20Keeper().GetTokenPairs(ctx) - suite.Require().ElementsMatch(expRes, res, tc.name) + s.Require().ElementsMatch(expRes, res, tc.name) }) } } -func (suite *KeeperTestSuite) TestGetTokenPairID() { +func (s *KeeperTestSuite) TestGetTokenPairID() { baseDenom, err := sdk.GetBaseDenom() - suite.Require().NoError(err, "failed to get base denom") + s.Require().NoError(err, "failed to get base denom") pair := types.NewTokenPair(utiltx.GenerateAddress(), baseDenom, types.OWNER_MODULE) @@ -75,23 +75,23 @@ func (suite *KeeperTestSuite) TestGetTokenPairID() { {"valid hex token", utiltx.GenerateAddress().String(), []byte{}}, } for _, tc := range testCases { - suite.SetupTest() - ctx := suite.network.GetContext() + s.SetupTest() + ctx := s.network.GetContext() - suite.network.App.Erc20Keeper.SetTokenPair(ctx, pair) + s.network.App.GetErc20Keeper().SetTokenPair(ctx, pair) - id := suite.network.App.Erc20Keeper.GetTokenPairID(ctx, tc.token) + id := s.network.App.GetErc20Keeper().GetTokenPairID(ctx, tc.token) if id != nil { - suite.Require().Equal(tc.expID, id, tc.name) + s.Require().Equal(tc.expID, id, tc.name) } else { - suite.Require().Nil(id) + s.Require().Nil(id) } } } -func (suite *KeeperTestSuite) TestGetTokenPair() { +func (s *KeeperTestSuite) TestGetTokenPair() { baseDenom, err := sdk.GetBaseDenom() - suite.Require().NoError(err, "failed to get base denom") + s.Require().NoError(err, "failed to get base denom") pair := types.NewTokenPair(utiltx.GenerateAddress(), baseDenom, types.OWNER_MODULE) @@ -105,23 +105,23 @@ func (suite *KeeperTestSuite) TestGetTokenPair() { {"pair not found", []byte{}, false}, } for _, tc := range testCases { - suite.SetupTest() - ctx := suite.network.GetContext() + s.SetupTest() + ctx := s.network.GetContext() - suite.network.App.Erc20Keeper.SetTokenPair(ctx, pair) - p, found := suite.network.App.Erc20Keeper.GetTokenPair(ctx, tc.id) + s.network.App.GetErc20Keeper().SetTokenPair(ctx, pair) + p, found := s.network.App.GetErc20Keeper().GetTokenPair(ctx, tc.id) if tc.ok { - suite.Require().True(found, tc.name) - suite.Require().Equal(pair, p, tc.name) + s.Require().True(found, tc.name) + s.Require().Equal(pair, p, tc.name) } else { - suite.Require().False(found, tc.name) + s.Require().False(found, tc.name) } } } -func (suite *KeeperTestSuite) TestDeleteTokenPair() { +func (s *KeeperTestSuite) TestDeleteTokenPair() { baseDenom, err := sdk.GetBaseDenom() - suite.Require().NoError(err, "failed to get base denom") + s.Require().NoError(err, "failed to get base denom") var ctx sdk.Context pair := types.NewTokenPair(utiltx.GenerateAddress(), baseDenom, types.OWNER_MODULE) @@ -140,30 +140,30 @@ func (suite *KeeperTestSuite) TestDeleteTokenPair() { "delete tokenpair", id, func() { - suite.network.App.Erc20Keeper.DeleteTokenPair(ctx, pair) + s.network.App.GetErc20Keeper().DeleteTokenPair(ctx, pair) }, false, }, } for _, tc := range testCases { - suite.SetupTest() - ctx = suite.network.GetContext() - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.SetupTest() + ctx = s.network.GetContext() + s.network.App.GetErc20Keeper().SetToken(ctx, pair) tc.malleate() - p, found := suite.network.App.Erc20Keeper.GetTokenPair(ctx, tc.id) + p, found := s.network.App.GetErc20Keeper().GetTokenPair(ctx, tc.id) if tc.ok { - suite.Require().True(found, tc.name) - suite.Require().Equal(pair, p, tc.name) + s.Require().True(found, tc.name) + s.Require().Equal(pair, p, tc.name) } else { - suite.Require().False(found, tc.name) + s.Require().False(found, tc.name) } } } -func (suite *KeeperTestSuite) TestIsTokenPairRegistered() { +func (s *KeeperTestSuite) TestIsTokenPairRegistered() { baseDenom, err := sdk.GetBaseDenom() - suite.Require().NoError(err, "failed to get base denom") + s.Require().NoError(err, "failed to get base denom") var ctx sdk.Context pair := types.NewTokenPair(utiltx.GenerateAddress(), baseDenom, types.OWNER_MODULE) @@ -177,20 +177,20 @@ func (suite *KeeperTestSuite) TestIsTokenPairRegistered() { {"pair not found", []byte{}, false}, } for _, tc := range testCases { - suite.SetupTest() - ctx = suite.network.GetContext() + s.SetupTest() + ctx = s.network.GetContext() - suite.network.App.Erc20Keeper.SetTokenPair(ctx, pair) - found := suite.network.App.Erc20Keeper.IsTokenPairRegistered(ctx, tc.id) + s.network.App.GetErc20Keeper().SetTokenPair(ctx, pair) + found := s.network.App.GetErc20Keeper().IsTokenPairRegistered(ctx, tc.id) if tc.ok { - suite.Require().True(found, tc.name) + s.Require().True(found, tc.name) } else { - suite.Require().False(found, tc.name) + s.Require().False(found, tc.name) } } } -func (suite *KeeperTestSuite) TestIsERC20Registered() { +func (s *KeeperTestSuite) TestIsERC20Registered() { var ctx sdk.Context addr := utiltx.GenerateAddress() pair := types.NewTokenPair(addr, "coin", types.OWNER_MODULE) @@ -207,30 +207,30 @@ func (suite *KeeperTestSuite) TestIsERC20Registered() { "deleted erc20 map", pair.GetERC20Contract(), func() { - suite.network.App.Erc20Keeper.DeleteTokenPair(ctx, pair) + s.network.App.GetErc20Keeper().DeleteTokenPair(ctx, pair) }, false, }, } for _, tc := range testCases { - suite.SetupTest() - ctx = suite.network.GetContext() + s.SetupTest() + ctx = s.network.GetContext() - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) tc.malleate() - found := suite.network.App.Erc20Keeper.IsERC20Registered(ctx, tc.erc20) + found := s.network.App.GetErc20Keeper().IsERC20Registered(ctx, tc.erc20) if tc.ok { - suite.Require().True(found, tc.name) + s.Require().True(found, tc.name) } else { - suite.Require().False(found, tc.name) + s.Require().False(found, tc.name) } } } -func (suite *KeeperTestSuite) TestIsDenomRegistered() { +func (s *KeeperTestSuite) TestIsDenomRegistered() { var ctx sdk.Context addr := utiltx.GenerateAddress() pair := types.NewTokenPair(addr, "coin", types.OWNER_MODULE) @@ -247,30 +247,30 @@ func (suite *KeeperTestSuite) TestIsDenomRegistered() { "deleted denom map", pair.GetDenom(), func() { - suite.network.App.Erc20Keeper.DeleteTokenPair(ctx, pair) + s.network.App.GetErc20Keeper().DeleteTokenPair(ctx, pair) }, false, }, } for _, tc := range testCases { - suite.SetupTest() - ctx = suite.network.GetContext() + s.SetupTest() + ctx = s.network.GetContext() - suite.network.App.Erc20Keeper.SetToken(ctx, pair) + s.network.App.GetErc20Keeper().SetToken(ctx, pair) tc.malleate() - found := suite.network.App.Erc20Keeper.IsDenomRegistered(ctx, tc.denom) + found := s.network.App.GetErc20Keeper().IsDenomRegistered(ctx, tc.denom) if tc.ok { - suite.Require().True(found, tc.name) + s.Require().True(found, tc.name) } else { - suite.Require().False(found, tc.name) + s.Require().False(found, tc.name) } } } -func (suite *KeeperTestSuite) TestGetTokenDenom() { +func (s *KeeperTestSuite) TestGetTokenDenom() { var ctx sdk.Context tokenAddress := utiltx.GenerateAddress() tokenDenom := "token" @@ -287,8 +287,8 @@ func (suite *KeeperTestSuite) TestGetTokenDenom() { tokenDenom, func() { pair := types.NewTokenPair(tokenAddress, tokenDenom, types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetTokenPair(ctx, pair) - suite.network.App.Erc20Keeper.SetERC20Map(ctx, tokenAddress, pair.GetID()) + s.network.App.GetErc20Keeper().SetTokenPair(ctx, pair) + s.network.App.GetErc20Keeper().SetERC20Map(ctx, tokenAddress, pair.GetID()) }, true, "", @@ -299,27 +299,27 @@ func (suite *KeeperTestSuite) TestGetTokenDenom() { func() { address := utiltx.GenerateAddress() pair := types.NewTokenPair(address, tokenDenom, types.OWNER_MODULE) - suite.network.App.Erc20Keeper.SetTokenPair(ctx, pair) - suite.network.App.Erc20Keeper.SetERC20Map(ctx, address, pair.GetID()) + s.network.App.GetErc20Keeper().SetTokenPair(ctx, pair) + s.network.App.GetErc20Keeper().SetERC20Map(ctx, address, pair.GetID()) }, false, fmt.Sprintf("token '%s' not registered", tokenAddress), }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() - ctx = suite.network.GetContext() + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() + ctx = s.network.GetContext() tc.malleate() - res, err := suite.network.App.Erc20Keeper.GetTokenDenom(ctx, tokenAddress) + res, err := s.network.App.GetErc20Keeper().GetTokenDenom(ctx, tokenAddress) if tc.expError { - suite.Require().NoError(err) - suite.Require().Equal(res, tokenDenom) + s.Require().NoError(err) + s.Require().Equal(res, tokenDenom) } else { - suite.Require().Error(err, "expected an error while getting the token denom") - suite.Require().ErrorContains(err, tc.errContains) + s.Require().Error(err, "expected an error while getting the token denom") + s.Require().ErrorContains(err, tc.errContains) } }) } diff --git a/tests/integration/x/erc20/test_util.go b/tests/integration/x/erc20/test_util.go new file mode 100644 index 000000000..8d6e1da79 --- /dev/null +++ b/tests/integration/x/erc20/test_util.go @@ -0,0 +1,80 @@ +package erc20 + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + + "github.com/cosmos/evm/contracts" + testutiltypes "github.com/cosmos/evm/testutil/types" + "github.com/cosmos/evm/x/erc20/keeper/testdata" + "github.com/cosmos/evm/x/erc20/types" + evmtypes "github.com/cosmos/evm/x/vm/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +// MintFeeCollector mints some coins to the fee collector address. +// Use this only for unit tests. For integration tests, you can use the +// mintFeeCollector flag to setup some balance on genesis +func (s *KeeperTestSuite) MintFeeCollector(coins sdk.Coins) { + err := s.network.App.GetBankKeeper().MintCoins(s.network.GetContext(), types.ModuleName, coins) + s.Require().NoError(err) + err = s.network.App.GetBankKeeper().SendCoinsFromModuleToModule(s.network.GetContext(), types.ModuleName, authtypes.FeeCollectorName, coins) + s.Require().NoError(err) +} + +func (s *KeeperTestSuite) DeployContract(name, symbol string, decimals uint8) (common.Address, error) { + addr, err := s.factory.DeployContract( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{}, + testutiltypes.ContractDeploymentData{ + Contract: contracts.ERC20MinterBurnerDecimalsContract, + ConstructorArgs: []interface{}{name, symbol, decimals}, + }, + ) + if err != nil { + return common.Address{}, err + } + + return addr, s.network.NextBlock() +} + +func (s *KeeperTestSuite) DeployContractMaliciousDelayed() (common.Address, error) { + maliciousDelayedContract, err := testdata.LoadMaliciousDelayedContract() + s.Require().NoError(err, "failed to load malicious delayed contract") + + addr, err := s.factory.DeployContract( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{}, + testutiltypes.ContractDeploymentData{ + Contract: maliciousDelayedContract, + ConstructorArgs: []interface{}{big.NewInt(1000000000000000000)}, + }, + ) + if err != nil { + return common.Address{}, err + } + + return addr, s.network.NextBlock() +} + +func (s *KeeperTestSuite) DeployContractDirectBalanceManipulation() (common.Address, error) { + balanceManipulationContract, err := testdata.LoadBalanceManipulationContract() + s.Require().NoError(err, "failed to load balance manipulation contract") + + addr, err := s.factory.DeployContract( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{}, + testutiltypes.ContractDeploymentData{ + Contract: balanceManipulationContract, + ConstructorArgs: []interface{}{big.NewInt(1000000000000000000)}, + }, + ) + if err != nil { + return common.Address{}, err + } + + return addr, s.network.NextBlock() +} diff --git a/x/feemarket/keeper/abci_test.go b/tests/integration/x/feemarket/test_abci.go similarity index 50% rename from x/feemarket/keeper/abci_test.go rename to tests/integration/x/feemarket/test_abci.go index 0c581a426..df7a0f5eb 100644 --- a/x/feemarket/keeper/abci_test.go +++ b/tests/integration/x/feemarket/test_abci.go @@ -1,18 +1,14 @@ -package keeper_test +package feemarket import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/network" storetypes "cosmossdk.io/store/types" sdk "github.com/cosmos/cosmos-sdk/types" ) -func TestEndBlock(t *testing.T) { +func (s *KeeperTestSuite) TestEndBlock() { var ( nw *network.UnitTestNetwork ctx sdk.Context @@ -36,30 +32,30 @@ func TestEndBlock(t *testing.T) { func() { meter := storetypes.NewGasMeter(uint64(1000000000)) ctx = ctx.WithBlockGasMeter(meter) - nw.App.FeeMarketKeeper.SetTransientBlockGasWanted(ctx, 5000000) + nw.App.GetFeeMarketKeeper().SetTransientBlockGasWanted(ctx, 5000000) }, uint64(2500000), }, } for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { + s.Run(tc.name, func() { // reset network and context - nw = network.NewUnitTestNetwork() + nw = network.NewUnitTestNetwork(s.create, s.options...) ctx = nw.GetContext() - params := nw.App.FeeMarketKeeper.GetParams(ctx) + params := nw.App.GetFeeMarketKeeper().GetParams(ctx) params.NoBaseFee = tc.NoBaseFee - err := nw.App.FeeMarketKeeper.SetParams(ctx, params) - require.NoError(t, err) + err := nw.App.GetFeeMarketKeeper().SetParams(ctx, params) + s.NoError(err) tc.malleate() - err = nw.App.FeeMarketKeeper.EndBlock(ctx) - require.NoError(t, err) + err = nw.App.GetFeeMarketKeeper().EndBlock(ctx) + s.NoError(err) - gasWanted := nw.App.FeeMarketKeeper.GetBlockGasWanted(ctx) - require.Equal(t, tc.expGasWanted, gasWanted, tc.name) + gasWanted := nw.App.GetFeeMarketKeeper().GetBlockGasWanted(ctx) + s.Equal(tc.expGasWanted, gasWanted, tc.name) }) } } diff --git a/x/feemarket/keeper/eip1559_test.go b/tests/integration/x/feemarket/test_eip1559.go similarity index 75% rename from x/feemarket/keeper/eip1559_test.go rename to tests/integration/x/feemarket/test_eip1559.go index 99b3ba17b..0529ca2ff 100644 --- a/x/feemarket/keeper/eip1559_test.go +++ b/tests/integration/x/feemarket/test_eip1559.go @@ -1,20 +1,16 @@ -package keeper_test +package feemarket import ( - "testing" - - "github.com/stretchr/testify/require" - tmproto "github.com/cometbft/cometbft/proto/tendermint/types" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/network" "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" ) -func TestCalculateBaseFee(t *testing.T) { +func (s *KeeperTestSuite) TestCalculateBaseFee() { var ( nw *network.UnitTestNetwork ctx sdk.Context @@ -43,7 +39,7 @@ func TestCalculateBaseFee(t *testing.T) { 0, 0, math.LegacyZeroDec(), - func() math.LegacyDec { return nw.App.FeeMarketKeeper.GetParams(ctx).BaseFee }, + func() math.LegacyDec { return nw.App.GetFeeMarketKeeper().GetParams(ctx).BaseFee }, }, { "with BaseFee - parent block wanted the same gas as its target (ElasticityMultiplier = 2)", @@ -51,7 +47,7 @@ func TestCalculateBaseFee(t *testing.T) { 1, 50, math.LegacyZeroDec(), - func() math.LegacyDec { return nw.App.FeeMarketKeeper.GetParams(ctx).BaseFee }, + func() math.LegacyDec { return nw.App.GetFeeMarketKeeper().GetParams(ctx).BaseFee }, }, { "with BaseFee - parent block wanted the same gas as its target, with higher min gas price (ElasticityMultiplier = 2)", @@ -59,7 +55,7 @@ func TestCalculateBaseFee(t *testing.T) { 1, 50, math.LegacyNewDec(1500000000), - func() math.LegacyDec { return nw.App.FeeMarketKeeper.GetParams(ctx).BaseFee }, + func() math.LegacyDec { return nw.App.GetFeeMarketKeeper().GetParams(ctx).BaseFee }, }, { "with BaseFee - parent block wanted more gas than its target (ElasticityMultiplier = 2)", @@ -95,16 +91,16 @@ func TestCalculateBaseFee(t *testing.T) { }, } for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { + s.Run(tc.name, func() { // reset network and context - nw = network.NewUnitTestNetwork() + nw = network.NewUnitTestNetwork(s.create, s.options...) ctx = nw.GetContext() - params := nw.App.FeeMarketKeeper.GetParams(ctx) + params := nw.App.GetFeeMarketKeeper().GetParams(ctx) params.NoBaseFee = tc.NoBaseFee params.MinGasPrice = tc.minGasPrice - err := nw.App.FeeMarketKeeper.SetParams(ctx, params) - require.NoError(t, err) + err := nw.App.GetFeeMarketKeeper().SetParams(ctx, params) + s.NoError(err) initialBaseFee = params.BaseFee @@ -112,7 +108,7 @@ func TestCalculateBaseFee(t *testing.T) { ctx = ctx.WithBlockHeight(tc.blockHeight) // Set parent block gas - nw.App.FeeMarketKeeper.SetBlockGasWanted(ctx, tc.parentBlockGasWanted) + nw.App.GetFeeMarketKeeper().SetBlockGasWanted(ctx, tc.parentBlockGasWanted) // Set next block target/gasLimit through Consensus Param MaxGas blockParams := tmproto.BlockParams{ @@ -122,11 +118,11 @@ func TestCalculateBaseFee(t *testing.T) { consParams := tmproto.ConsensusParams{Block: &blockParams} ctx = ctx.WithConsensusParams(consParams) - fee := nw.App.FeeMarketKeeper.CalculateBaseFee(ctx) + fee := nw.App.GetFeeMarketKeeper().CalculateBaseFee(ctx) if tc.NoBaseFee { - require.True(t, fee.IsNil(), tc.name) + s.True(fee.IsNil(), tc.name) } else { - require.Equal(t, tc.expFee(), fee, tc.name) + s.Equal(tc.expFee(), fee, tc.name) } }) } diff --git a/x/feemarket/keeper/grpc_query_test.go b/tests/integration/x/feemarket/test_grpc_query.go similarity index 64% rename from x/feemarket/keeper/grpc_query_test.go rename to tests/integration/x/feemarket/test_grpc_query.go index c48db38b5..41cab9cea 100644 --- a/x/feemarket/keeper/grpc_query_test.go +++ b/tests/integration/x/feemarket/test_grpc_query.go @@ -1,11 +1,7 @@ -package keeper_test +package feemarket import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/network" "github.com/cosmos/evm/x/feemarket/types" sdkmath "cosmossdk.io/math" @@ -13,7 +9,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -func TestQueryParams(t *testing.T) { +func (s *KeeperTestSuite) TestQueryParams() { var ( nw *network.UnitTestNetwork ctx sdk.Context @@ -29,27 +25,27 @@ func TestQueryParams(t *testing.T) { }, } for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { + s.Run(tc.name, func() { // reset network and context - nw = network.NewUnitTestNetwork() + nw = network.NewUnitTestNetwork(s.create, s.options...) ctx = nw.GetContext() qc := nw.GetFeeMarketClient() - params := nw.App.FeeMarketKeeper.GetParams(ctx) + params := nw.App.GetFeeMarketKeeper().GetParams(ctx) exp := &types.QueryParamsResponse{Params: params} res, err := qc.Params(ctx.Context(), &types.QueryParamsRequest{}) if tc.expPass { - require.Equal(t, exp, res, tc.name) - require.NoError(t, err) + s.Equal(exp, res, tc.name) + s.NoError(err) } else { - require.Error(t, err) + s.Error(err) } }) } } -func TestQueryBaseFee(t *testing.T) { +func (s *KeeperTestSuite) TestQueryBaseFee() { var ( expRes *types.QueryBaseFeeResponse nw *network.UnitTestNetwork @@ -73,7 +69,7 @@ func TestQueryBaseFee(t *testing.T) { "pass - non-nil Base Fee", func() { baseFee := sdkmath.LegacyNewDec(1) - nw.App.FeeMarketKeeper.SetBaseFee(ctx, baseFee) + nw.App.GetFeeMarketKeeper().SetBaseFee(ctx, baseFee) expRes = &types.QueryBaseFeeResponse{BaseFee: &baseFee} }, @@ -81,28 +77,28 @@ func TestQueryBaseFee(t *testing.T) { }, } for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { + s.Run(tc.name, func() { // reset network and context - nw = network.NewUnitTestNetwork() + nw = network.NewUnitTestNetwork(s.create, s.options...) ctx = nw.GetContext() qc := nw.GetFeeMarketClient() - initialBaseFee = nw.App.FeeMarketKeeper.GetBaseFee(ctx) + initialBaseFee = nw.App.GetFeeMarketKeeper().GetBaseFee(ctx) tc.malleate() res, err := qc.BaseFee(ctx.Context(), &types.QueryBaseFeeRequest{}) if tc.expPass { - require.NotNil(t, res) - require.Equal(t, expRes, res, tc.name) - require.NoError(t, err) + s.NotNil(res) + s.Equal(expRes, res, tc.name) + s.NoError(err) } else { - require.Error(t, err) + s.Error(err) } }) } } -func TestQueryBlockGas(t *testing.T) { +func (s *KeeperTestSuite) TestQueryBlockGas() { var ( nw *network.UnitTestNetwork ctx sdk.Context @@ -117,21 +113,21 @@ func TestQueryBlockGas(t *testing.T) { }, } for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { + s.Run(tc.name, func() { // reset network and context - nw = network.NewUnitTestNetwork() + nw = network.NewUnitTestNetwork(s.create, s.options...) ctx = nw.GetContext() qc := nw.GetFeeMarketClient() - gas := nw.App.FeeMarketKeeper.GetBlockGasWanted(ctx) + gas := nw.App.GetFeeMarketKeeper().GetBlockGasWanted(ctx) exp := &types.QueryBlockGasResponse{Gas: int64(gas)} //#nosec G115 res, err := qc.BlockGas(ctx.Context(), &types.QueryBlockGasRequest{}) if tc.expPass { - require.Equal(t, exp, res, tc.name) - require.NoError(t, err) + s.Equal(exp, res, tc.name) + s.NoError(err) } else { - require.Error(t, err) + s.Error(err) } }) } diff --git a/tests/integration/x/feemarket/test_integration.go b/tests/integration/x/feemarket/test_integration.go new file mode 100644 index 000000000..8902eb2ec --- /dev/null +++ b/tests/integration/x/feemarket/test_integration.go @@ -0,0 +1,691 @@ +package feemarket + +import ( + "math/big" + "testing" + + ethtypes "github.com/ethereum/go-ethereum/core/types" + + //nolint:revive // dot imports are fine for Ginkgo + . "github.com/onsi/ginkgo/v2" + //nolint:revive // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" + + "github.com/cosmos/evm/testutil/integration/base/factory" + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/integration/evm/utils" + fmkttypes "github.com/cosmos/evm/x/feemarket/types" + evmtypes "github.com/cosmos/evm/x/vm/types" + + "cosmossdk.io/math" + + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +type txParams struct { + gasPrice *big.Int + gasFeeCap *big.Int + gasTipCap *big.Int + accesses *ethtypes.AccessList +} +type getprices func() txParams + +var CreateApp network.CreateEvmApp + +func TestKeeperIntegrationTestSuite(t *testing.T) { + if CreateApp == nil { + panic("CreateApp must be set before running the tests") + } + + var _ = Describe("Feemarket", func() { + var ( + s *KeeperTestSuite + privKey cryptotypes.PrivKey + ) + + BeforeEach(func() { + s = new(KeeperTestSuite) + s.create = CreateApp + s.SetupTest() + privKey = s.keyring.GetPrivKey(0) + }) + + Describe("Performing Cosmos transactions", func() { + var ( + txArgs factory.CosmosTxArgs + gasWanted uint64 = 200_000 + ) + + BeforeEach(func() { + msg := banktypes.MsgSend{ + FromAddress: s.keyring.GetAccAddr(0).String(), + ToAddress: s.keyring.GetAccAddr(1).String(), + Amount: sdk.Coins{sdk.Coin{ + Denom: s.denom, + Amount: math.NewInt(10000), + }}, + } + txArgs = factory.CosmosTxArgs{ + ChainID: s.network.GetChainID(), + Msgs: []sdk.Msg{&msg}, + Gas: &gasWanted, + } + }) + + Context("with min-gas-prices (local) < MinGasPrices (feemarket param)", func() { + // minGasPrices is the feemarket MinGasPrices + const minGasPrices int64 = 15 + + BeforeEach(func() { + // local min-gas-prices is 10aatom + params := fmkttypes.DefaultParams() + params.MinGasPrice = math.LegacyNewDec(minGasPrices) + params.BaseFee = math.LegacyNewDec(0) + err := utils.UpdateFeeMarketParams( + utils.UpdateParamsInput{ + Tf: s.factory, + Network: s.network, + Pk: privKey, + Params: params, + }, + ) + Expect(err).To(BeNil()) + }) + + Context("during CheckTx", func() { + It("should reject transactions with gasPrice < MinGasPrices", func() { + gasPrice := math.NewInt(minGasPrices - 3) + txArgs.GasPrice = &gasPrice + tx, err := s.factory.BuildCosmosTx(privKey, txArgs) + Expect(err).To(BeNil()) + bz, err := s.factory.EncodeTx(tx) + Expect(err).To(BeNil()) + + res, err := s.network.CheckTx(bz) + Expect(err).To(BeNil()) + Expect(res.IsOK()).To(BeFalse()) + Expect(res.Log).To(ContainSubstring("provided fee < minimum global fee")) + }) + + It("should accept transactions with gasPrice >= MinGasPrices", func() { + gasPrice := math.NewInt(minGasPrices) + txArgs.GasPrice = &gasPrice + tx, err := s.factory.BuildCosmosTx(privKey, txArgs) + Expect(err).To(BeNil()) + bz, err := s.factory.EncodeTx(tx) + Expect(err).To(BeNil()) + + res, err := s.network.CheckTx(bz) + Expect(err).To(BeNil()) + Expect(res.IsOK()).To(BeTrue(), "transaction should have succeeded", res.GetLog()) + }) + }) + + Context("during DeliverTx", func() { + It("should reject transactions with gasPrice < MinGasPrices", func() { + gasPrice := math.NewInt(minGasPrices - 2) + txArgs.GasPrice = &gasPrice + res, err := s.factory.ExecuteCosmosTx(privKey, txArgs) + Expect(err).To(BeNil()) + Expect(res.IsOK()).To(BeFalse()) + Expect(res.Log).To(ContainSubstring("provided fee < minimum global fee")) + }) + + It("should accept transactions with gasPrice >= MinGasPrices", func() { + gasPrice := math.NewInt(minGasPrices) + txArgs.GasPrice = &gasPrice + res, err := s.factory.ExecuteCosmosTx(privKey, txArgs) + Expect(err).To(BeNil()) + Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog()) + }) + }) + }) + + Context("with min-gas-prices (local) == MinGasPrices (feemarket param)", func() { + // minGasPrices is the feemarket MinGasPrices + const minGasPrices int64 = 10 + BeforeEach(func() { + // local min-gas-prices is 10aatom + params := fmkttypes.DefaultParams() + params.MinGasPrice = math.LegacyNewDec(minGasPrices) + params.BaseFee = math.LegacyNewDec(0) + + err := utils.UpdateFeeMarketParams( + utils.UpdateParamsInput{ + Tf: s.factory, + Network: s.network, + Pk: privKey, + Params: params, + }, + ) + Expect(err).To(BeNil()) + }) + + Context("during CheckTx", func() { + It("should reject transactions with gasPrice < min-gas-prices", func() { + gasPrice := math.NewInt(minGasPrices - 3) + txArgs.GasPrice = &gasPrice + tx, err := s.factory.BuildCosmosTx(privKey, txArgs) + Expect(err).To(BeNil()) + bz, err := s.factory.EncodeTx(tx) + Expect(err).To(BeNil()) + + res, err := s.network.CheckTx(bz) + Expect(err).To(BeNil()) + Expect(res.IsOK()).To(BeFalse()) + Expect(res.Log).To(ContainSubstring("insufficient fee")) + }) + + It("should accept transactions with gasPrice >= MinGasPrices", func() { + gasPrice := math.NewInt(minGasPrices) + txArgs.GasPrice = &gasPrice + tx, err := s.factory.BuildCosmosTx(privKey, txArgs) + Expect(err).To(BeNil()) + bz, err := s.factory.EncodeTx(tx) + Expect(err).To(BeNil()) + + res, err := s.network.CheckTx(bz) + Expect(err).To(BeNil()) + Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog()) + }) + }) + + Context("during DeliverTx", func() { + It("should reject transactions with gasPrice < MinGasPrices", func() { + gasPrice := math.NewInt(minGasPrices - 2) + txArgs.GasPrice = &gasPrice + res, err := s.factory.ExecuteCosmosTx(privKey, txArgs) + Expect(err).To(BeNil()) + Expect(res.IsOK()).To(BeFalse()) + Expect(res.Log).To(ContainSubstring("provided fee < minimum global fee")) + }) + + It("should accept transactions with gasPrice >= MinGasPrices", func() { + gasPrice := math.NewInt(minGasPrices) + txArgs.GasPrice = &gasPrice + res, err := s.factory.ExecuteCosmosTx(privKey, txArgs) + Expect(err).To(BeNil()) + Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog()) + }) + }) + }) + + Context("with MinGasPrices (feemarket param) < min-gas-prices (local)", func() { + // minGasPrices is the feemarket MinGasPrices + const minGasPrices int64 = 7 + baseFee := math.LegacyNewDec(15) + + BeforeEach(func() { + // local min-gas-prices is 10aatom + params := fmkttypes.DefaultParams() + params.MinGasPrice = math.LegacyNewDec(minGasPrices) + params.BaseFee = baseFee + + err := utils.UpdateFeeMarketParams( + utils.UpdateParamsInput{ + Tf: s.factory, + Network: s.network, + Pk: privKey, + Params: params, + }, + ) + Expect(err).To(BeNil()) + }) + + Context("during CheckTx", func() { + It("should reject transactions with gasPrice < MinGasPrices", func() { + gasPrice := math.NewInt(minGasPrices - 3) + txArgs.GasPrice = &gasPrice + tx, err := s.factory.BuildCosmosTx(privKey, txArgs) + Expect(err).To(BeNil()) + bz, err := s.factory.EncodeTx(tx) + Expect(err).To(BeNil()) + + res, err := s.network.CheckTx(bz) + Expect(err).To(BeNil()) + Expect(res.IsOK()).To(BeFalse()) + Expect(res.Log).To(ContainSubstring("insufficient fee")) + }) + + It("should reject transactions with MinGasPrices < gasPrice < baseFee", func() { + gasPrice := math.NewInt(minGasPrices + 1) + txArgs.GasPrice = &gasPrice + tx, err := s.factory.BuildCosmosTx(privKey, txArgs) + Expect(err).To(BeNil()) + bz, err := s.factory.EncodeTx(tx) + Expect(err).To(BeNil()) + + res, err := s.network.CheckTx(bz) + Expect(err).To(BeNil()) + Expect(res.IsOK()).To(BeFalse()) + Expect(res.Log).To(ContainSubstring("insufficient fee")) + }) + + It("should accept transactions with gasPrice >= baseFee", func() { + gasPrice := baseFee.TruncateInt() + txArgs.GasPrice = &gasPrice + tx, err := s.factory.BuildCosmosTx(privKey, txArgs) + Expect(err).To(BeNil()) + bz, err := s.factory.EncodeTx(tx) + Expect(err).To(BeNil()) + + res, err := s.network.CheckTx(bz) + Expect(err).To(BeNil()) + Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog()) + }) + }) + + Context("during DeliverTx", func() { + It("should reject transactions with gasPrice < MinGasPrices", func() { + gasPrice := math.NewInt(minGasPrices - 2) + txArgs.GasPrice = &gasPrice + res, err := s.factory.ExecuteCosmosTx(privKey, txArgs) + Expect(err).To(BeNil()) + Expect(res.IsOK()).To(BeFalse()) + Expect(res.Log).To(ContainSubstring("provided fee < minimum global fee")) + }) + + It("should reject transactions with MinGasPrices < gasPrice < baseFee", func() { + gasPrice := math.NewInt(minGasPrices + 1) + txArgs.GasPrice = &gasPrice + res, err := s.factory.ExecuteCosmosTx(privKey, txArgs) + Expect(err).To(BeNil()) + Expect(res.IsOK()).To(BeFalse()) + Expect(res.Log).To(ContainSubstring("insufficient fee")) + }) + It("should accept transactions with gasPrice >= baseFee", func() { + gasPrice := baseFee.TruncateInt() + txArgs.GasPrice = &gasPrice + res, err := s.factory.ExecuteCosmosTx(privKey, txArgs) + Expect(err).To(BeNil()) + Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog()) + }) + }) + }) + }) + + Describe("Performing EVM transactions", func() { + var ( + txArgs evmtypes.EvmTxArgs + gasWanted uint64 = 200_000 + ) + + BeforeEach(func() { + toAddr := s.keyring.GetAddr(1) + txArgs = evmtypes.EvmTxArgs{ + ChainID: s.network.GetEIP155ChainID(), + GasLimit: gasWanted, + To: &toAddr, + Amount: big.NewInt(10000), + } + }) + + Context("with MinGasPrices (feemarket param) < BaseFee (feemarket)", func() { + var ( + baseFee int64 + minGasPrices int64 + ) + + BeforeEach(func() { + baseFee = 10_000_000_000 + minGasPrices = baseFee - 5_000_000_000 + + params := fmkttypes.DefaultParams() + params.MinGasPrice = math.LegacyNewDec(minGasPrices) + params.BaseFee = math.LegacyNewDec(baseFee) + + // Note that the tests run the same transactions with `gasLimit = + // 200_000`. With the fee calculation `Fee = (baseFee + tip) * gasLimit`, + // a `minGasPrices = 5_000_000_000` results in `minGlobalFee = + // 1_000_000_000_000_000` + err := utils.UpdateFeeMarketParams( + utils.UpdateParamsInput{ + Tf: s.factory, + Network: s.network, + Pk: privKey, + Params: params, + }, + ) + Expect(err).To(BeNil()) + }) + + Context("during CheckTx", func() { + DescribeTable("should reject transactions with gasPrice < MinGasPrices", + func(malleate getprices) { + p := malleate() + + txArgs.GasPrice = p.gasPrice + txArgs.GasFeeCap = p.gasFeeCap + txArgs.GasTipCap = p.gasTipCap + txArgs.Accesses = p.accesses + + tx, err := s.factory.GenerateSignedEthTx(privKey, txArgs) + Expect(err).To(BeNil()) + + Expect(err).To(BeNil()) + bz, err := s.factory.EncodeTx(tx) + Expect(err).To(BeNil()) + + res, err := s.network.CheckTx(bz) + Expect(err).To(BeNil()) + Expect(res.IsOK()).To(BeFalse()) + Expect(res.Log).To(ContainSubstring("provided fee < minimum global fee")) + }, + Entry("legacy tx", func() txParams { + return txParams{big.NewInt(minGasPrices - 1_000_000_000), nil, nil, nil} + }), + Entry("dynamic tx with GasFeeCap < MinGasPrices, no gasTipCap", func() txParams { + return txParams{nil, big.NewInt(minGasPrices - 1_000_000_000), big.NewInt(0), ðtypes.AccessList{}} + }), + Entry("dynamic tx with GasFeeCap < MinGasPrices, max gasTipCap", func() txParams { + return txParams{nil, big.NewInt(minGasPrices - 1_000_000_000), big.NewInt(minGasPrices - 1_000_000_000), ðtypes.AccessList{}} + }), + ) + + DescribeTable("should reject transactions with MinGasPrices < tx gasPrice < EffectivePrice", + func(malleate getprices) { + p := malleate() + + txArgs.GasPrice = p.gasPrice + txArgs.GasFeeCap = p.gasFeeCap + txArgs.GasTipCap = p.gasTipCap + txArgs.Accesses = p.accesses + + tx, err := s.factory.GenerateSignedEthTx(privKey, txArgs) + Expect(err).To(BeNil()) + + Expect(err).To(BeNil()) + bz, err := s.factory.EncodeTx(tx) + Expect(err).To(BeNil()) + + res, err := s.network.CheckTx(bz) + Expect(err).To(BeNil()) + Expect(res.IsOK()).To(BeFalse()) + Expect(res.Log).To(ContainSubstring("insufficient fee")) + }, + Entry("legacy tx", func() txParams { + return txParams{big.NewInt(baseFee - 2_000_000_000), nil, nil, nil} + }), + Entry("dynamic tx", func() txParams { + return txParams{nil, big.NewInt(baseFee - 2_000_000_000), big.NewInt(0), ðtypes.AccessList{}} + }), + ) + + DescribeTable("should accept transactions with gasPrice >= EffectivePrice", + func(malleate getprices) { + p := malleate() + txArgs.GasPrice = p.gasPrice + txArgs.GasFeeCap = p.gasFeeCap + txArgs.GasTipCap = p.gasTipCap + txArgs.Accesses = p.accesses + + tx, err := s.factory.GenerateSignedEthTx(privKey, txArgs) + Expect(err).To(BeNil()) + + Expect(err).To(BeNil()) + bz, err := s.factory.EncodeTx(tx) + Expect(err).To(BeNil()) + + res, err := s.network.CheckTx(bz) + Expect(err).To(BeNil(), "transaction should have succeeded") + Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog()) + }, + Entry("legacy tx", func() txParams { + return txParams{big.NewInt(baseFee), nil, nil, nil} + }), + Entry("dynamic tx", func() txParams { + return txParams{nil, big.NewInt(baseFee), big.NewInt(0), ðtypes.AccessList{}} + }), + ) + }) + + Context("during DeliverTx", func() { + DescribeTable("should reject transactions with gasPrice < MinGasPrices", + func(malleate getprices) { + p := malleate() + + txArgs.GasPrice = p.gasPrice + txArgs.GasFeeCap = p.gasFeeCap + txArgs.GasTipCap = p.gasTipCap + txArgs.Accesses = p.accesses + + res, err := s.factory.ExecuteEthTx(privKey, txArgs) + Expect(err).NotTo(BeNil()) + Expect(res.IsOK()).To(BeFalse()) + Expect(res.Log).To(ContainSubstring("provided fee < minimum global fee")) + }, + Entry("legacy tx", func() txParams { + return txParams{big.NewInt(minGasPrices - 1_000_000_000), nil, nil, nil} + }), + Entry("dynamic tx", func() txParams { + return txParams{nil, big.NewInt(minGasPrices - 1_000_000_000), nil, ðtypes.AccessList{}} + }), + ) + + DescribeTable("should reject transactions with MinGasPrices < gasPrice < EffectivePrice", + func(malleate getprices) { + p := malleate() + + txArgs.GasPrice = p.gasPrice + txArgs.GasFeeCap = p.gasFeeCap + txArgs.GasTipCap = p.gasTipCap + txArgs.Accesses = p.accesses + + res, err := s.factory.ExecuteEthTx(privKey, txArgs) + Expect(err).NotTo(BeNil()) + Expect(res.IsOK()).To(BeFalse()) + Expect(res.Log).To(ContainSubstring("insufficient fee")) + }, + // Note that the baseFee is not 10_000_000_000 anymore but updates to 7_656_250_000 because of the s.Commit + Entry("legacy tx", func() txParams { + return txParams{big.NewInt(baseFee - 2_500_000_000), nil, nil, nil} + }), + Entry("dynamic tx", func() txParams { + return txParams{nil, big.NewInt(baseFee - 2_500_000_000), big.NewInt(0), ðtypes.AccessList{}} + }), + ) + + DescribeTable("should accept transactions with gasPrice >= EffectivePrice", + func(malleate getprices) { + p := malleate() + + txArgs.GasPrice = p.gasPrice + txArgs.GasFeeCap = p.gasFeeCap + txArgs.GasTipCap = p.gasTipCap + txArgs.Accesses = p.accesses + + res, err := s.factory.ExecuteEthTx(privKey, txArgs) + Expect(err).To(BeNil()) + Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog()) + }, + Entry("legacy tx", func() txParams { + return txParams{big.NewInt(baseFee), nil, nil, nil} + }), + Entry("dynamic tx", func() txParams { + return txParams{nil, big.NewInt(baseFee), big.NewInt(0), ðtypes.AccessList{}} + }), + ) + }) + }) + + Context("with BaseFee (feemarket) < MinGasPrices (feemarket param)", func() { + var ( + baseFee int64 + minGasPrices int64 + ) + + Context("during CheckTx", func() { + BeforeEach(func() { + baseFee = 10_000_000_000 + minGasPrices = baseFee + 30_000_000_000 + + // Note that the tests run the same transactions with `gasLimit = + // 200000`. With the fee calculation `Fee = (baseFee + tip) * gasLimit`, + // with `minGasPrices = 40_000_000_000` results in `minGlobalFee = + // 8000000000000000` + // local min-gas-prices is 10aatom + params := fmkttypes.DefaultParams() + params.MinGasPrice = math.LegacyNewDec(minGasPrices) + params.BaseFee = math.LegacyNewDec(baseFee) + + // Note that the tests run the same transactions with `gasLimit = + // 200_000`. With the fee calculation `Fee = (baseFee + tip) * gasLimit`, + // a `minGasPrices = 5_000_000_000` results in `minGlobalFee = + // 1_000_000_000_000_000` + err := utils.UpdateFeeMarketParams( + utils.UpdateParamsInput{ + Tf: s.factory, + Network: s.network, + Pk: privKey, + Params: params, + }, + ) + Expect(err).To(BeNil()) + }) + + DescribeTable("should reject transactions with EffectivePrice < MinGasPrices", + func(malleate getprices) { + p := malleate() + + txArgs.GasPrice = p.gasPrice + txArgs.GasFeeCap = p.gasFeeCap + txArgs.GasTipCap = p.gasTipCap + txArgs.Accesses = p.accesses + + tx, err := s.factory.GenerateSignedEthTx(privKey, txArgs) + Expect(err).To(BeNil()) + + Expect(err).To(BeNil()) + bz, err := s.factory.EncodeTx(tx) + Expect(err).To(BeNil()) + + res, err := s.network.CheckTx(bz) + Expect(err).To(BeNil()) + Expect(res.IsOK()).To(BeFalse()) + Expect(res.Log).To(ContainSubstring("provided fee < minimum global fee")) + }, + Entry("legacy tx", func() txParams { + return txParams{big.NewInt(minGasPrices - 10_000_000_000), nil, nil, nil} + }), + Entry("dynamic tx with GasFeeCap < MinGasPrices, no gasTipCap", func() txParams { + return txParams{nil, big.NewInt(minGasPrices - 10_000_000_000), big.NewInt(0), ðtypes.AccessList{}} + }), + Entry("dynamic tx with GasFeeCap < MinGasPrices, max gasTipCap", func() txParams { + // Note that max priority fee per gas can't be higher than the max fee per gas (gasFeeCap), i.e. 30_000_000_000) + return txParams{nil, big.NewInt(minGasPrices - 10_000_000_000), big.NewInt(30_000_000_000), ðtypes.AccessList{}} + }), + ) + + DescribeTable("should accept transactions with gasPrice >= MinGasPrices", + func(malleate getprices) { + p := malleate() + + txArgs.GasPrice = p.gasPrice + txArgs.GasFeeCap = p.gasFeeCap + txArgs.GasTipCap = p.gasTipCap + txArgs.Accesses = p.accesses + + tx, err := s.factory.GenerateSignedEthTx(privKey, txArgs) + Expect(err).To(BeNil()) + + Expect(err).To(BeNil()) + bz, err := s.factory.EncodeTx(tx) + Expect(err).To(BeNil()) + + res, err := s.network.CheckTx(bz) + Expect(err).To(BeNil()) + Expect(res.IsOK()).To(BeTrue(), "transaction should have succeeded", res.GetLog()) + }, + Entry("legacy tx", func() txParams { + return txParams{big.NewInt(minGasPrices), nil, nil, nil} + }), + // Note that this tx is not rejected on CheckTx, but not on DeliverTx, + // as the baseFee is set to minGasPrices during DeliverTx when baseFee + // < minGasPrices + Entry("dynamic tx with GasFeeCap > MinGasPrices, EffectivePrice > MinGasPrices", func() txParams { + return txParams{nil, big.NewInt(minGasPrices), big.NewInt(30_000_000_000), ðtypes.AccessList{}} + }), + ) + }) + + Context("during DeliverTx", func() { + BeforeEach(func() { + baseFee = 10_000_000_000 + minGasPrices = baseFee + 30_000_000_000 + + // Note that the tests run the same transactions with `gasLimit = + // 200000`. With the fee calculation `Fee = (baseFee + tip) * gasLimit`, + // with `minGasPrices = 40_000_000_000` results in `minGlobalFee = + // 8000000000000000` + // local min-gas-prices is 10aatom + params := fmkttypes.DefaultParams() + params.MinGasPrice = math.LegacyNewDec(minGasPrices) + params.BaseFee = math.LegacyNewDec(baseFee) + + err := utils.UpdateFeeMarketParams( + utils.UpdateParamsInput{ + Tf: s.factory, + Network: s.network, + Pk: privKey, + Params: params, + }, + ) + Expect(err).To(BeNil()) + }) + DescribeTable("should reject transactions with gasPrice < MinGasPrices", + func(malleate getprices) { + p := malleate() + + txArgs.GasPrice = p.gasPrice + txArgs.GasFeeCap = p.gasFeeCap + txArgs.GasTipCap = p.gasTipCap + txArgs.Accesses = p.accesses + + res, err := s.factory.ExecuteEthTx(privKey, txArgs) + Expect(err).NotTo(BeNil()) + Expect(res.IsOK()).To(BeFalse()) + Expect(res.Log).To(ContainSubstring("provided fee < minimum global fee")) + }, + Entry("legacy tx", func() txParams { + return txParams{big.NewInt(minGasPrices - 10_000_000_000), nil, nil, nil} + }), + Entry("dynamic tx with GasFeeCap < MinGasPrices, no gasTipCap", func() txParams { + return txParams{nil, big.NewInt(minGasPrices - 10_000_000_000), big.NewInt(0), ðtypes.AccessList{}} + }), + Entry("dynamic tx with GasFeeCap < MinGasPrices, max gasTipCap", func() txParams { + // Note that max priority fee per gas can't be higher than the max fee per gas (gasFeeCap), i.e. 30_000_000_000) + return txParams{nil, big.NewInt(minGasPrices - 10_000_000_000), big.NewInt(30_000_000_000), ðtypes.AccessList{}} + }), + ) + + DescribeTable("should accept transactions with gasPrice >= MinGasPrices", + func(malleate getprices) { + p := malleate() + + txArgs.GasPrice = p.gasPrice + txArgs.GasFeeCap = p.gasFeeCap + txArgs.GasTipCap = p.gasTipCap + txArgs.Accesses = p.accesses + + res, err := s.factory.ExecuteEthTx(privKey, txArgs) + Expect(err).To(BeNil(), "transaction should have succeeded") + Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog()) + }, + Entry("legacy tx", func() txParams { + return txParams{big.NewInt(minGasPrices + 1), nil, nil, nil} + }), + Entry("dynamic tx, EffectivePrice > MinGasPrices", func() txParams { + return txParams{nil, big.NewInt(minGasPrices + 10_000_000_000), big.NewInt(30_000_000_000), ðtypes.AccessList{}} + }), + ) + }) + }) + }) + }) + + // Run Ginkgo integration tests + RegisterFailHandler(Fail) + RunSpecs(t, "Keeper Suite") +} diff --git a/x/feemarket/keeper/keeper_test.go b/tests/integration/x/feemarket/test_keeper.go similarity index 52% rename from x/feemarket/keeper/keeper_test.go rename to tests/integration/x/feemarket/test_keeper.go index d03188cc3..48ae1e0e2 100644 --- a/x/feemarket/keeper/keeper_test.go +++ b/tests/integration/x/feemarket/test_keeper.go @@ -1,18 +1,14 @@ -package keeper_test +package feemarket import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/network" "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" ) -func TestSetGetBlockGasWanted(t *testing.T) { +func (s *KeeperTestSuite) TestSetGetBlockGasWanted() { var ( nw *network.UnitTestNetwork ctx sdk.Context @@ -25,26 +21,26 @@ func TestSetGetBlockGasWanted(t *testing.T) { { "with last block given", func() { - nw.App.FeeMarketKeeper.SetBlockGasWanted(ctx, uint64(1000000)) + nw.App.GetFeeMarketKeeper().SetBlockGasWanted(ctx, uint64(1000000)) }, uint64(1000000), }, } for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { + s.Run(tc.name, func() { // reset network and context - nw = network.NewUnitTestNetwork() + nw = network.NewUnitTestNetwork(s.create, s.options...) ctx = nw.GetContext() tc.malleate() - gas := nw.App.FeeMarketKeeper.GetBlockGasWanted(ctx) - require.Equal(t, tc.expGas, gas, tc.name) + gas := nw.App.GetFeeMarketKeeper().GetBlockGasWanted(ctx) + s.Equal(tc.expGas, gas, tc.name) }) } } -func TestSetGetGasFee(t *testing.T) { +func (s *KeeperTestSuite) TestSetGetGasFee() { var ( nw *network.UnitTestNetwork ctx sdk.Context @@ -57,22 +53,22 @@ func TestSetGetGasFee(t *testing.T) { { "with last block given", func() { - nw.App.FeeMarketKeeper.SetBaseFee(ctx, math.LegacyOneDec()) + nw.App.GetFeeMarketKeeper().SetBaseFee(ctx, math.LegacyOneDec()) }, math.LegacyOneDec(), }, } for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { + s.Run(tc.name, func() { // reset network and context - nw = network.NewUnitTestNetwork() + nw = network.NewUnitTestNetwork(s.create, s.options...) ctx = nw.GetContext() tc.malleate() - fee := nw.App.FeeMarketKeeper.GetBaseFee(ctx) - require.Equal(t, tc.expFee, fee, tc.name) + fee := nw.App.GetFeeMarketKeeper().GetBaseFee(ctx) + s.Equal(tc.expFee, fee, tc.name) }) } } diff --git a/x/feemarket/keeper/msg_server_test.go b/tests/integration/x/feemarket/test_msg_server.go similarity index 70% rename from x/feemarket/keeper/msg_server_test.go rename to tests/integration/x/feemarket/test_msg_server.go index 5145af9aa..b5b42850a 100644 --- a/x/feemarket/keeper/msg_server_test.go +++ b/tests/integration/x/feemarket/test_msg_server.go @@ -1,11 +1,7 @@ -package keeper_test +package feemarket import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/network" "github.com/cosmos/evm/x/feemarket/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -13,7 +9,7 @@ import ( govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) -func TestUpdateParams(t *testing.T) { +func (s *KeeperTestSuite) TestUpdateParams() { var ( nw *network.UnitTestNetwork ctx sdk.Context @@ -40,16 +36,16 @@ func TestUpdateParams(t *testing.T) { } for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { + s.Run(tc.name, func() { // reset network and context - nw = network.NewUnitTestNetwork() + nw = network.NewUnitTestNetwork(s.create, s.options...) ctx = nw.GetContext() - _, err := nw.App.FeeMarketKeeper.UpdateParams(ctx, tc.request) + _, err := nw.App.GetFeeMarketKeeper().UpdateParams(ctx, tc.request) if tc.expectErr { - require.Error(t, err) + s.Error(err) } else { - require.NoError(t, err) + s.NoError(err) } }) } diff --git a/x/feemarket/keeper/params_test.go b/tests/integration/x/feemarket/test_params.go similarity index 53% rename from x/feemarket/keeper/params_test.go rename to tests/integration/x/feemarket/test_params.go index 67aeedca4..fbf8fd5f8 100644 --- a/x/feemarket/keeper/params_test.go +++ b/tests/integration/x/feemarket/test_params.go @@ -1,32 +1,29 @@ -package keeper_test +package feemarket import ( "reflect" - "testing" - "github.com/stretchr/testify/require" - - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/network" "github.com/cosmos/evm/x/feemarket/types" ) -func TestGetParams(t *testing.T) { - nw := network.NewUnitTestNetwork() +func (s *KeeperTestSuite) TestGetParams() { + nw := network.NewUnitTestNetwork(s.create, s.options...) ctx := nw.GetContext() - params := nw.App.FeeMarketKeeper.GetParams(ctx) - require.NotNil(t, params.BaseFee) - require.NotNil(t, params.MinGasPrice) - require.NotNil(t, params.MinGasMultiplier) + params := nw.App.GetFeeMarketKeeper().GetParams(ctx) + s.NotNil(params.BaseFee) + s.NotNil(params.MinGasPrice) + s.NotNil(params.MinGasMultiplier) } -func TestSetGetParams(t *testing.T) { - nw := network.NewUnitTestNetwork() +func (s *KeeperTestSuite) TestSetGetParams() { + nw := network.NewUnitTestNetwork(s.create, s.options...) ctx := nw.GetContext() params := types.DefaultParams() - err := nw.App.FeeMarketKeeper.SetParams(ctx, params) - require.NoError(t, err) + err := nw.App.GetFeeMarketKeeper().SetParams(ctx, params) + s.NoError(err) testCases := []struct { name string @@ -40,7 +37,7 @@ func TestSetGetParams(t *testing.T) { return types.DefaultParams() }, func() interface{} { - return nw.App.FeeMarketKeeper.GetParams(ctx) + return nw.App.GetFeeMarketKeeper().GetParams(ctx) }, true, }, @@ -48,24 +45,24 @@ func TestSetGetParams(t *testing.T) { "success - Check ElasticityMultiplier is set to 3 and can be retrieved correctly", func() interface{} { params.ElasticityMultiplier = 3 - err := nw.App.FeeMarketKeeper.SetParams(ctx, params) - require.NoError(t, err) + err := nw.App.GetFeeMarketKeeper().SetParams(ctx, params) + s.NoError(err) return params.ElasticityMultiplier }, func() interface{} { - return nw.App.FeeMarketKeeper.GetParams(ctx).ElasticityMultiplier + return nw.App.GetFeeMarketKeeper().GetParams(ctx).ElasticityMultiplier }, true, }, { "success - Check BaseFeeEnabled is computed with its default params and can be retrieved correctly", func() interface{} { - err := nw.App.FeeMarketKeeper.SetParams(ctx, types.DefaultParams()) - require.NoError(t, err) + err := nw.App.GetFeeMarketKeeper().SetParams(ctx, types.DefaultParams()) + s.NoError(err) return true }, func() interface{} { - return nw.App.FeeMarketKeeper.GetBaseFeeEnabled(ctx) + return nw.App.GetFeeMarketKeeper().GetBaseFeeEnabled(ctx) }, true, }, @@ -74,20 +71,20 @@ func TestSetGetParams(t *testing.T) { func() interface{} { params.NoBaseFee = true params.EnableHeight = 5 - err := nw.App.FeeMarketKeeper.SetParams(ctx, params) - require.NoError(t, err) + err := nw.App.GetFeeMarketKeeper().SetParams(ctx, params) + s.NoError(err) return true }, func() interface{} { - return nw.App.FeeMarketKeeper.GetBaseFeeEnabled(ctx) + return nw.App.GetFeeMarketKeeper().GetBaseFeeEnabled(ctx) }, false, }, } for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { + s.Run(tc.name, func() { outcome := reflect.DeepEqual(tc.paramsFun(), tc.getFun()) - require.Equal(t, tc.expected, outcome) + s.Equal(tc.expected, outcome) }) } } diff --git a/tests/integration/x/feemarket/test_setup.go b/tests/integration/x/feemarket/test_setup.go new file mode 100644 index 000000000..30c176ed7 --- /dev/null +++ b/tests/integration/x/feemarket/test_setup.go @@ -0,0 +1,64 @@ +package feemarket + +import ( + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + testkeyring "github.com/cosmos/evm/testutil/keyring" + + "github.com/cosmos/cosmos-sdk/baseapp" +) + +type KeeperTestSuite struct { + suite.Suite + + create network.CreateEvmApp + options []network.ConfigOption + network *network.UnitTestNetwork + factory factory.TxFactory + grpcHandler grpc.Handler + keyring testkeyring.Keyring + + denom string +} + +func NewTestKeeperTestSuite( + create network.CreateEvmApp, + options ...network.ConfigOption, +) *KeeperTestSuite { + return &KeeperTestSuite{ + create: create, + options: options, + } +} + +// SetupTest setup test environment +func (s *KeeperTestSuite) SetupTest() { + if s.create == nil { + s.create = CreateApp + } + keyring := testkeyring.New(2) + options := []network.ConfigOption{ + network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), + network.WithCustomBaseAppOpts(baseapp.SetMinGasPrices("10aatom")), + } + options = append(options, s.options...) + nw := network.NewUnitTestNetwork(s.create, options...) + grpcHandler := grpc.NewIntegrationHandler(nw) + txFactory := factory.New(nw, grpcHandler) + + ctx := nw.GetContext() + sk := nw.App.GetStakingKeeper() + bondDenom, err := sk.BondDenom(ctx) + if err != nil { + panic(err) + } + + s.denom = bondDenom + s.factory = txFactory + s.grpcHandler = grpcHandler + s.keyring = keyring + s.network = nw +} diff --git a/x/ibc/transfer/keeper/keeper_test.go b/tests/integration/x/ibc/test_keeper.go similarity index 65% rename from x/ibc/transfer/keeper/keeper_test.go rename to tests/integration/x/ibc/test_keeper.go index f51b46c31..71a21f685 100644 --- a/x/ibc/transfer/keeper/keeper_test.go +++ b/tests/integration/x/ibc/test_keeper.go @@ -1,8 +1,7 @@ -package keeper_test +package ibc import ( "math/big" - "testing" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/mock" @@ -11,13 +10,14 @@ import ( abcitypes "github.com/cometbft/cometbft/abci/types" "github.com/cosmos/evm/contracts" - cmnfactory "github.com/cosmos/evm/testutil/integration/common/factory" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" + cmnfactory "github.com/cosmos/evm/testutil/integration/base/factory" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/keyring" + testutiltypes "github.com/cosmos/evm/testutil/types" erc20types "github.com/cosmos/evm/x/erc20/types" - evm "github.com/cosmos/evm/x/vm/types" + evmtypes "github.com/cosmos/evm/x/vm/types" transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" @@ -32,6 +32,8 @@ import ( type KeeperTestSuite struct { suite.Suite + create network.CreateEvmApp + options []network.ConfigOption network *network.UnitTestNetwork handler grpc.Handler keyring keyring.Keyring @@ -42,26 +44,30 @@ type KeeperTestSuite struct { var timeoutHeight = clienttypes.NewHeight(1000, 1000) -func TestKeeperTestSuite(t *testing.T) { - s := new(KeeperTestSuite) - suite.Run(t, s) +func NewKeeperTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *KeeperTestSuite { + return &KeeperTestSuite{ + create: create, + options: options, + } } -func (suite *KeeperTestSuite) SetupTest() { +func (s *KeeperTestSuite) SetupTest() { keys := keyring.New(2) - suite.otherDenom = "xmpl" + s.otherDenom = "xmpl" - nw := network.NewUnitTestNetwork( + options := []network.ConfigOption{ network.WithPreFundedAccounts(keys.GetAllAccAddrs()...), - network.WithOtherDenoms([]string{suite.otherDenom}), - ) + network.WithOtherDenoms([]string{s.otherDenom}), + } + options = append(options, s.options...) + nw := network.NewUnitTestNetwork(s.create, options...) gh := grpc.NewIntegrationHandler(nw) tf := factory.New(nw, gh) - suite.network = nw - suite.factory = tf - suite.handler = gh - suite.keyring = keys + s.network = nw + s.factory = tf + s.handler = gh + s.keyring = keys } var _ transfertypes.ChannelKeeper = &MockChannelKeeper{} @@ -115,13 +121,13 @@ func (b *MockICS4Wrapper) SendPacket( return 0, nil } -func (suite *KeeperTestSuite) MintERC20Token(contractAddr, to common.Address, amount *big.Int) (abcitypes.ExecTxResult, error) { - res, err := suite.factory.ExecuteContractCall( - suite.keyring.GetPrivKey(0), - evm.EvmTxArgs{ +func (s *KeeperTestSuite) MintERC20Token(contractAddr, to common.Address, amount *big.Int) (abcitypes.ExecTxResult, error) { + res, err := s.factory.ExecuteContractCall( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{ To: &contractAddr, }, - factory.CallArgs{ + testutiltypes.CallArgs{ ContractABI: contracts.ERC20MinterBurnerDecimalsContract.ABI, MethodName: "mint", Args: []interface{}{to, amount}, @@ -131,14 +137,14 @@ func (suite *KeeperTestSuite) MintERC20Token(contractAddr, to common.Address, am return res, err } - return res, suite.network.NextBlock() + return res, s.network.NextBlock() } -func (suite *KeeperTestSuite) DeployContract(name, symbol string, decimals uint8) (common.Address, error) { - addr, err := suite.factory.DeployContract( - suite.keyring.GetPrivKey(0), - evm.EvmTxArgs{}, - factory.ContractDeploymentData{ +func (s *KeeperTestSuite) DeployContract(name, symbol string, decimals uint8) (common.Address, error) { + addr, err := s.factory.DeployContract( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{}, + testutiltypes.ContractDeploymentData{ Contract: contracts.ERC20MinterBurnerDecimalsContract, ConstructorArgs: []interface{}{name, symbol, decimals}, }, @@ -147,17 +153,17 @@ func (suite *KeeperTestSuite) DeployContract(name, symbol string, decimals uint8 return common.Address{}, err } - return addr, suite.network.NextBlock() + return addr, s.network.NextBlock() } -func (suite *KeeperTestSuite) ConvertERC20(sender keyring.Key, contractAddr common.Address, amt math.Int) error { +func (s *KeeperTestSuite) ConvertERC20(sender keyring.Key, contractAddr common.Address, amt math.Int) error { msg := &erc20types.MsgConvertERC20{ ContractAddress: contractAddr.Hex(), Amount: amt, Sender: sender.Addr.String(), Receiver: sender.AccAddr.String(), } - _, err := suite.factory.CommitCosmosTx(sender.Priv, cmnfactory.CosmosTxArgs{ + _, err := s.factory.CommitCosmosTx(sender.Priv, cmnfactory.CosmosTxArgs{ Msgs: []sdk.Msg{msg}, }) diff --git a/x/ibc/transfer/keeper/msg_server_test.go b/tests/integration/x/ibc/test_msg_server.go similarity index 85% rename from x/ibc/transfer/keeper/msg_server_test.go rename to tests/integration/x/ibc/test_msg_server.go index 318364740..3f7c34431 100644 --- a/x/ibc/transfer/keeper/msg_server_test.go +++ b/tests/integration/x/ibc/test_msg_server.go @@ -1,14 +1,14 @@ -package keeper_test +package ibc import ( "fmt" "github.com/stretchr/testify/mock" - "github.com/cosmos/evm/testutil/integration/os/keyring" - testutils "github.com/cosmos/evm/testutil/integration/os/utils" + "github.com/cosmos/evm/testutil/integration/evm/utils" + "github.com/cosmos/evm/testutil/keyring" erc20types "github.com/cosmos/evm/x/erc20/types" - "github.com/cosmos/evm/x/ibc/transfer/keeper" + transferkeeper "github.com/cosmos/evm/x/ibc/transfer/keeper" evmtypes "github.com/cosmos/evm/x/vm/types" "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" @@ -67,7 +67,7 @@ func (suite *KeeperTestSuite) TestTransfer() { contractAddr, err := suite.DeployContract("coin", "token", uint8(6)) suite.Require().NoError(err) - pair, err := testutils.RegisterERC20(suite.factory, suite.network, testutils.ERC20RegistrationData{ + pair, err := utils.RegisterERC20(suite.factory, suite.network, utils.ERC20RegistrationData{ Addresses: []string{contractAddr.Hex()}, ProposerPriv: sender.Priv, }) @@ -82,10 +82,10 @@ func (suite *KeeperTestSuite) TestTransfer() { err = suite.ConvertERC20(sender, contractAddr, amt) suite.Require().NoError(err) - params := suite.network.App.Erc20Keeper.GetParams(ctx) + params := suite.network.App.GetErc20Keeper().GetParams(ctx) params.EnableErc20 = false - err = testutils.UpdateERC20Params(testutils.UpdateParamsInput{ + err = utils.UpdateERC20Params(utils.UpdateParamsInput{ Tf: suite.factory, Network: suite.network, Pk: sender.Priv, @@ -106,7 +106,7 @@ func (suite *KeeperTestSuite) TestTransfer() { contractAddr, err := suite.DeployContract("coin", "token", uint8(6)) suite.Require().NoError(err) - pair, err := testutils.RegisterERC20(suite.factory, suite.network, testutils.ERC20RegistrationData{ + pair, err := utils.RegisterERC20(suite.factory, suite.network, utils.ERC20RegistrationData{ Addresses: []string{contractAddr.Hex()}, ProposerPriv: sender.Priv, }) @@ -118,12 +118,12 @@ func (suite *KeeperTestSuite) TestTransfer() { suite.Require().NoError(err) // No conversion to IBC coin, so the balance is insufficient - suite.Require().EqualValues(suite.network.App.BankKeeper.GetBalance( + suite.Require().EqualValues(suite.network.App.GetBankKeeper().GetBalance( ctx, sender.AccAddr, pair[0].Denom).Amount, math.ZeroInt()) - params := suite.network.App.Erc20Keeper.GetParams(ctx) + params := suite.network.App.GetErc20Keeper().GetParams(ctx) params.EnableErc20 = false - err = testutils.UpdateERC20Params(testutils.UpdateParamsInput{ + err = utils.UpdateERC20Params(utils.UpdateParamsInput{ Tf: suite.factory, Network: suite.network, Pk: sender.Priv, @@ -153,7 +153,7 @@ func (suite *KeeperTestSuite) TestTransfer() { contractAddr, err := suite.DeployContract("coin", "token", uint8(6)) suite.Require().NoError(err) - pair, err := testutils.RegisterERC20(suite.factory, suite.network, testutils.ERC20RegistrationData{ + pair, err := utils.RegisterERC20(suite.factory, suite.network, utils.ERC20RegistrationData{ Addresses: []string{contractAddr.Hex()}, ProposerPriv: sender.Priv, }) @@ -169,7 +169,7 @@ func (suite *KeeperTestSuite) TestTransfer() { suite.Require().NoError(err) // disable token conversion - err = testutils.ToggleTokenConversion(suite.factory, suite.network, sender.Priv, pair[0].Denom) + err = utils.ToggleTokenConversion(suite.factory, suite.network, sender.Priv, pair[0].Denom) suite.Require().NoError(err) coin := sdk.NewCoin(pair[0].Denom, math.NewInt(10)) @@ -185,7 +185,7 @@ func (suite *KeeperTestSuite) TestTransfer() { contractAddr, err := suite.DeployContract("coin", "token", uint8(6)) suite.Require().NoError(err) - res, err := testutils.RegisterERC20(suite.factory, suite.network, testutils.ERC20RegistrationData{ + res, err := utils.RegisterERC20(suite.factory, suite.network, utils.ERC20RegistrationData{ Addresses: []string{contractAddr.Hex()}, ProposerPriv: sender.Priv, }) @@ -210,7 +210,7 @@ func (suite *KeeperTestSuite) TestTransfer() { contractAddr, err := suite.DeployContract("coin", "token", uint8(6)) suite.Require().NoError(err) - pair, err := testutils.RegisterERC20(suite.factory, suite.network, testutils.ERC20RegistrationData{ + pair, err := utils.RegisterERC20(suite.factory, suite.network, utils.ERC20RegistrationData{ Addresses: []string{contractAddr.Hex()}, ProposerPriv: sender.Priv, }) @@ -238,7 +238,7 @@ func (suite *KeeperTestSuite) TestTransfer() { contractAddr, err := suite.DeployContract("coin", "token", uint8(6)) suite.Require().NoError(err) - pair, err := testutils.RegisterERC20(suite.factory, suite.network, testutils.ERC20RegistrationData{ + pair, err := utils.RegisterERC20(suite.factory, suite.network, utils.ERC20RegistrationData{ Addresses: []string{contractAddr.Hex()}, ProposerPriv: sender.Priv, }) @@ -280,7 +280,7 @@ func (suite *KeeperTestSuite) TestTransfer() { coin := sdk.NewCoin(denom, math.NewInt(10)) - pair, err := suite.network.App.Erc20Keeper.RegisterERC20Extension(suite.network.GetContext(), coinMetadata.Base) + pair, err := suite.network.App.GetErc20Keeper().RegisterERC20Extension(suite.network.GetContext(), coinMetadata.Base) suite.Require().Equal(pair.Denom, denom) suite.Require().NoError(err) @@ -297,24 +297,24 @@ func (suite *KeeperTestSuite) TestTransfer() { sender = suite.keyring.GetKey(0) ctx = suite.network.GetContext() - suite.network.App.TransferKeeper = keeper.NewKeeper( + suite.network.App.SetTransferKeeper(transferkeeper.NewKeeper( suite.network.App.AppCodec(), runtime.NewKVStoreService(suite.network.App.GetKey(types.StoreKey)), suite.network.App.GetSubspace(types.ModuleName), &MockICS4Wrapper{}, // ICS4 Wrapper mockChannelKeeper, suite.network.App.MsgServiceRouter(), - suite.network.App.AccountKeeper, - suite.network.App.BankKeeper, - suite.network.App.Erc20Keeper, // Add ERC20 Keeper for ERC20 transfers + suite.network.App.GetAccountKeeper(), + suite.network.App.GetBankKeeper(), + suite.network.App.GetErc20Keeper(), // Add ERC20 Keeper for ERC20 transfers authAddr, - ) + )) msg := tc.malleate() // get updated context with the latest changes ctx = suite.network.GetContext() - _, err := suite.network.App.TransferKeeper.Transfer(ctx, msg) + _, err := suite.network.App.GetTransferKeeper().Transfer(ctx, msg) if tc.expPass { suite.Require().NoError(err) } else { diff --git a/x/precisebank/keeper/burn_integration_test.go b/tests/integration/x/precisebank/test_burn_integration.go similarity index 65% rename from x/precisebank/keeper/burn_integration_test.go rename to tests/integration/x/precisebank/test_burn_integration.go index ba589fd0a..800fdf136 100644 --- a/x/precisebank/keeper/burn_integration_test.go +++ b/tests/integration/x/precisebank/test_burn_integration.go @@ -1,4 +1,4 @@ -package keeper_test +package precisebank import ( "fmt" @@ -19,7 +19,7 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) -func (suite *KeeperIntegrationTestSuite) TestBurnCoins_MatchingErrors() { +func (s *KeeperIntegrationTestSuite) TestBurnCoins_MatchingErrors() { // x/precisebank BurnCoins should be identical to x/bank BurnCoins to // consumers. This test ensures that the panics & errors returned by // x/precisebank are identical to x/bank. @@ -69,24 +69,24 @@ func (suite *KeeperIntegrationTestSuite) TestBurnCoins_MatchingErrors() { } for _, tt := range tests { - suite.Run(tt.name, func() { + s.Run(tt.name, func() { // Reset - suite.SetupTest() + s.SetupTest() if tt.wantErr == "" && tt.wantPanic == "" { - suite.Fail("test must specify either wantErr or wantPanic") + s.Fail("test must specify either wantErr or wantPanic") } if tt.wantErr != "" { // Check x/bank BurnCoins for identical error - bankErr := suite.network.App.BankKeeper.BurnCoins(suite.network.GetContext(), tt.recipientModule, tt.burnAmount) - suite.Require().Error(bankErr) - suite.Require().EqualError(bankErr, tt.wantErr, "expected error should match x/bank BurnCoins error") + bankErr := s.network.App.GetBankKeeper().BurnCoins(s.network.GetContext(), tt.recipientModule, tt.burnAmount) + s.Require().Error(bankErr) + s.Require().EqualError(bankErr, tt.wantErr, "expected error should match x/bank BurnCoins error") - pbankErr := suite.network.App.PreciseBankKeeper.BurnCoins(suite.network.GetContext(), tt.recipientModule, tt.burnAmount) - suite.Require().Error(pbankErr) + pbankErr := s.network.App.GetPreciseBankKeeper().BurnCoins(s.network.GetContext(), tt.recipientModule, tt.burnAmount) + s.Require().Error(pbankErr) // Compare strings instead of errors, as error stack is still different - suite.Require().Equal( + s.Require().Equal( bankErr.Error(), pbankErr.Error(), "x/precisebank error should match x/bank BurnCoins error", @@ -97,19 +97,19 @@ func (suite *KeeperIntegrationTestSuite) TestBurnCoins_MatchingErrors() { // First check the wantPanic string is correct. // Actually specify the panic string in the test since it makes // it more clear we are testing specific and different cases. - suite.Require().PanicsWithError(tt.wantPanic, func() { - _ = suite.network.App.BankKeeper.BurnCoins(suite.network.GetContext(), tt.recipientModule, tt.burnAmount) + s.Require().PanicsWithError(tt.wantPanic, func() { + _ = s.network.App.GetBankKeeper().BurnCoins(s.network.GetContext(), tt.recipientModule, tt.burnAmount) }, "expected panic error should match x/bank BurnCoins") - suite.Require().PanicsWithError(tt.wantPanic, func() { - _ = suite.network.App.PreciseBankKeeper.BurnCoins(suite.network.GetContext(), tt.recipientModule, tt.burnAmount) + s.Require().PanicsWithError(tt.wantPanic, func() { + _ = s.network.App.GetPreciseBankKeeper().BurnCoins(s.network.GetContext(), tt.recipientModule, tt.burnAmount) }, "x/precisebank panic should match x/bank BurnCoins") } }) } } -func (suite *KeeperIntegrationTestSuite) TestBurnCoins() { +func (s *KeeperIntegrationTestSuite) TestBurnCoins() { tests := []struct { name string startBalance sdk.Coins @@ -166,34 +166,34 @@ func (suite *KeeperIntegrationTestSuite) TestBurnCoins() { } for _, tt := range tests { - suite.Run(tt.name, func() { + s.Run(tt.name, func() { // Reset - suite.SetupTest() + s.SetupTest() moduleName := evmtypes.ModuleName - recipientAddr := suite.network.App.AccountKeeper.GetModuleAddress(moduleName) + recipientAddr := s.network.App.GetAccountKeeper().GetModuleAddress(moduleName) // Start balance - err := suite.network.App.PreciseBankKeeper.MintCoins(suite.network.GetContext(), moduleName, tt.startBalance) - suite.Require().NoError(err) + err := s.network.App.GetPreciseBankKeeper().MintCoins(s.network.GetContext(), moduleName, tt.startBalance) + s.Require().NoError(err) // Burn - err = suite.network.App.PreciseBankKeeper.BurnCoins(suite.network.GetContext(), moduleName, tt.burnCoins) + err = s.network.App.GetPreciseBankKeeper().BurnCoins(s.network.GetContext(), moduleName, tt.burnCoins) if tt.wantErr != "" { - suite.Require().Error(err) - suite.Require().EqualError(err, tt.wantErr) + s.Require().Error(err) + s.Require().EqualError(err, tt.wantErr) return } - suite.Require().NoError(err) + s.Require().NoError(err) // ------------------------------------------------------------- // Check FULL balances // x/bank balances + x/precisebank balance // Exclude "uatom" as x/precisebank balance will include it - afterBalance := suite.GetAllBalances(recipientAddr) + afterBalance := s.GetAllBalances(recipientAddr) - suite.Require().Equal( + s.Require().Equal( tt.wantBalance.String(), afterBalance.String(), "unexpected balance after minting %s to %s", @@ -210,98 +210,98 @@ func (suite *KeeperIntegrationTestSuite) TestBurnCoins() { totalExtCoinAmt, )) - events := suite.network.GetContext().EventManager().Events() + events := s.network.GetContext().EventManager().Events() expBurnEvent := banktypes.NewCoinBurnEvent(recipientAddr, spentCoins) expSpendEvent := banktypes.NewCoinSpentEvent(recipientAddr, spentCoins) if totalExtCoinAmt.IsZero() { - suite.Require().NotContains(events, expBurnEvent) - suite.Require().NotContains(events, expSpendEvent) + s.Require().NotContains(events, expBurnEvent) + s.Require().NotContains(events, expSpendEvent) } else { - suite.Require().Contains(events, expBurnEvent) - suite.Require().Contains(events, expSpendEvent) + s.Require().Contains(events, expBurnEvent) + s.Require().Contains(events, expSpendEvent) } }) } } -func (suite *KeeperIntegrationTestSuite) TestBurnCoins_Remainder() { +func (s *KeeperIntegrationTestSuite) TestBurnCoins_Remainder() { // This tests a series of small burns to ensure the remainder is both // updated correctly and reserve is correctly updated. This only burns from // 1 single account. - reserveAddr := suite.network.App.AccountKeeper.GetModuleAddress(types.ModuleName) + reserveAddr := s.network.App.GetAccountKeeper().GetModuleAddress(types.ModuleName) moduleName := evmtypes.ModuleName - moduleAddr := suite.network.App.AccountKeeper.GetModuleAddress(moduleName) + moduleAddr := s.network.App.GetAccountKeeper().GetModuleAddress(moduleName) startCoins := cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().MulRaw(5))) // Start balance - err := suite.network.App.PreciseBankKeeper.MintCoins( - suite.network.GetContext(), + err := s.network.App.GetPreciseBankKeeper().MintCoins( + s.network.GetContext(), moduleName, startCoins, ) - suite.Require().NoError(err) + s.Require().NoError(err) burnAmt := types.ConversionFactor().QuoRaw(10) burnCoins := cs(ci(types.ExtendedCoinDenom(), burnAmt)) // Burn 0.1 until balance is 0 for { - reserveBalBefore := suite.network.App.BankKeeper.GetBalance( - suite.network.GetContext(), + reserveBalBefore := s.network.App.GetBankKeeper().GetBalance( + s.network.GetContext(), reserveAddr, types.IntegerCoinDenom(), ) - balBefore := suite.network.App.PreciseBankKeeper.GetBalance( - suite.network.GetContext(), + balBefore := s.network.App.GetPreciseBankKeeper().GetBalance( + s.network.GetContext(), moduleAddr, types.ExtendedCoinDenom(), ) - remainderBefore := suite.network.App.PreciseBankKeeper.GetRemainderAmount(suite.network.GetContext()) + remainderBefore := s.network.App.GetPreciseBankKeeper().GetRemainderAmount(s.network.GetContext()) // ---------------------------------------- // Burn - err := suite.network.App.PreciseBankKeeper.BurnCoins( - suite.network.GetContext(), + err := s.network.App.GetPreciseBankKeeper().BurnCoins( + s.network.GetContext(), moduleName, burnCoins, ) - suite.Require().NoError(err) + s.Require().NoError(err) // ---------------------------------------- // Checks - remainderAfter := suite.network.App.PreciseBankKeeper.GetRemainderAmount(suite.network.GetContext()) - balAfter := suite.network.App.PreciseBankKeeper.GetBalance( - suite.network.GetContext(), + remainderAfter := s.network.App.GetPreciseBankKeeper().GetRemainderAmount(s.network.GetContext()) + balAfter := s.network.App.GetPreciseBankKeeper().GetBalance( + s.network.GetContext(), moduleAddr, types.ExtendedCoinDenom(), ) - reserveBalAfter := suite.network.App.BankKeeper.GetBalance( - suite.network.GetContext(), + reserveBalAfter := s.network.App.GetBankKeeper().GetBalance( + s.network.GetContext(), reserveAddr, types.IntegerCoinDenom(), ) - suite.Require().Equal( + s.Require().Equal( balBefore.Amount.Sub(burnAmt).String(), balAfter.Amount.String(), "balance should decrease by burn amount", ) // Remainder should be updated correctly - suite.Require().Equal( + s.Require().Equal( remainderBefore.Add(burnAmt).Mod(types.ConversionFactor()), remainderAfter, ) // If remainder has exceeded (then rolled over), reserve should be updated if remainderAfter.LT(remainderBefore) { - suite.Require().Equal( + s.Require().Equal( reserveBalBefore.Amount.SubRaw(1).String(), reserveBalAfter.Amount.String(), "reserve should decrease by 1 if remainder exceeds ConversionFactor", @@ -315,15 +315,15 @@ func (suite *KeeperIntegrationTestSuite) TestBurnCoins_Remainder() { } } -func (suite *KeeperIntegrationTestSuite) TestBurnCoins_Spread_Remainder() { +func (s *KeeperIntegrationTestSuite) TestBurnCoins_Spread_Remainder() { // This tests a series of small burns to ensure the remainder is both // updated correctly and reserve is correctly updated. This burns from // a series of multiple accounts, to test when the remainder is modified // by multiple accounts. - reserveAddr := suite.network.App.AccountKeeper.GetModuleAddress(types.ModuleName) + reserveAddr := s.network.App.GetAccountKeeper().GetModuleAddress(types.ModuleName) burnerModuleName := evmtypes.ModuleName - burnerAddr := suite.network.App.AccountKeeper.GetModuleAddress(burnerModuleName) + burnerAddr := s.network.App.GetAccountKeeper().GetModuleAddress(burnerModuleName) accCount := 20 startCoins := cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().MulRaw(5))) @@ -332,7 +332,7 @@ func (suite *KeeperIntegrationTestSuite) TestBurnCoins_Spread_Remainder() { for i := 0; i < accCount; i++ { addr := sdk.AccAddress(fmt.Sprintf("addr%d", i)) - suite.MintToAccount(addr, startCoins) + s.MintToAccount(addr, startCoins) addrs = append(addrs, addr) } @@ -342,66 +342,66 @@ func (suite *KeeperIntegrationTestSuite) TestBurnCoins_Spread_Remainder() { // Burn 0.1 from each account for _, addr := range addrs { - reserveBalBefore := suite.network.App.BankKeeper.GetBalance( - suite.network.GetContext(), + reserveBalBefore := s.network.App.GetBankKeeper().GetBalance( + s.network.GetContext(), reserveAddr, types.IntegerCoinDenom(), ) - balBefore := suite.network.App.PreciseBankKeeper.GetBalance( - suite.network.GetContext(), + balBefore := s.network.App.GetPreciseBankKeeper().GetBalance( + s.network.GetContext(), addr, types.ExtendedCoinDenom(), ) - remainderBefore := suite.network.App.PreciseBankKeeper.GetRemainderAmount(suite.network.GetContext()) + remainderBefore := s.network.App.GetPreciseBankKeeper().GetRemainderAmount(s.network.GetContext()) // ---------------------------------------- // Send & Burn - err := suite.network.App.PreciseBankKeeper.SendCoins( - suite.network.GetContext(), + err := s.network.App.GetPreciseBankKeeper().SendCoins( + s.network.GetContext(), addr, burnerAddr, burnCoins, ) - suite.Require().NoError(err) + s.Require().NoError(err) - err = suite.network.App.PreciseBankKeeper.BurnCoins( - suite.network.GetContext(), + err = s.network.App.GetPreciseBankKeeper().BurnCoins( + s.network.GetContext(), burnerModuleName, burnCoins, ) - suite.Require().NoError(err) + s.Require().NoError(err) // ---------------------------------------- // Checks - remainderAfter := suite.network.App.PreciseBankKeeper.GetRemainderAmount(suite.network.GetContext()) - balAfter := suite.network.App.PreciseBankKeeper.GetBalance( - suite.network.GetContext(), + remainderAfter := s.network.App.GetPreciseBankKeeper().GetRemainderAmount(s.network.GetContext()) + balAfter := s.network.App.GetPreciseBankKeeper().GetBalance( + s.network.GetContext(), addr, types.ExtendedCoinDenom(), ) - reserveBalAfter := suite.network.App.BankKeeper.GetBalance( - suite.network.GetContext(), + reserveBalAfter := s.network.App.GetBankKeeper().GetBalance( + s.network.GetContext(), reserveAddr, types.IntegerCoinDenom(), ) - suite.Require().Equal( + s.Require().Equal( balBefore.Amount.Sub(burnAmt).String(), balAfter.Amount.String(), "balance should decrease by burn amount", ) // Remainder should be updated correctly - suite.Require().Equal( + s.Require().Equal( remainderBefore.Add(burnAmt).Mod(types.ConversionFactor()), remainderAfter, ) - suite.T().Logf("acc: %s", string(addr.Bytes())) - suite.T().Logf("acc bal: %s -> %s", balBefore, balAfter) - suite.T().Logf("remainder: %s -> %s", remainderBefore, remainderAfter) - suite.T().Logf("reserve: %v -> %v", reserveBalBefore, reserveBalAfter) + s.T().Logf("acc: %s", string(addr.Bytes())) + s.T().Logf("acc bal: %s -> %s", balBefore, balAfter) + s.T().Logf("remainder: %s -> %s", remainderBefore, remainderAfter) + s.T().Logf("reserve: %v -> %v", reserveBalBefore, reserveBalAfter) // Reserve will change when: // 1. Account needs to borrow from integer (transfers to reserve) @@ -418,7 +418,7 @@ func (suite *KeeperIntegrationTestSuite) TestBurnCoins_Spread_Remainder() { reserveIncrease = reserveIncrease.SubRaw(1) } - suite.Require().Equal( + s.Require().Equal( reserveBalBefore.Amount.Add(reserveIncrease).String(), reserveBalAfter.Amount.String(), "reserve should be updated by remainder and borrowing", @@ -426,7 +426,7 @@ func (suite *KeeperIntegrationTestSuite) TestBurnCoins_Spread_Remainder() { } } -func (suite *KeeperIntegrationTestSuite) TestBurnCoins_RandomValueMultiDecimals() { +func (s *KeeperIntegrationTestSuite) TestBurnCoins_RandomValueMultiDecimals() { tests := []struct { name string chainID testconstants.ChainID @@ -446,8 +446,8 @@ func (suite *KeeperIntegrationTestSuite) TestBurnCoins_RandomValueMultiDecimals( } for _, tt := range tests { - suite.Run(tt.name, func() { - suite.SetupTestWithChainID(tt.chainID) + s.Run(tt.name, func() { + s.SetupTestWithChainID(tt.chainID) // Has burn permissions burnerModuleName := evmtypes.ModuleName @@ -456,10 +456,10 @@ func (suite *KeeperIntegrationTestSuite) TestBurnCoins_RandomValueMultiDecimals( // Initial balance large enough to cover many small burns initialBalance := types.ConversionFactor().MulRaw(100) initialCoin := cs(ci(types.ExtendedCoinDenom(), initialBalance)) - err := suite.network.App.PreciseBankKeeper.MintCoins(suite.network.GetContext(), burnerModuleName, initialCoin) - suite.Require().NoError(err) - err = suite.network.App.PreciseBankKeeper.SendCoinsFromModuleToAccount(suite.network.GetContext(), burnerModuleName, burner, initialCoin) - suite.Require().NoError(err) + err := s.network.App.GetPreciseBankKeeper().MintCoins(s.network.GetContext(), burnerModuleName, initialCoin) + s.Require().NoError(err) + err = s.network.App.GetPreciseBankKeeper().SendCoinsFromModuleToAccount(s.network.GetContext(), burnerModuleName, burner, initialCoin) + s.Require().NoError(err) // Setup test parameters maxBurnUnit := types.ConversionFactor().MulRaw(2).SubRaw(1) @@ -471,7 +471,7 @@ func (suite *KeeperIntegrationTestSuite) TestBurnCoins_RandomValueMultiDecimals( // Continue burns as long as burner has balance remaining for { // Check current burner balance - burnerAmount := suite.GetAllBalances(burner).AmountOf(types.ExtendedCoinDenom()) + burnerAmount := s.GetAllBalances(burner).AmountOf(types.ExtendedCoinDenom()) if burnerAmount.IsZero() { break } @@ -485,26 +485,26 @@ func (suite *KeeperIntegrationTestSuite) TestBurnCoins_RandomValueMultiDecimals( // 1. send to burner module burnCoins := cs(ci(types.ExtendedCoinDenom(), randAmount)) - err := suite.network.App.PreciseBankKeeper.SendCoinsFromAccountToModule(suite.network.GetContext(), burner, burnerModuleName, burnCoins) - suite.Require().NoError(err) + err := s.network.App.GetPreciseBankKeeper().SendCoinsFromAccountToModule(s.network.GetContext(), burner, burnerModuleName, burnCoins) + s.Require().NoError(err) // 2. burn from burner module - err = suite.network.App.PreciseBankKeeper.BurnCoins(suite.network.GetContext(), burnerModuleName, burnCoins) - suite.Require().NoError(err) + err = s.network.App.GetPreciseBankKeeper().BurnCoins(s.network.GetContext(), burnerModuleName, burnCoins) + s.Require().NoError(err) totalBurned = totalBurned.Add(randAmount) burnCount++ } - suite.T().Logf("Completed %d random burns, total burned: %s", burnCount, totalBurned) + s.T().Logf("Completed %d random burns, total burned: %s", burnCount, totalBurned) // Check burner balance - burnerBal := suite.GetAllBalances(burner).AmountOf(types.ExtendedCoinDenom()) - suite.Equal(burnerBal.BigInt().Cmp(big.NewInt(0)), 0, "burner balance mismatch (expected: %s, actual: %s)", big.NewInt(0), burnerBal) + burnerBal := s.GetAllBalances(burner).AmountOf(types.ExtendedCoinDenom()) + s.Equal(burnerBal.BigInt().Cmp(big.NewInt(0)), 0, "burner balance mismatch (expected: %s, actual: %s)", big.NewInt(0), burnerBal) // Check remainder - remainder := suite.network.App.PreciseBankKeeper.GetRemainderAmount(suite.network.GetContext()) - suite.Equal(remainder.BigInt().Cmp(big.NewInt(0)), 0, "remainder should be zero (expected: %s, actual: %s)", big.NewInt(0), remainder) + remainder := s.network.App.GetPreciseBankKeeper().GetRemainderAmount(s.network.GetContext()) + s.Equal(remainder.BigInt().Cmp(big.NewInt(0)), 0, "remainder should be zero (expected: %s, actual: %s)", big.NewInt(0), remainder) }) } } @@ -538,10 +538,10 @@ func FuzzBurnCoins(f *testing.F) { // Has both mint & burn permissions moduleName := evmtypes.ModuleName - moduleAddr := suite.network.App.AccountKeeper.GetModuleAddress(moduleName) + moduleAddr := suite.network.App.GetAccountKeeper().GetModuleAddress(moduleName) // Start balance - err := suite.network.App.PreciseBankKeeper.MintCoins( + err := suite.network.App.GetPreciseBankKeeper().MintCoins( suite.network.GetContext(), moduleName, cs(ci(types.ExtendedCoinDenom(), sdkmath.NewInt(amount).MulRaw(burnCount))), @@ -550,7 +550,7 @@ func FuzzBurnCoins(f *testing.F) { // Burn multiple times to ensure different balance scenarios for i := int64(0); i < burnCount; i++ { - err := suite.network.App.PreciseBankKeeper.BurnCoins( + err := suite.network.App.GetPreciseBankKeeper().BurnCoins( suite.network.GetContext(), moduleName, cs(c(types.ExtendedCoinDenom(), amount)), @@ -559,7 +559,7 @@ func FuzzBurnCoins(f *testing.F) { } // Check full balances - balAfter := suite.network.App.PreciseBankKeeper.GetBalance(suite.network.GetContext(), moduleAddr, types.ExtendedCoinDenom()) + balAfter := suite.network.App.GetPreciseBankKeeper().GetBalance(suite.network.GetContext(), moduleAddr, types.ExtendedCoinDenom()) suite.Require().Equalf( int64(0), diff --git a/x/precisebank/genesis_test.go b/tests/integration/x/precisebank/test_genesis.go similarity index 66% rename from x/precisebank/genesis_test.go rename to tests/integration/x/precisebank/test_genesis.go index 121fb12d4..2e37acb84 100644 --- a/x/precisebank/genesis_test.go +++ b/tests/integration/x/precisebank/test_genesis.go @@ -1,13 +1,12 @@ -package precisebank_test +package precisebank import ( "fmt" - "testing" "github.com/stretchr/testify/suite" testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/network" "github.com/cosmos/evm/x/precisebank" "github.com/cosmos/evm/x/precisebank/types" @@ -20,19 +19,26 @@ type GenesisTestSuite struct { suite.Suite network *network.UnitTestNetwork + create network.CreateEvmApp + options []network.ConfigOption } -func TestGenesisTestSuite(t *testing.T) { - suite.Run(t, new(GenesisTestSuite)) +func NewGenesisTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *GenesisTestSuite { + return &GenesisTestSuite{ + create: create, + options: options, + } } -func (suite *GenesisTestSuite) SetupTest() { - suite.network = network.NewUnitTestNetwork( +func (s *GenesisTestSuite) SetupTest() { + options := []network.ConfigOption{ network.WithChainID(testconstants.SixDecimalsChainID), - ) + } + options = append(options, s.options...) + s.network = network.NewUnitTestNetwork(s.create, options...) } -func (suite *GenesisTestSuite) TestInitGenesis() { +func (s *GenesisTestSuite) TestInitGenesis() { tests := []struct { name string setupFn func() @@ -55,12 +61,12 @@ func (suite *GenesisTestSuite) TestInitGenesis() { "valid - module balance matches non-zero amount", func() { // Set module account balance to expected amount - err := suite.network.App.BankKeeper.MintCoins( - suite.network.GetContext(), + err := s.network.App.GetBankKeeper().MintCoins( + s.network.GetContext(), types.ModuleName, sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom(), sdkmath.NewInt(2))), ) - suite.Require().NoError(err) + s.Require().NoError(err) }, types.NewGenesisState( types.FractionalBalances{ @@ -103,12 +109,12 @@ func (suite *GenesisTestSuite) TestInitGenesis() { "invalid - module balance excessive", func() { // Set module account balance to greater than expected amount - err := suite.network.App.BankKeeper.MintCoins( - suite.network.GetContext(), + err := s.network.App.GetBankKeeper().MintCoins( + s.network.GetContext(), types.ModuleName, sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom(), sdkmath.NewInt(100))), ) - suite.Require().NoError(err) + s.Require().NoError(err) }, types.NewGenesisState( types.FractionalBalances{ @@ -124,13 +130,13 @@ func (suite *GenesisTestSuite) TestInitGenesis() { "sets module account", func() { // Delete the module account first to ensure it's created here - moduleAcc := suite.network.App.AccountKeeper.GetModuleAccount(suite.network.GetContext(), types.ModuleName) - suite.network.App.AccountKeeper.RemoveAccount(suite.network.GetContext(), moduleAcc) + moduleAcc := s.network.App.GetAccountKeeper().GetModuleAccount(s.network.GetContext(), types.ModuleName) + s.network.App.GetAccountKeeper().RemoveAccount(s.network.GetContext(), moduleAcc) // Ensure module account is deleted in state. // GetModuleAccount() will always return non-nil and does not // necessarily equate to the account being stored in the account store. - suite.Require().Nil(suite.network.App.AccountKeeper.GetAccount(suite.network.GetContext(), moduleAcc.GetAddress())) + s.Require().Nil(s.network.App.GetAccountKeeper().GetAccount(s.network.GetContext(), moduleAcc.GetAddress())) }, types.DefaultGenesisState(), "", @@ -138,19 +144,19 @@ func (suite *GenesisTestSuite) TestInitGenesis() { } for _, tc := range tests { - suite.Run(tc.name, func() { - suite.SetupTest() + s.Run(tc.name, func() { + s.SetupTest() tc.setupFn() if tc.panicMsg != "" { - suite.Require().PanicsWithValue( + s.Require().PanicsWithValue( tc.panicMsg, func() { precisebank.InitGenesis( - suite.network.GetContext(), - suite.network.App.PreciseBankKeeper, - suite.network.App.AccountKeeper, - suite.network.App.BankKeeper, + s.network.GetContext(), + *s.network.App.GetPreciseBankKeeper(), + s.network.App.GetAccountKeeper(), + s.network.App.GetBankKeeper(), tc.genesisState, ) }, @@ -159,42 +165,42 @@ func (suite *GenesisTestSuite) TestInitGenesis() { return } - suite.Require().NotPanics(func() { + s.Require().NotPanics(func() { precisebank.InitGenesis( - suite.network.GetContext(), - suite.network.App.PreciseBankKeeper, - suite.network.App.AccountKeeper, - suite.network.App.BankKeeper, + s.network.GetContext(), + *s.network.App.GetPreciseBankKeeper(), + s.network.App.GetAccountKeeper(), + s.network.App.GetBankKeeper(), tc.genesisState, ) }) // Ensure module account is created - moduleAcc := suite.network.App.AccountKeeper.GetModuleAccount(suite.network.GetContext(), types.ModuleName) - suite.NotNil(moduleAcc) - suite.NotNil( - suite.network.App.AccountKeeper.GetAccount(suite.network.GetContext(), moduleAcc.GetAddress()), + moduleAcc := s.network.App.GetAccountKeeper().GetModuleAccount(s.network.GetContext(), types.ModuleName) + s.NotNil(moduleAcc) + s.NotNil( + s.network.App.GetAccountKeeper().GetAccount(s.network.GetContext(), moduleAcc.GetAddress()), "module account should be created & stored in account store", ) // Verify balances are set in state, get full list of balances in // state to ensure they are set AND no extra balances are set var bals []types.FractionalBalance - suite.network.App.PreciseBankKeeper.IterateFractionalBalances(suite.network.GetContext(), func(addr sdk.AccAddress, bal sdkmath.Int) bool { + s.network.App.GetPreciseBankKeeper().IterateFractionalBalances(s.network.GetContext(), func(addr sdk.AccAddress, bal sdkmath.Int) bool { bals = append(bals, types.NewFractionalBalance(addr.String(), bal)) return false }) - suite.Require().ElementsMatch(tc.genesisState.Balances, bals, "balances should be set in state") + s.Require().ElementsMatch(tc.genesisState.Balances, bals, "balances should be set in state") - remainder := suite.network.App.PreciseBankKeeper.GetRemainderAmount(suite.network.GetContext()) - suite.Require().Equal(tc.genesisState.Remainder, remainder, "remainder should be set in state") + remainder := s.network.App.GetPreciseBankKeeper().GetRemainderAmount(s.network.GetContext()) + s.Require().Equal(tc.genesisState.Remainder, remainder, "remainder should be set in state") }) } } -func (suite *GenesisTestSuite) TestExportGenesis() { +func (s *GenesisTestSuite) TestExportGenesis() { // ExportGenesis(InitGenesis(genesisState)) == genesisState // Must also be valid. @@ -209,12 +215,12 @@ func (suite *GenesisTestSuite) TestExportGenesis() { { "balances, no remainder", func() *types.GenesisState { - err := suite.network.App.BankKeeper.MintCoins( - suite.network.GetContext(), + err := s.network.App.GetBankKeeper().MintCoins( + s.network.GetContext(), types.ModuleName, sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom(), sdkmath.NewInt(1))), ) - suite.Require().NoError(err) + s.Require().NoError(err) return types.NewGenesisState( types.FractionalBalances{ @@ -228,12 +234,12 @@ func (suite *GenesisTestSuite) TestExportGenesis() { { "balances, remainder", func() *types.GenesisState { - err := suite.network.App.BankKeeper.MintCoins( - suite.network.GetContext(), + err := s.network.App.GetBankKeeper().MintCoins( + s.network.GetContext(), types.ModuleName, sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom(), sdkmath.NewInt(1))), ) - suite.Require().NoError(err) + s.Require().NoError(err) return types.NewGenesisState( types.FractionalBalances{ @@ -247,26 +253,26 @@ func (suite *GenesisTestSuite) TestExportGenesis() { } for _, tc := range tests { - suite.Run(tc.name, func() { + s.Run(tc.name, func() { // Reset state - suite.SetupTest() + s.SetupTest() initGs := tc.initGenesisState() - suite.Require().NotPanics(func() { + s.Require().NotPanics(func() { precisebank.InitGenesis( - suite.network.GetContext(), - suite.network.App.PreciseBankKeeper, - suite.network.App.AccountKeeper, - suite.network.App.BankKeeper, + s.network.GetContext(), + *s.network.App.GetPreciseBankKeeper(), + s.network.App.GetAccountKeeper(), + s.network.App.GetBankKeeper(), initGs, ) }) - genesisState := precisebank.ExportGenesis(suite.network.GetContext(), suite.network.App.PreciseBankKeeper) - suite.Require().NoError(genesisState.Validate(), "exported genesis state should be valid") + genesisState := precisebank.ExportGenesis(s.network.GetContext(), *s.network.App.GetPreciseBankKeeper()) + s.Require().NoError(genesisState.Validate(), "exported genesis state should be valid") - suite.Require().Equal( + s.Require().Equal( initGs, genesisState, "exported genesis state should equal initial genesis state", diff --git a/x/precisebank/keeper/grpc_query_test.go b/tests/integration/x/precisebank/test_grpc_query.go similarity index 66% rename from x/precisebank/keeper/grpc_query_test.go rename to tests/integration/x/precisebank/test_grpc_query.go index 4826df61d..317c21add 100644 --- a/x/precisebank/keeper/grpc_query_test.go +++ b/tests/integration/x/precisebank/test_grpc_query.go @@ -1,4 +1,4 @@ -package keeper_test +package precisebank import ( "context" @@ -11,39 +11,39 @@ import ( minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" ) -func (suite *KeeperIntegrationTestSuite) TestQueryRemainder() { - res, err := suite.network.GetPreciseBankClient().Remainder( +func (s *KeeperIntegrationTestSuite) TestQueryRemainder() { + res, err := s.network.GetPreciseBankClient().Remainder( context.Background(), &types.QueryRemainderRequest{}, ) - suite.Require().NoError(err) + s.Require().NoError(err) expRemainder := sdk.NewCoin(types.ExtendedCoinDenom(), sdkmath.ZeroInt()) - suite.Require().Equal(expRemainder, res.Remainder) + s.Require().Equal(expRemainder, res.Remainder) // Mint fractional coins to create non-zero remainder - pbk := suite.network.App.PreciseBankKeeper + pbk := s.network.App.GetPreciseBankKeeper() coin := sdk.NewCoin(types.ExtendedCoinDenom(), sdkmath.OneInt()) err = pbk.MintCoins( - suite.network.GetContext(), + s.network.GetContext(), minttypes.ModuleName, sdk.NewCoins(coin), ) - suite.Require().NoError(err) + s.Require().NoError(err) - res, err = suite.network.GetPreciseBankClient().Remainder( + res, err = s.network.GetPreciseBankClient().Remainder( context.Background(), &types.QueryRemainderRequest{}, ) - suite.Require().NoError(err) + s.Require().NoError(err) expRemainder.Amount = types.ConversionFactor().Sub(coin.Amount) - suite.Require().Equal(expRemainder, res.Remainder) + s.Require().Equal(expRemainder, res.Remainder) } -func (suite *KeeperIntegrationTestSuite) TestQueryFractionalBalance() { +func (s *KeeperIntegrationTestSuite) TestQueryFractionalBalance() { testCases := []struct { name string giveBalance sdkmath.Int @@ -71,26 +71,26 @@ func (suite *KeeperIntegrationTestSuite) TestQueryFractionalBalance() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() + s.Run(tc.name, func() { + s.SetupTest() addr := sdk.AccAddress([]byte("test")) coin := sdk.NewCoin(types.ExtendedCoinDenom(), tc.giveBalance) - suite.MintToAccount(addr, sdk.NewCoins(coin)) + s.MintToAccount(addr, sdk.NewCoins(coin)) - res, err := suite.network.GetPreciseBankClient().FractionalBalance( + res, err := s.network.GetPreciseBankClient().FractionalBalance( context.Background(), &types.QueryFractionalBalanceRequest{ Address: addr.String(), }, ) - suite.Require().NoError(err) + s.Require().NoError(err) // Only fractional amount, even if minted more than conversion factor expAmount := tc.giveBalance.Mod(types.ConversionFactor()) expFractionalBalance := sdk.NewCoin(types.ExtendedCoinDenom(), expAmount) - suite.Require().Equal(expFractionalBalance, res.FractionalBalance) + s.Require().Equal(expFractionalBalance, res.FractionalBalance) }) } } diff --git a/x/precisebank/keeper/integration_test.go b/tests/integration/x/precisebank/test_integration.go similarity index 55% rename from x/precisebank/keeper/integration_test.go rename to tests/integration/x/precisebank/test_integration.go index d85801707..42071575e 100644 --- a/x/precisebank/keeper/integration_test.go +++ b/tests/integration/x/precisebank/test_integration.go @@ -1,4 +1,4 @@ -package keeper_test +package precisebank import ( "math/big" @@ -8,8 +8,8 @@ import ( "github.com/cosmos/evm/contracts" testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/utils" + "github.com/cosmos/evm/testutil/integration/evm/utils" + testutiltypes "github.com/cosmos/evm/testutil/types" "github.com/cosmos/evm/x/precisebank/types" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -18,7 +18,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -func (suite *KeeperIntegrationTestSuite) TestMintBurnSendCoins_RandomValueMultiDecimals() { +func (s *KeeperIntegrationTestSuite) TestMintBurnSendCoins_RandomValueMultiDecimals() { tests := []struct { name string chainID testconstants.ChainID @@ -38,8 +38,8 @@ func (suite *KeeperIntegrationTestSuite) TestMintBurnSendCoins_RandomValueMultiD } for _, tt := range tests { - suite.Run(tt.name, func() { - suite.SetupTest() + s.Run(tt.name, func() { + s.SetupTest() moduleName := evmtypes.ModuleName sender := sdk.AccAddress([]byte{1}) @@ -48,8 +48,8 @@ func (suite *KeeperIntegrationTestSuite) TestMintBurnSendCoins_RandomValueMultiD // Mint initial balance to sender initialBalance := types.ConversionFactor().MulRaw(100) initialCoins := cs(ci(types.ExtendedCoinDenom(), initialBalance)) - suite.Require().NoError(suite.network.App.PreciseBankKeeper.MintCoins(suite.network.GetContext(), moduleName, initialCoins)) - suite.Require().NoError(suite.network.App.PreciseBankKeeper.SendCoinsFromModuleToAccount(suite.network.GetContext(), moduleName, sender, initialCoins)) + s.Require().NoError(s.network.App.GetPreciseBankKeeper().MintCoins(s.network.GetContext(), moduleName, initialCoins)) + s.Require().NoError(s.network.App.GetPreciseBankKeeper().SendCoinsFromModuleToAccount(s.network.GetContext(), moduleName, sender, initialCoins)) maxUnit := types.ConversionFactor().MulRaw(2).SubRaw(1) r := rand.New(rand.NewSource(SEED)) @@ -70,10 +70,10 @@ func (suite *KeeperIntegrationTestSuite) TestMintBurnSendCoins_RandomValueMultiD case 0: // Mint to sender via module randAmount := sdkmath.NewIntFromBigInt(new(big.Int).Rand(r, maxUnit.BigInt())).AddRaw(1) mintCoins := cs(ci(types.ExtendedCoinDenom(), randAmount)) - if err := suite.network.App.PreciseBankKeeper.MintCoins(suite.network.GetContext(), moduleName, mintCoins); err != nil { + if err := s.network.App.GetPreciseBankKeeper().MintCoins(s.network.GetContext(), moduleName, mintCoins); err != nil { continue } - if err := suite.network.App.PreciseBankKeeper.SendCoinsFromModuleToAccount(suite.network.GetContext(), moduleName, sender, mintCoins); err != nil { + if err := s.network.App.GetPreciseBankKeeper().SendCoinsFromModuleToAccount(s.network.GetContext(), moduleName, sender, mintCoins); err != nil { continue } expectedSenderBal = expectedSenderBal.Add(randAmount) @@ -81,17 +81,17 @@ func (suite *KeeperIntegrationTestSuite) TestMintBurnSendCoins_RandomValueMultiD mintCount++ case 1: // Burn from sender via module - senderBal := suite.GetAllBalances(sender).AmountOf(types.ExtendedCoinDenom()) + senderBal := s.GetAllBalances(sender).AmountOf(types.ExtendedCoinDenom()) if senderBal.IsZero() { continue } burnable := sdkmath.MinInt(senderBal, maxUnit) randAmount := sdkmath.NewIntFromBigInt(new(big.Int).Rand(r, burnable.BigInt())).AddRaw(1) burnCoins := cs(ci(types.ExtendedCoinDenom(), randAmount)) - if err := suite.network.App.PreciseBankKeeper.SendCoinsFromAccountToModule(suite.network.GetContext(), sender, moduleName, burnCoins); err != nil { + if err := s.network.App.GetPreciseBankKeeper().SendCoinsFromAccountToModule(s.network.GetContext(), sender, moduleName, burnCoins); err != nil { continue } - if err := suite.network.App.PreciseBankKeeper.BurnCoins(suite.network.GetContext(), moduleName, burnCoins); err != nil { + if err := s.network.App.GetPreciseBankKeeper().BurnCoins(s.network.GetContext(), moduleName, burnCoins); err != nil { continue } expectedSenderBal = expectedSenderBal.Sub(randAmount) @@ -99,14 +99,14 @@ func (suite *KeeperIntegrationTestSuite) TestMintBurnSendCoins_RandomValueMultiD burnCount++ case 2: // Send from sender to recipient - senderBal := suite.GetAllBalances(sender).AmountOf(types.ExtendedCoinDenom()) + senderBal := s.GetAllBalances(sender).AmountOf(types.ExtendedCoinDenom()) if senderBal.IsZero() { continue } sendable := sdkmath.MinInt(senderBal, maxUnit) randAmount := sdkmath.NewIntFromBigInt(new(big.Int).Rand(r, sendable.BigInt())).AddRaw(1) sendCoins := cs(ci(types.ExtendedCoinDenom(), randAmount)) - if err := suite.network.App.PreciseBankKeeper.SendCoins(suite.network.GetContext(), sender, recipient, sendCoins); err != nil { + if err := s.network.App.GetPreciseBankKeeper().SendCoins(s.network.GetContext(), sender, recipient, sendCoins); err != nil { continue } expectedSenderBal = expectedSenderBal.Sub(randAmount) @@ -115,23 +115,23 @@ func (suite *KeeperIntegrationTestSuite) TestMintBurnSendCoins_RandomValueMultiD } } - suite.T().Logf("Executed operations: %d mints, %d burns, %d sends", mintCount, burnCount, sendCount) + s.T().Logf("Executed operations: %d mints, %d burns, %d sends", mintCount, burnCount, sendCount) // Check balances - actualSenderBal := suite.GetAllBalances(sender).AmountOf(types.ExtendedCoinDenom()) - actualRecipientBal := suite.GetAllBalances(recipient).AmountOf(types.ExtendedCoinDenom()) - suite.Require().Equal(expectedSenderBal.BigInt().Cmp(actualSenderBal.BigInt()), 0, "Sender balance mismatch (expected: %s, actual: %s)", expectedSenderBal, actualSenderBal) - suite.Require().Equal(expectedRecipientBal.BigInt().Cmp(actualRecipientBal.BigInt()), 0, "Recipient balance mismatch (expected: %s, actual: %s)", expectedRecipientBal, actualRecipientBal) + actualSenderBal := s.GetAllBalances(sender).AmountOf(types.ExtendedCoinDenom()) + actualRecipientBal := s.GetAllBalances(recipient).AmountOf(types.ExtendedCoinDenom()) + s.Require().Equal(expectedSenderBal.BigInt().Cmp(actualSenderBal.BigInt()), 0, "Sender balance mismatch (expected: %s, actual: %s)", expectedSenderBal, actualSenderBal) + s.Require().Equal(expectedRecipientBal.BigInt().Cmp(actualRecipientBal.BigInt()), 0, "Recipient balance mismatch (expected: %s, actual: %s)", expectedRecipientBal, actualRecipientBal) // Check remainder expectedRemainder := burnAmount.Sub(mintAmount).Mod(types.ConversionFactor()) - actualRemainder := suite.network.App.PreciseBankKeeper.GetRemainderAmount(suite.network.GetContext()) - suite.Require().Equal(expectedRemainder.BigInt().Cmp(actualRemainder.BigInt()), 0, "Remainder mismatch (expected: %s, actual: %s)", expectedRemainder, actualRemainder) + actualRemainder := s.network.App.GetPreciseBankKeeper().GetRemainderAmount(s.network.GetContext()) + s.Require().Equal(expectedRemainder.BigInt().Cmp(actualRemainder.BigInt()), 0, "Remainder mismatch (expected: %s, actual: %s)", expectedRemainder, actualRemainder) }) } } -func (suite *KeeperIntegrationTestSuite) TestSendEvmTx_RandomValueMultiDecimals() { +func (s *KeeperIntegrationTestSuite) TestSendEvmTx_RandomValueMultiDecimals() { maxGasLimit := int64(500000) defaultEVMCoinTransferGasLimit := int64(21000) @@ -154,41 +154,41 @@ func (suite *KeeperIntegrationTestSuite) TestSendEvmTx_RandomValueMultiDecimals( } for _, tt := range tests { - suite.Run(tt.name, func() { - suite.SetupTestWithChainID(tt.chainID) + s.Run(tt.name, func() { + s.SetupTestWithChainID(tt.chainID) - sender := suite.keyring.GetKey(0) - recipient := suite.keyring.GetKey(1) + sender := s.keyring.GetKey(0) + recipient := s.keyring.GetKey(1) burnerAddr := common.HexToAddress("0x0000000000000000000000000000000000000000") - baseFeeResp, err := suite.network.GetEvmClient().BaseFee(suite.network.GetContext(), &evmtypes.QueryBaseFeeRequest{}) - suite.Require().NoError(err) + baseFeeResp, err := s.network.GetEvmClient().BaseFee(s.network.GetContext(), &evmtypes.QueryBaseFeeRequest{}) + s.Require().NoError(err) gasPrice := sdkmath.NewIntFromBigInt(baseFeeResp.BaseFee.BigInt()) gasFee := gasPrice.Mul(sdkmath.NewInt(defaultEVMCoinTransferGasLimit)) // Burn balance from sender except for initial balance initialBalance := types.ConversionFactor().MulRaw(100) - senderBal := suite.GetAllBalances(sender.AccAddr).AmountOf(types.ExtendedCoinDenom()).Sub(gasFee).Sub(initialBalance) - _, err = suite.factory.ExecuteEthTx(sender.Priv, evmtypes.EvmTxArgs{ + senderBal := s.GetAllBalances(sender.AccAddr).AmountOf(types.ExtendedCoinDenom()).Sub(gasFee).Sub(initialBalance) + _, err = s.factory.ExecuteEthTx(sender.Priv, evmtypes.EvmTxArgs{ To: &burnerAddr, Amount: senderBal.BigInt(), GasLimit: uint64(defaultEVMCoinTransferGasLimit), //nolint:gosec // G115 GasPrice: gasPrice.BigInt(), }) - suite.Require().NoError(err) + s.Require().NoError(err) // Burn balance from recipient - recipientBal := suite.GetAllBalances(recipient.AccAddr).AmountOf(types.ExtendedCoinDenom()).Sub(gasFee) - _, err = suite.factory.ExecuteEthTx(recipient.Priv, evmtypes.EvmTxArgs{ + recipientBal := s.GetAllBalances(recipient.AccAddr).AmountOf(types.ExtendedCoinDenom()).Sub(gasFee) + _, err = s.factory.ExecuteEthTx(recipient.Priv, evmtypes.EvmTxArgs{ To: &burnerAddr, Amount: recipientBal.BigInt(), GasLimit: uint64(defaultEVMCoinTransferGasLimit), //nolint:gosec // G115 GasPrice: gasPrice.BigInt(), }) - suite.Require().NoError(err) + s.Require().NoError(err) - err = suite.network.NextBlock() - suite.Require().NoError(err) + err = s.network.NextBlock() + s.Require().NoError(err) maxSendUnit := types.ConversionFactor().MulRaw(2).SubRaw(1) r := rand.New(rand.NewSource(SEED)) @@ -199,22 +199,22 @@ func (suite *KeeperIntegrationTestSuite) TestSendEvmTx_RandomValueMultiDecimals( sentCount := 0 for { gasLimit := r.Int63n(maxGasLimit-defaultEVMCoinTransferGasLimit) + defaultEVMCoinTransferGasLimit - baseFeeResp, err = suite.network.GetEvmClient().BaseFee(suite.network.GetContext(), &evmtypes.QueryBaseFeeRequest{}) - suite.Require().NoError(err) + baseFeeResp, err = s.network.GetEvmClient().BaseFee(s.network.GetContext(), &evmtypes.QueryBaseFeeRequest{}) + s.Require().NoError(err) gasPrice = sdkmath.NewIntFromBigInt(baseFeeResp.BaseFee.BigInt()) // Generate random value to send randAmount := sdkmath.NewIntFromBigInt(new(big.Int).Rand(r, maxSendUnit.BigInt())).AddRaw(1) // Execute EVM coin transfer - txRes, _ := suite.factory.ExecuteEthTx(sender.Priv, evmtypes.EvmTxArgs{ + txRes, _ := s.factory.ExecuteEthTx(sender.Priv, evmtypes.EvmTxArgs{ To: &recipient.Addr, Amount: randAmount.BigInt(), GasLimit: uint64(gasLimit), //nolint:gosec // G115 GasPrice: gasPrice.BigInt(), }) - err = suite.network.NextBlock() - suite.Require().NoError(err) + err = s.network.NextBlock() + s.Require().NoError(err) // Calculate gas fee used gasUsed := txRes.GasUsed @@ -232,22 +232,22 @@ func (suite *KeeperIntegrationTestSuite) TestSendEvmTx_RandomValueMultiDecimals( expectedRecipientBal = expectedRecipientBal.Add(randAmount) } - suite.T().Logf("Completed %d random evm sends", sentCount) + s.T().Logf("Completed %d random evm sends", sentCount) // Check sender balance - actualSenderBal := suite.GetAllBalances(sender.AccAddr).AmountOf(types.ExtendedCoinDenom()) - suite.Require().Equal(expectedSenderBal.BigInt().Cmp(actualSenderBal.BigInt()), 0, + actualSenderBal := s.GetAllBalances(sender.AccAddr).AmountOf(types.ExtendedCoinDenom()) + s.Require().Equal(expectedSenderBal.BigInt().Cmp(actualSenderBal.BigInt()), 0, "Sender balance mismatch (expected: %s, actual: %s)", expectedSenderBal, actualSenderBal) // Check recipient balance - actualRecipientBal := suite.GetAllBalances(recipient.AccAddr).AmountOf(types.ExtendedCoinDenom()) - suite.Require().Equal(expectedRecipientBal.BigInt().Cmp(actualRecipientBal.BigInt()), 0, + actualRecipientBal := s.GetAllBalances(recipient.AccAddr).AmountOf(types.ExtendedCoinDenom()) + s.Require().Equal(expectedRecipientBal.BigInt().Cmp(actualRecipientBal.BigInt()), 0, "Recipient balance mismatch (expected: %s, actual: %s)", expectedRecipientBal, actualRecipientBal) }) } } -func (suite *KeeperIntegrationTestSuite) TestWATOMWrapUnwrap_MultiDecimal() { +func (s *KeeperIntegrationTestSuite) TestWATOMWrapUnwrap_MultiDecimal() { tests := []struct { name string chainID testconstants.ChainID @@ -267,30 +267,30 @@ func (suite *KeeperIntegrationTestSuite) TestWATOMWrapUnwrap_MultiDecimal() { } for _, tt := range tests { - suite.Run(tt.name, func() { - suite.SetupTestWithChainID(tt.chainID) + s.Run(tt.name, func() { + s.SetupTestWithChainID(tt.chainID) - sender := suite.keyring.GetKey(0) + sender := s.keyring.GetKey(0) amount := big.NewInt(1) // Deploy WATOM contract - watomAddr, err := suite.factory.DeployContract( + watomAddr, err := s.factory.DeployContract( sender.Priv, evmtypes.EvmTxArgs{}, - factory.ContractDeploymentData{ + testutiltypes.ContractDeploymentData{ Contract: contracts.WATOMContract, }, ) - suite.Require().NoError(err) + s.Require().NoError(err) - err = suite.network.NextBlock() - suite.Require().NoError(err) + err = s.network.NextBlock() + s.Require().NoError(err) - baseFeeRes, err := suite.network.GetEvmClient().BaseFee(suite.network.GetContext(), &evmtypes.QueryBaseFeeRequest{}) - suite.Require().NoError(err) + baseFeeRes, err := s.network.GetEvmClient().BaseFee(s.network.GetContext(), &evmtypes.QueryBaseFeeRequest{}) + s.Require().NoError(err) // Call deposit() with msg.value = wrapAmount - _, err = suite.factory.ExecuteContractCall( + _, err = s.factory.ExecuteContractCall( sender.Priv, evmtypes.EvmTxArgs{ To: &watomAddr, @@ -299,25 +299,25 @@ func (suite *KeeperIntegrationTestSuite) TestWATOMWrapUnwrap_MultiDecimal() { GasFeeCap: baseFeeRes.BaseFee.BigInt(), GasTipCap: big.NewInt(1), }, - factory.CallArgs{ + testutiltypes.CallArgs{ ContractABI: contracts.WATOMContract.ABI, MethodName: "deposit", }, ) - suite.Require().NoError(err) - err = suite.network.NextBlock() - suite.Require().NoError(err) + s.Require().NoError(err) + err = s.network.NextBlock() + s.Require().NoError(err) // Check WATOM balance == wrapAmount - bal, err := utils.GetERC20Balance(suite.network, watomAddr, sender.Addr) - suite.Require().NoError(err) - suite.Require().Equal(amount.Cmp(bal), 0, "WATOM balance should match deposited amount (expected: %s, actual: %s)", amount, bal) + bal, err := utils.GetERC20Balance(s.network, watomAddr, sender.Addr) + s.Require().NoError(err) + s.Require().Equal(amount.Cmp(bal), 0, "WATOM balance should match deposited amount (expected: %s, actual: %s)", amount, bal) - baseFeeRes, err = suite.network.GetEvmClient().BaseFee(suite.network.GetContext(), &evmtypes.QueryBaseFeeRequest{}) - suite.Require().NoError(err) + baseFeeRes, err = s.network.GetEvmClient().BaseFee(s.network.GetContext(), &evmtypes.QueryBaseFeeRequest{}) + s.Require().NoError(err) // Call withdraw(wrapAmount) - _, err = suite.factory.ExecuteContractCall( + _, err = s.factory.ExecuteContractCall( sender.Priv, evmtypes.EvmTxArgs{ To: &watomAddr, @@ -325,19 +325,19 @@ func (suite *KeeperIntegrationTestSuite) TestWATOMWrapUnwrap_MultiDecimal() { GasFeeCap: baseFeeRes.BaseFee.BigInt(), GasTipCap: big.NewInt(1), }, - factory.CallArgs{ + testutiltypes.CallArgs{ ContractABI: contracts.WATOMContract.ABI, MethodName: "withdraw", Args: []interface{}{amount}, }, ) - suite.Require().NoError(err) - suite.Require().NoError(suite.network.NextBlock()) + s.Require().NoError(err) + s.Require().NoError(s.network.NextBlock()) // Final WATOM balance should be 0 - bal, err = utils.GetERC20Balance(suite.network, watomAddr, sender.Addr) - suite.Require().NoError(err) - suite.Require().Equal("0", bal.String(), "WATOM balance should be zero after withdraw") + bal, err = utils.GetERC20Balance(s.network, watomAddr, sender.Addr) + s.Require().NoError(err) + s.Require().Equal("0", bal.String(), "WATOM balance should be zero after withdraw") }) } } diff --git a/x/precisebank/keeper/mint_integration_test.go b/tests/integration/x/precisebank/test_mint_integration.go similarity index 76% rename from x/precisebank/keeper/mint_integration_test.go rename to tests/integration/x/precisebank/test_mint_integration.go index 18663bc99..bd92a00e4 100644 --- a/x/precisebank/keeper/mint_integration_test.go +++ b/tests/integration/x/precisebank/test_mint_integration.go @@ -1,4 +1,4 @@ -package keeper_test +package precisebank import ( "fmt" @@ -20,30 +20,30 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) -func (suite *KeeperIntegrationTestSuite) TestBlockedRecipient() { +func (s *KeeperIntegrationTestSuite) TestBlockedRecipient() { // Tests that sending funds to x/precisebank is disallowed. // x/precisebank balance is used as the reserve funds and should not be // directly interacted with by external modules or users. - msgServer := bankkeeper.NewMsgServerImpl(suite.network.App.BankKeeper) + msgServer := bankkeeper.NewMsgServerImpl(s.network.App.GetBankKeeper()) fromAddr := sdk.AccAddress{1} // To x/precisebank - toAddr := suite.network.App.AccountKeeper.GetModuleAddress(types.ModuleName) + toAddr := s.network.App.GetAccountKeeper().GetModuleAddress(types.ModuleName) amount := cs(c(types.IntegerCoinDenom(), 1000)) msg := banktypes.NewMsgSend(fromAddr, toAddr, amount) - _, err := msgServer.Send(suite.network.GetContext(), msg) - suite.Require().Error(err) + _, err := msgServer.Send(s.network.GetContext(), msg) + s.Require().Error(err) - suite.Require().EqualError( + s.Require().EqualError( err, fmt.Sprintf("%s is not allowed to receive funds: unauthorized", toAddr.String()), ) } -func (suite *KeeperIntegrationTestSuite) TestMintCoins_MatchingErrors() { +func (s *KeeperIntegrationTestSuite) TestMintCoins_MatchingErrors() { // x/precisebank MintCoins should be identical to x/bank MintCoins to // consumers. This test ensures that the panics & errors returned by // x/precisebank are identical to x/bank. @@ -80,24 +80,24 @@ func (suite *KeeperIntegrationTestSuite) TestMintCoins_MatchingErrors() { } for _, tt := range tests { - suite.Run(tt.name, func() { + s.Run(tt.name, func() { // Reset - suite.SetupTest() + s.SetupTest() if tt.wantErr == "" && tt.wantPanic == "" { - suite.Fail("test must specify either wantErr or wantPanic") + s.Fail("test must specify either wantErr or wantPanic") } if tt.wantErr != "" { // Check x/bank MintCoins for identical error - bankErr := suite.network.App.BankKeeper.MintCoins(suite.network.GetContext(), tt.recipientModule, tt.mintAmount) - suite.Require().Error(bankErr) - suite.Require().EqualError(bankErr, tt.wantErr, "expected error should match x/bank MintCoins error") + bankErr := s.network.App.GetBankKeeper().MintCoins(s.network.GetContext(), tt.recipientModule, tt.mintAmount) + s.Require().Error(bankErr) + s.Require().EqualError(bankErr, tt.wantErr, "expected error should match x/bank MintCoins error") - pbankErr := suite.network.App.PreciseBankKeeper.MintCoins(suite.network.GetContext(), tt.recipientModule, tt.mintAmount) - suite.Require().Error(pbankErr) + pbankErr := s.network.App.GetPreciseBankKeeper().MintCoins(s.network.GetContext(), tt.recipientModule, tt.mintAmount) + s.Require().Error(pbankErr) // Compare strings instead of errors, as error stack is still different - suite.Require().Equal( + s.Require().Equal( bankErr.Error(), pbankErr.Error(), "x/precisebank error should match x/bank MintCoins error", @@ -108,19 +108,19 @@ func (suite *KeeperIntegrationTestSuite) TestMintCoins_MatchingErrors() { // First check the wantPanic string is correct. // Actually specify the panic string in the test since it makes // it more clear we are testing specific and different cases. - suite.Require().PanicsWithError(tt.wantPanic, func() { - _ = suite.network.App.BankKeeper.MintCoins(suite.network.GetContext(), tt.recipientModule, tt.mintAmount) + s.Require().PanicsWithError(tt.wantPanic, func() { + _ = s.network.App.GetBankKeeper().MintCoins(s.network.GetContext(), tt.recipientModule, tt.mintAmount) }, "expected panic error should match x/bank MintCoins") - suite.Require().PanicsWithError(tt.wantPanic, func() { - _ = suite.network.App.PreciseBankKeeper.MintCoins(suite.network.GetContext(), tt.recipientModule, tt.mintAmount) + s.Require().PanicsWithError(tt.wantPanic, func() { + _ = s.network.App.GetPreciseBankKeeper().MintCoins(s.network.GetContext(), tt.recipientModule, tt.mintAmount) }, "x/precisebank panic should match x/bank MintCoins") } }) } } -func (suite *KeeperIntegrationTestSuite) TestMintCoins() { +func (s *KeeperIntegrationTestSuite) TestMintCoins() { type mintTest struct { mintAmount sdk.Coins // Expected **full** balances after MintCoins(mintAmount) @@ -276,21 +276,21 @@ func (suite *KeeperIntegrationTestSuite) TestMintCoins() { } for _, tt := range tests { - suite.Run(tt.name, func() { + s.Run(tt.name, func() { // Reset - suite.SetupTest() + s.SetupTest() - recipientAddr := suite.network.App.AccountKeeper.GetModuleAddress(tt.recipientModule) + recipientAddr := s.network.App.GetAccountKeeper().GetModuleAddress(tt.recipientModule) for _, mt := range tt.mints { - err := suite.network.App.PreciseBankKeeper.MintCoins(suite.network.GetContext(), tt.recipientModule, mt.mintAmount) - suite.Require().NoError(err) + err := s.network.App.GetPreciseBankKeeper().MintCoins(s.network.GetContext(), tt.recipientModule, mt.mintAmount) + s.Require().NoError(err) // ------------------------------------------------------------- // Check FULL balances // x/bank balances + x/precisebank balance // Exclude "uatom" as x/precisebank balance will include it - bankCoins := suite.network.App.BankKeeper.GetAllBalances(suite.network.GetContext(), recipientAddr) + bankCoins := s.network.App.GetBankKeeper().GetAllBalances(s.network.GetContext(), recipientAddr) // Only use x/bank balances for non-uatom denoms var denoms []string @@ -311,11 +311,11 @@ func (suite *KeeperIntegrationTestSuite) TestMintCoins() { // All balance queries through x/precisebank afterBalance := sdk.NewCoins() for _, denom := range denoms { - coin := suite.network.App.PreciseBankKeeper.GetBalance(suite.network.GetContext(), recipientAddr, denom) + coin := s.network.App.GetPreciseBankKeeper().GetBalance(s.network.GetContext(), recipientAddr, denom) afterBalance = afterBalance.Add(coin) } - suite.Require().Equal( + s.Require().Equal( mt.wantBalance.String(), afterBalance.String(), "unexpected balance after minting %s to %s", @@ -331,7 +331,7 @@ func (suite *KeeperIntegrationTestSuite) TestMintCoins() { extCoins := sdk.NewCoins(sdk.NewCoin(types.ExtendedCoinDenom(), totalExtCoinAmt)) // Check for mint event - events := suite.network.GetContext().EventManager().Events() + events := s.network.GetContext().EventManager().Events() expMintEvent := banktypes.NewCoinMintEvent( recipientAddr, @@ -344,18 +344,18 @@ func (suite *KeeperIntegrationTestSuite) TestMintCoins() { ) if totalExtCoinAmt.IsZero() { - suite.Require().NotContains(events, expMintEvent) - suite.Require().NotContains(events, expReceivedEvent) + s.Require().NotContains(events, expMintEvent) + s.Require().NotContains(events, expReceivedEvent) } else { - suite.Require().Contains(events, expMintEvent) - suite.Require().Contains(events, expReceivedEvent) + s.Require().Contains(events, expMintEvent) + s.Require().Contains(events, expReceivedEvent) } } }) } } -func (suite *KeeperIntegrationTestSuite) TestMintCoins_RandomValueMultiDecimals() { +func (s *KeeperIntegrationTestSuite) TestMintCoins_RandomValueMultiDecimals() { tests := []struct { name string chainID testconstants.ChainID @@ -375,8 +375,8 @@ func (suite *KeeperIntegrationTestSuite) TestMintCoins_RandomValueMultiDecimals( } for _, tt := range tests { - suite.Run(tt.name, func() { - suite.SetupTestWithChainID(tt.chainID) + s.Run(tt.name, func() { + s.SetupTestWithChainID(tt.chainID) // Has mint permissions minterModuleName := evmtypes.ModuleName @@ -395,7 +395,7 @@ func (suite *KeeperIntegrationTestSuite) TestMintCoins_RandomValueMultiDecimals( // Continue mints as long as target balance is not reached for { // Check current minter balance - minterBal := suite.GetAllBalances(minter).AmountOf(types.ExtendedCoinDenom()) + minterBal := s.GetAllBalances(minter).AmountOf(types.ExtendedCoinDenom()) if minterBal.GTE(targetBalance) { break } @@ -407,26 +407,26 @@ func (suite *KeeperIntegrationTestSuite) TestMintCoins_RandomValueMultiDecimals( // 1. mint to evm module mintCoins := cs(ci(types.ExtendedCoinDenom(), randAmount)) - err := suite.network.App.PreciseBankKeeper.MintCoins(suite.network.GetContext(), minterModuleName, mintCoins) - suite.Require().NoError(err) + err := s.network.App.GetPreciseBankKeeper().MintCoins(s.network.GetContext(), minterModuleName, mintCoins) + s.Require().NoError(err) // 2. send to account - err = suite.network.App.PreciseBankKeeper.SendCoinsFromModuleToAccount(suite.network.GetContext(), minterModuleName, minter, mintCoins) - suite.Require().NoError(err) + err = s.network.App.GetPreciseBankKeeper().SendCoinsFromModuleToAccount(s.network.GetContext(), minterModuleName, minter, mintCoins) + s.Require().NoError(err) totalMinted = totalMinted.Add(randAmount) mintCount++ } - suite.T().Logf("Completed %d random mints, total minted: %s", mintCount, totalMinted) + s.T().Logf("Completed %d random mints, total minted: %s", mintCount, totalMinted) // Check minter balance - minterBal := suite.GetAllBalances(minter).AmountOf(types.ExtendedCoinDenom()) - suite.Equal(minterBal.BigInt().Cmp(targetBalance.BigInt()), 0, "minter balance mismatch (expected: %s, actual: %s)", targetBalance, minterBal) + minterBal := s.GetAllBalances(minter).AmountOf(types.ExtendedCoinDenom()) + s.Equal(minterBal.BigInt().Cmp(targetBalance.BigInt()), 0, "minter balance mismatch (expected: %s, actual: %s)", targetBalance, minterBal) // Check remainder - remainder := suite.network.App.PreciseBankKeeper.GetRemainderAmount(suite.network.GetContext()) - suite.Equal(remainder.BigInt().Cmp(big.NewInt(0)), 0, "remainder should be zero (expected: %s, actual: %s)", big.NewInt(0), remainder) + remainder := s.network.App.GetPreciseBankKeeper().GetRemainderAmount(s.network.GetContext()) + s.Equal(remainder.BigInt().Cmp(big.NewInt(0)), 0, "remainder should be zero (expected: %s, actual: %s)", big.NewInt(0), remainder) }) } } @@ -463,7 +463,7 @@ func FuzzMintCoins(f *testing.F) { // Mint 10 times to include mints from non-zero balances for i := int64(0); i < mintCount; i++ { - err := suite.network.App.PreciseBankKeeper.MintCoins( + err := suite.network.App.GetPreciseBankKeeper().MintCoins( suite.network.GetContext(), evmtypes.ModuleName, cs(c(types.ExtendedCoinDenom(), amount)), @@ -472,8 +472,8 @@ func FuzzMintCoins(f *testing.F) { } // Check full balances - recipientAddr := suite.network.App.AccountKeeper.GetModuleAddress(evmtypes.ModuleName) - bal := suite.network.App.PreciseBankKeeper.GetBalance(suite.network.GetContext(), recipientAddr, types.ExtendedCoinDenom()) + recipientAddr := suite.network.App.GetAccountKeeper().GetModuleAddress(evmtypes.ModuleName) + bal := suite.network.App.GetPreciseBankKeeper().GetBalance(suite.network.GetContext(), recipientAddr, types.ExtendedCoinDenom()) suite.Require().Equalf( amount*mintCount, diff --git a/x/precisebank/keeper/send_integration_test.go b/tests/integration/x/precisebank/test_send_integration.go similarity index 71% rename from x/precisebank/keeper/send_integration_test.go rename to tests/integration/x/precisebank/test_send_integration.go index d7b8313f3..ac0e4fdfa 100644 --- a/x/precisebank/keeper/send_integration_test.go +++ b/tests/integration/x/precisebank/test_send_integration.go @@ -1,4 +1,4 @@ -package keeper_test +package precisebank import ( "fmt" @@ -6,9 +6,9 @@ import ( "math/rand" "testing" + "cosmosevm.io/evmd" "github.com/stretchr/testify/require" - "github.com/cosmos/evm/evmd" testconstants "github.com/cosmos/evm/testutil/constants" "github.com/cosmos/evm/x/precisebank/types" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -22,7 +22,7 @@ import ( stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) -func (suite *KeeperIntegrationTestSuite) TestSendCoinsFromAccountToModule_MatchingErrors() { +func (s *KeeperIntegrationTestSuite) TestSendCoinsFromAccountToModule_MatchingErrors() { // No specific errors for SendCoinsFromAccountToModule, only 1 panic if // the module account does not exist @@ -51,26 +51,26 @@ func (suite *KeeperIntegrationTestSuite) TestSendCoinsFromAccountToModule_Matchi } for _, tt := range tests { - suite.Run(tt.name, func() { + s.Run(tt.name, func() { // Reset - suite.SetupTest() + s.SetupTest() - suite.Require().NotEmpty(tt.wantPanic, "test case must have a wantPanic") + s.Require().NotEmpty(tt.wantPanic, "test case must have a wantPanic") - suite.Require().PanicsWithError(tt.wantPanic, func() { - err := suite.network.App.BankKeeper.SendCoinsFromAccountToModule(suite.network.GetContext(), tt.sender, tt.recipientModule, tt.sendAmount) - suite.Require().Error(err) + s.Require().PanicsWithError(tt.wantPanic, func() { + err := s.network.App.GetBankKeeper().SendCoinsFromAccountToModule(s.network.GetContext(), tt.sender, tt.recipientModule, tt.sendAmount) + s.Require().Error(err) }, "wantPanic should match x/bank SendCoinsFromAccountToModule panic") - suite.Require().PanicsWithError(tt.wantPanic, func() { - err := suite.network.App.PreciseBankKeeper.SendCoinsFromAccountToModule(suite.network.GetContext(), tt.sender, tt.recipientModule, tt.sendAmount) - suite.Require().Error(err) + s.Require().PanicsWithError(tt.wantPanic, func() { + err := s.network.App.GetPreciseBankKeeper().SendCoinsFromAccountToModule(s.network.GetContext(), tt.sender, tt.recipientModule, tt.sendAmount) + s.Require().Error(err) }, "x/precisebank panic should match x/bank SendCoinsFromAccountToModule panic") }) } } -func (suite *KeeperIntegrationTestSuite) TestSendCoinsFromModuleToAccount_MatchingErrors() { +func (s *KeeperIntegrationTestSuite) TestSendCoinsFromModuleToAccount_MatchingErrors() { // Ensure errors match x/bank errors AND panics. This needs to be well // tested before SendCoins as all send tests rely on this to initialize // account balances. @@ -79,7 +79,7 @@ func (suite *KeeperIntegrationTestSuite) TestSendCoinsFromModuleToAccount_Matchi // remaining logic is the same as SendCoins. blockedMacAddrs := evmd.BlockedAddresses() - precisebankAddr := suite.network.App.AccountKeeper.GetModuleAddress(types.ModuleName) + precisebankAddr := s.network.App.GetAccountKeeper().GetModuleAddress(types.ModuleName) var blockedAddr sdk.AccAddress // Get the first blocked address @@ -106,8 +106,8 @@ func (suite *KeeperIntegrationTestSuite) TestSendCoinsFromModuleToAccount_Matchi } } - suite.Require().NotEmpty(blockedAddr, "no blocked addresses found") - suite.Require().NotEmpty(senderModuleName, "no sender module name found") + s.Require().NotEmpty(blockedAddr, "no blocked addresses found") + s.Require().NotEmpty(senderModuleName, "no sender module name found") tests := []struct { name string @@ -182,37 +182,37 @@ func (suite *KeeperIntegrationTestSuite) TestSendCoinsFromModuleToAccount_Matchi } for _, tt := range tests { - suite.Run(tt.name, func() { + s.Run(tt.name, func() { // Reset - suite.SetupTest() + s.SetupTest() if tt.wantPanic == "" && tt.wantErr == "" { - suite.FailNow("test case must have a wantErr or wantPanic") + s.FailNow("test case must have a wantErr or wantPanic") } if tt.wantPanic != "" { - suite.Require().Empty(tt.wantErr, "test case must not have a wantErr if wantPanic is set") + s.Require().Empty(tt.wantErr, "test case must not have a wantErr if wantPanic is set") - suite.Require().PanicsWithError(tt.wantPanic, func() { - err := suite.network.App.BankKeeper.SendCoinsFromModuleToAccount(suite.network.GetContext(), tt.senderModule, tt.recipient, tt.sendAmount) - suite.Require().Error(err) + s.Require().PanicsWithError(tt.wantPanic, func() { + err := s.network.App.GetBankKeeper().SendCoinsFromModuleToAccount(s.network.GetContext(), tt.senderModule, tt.recipient, tt.sendAmount) + s.Require().Error(err) }, "wantPanic should match x/bank SendCoinsFromModuleToAccount panic") - suite.Require().PanicsWithError(tt.wantPanic, func() { - err := suite.network.App.PreciseBankKeeper.SendCoinsFromModuleToAccount(suite.network.GetContext(), tt.senderModule, tt.recipient, tt.sendAmount) - suite.Require().Error(err) + s.Require().PanicsWithError(tt.wantPanic, func() { + err := s.network.App.GetPreciseBankKeeper().SendCoinsFromModuleToAccount(s.network.GetContext(), tt.senderModule, tt.recipient, tt.sendAmount) + s.Require().Error(err) }, "x/precisebank panic should match x/bank SendCoinsFromModuleToAccount panic") } if tt.wantErr != "" { - bankErr := suite.network.App.BankKeeper.SendCoinsFromModuleToAccount(suite.network.GetContext(), tt.senderModule, tt.recipient, tt.sendAmount) - suite.Require().Error(bankErr) - suite.Require().EqualError(bankErr, tt.wantErr, "expected error should match x/bank SendCoins error") + bankErr := s.network.App.GetBankKeeper().SendCoinsFromModuleToAccount(s.network.GetContext(), tt.senderModule, tt.recipient, tt.sendAmount) + s.Require().Error(bankErr) + s.Require().EqualError(bankErr, tt.wantErr, "expected error should match x/bank SendCoins error") - pbankErr := suite.network.App.PreciseBankKeeper.SendCoinsFromModuleToAccount(suite.network.GetContext(), tt.senderModule, tt.recipient, tt.sendAmount) - suite.Require().Error(pbankErr) + pbankErr := s.network.App.GetPreciseBankKeeper().SendCoinsFromModuleToAccount(s.network.GetContext(), tt.senderModule, tt.recipient, tt.sendAmount) + s.Require().Error(pbankErr) // Compare strings instead of errors, as error stack is still different - suite.Require().Equal( + s.Require().Equal( bankErr.Error(), pbankErr.Error(), "x/precisebank error should match x/bank SendCoins error", @@ -222,7 +222,7 @@ func (suite *KeeperIntegrationTestSuite) TestSendCoinsFromModuleToAccount_Matchi } } -func (suite *KeeperIntegrationTestSuite) TestSendCoins_MatchingErrors() { +func (s *KeeperIntegrationTestSuite) TestSendCoins_MatchingErrors() { // Ensure errors match x/bank errors tests := []struct { @@ -266,24 +266,24 @@ func (suite *KeeperIntegrationTestSuite) TestSendCoins_MatchingErrors() { } for _, tt := range tests { - suite.Run(tt.name, func() { + s.Run(tt.name, func() { // Reset - suite.SetupTest() + s.SetupTest() sender := sdk.AccAddress([]byte{1}) recipient := sdk.AccAddress([]byte{2}) - suite.Require().NotEmpty(tt.wantErr, "test case must have a wantErr") + s.Require().NotEmpty(tt.wantErr, "test case must have a wantErr") - suite.MintToAccount(sender, tt.initialAmount) + s.MintToAccount(sender, tt.initialAmount) - bankErr := suite.network.App.BankKeeper.SendCoins(suite.network.GetContext(), sender, recipient, tt.sendAmount) - suite.Require().Error(bankErr) - suite.Require().EqualError(bankErr, tt.wantErr, "expected error should match x/bank SendCoins error") + bankErr := s.network.App.GetBankKeeper().SendCoins(s.network.GetContext(), sender, recipient, tt.sendAmount) + s.Require().Error(bankErr) + s.Require().EqualError(bankErr, tt.wantErr, "expected error should match x/bank SendCoins error") - pbankErr := suite.network.App.PreciseBankKeeper.SendCoins(suite.network.GetContext(), sender, recipient, tt.sendAmount) - suite.Require().Error(pbankErr) + pbankErr := s.network.App.GetPreciseBankKeeper().SendCoins(s.network.GetContext(), sender, recipient, tt.sendAmount) + s.Require().Error(pbankErr) // Compare strings instead of errors, as error stack is still different - suite.Require().Equal( + s.Require().Equal( bankErr.Error(), pbankErr.Error(), "x/precisebank error should match x/bank SendCoins error", @@ -292,7 +292,7 @@ func (suite *KeeperIntegrationTestSuite) TestSendCoins_MatchingErrors() { } } -func (suite *KeeperIntegrationTestSuite) TestSendCoins() { +func (s *KeeperIntegrationTestSuite) TestSendCoins() { // SendCoins is tested mostly in this integration test, as a unit test with // mocked BankKeeper overcomplicates expected keepers and makes initializing // balances very complex. @@ -379,31 +379,31 @@ func (suite *KeeperIntegrationTestSuite) TestSendCoins() { } for _, tt := range tests { - suite.Run(tt.name, func() { - suite.SetupTest() + s.Run(tt.name, func() { + s.SetupTest() sender := sdk.AccAddress([]byte{1}) recipient := sdk.AccAddress([]byte{2}) // Initialize balances - suite.MintToAccount(sender, tt.giveStartBalSender) - suite.MintToAccount(recipient, tt.giveStartBalRecipient) + s.MintToAccount(sender, tt.giveStartBalSender) + s.MintToAccount(recipient, tt.giveStartBalRecipient) - senderBalBefore := suite.GetAllBalances(sender) - recipientBalBefore := suite.GetAllBalances(recipient) + senderBalBefore := s.GetAllBalances(sender) + recipientBalBefore := s.GetAllBalances(recipient) - err := suite.network.App.PreciseBankKeeper.SendCoins(suite.network.GetContext(), sender, recipient, tt.giveAmt) + err := s.network.App.GetPreciseBankKeeper().SendCoins(s.network.GetContext(), sender, recipient, tt.giveAmt) if tt.wantErr != "" { - suite.Require().Error(err) - suite.Require().EqualError(err, tt.wantErr) + s.Require().Error(err) + s.Require().EqualError(err, tt.wantErr) return } - suite.Require().NoError(err) + s.Require().NoError(err) // Check balances - senderBalAfter := suite.GetAllBalances(sender) - recipientBalAfter := suite.GetAllBalances(recipient) + senderBalAfter := s.GetAllBalances(sender) + recipientBalAfter := s.GetAllBalances(recipient) // Convert send amount coins to extended coins. i.e. if send coins // includes uatom, convert it so that its the equivalent aatom @@ -420,12 +420,12 @@ func (suite *KeeperIntegrationTestSuite) TestSendCoins() { sendAmountFullExtended = sendAmountFullExtended.Add(extendedCoin) } - suite.Require().Equal( + s.Require().Equal( senderBalBefore.Sub(sendAmountFullExtended...), senderBalAfter, ) - suite.Require().Equal( + s.Require().Equal( recipientBalBefore.Add(sendAmountFullExtended...), recipientBalAfter, ) @@ -461,16 +461,16 @@ func (suite *KeeperIntegrationTestSuite) TestSendCoins() { extCoins, ) - events := suite.network.GetContext().EventManager().Events() + events := s.network.GetContext().EventManager().Events() - suite.Require().Contains(events, extendedEvent) - suite.Require().Contains(events, expReceivedEvent) - suite.Require().Contains(events, expSentEvent) + s.Require().Contains(events, extendedEvent) + s.Require().Contains(events, expReceivedEvent) + s.Require().Contains(events, expSentEvent) }) } } -func (suite *KeeperIntegrationTestSuite) TestSendCoins_Matrix() { +func (s *KeeperIntegrationTestSuite) TestSendCoins_Matrix() { // SendCoins is tested mostly in this integration test, as a unit test with // mocked BankKeeper overcomplicates expected keepers and makes initializing // balances very complex. @@ -531,49 +531,49 @@ func (suite *KeeperIntegrationTestSuite) TestSendCoins_Matrix() { sendAmt.name, sendAmt.amt, ) - suite.Run(testName, func() { - suite.SetupTest() + s.Run(testName, func() { + s.SetupTest() sender := sdk.AccAddress([]byte{1}) recipient := sdk.AccAddress([]byte{2}) // Initialize balances - suite.MintToAccount(sender, senderStartBal.bal) - suite.MintToAccount(recipient, recipientStartBal.bal) + s.MintToAccount(sender, senderStartBal.bal) + s.MintToAccount(recipient, recipientStartBal.bal) // balances & send amount will only contain total equivalent // extended coins and no integer coins so its easier to compare - senderBalBefore := suite.GetAllBalances(sender) - recipientBalBefore := suite.GetAllBalances(recipient) + senderBalBefore := s.GetAllBalances(sender) + recipientBalBefore := s.GetAllBalances(recipient) sendAmtNormalized := ConvertCoinsToExtendedCoinDenom(sendAmt.amt) - err := suite.network.App.PreciseBankKeeper.SendCoins(suite.network.GetContext(), sender, recipient, sendAmt.amt) + err := s.network.App.GetPreciseBankKeeper().SendCoins(s.network.GetContext(), sender, recipient, sendAmt.amt) hasSufficientBal := senderBalBefore.IsAllGTE(sendAmtNormalized) if hasSufficientBal { - suite.Require().NoError(err) + s.Require().NoError(err) } else { - suite.Require().Error(err, "expected insufficient funds error") + s.Require().Error(err, "expected insufficient funds error") // No balance checks if insufficient funds return } // Check balances - senderBalAfter := suite.GetAllBalances(sender) - recipientBalAfter := suite.GetAllBalances(recipient) + senderBalAfter := s.GetAllBalances(sender) + recipientBalAfter := s.GetAllBalances(recipient) // Convert send amount coins to extended coins. i.e. if send coins // includes uatom, convert it so that its the equivalent aatom // amount so its easier to compare. Compare extended coins only. - suite.Require().Equal( + s.Require().Equal( senderBalBefore.Sub(sendAmtNormalized...), senderBalAfter, ) - suite.Require().Equal( + s.Require().Equal( recipientBalBefore.Add(sendAmtNormalized...), recipientBalAfter, ) @@ -583,43 +583,43 @@ func (suite *KeeperIntegrationTestSuite) TestSendCoins_Matrix() { } } -func (suite *KeeperIntegrationTestSuite) TestSendCoinsFromAccountToModule() { +func (s *KeeperIntegrationTestSuite) TestSendCoinsFromAccountToModule() { // Ensure recipient correctly matches the specified module account. Specific // send amount and cases are handled by SendCoins() tests, so we are only // checking SendCoinsFromAccountToModule specific behavior here. sender := sdk.AccAddress([]byte{1}) recipientModule := minttypes.ModuleName - recipientAddr := suite.network.App.AccountKeeper.GetModuleAddress(recipientModule) + recipientAddr := s.network.App.GetAccountKeeper().GetModuleAddress(recipientModule) sendAmt := cs(c(types.ExtendedCoinDenom(), 1000)) - suite.MintToAccount(sender, sendAmt) + s.MintToAccount(sender, sendAmt) - err := suite.network.App.PreciseBankKeeper.SendCoinsFromAccountToModule( - suite.network.GetContext(), + err := s.network.App.GetPreciseBankKeeper().SendCoinsFromAccountToModule( + s.network.GetContext(), sender, recipientModule, sendAmt, ) - suite.Require().NoError(err) + s.Require().NoError(err) // Check balances - senderBalAfter := suite.GetAllBalances(sender) - recipientBalAfter := suite.GetAllBalances(recipientAddr) + senderBalAfter := s.GetAllBalances(sender) + recipientBalAfter := s.GetAllBalances(recipientAddr) - suite.Require().Equal( + s.Require().Equal( cs(), senderBalAfter, ) - suite.Require().Equal( + s.Require().Equal( sendAmt, recipientBalAfter, ) } -func (suite *KeeperIntegrationTestSuite) TestSendCoinsFromAccountToModule_BlockedRecipientCarry() { +func (s *KeeperIntegrationTestSuite) TestSendCoinsFromAccountToModule_BlockedRecipientCarry() { // Carrying to module account balance. This tests that SendCoinsFromAccountToModule // does not fail when sending to a blocked module account. @@ -628,27 +628,27 @@ func (suite *KeeperIntegrationTestSuite) TestSendCoinsFromAccountToModule_Blocke sendAmt := cs(c(types.ExtendedCoinDenom(), 1000)) sendAmt2 := cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().SubRaw(10))) - suite.MintToAccount(sender, sendAmt.Add(sendAmt2...)) + s.MintToAccount(sender, sendAmt.Add(sendAmt2...)) - err := suite.network.App.PreciseBankKeeper.SendCoinsFromAccountToModule( - suite.network.GetContext(), + err := s.network.App.GetPreciseBankKeeper().SendCoinsFromAccountToModule( + s.network.GetContext(), sender, authtypes.FeeCollectorName, sendAmt, ) - suite.Require().NoError(err) + s.Require().NoError(err) // Trigger carry for fee_collector module account - err = suite.network.App.PreciseBankKeeper.SendCoinsFromAccountToModule( - suite.network.GetContext(), + err = s.network.App.GetPreciseBankKeeper().SendCoinsFromAccountToModule( + s.network.GetContext(), sender, authtypes.FeeCollectorName, sendAmt2, ) - suite.Require().NoError(err) + s.Require().NoError(err) } -func (suite *KeeperIntegrationTestSuite) TestSendCoins_BlockedRecipientCarry() { +func (s *KeeperIntegrationTestSuite) TestSendCoins_BlockedRecipientCarry() { // Same test as TestSendCoinsFromModuleToAccount_Blocked, but with SendCoins // which also should not fail when sending to a blocked module account. sender := sdk.AccAddress([]byte{1}) @@ -656,66 +656,66 @@ func (suite *KeeperIntegrationTestSuite) TestSendCoins_BlockedRecipientCarry() { sendAmt := cs(c(types.ExtendedCoinDenom(), 1000)) sendAmt2 := cs(ci(types.ExtendedCoinDenom(), types.ConversionFactor().SubRaw(10))) - suite.MintToAccount(sender, sendAmt.Add(sendAmt2...)) + s.MintToAccount(sender, sendAmt.Add(sendAmt2...)) - recipient := suite.network.App.AccountKeeper.GetModuleAddress(authtypes.FeeCollectorName) + recipient := s.network.App.GetAccountKeeper().GetModuleAddress(authtypes.FeeCollectorName) - err := suite.network.App.PreciseBankKeeper.SendCoins( - suite.network.GetContext(), + err := s.network.App.GetPreciseBankKeeper().SendCoins( + s.network.GetContext(), sender, recipient, sendAmt, ) - suite.Require().NoError(err) + s.Require().NoError(err) // Trigger carry for fee_collector module account - err = suite.network.App.PreciseBankKeeper.SendCoins( - suite.network.GetContext(), + err = s.network.App.GetPreciseBankKeeper().SendCoins( + s.network.GetContext(), sender, recipient, sendAmt2, ) - suite.Require().NoError(err) + s.Require().NoError(err) } -func (suite *KeeperIntegrationTestSuite) TestSendCoinsFromModuleToAccount() { +func (s *KeeperIntegrationTestSuite) TestSendCoinsFromModuleToAccount() { // Ensure sender correctly matches the specified module account. Opposite // of SendCoinsFromAccountToModule, so we are only checking the correct // addresses are being used. senderModule := evmtypes.ModuleName - senderAddr := suite.network.App.AccountKeeper.GetModuleAddress(senderModule) + senderAddr := s.network.App.GetAccountKeeper().GetModuleAddress(senderModule) recipient := sdk.AccAddress([]byte{1}) sendAmt := cs(c(types.ExtendedCoinDenom(), 1000)) - suite.MintToModuleAccount(senderModule, sendAmt) + s.MintToModuleAccount(senderModule, sendAmt) - err := suite.network.App.PreciseBankKeeper.SendCoinsFromModuleToAccount( - suite.network.GetContext(), + err := s.network.App.GetPreciseBankKeeper().SendCoinsFromModuleToAccount( + s.network.GetContext(), senderModule, recipient, sendAmt, ) - suite.Require().NoError(err) + s.Require().NoError(err) // Check balances - senderBalAfter := suite.GetAllBalances(senderAddr) - recipientBalAfter := suite.GetAllBalances(recipient) + senderBalAfter := s.GetAllBalances(senderAddr) + recipientBalAfter := s.GetAllBalances(recipient) - suite.Require().Equal( + s.Require().Equal( cs(), senderBalAfter, ) - suite.Require().Equal( + s.Require().Equal( sendAmt, recipientBalAfter, ) } -func (suite *KeeperIntegrationTestSuite) TestSendCoins_RandomValueMultiDecimals() { +func (s *KeeperIntegrationTestSuite) TestSendCoins_RandomValueMultiDecimals() { tests := []struct { name string chainID testconstants.ChainID @@ -735,15 +735,15 @@ func (suite *KeeperIntegrationTestSuite) TestSendCoins_RandomValueMultiDecimals( } for _, tt := range tests { - suite.Run(tt.name, func() { - suite.SetupTestWithChainID(tt.chainID) + s.Run(tt.name, func() { + s.SetupTestWithChainID(tt.chainID) sender := sdk.AccAddress([]byte{1}) recipient := sdk.AccAddress([]byte{2}) // Initial balance large enough to cover many small sends initialBalance := types.ConversionFactor().MulRaw(100) - suite.MintToAccount(sender, cs(ci(types.ExtendedCoinDenom(), initialBalance))) + s.MintToAccount(sender, cs(ci(types.ExtendedCoinDenom(), initialBalance))) // Setup test parameters maxSendUnit := types.ConversionFactor().MulRaw(2).SubRaw(1) @@ -755,7 +755,7 @@ func (suite *KeeperIntegrationTestSuite) TestSendCoins_RandomValueMultiDecimals( // Continue transfers as long as sender has balance remaining for { // Check current sender balance - senderAmount := suite.GetAllBalances(sender).AmountOf(types.ExtendedCoinDenom()) + senderAmount := s.GetAllBalances(sender).AmountOf(types.ExtendedCoinDenom()) if senderAmount.IsZero() { break } @@ -768,28 +768,28 @@ func (suite *KeeperIntegrationTestSuite) TestSendCoins_RandomValueMultiDecimals( randAmount := sdkmath.NewIntFromBigInt(new(big.Int).Rand(r, maxPossibleSend.BigInt())).AddRaw(1) sendAmount := cs(ci(types.ExtendedCoinDenom(), randAmount)) - err := suite.network.App.PreciseBankKeeper.SendCoins(suite.network.GetContext(), sender, recipient, sendAmount) - suite.NoError(err) + err := s.network.App.GetPreciseBankKeeper().SendCoins(s.network.GetContext(), sender, recipient, sendAmount) + s.NoError(err) totalSent = totalSent.Add(randAmount) sentCount++ } - suite.T().Logf("Completed %d random sends, total sent: %s", sentCount, totalSent.String()) + s.T().Logf("Completed %d random sends, total sent: %s", sentCount, totalSent.String()) // Check sender balance - senderAmount := suite.GetAllBalances(sender).AmountOf(types.ExtendedCoinDenom()) - suite.Equal(senderAmount.BigInt().Cmp(big.NewInt(0)), 0, "sender balance should be zero") + senderAmount := s.GetAllBalances(sender).AmountOf(types.ExtendedCoinDenom()) + s.Equal(senderAmount.BigInt().Cmp(big.NewInt(0)), 0, "sender balance should be zero") // Check recipient balance - recipientBal := suite.GetAllBalances(recipient) + recipientBal := s.GetAllBalances(recipient) intReceived := recipientBal.AmountOf(types.ExtendedCoinDenom()).Quo(types.ConversionFactor()) - fracReceived := suite.network.App.PreciseBankKeeper.GetFractionalBalance(suite.network.GetContext(), recipient) + fracReceived := s.network.App.GetPreciseBankKeeper().GetFractionalBalance(s.network.GetContext(), recipient) expectedInt := totalSent.Quo(types.ConversionFactor()) expectedFrac := totalSent.Mod(types.ConversionFactor()) - suite.Equal(expectedInt.BigInt().Cmp(intReceived.BigInt()), 0, "integer carry mismatch (expected: %s, received: %s)", expectedInt, intReceived) - suite.Equal(expectedFrac.BigInt().Cmp(fracReceived.BigInt()), 0, "fractional balance mismatch (expected: %s, received: %s)", expectedFrac, fracReceived) + s.Equal(expectedInt.BigInt().Cmp(intReceived.BigInt()), 0, "integer carry mismatch (expected: %s, received: %s)", expectedInt, intReceived) + s.Equal(expectedFrac.BigInt().Cmp(fracReceived.BigInt()), 0, "fractional balance mismatch (expected: %s, received: %s)", expectedFrac, fracReceived) }) } } @@ -831,7 +831,7 @@ func FuzzSendCoins(f *testing.F) { // Send amount sendCoins := cs(c(types.ExtendedCoinDenom(), int64(sendAmount))) //nolint:gosec // G115 - err := suite.network.App.PreciseBankKeeper.SendCoins(suite.network.GetContext(), sender, recipient, sendCoins) + err := suite.network.App.GetPreciseBankKeeper().SendCoins(suite.network.GetContext(), sender, recipient, sendCoins) if startBalSender < sendAmount { suite.Require().Error(err, "expected insufficient funds error") return diff --git a/tests/integration/x/precisebank/test_setup.go b/tests/integration/x/precisebank/test_setup.go new file mode 100644 index 000000000..8b782ebf6 --- /dev/null +++ b/tests/integration/x/precisebank/test_setup.go @@ -0,0 +1,50 @@ +package precisebank + +import ( + "github.com/stretchr/testify/suite" + + testconstants "github.com/cosmos/evm/testutil/constants" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/keyring" +) + +const SEED = int64(42) + +type KeeperIntegrationTestSuite struct { + suite.Suite + + create network.CreateEvmApp + options []network.ConfigOption + network *network.UnitTestNetwork + factory factory.TxFactory + keyring keyring.Keyring +} + +func NewKeeperIntegrationTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *KeeperIntegrationTestSuite { + return &KeeperIntegrationTestSuite{ + create: create, + options: options, + } +} + +func (s *KeeperIntegrationTestSuite) SetupTest() { + s.SetupTestWithChainID(testconstants.SixDecimalsChainID) +} + +func (s *KeeperIntegrationTestSuite) SetupTestWithChainID(chainID testconstants.ChainID) { + s.keyring = keyring.New(2) + + options := []network.ConfigOption{ + network.WithChainID(chainID), + network.WithPreFundedAccounts(s.keyring.GetAllAccAddrs()...), + } + options = append(options, s.options...) + nw := network.NewUnitTestNetwork(s.create, options...) + gh := grpc.NewIntegrationHandler(nw) + tf := factory.New(nw, gh) + + s.network = nw + s.factory = tf +} diff --git a/x/precisebank/keeper/util_test.go b/tests/integration/x/precisebank/test_utils.go similarity index 53% rename from x/precisebank/keeper/util_test.go rename to tests/integration/x/precisebank/test_utils.go index e9b4e9f73..2ac668c87 100644 --- a/x/precisebank/keeper/util_test.go +++ b/tests/integration/x/precisebank/test_utils.go @@ -1,8 +1,10 @@ -package keeper_test +package precisebank import ( "github.com/cosmos/evm/x/precisebank/types" + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" ) @@ -10,52 +12,52 @@ import ( // MintToAccount mints coins to an account with the x/precisebank methods. This // must be used when minting extended coins, ie. aatom coins. This depends on // the methods to be properly tested to be implemented correctly. -func (suite *KeeperIntegrationTestSuite) MintToAccount(addr sdk.AccAddress, amt sdk.Coins) { - accBalancesBefore := suite.GetAllBalances(addr) +func (s *KeeperIntegrationTestSuite) MintToAccount(addr sdk.AccAddress, amt sdk.Coins) { + accBalancesBefore := s.GetAllBalances(addr) - err := suite.network.App.PreciseBankKeeper.MintCoins(suite.network.GetContext(), minttypes.ModuleName, amt) - suite.Require().NoError(err) + err := s.network.App.GetPreciseBankKeeper().MintCoins(s.network.GetContext(), minttypes.ModuleName, amt) + s.Require().NoError(err) - err = suite.network.App.PreciseBankKeeper.SendCoinsFromModuleToAccount(suite.network.GetContext(), minttypes.ModuleName, addr, amt) - suite.Require().NoError(err) + err = s.network.App.GetPreciseBankKeeper().SendCoinsFromModuleToAccount(s.network.GetContext(), minttypes.ModuleName, addr, amt) + s.Require().NoError(err) // Double check balances are correctly minted and sent to account - accBalancesAfter := suite.GetAllBalances(addr) + accBalancesAfter := s.GetAllBalances(addr) netIncrease := accBalancesAfter.Sub(accBalancesBefore...) - suite.Require().Equal(ConvertCoinsToExtendedCoinDenom(amt), netIncrease) + s.Require().Equal(ConvertCoinsToExtendedCoinDenom(amt), netIncrease) - suite.T().Logf("minted %s to %s", amt, addr) + s.T().Logf("minted %s to %s", amt, addr) } // MintToModuleAccount mints coins to an account with the x/precisebank methods. This // must be used when minting extended coins, ie. aatom coins. This depends on // the methods to be properly tested to be implemented correctly. -func (suite *KeeperIntegrationTestSuite) MintToModuleAccount(moduleName string, amt sdk.Coins) { - moduleAddr := suite.network.App.AccountKeeper.GetModuleAddress(moduleName) - accBalancesBefore := suite.GetAllBalances(moduleAddr) +func (s *KeeperIntegrationTestSuite) MintToModuleAccount(moduleName string, amt sdk.Coins) { + moduleAddr := s.network.App.GetAccountKeeper().GetModuleAddress(moduleName) + accBalancesBefore := s.GetAllBalances(moduleAddr) - err := suite.network.App.PreciseBankKeeper.MintCoins(suite.network.GetContext(), minttypes.ModuleName, amt) - suite.Require().NoError(err) + err := s.network.App.GetPreciseBankKeeper().MintCoins(s.network.GetContext(), minttypes.ModuleName, amt) + s.Require().NoError(err) - err = suite.network.App.PreciseBankKeeper.SendCoinsFromModuleToModule(suite.network.GetContext(), minttypes.ModuleName, moduleName, amt) - suite.Require().NoError(err) + err = s.network.App.GetPreciseBankKeeper().SendCoinsFromModuleToModule(s.network.GetContext(), minttypes.ModuleName, moduleName, amt) + s.Require().NoError(err) // Double check balances are correctly minted and sent to account - accBalancesAfter := suite.GetAllBalances(moduleAddr) + accBalancesAfter := s.GetAllBalances(moduleAddr) netIncrease := accBalancesAfter.Sub(accBalancesBefore...) - suite.Require().Equal(ConvertCoinsToExtendedCoinDenom(amt), netIncrease) + s.Require().Equal(ConvertCoinsToExtendedCoinDenom(amt), netIncrease) - suite.T().Logf("minted %s to %s", amt, moduleName) + s.T().Logf("minted %s to %s", amt, moduleName) } // GetAllBalances returns all the account balances for the given account address. // This returns the extended coin balance if the account has a non-zero balance, // WITHOUT the integer coin balance. -func (suite *KeeperIntegrationTestSuite) GetAllBalances(addr sdk.AccAddress) sdk.Coins { +func (s *KeeperIntegrationTestSuite) GetAllBalances(addr sdk.AccAddress) sdk.Coins { // Get all balances for an account - bankBalances := suite.network.App.BankKeeper.GetAllBalances(suite.network.GetContext(), addr) + bankBalances := s.network.App.GetBankKeeper().GetAllBalances(s.network.GetContext(), addr) // Remove integer coins from the balance for _, coin := range bankBalances { @@ -65,7 +67,7 @@ func (suite *KeeperIntegrationTestSuite) GetAllBalances(addr sdk.AccAddress) sdk } // Replace the integer coin with the extended coin, from x/precisebank - extendedBal := suite.network.App.PreciseBankKeeper.GetBalance(suite.network.GetContext(), addr, types.ExtendedCoinDenom()) + extendedBal := s.network.App.GetPreciseBankKeeper().GetBalance(s.network.GetContext(), addr, types.ExtendedCoinDenom()) return bankBalances.Add(extendedBal) } @@ -88,3 +90,7 @@ func ConvertCoinsToExtendedCoinDenom(coins sdk.Coins) sdk.Coins { return coins.Sub(integerCoin).Add(extendedCoin) } + +func c(denom string, amount int64) sdk.Coin { return sdk.NewInt64Coin(denom, amount) } +func ci(denom string, amount sdkmath.Int) sdk.Coin { return sdk.NewCoin(denom, amount) } +func cs(coins ...sdk.Coin) sdk.Coins { return sdk.NewCoins(coins...) } diff --git a/x/precisebank/keeper/view_integration_test.go b/tests/integration/x/precisebank/test_view_integration.go similarity index 74% rename from x/precisebank/keeper/view_integration_test.go rename to tests/integration/x/precisebank/test_view_integration.go index 2579f514f..ab4ab954c 100644 --- a/x/precisebank/keeper/view_integration_test.go +++ b/tests/integration/x/precisebank/test_view_integration.go @@ -1,4 +1,4 @@ -package keeper_test +package precisebank import ( "github.com/cosmos/evm/x/precisebank/types" @@ -10,7 +10,7 @@ import ( vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" ) -func (suite *KeeperIntegrationTestSuite) TestKeeper_SpendableCoin() { +func (s *KeeperIntegrationTestSuite) TestKeeper_SpendableCoin() { tests := []struct { name string giveDenom string // queried denom for balance @@ -67,18 +67,18 @@ func (suite *KeeperIntegrationTestSuite) TestKeeper_SpendableCoin() { } for _, tt := range tests { - suite.Run(tt.name, func() { - suite.SetupTest() + s.Run(tt.name, func() { + s.SetupTest() addr := sdk.AccAddress([]byte("test-address")) - suite.MintToAccount(addr, tt.giveBankBal) + s.MintToAccount(addr, tt.giveBankBal) // Set fractional balance in store before query - suite.network.App.PreciseBankKeeper.SetFractionalBalance(suite.network.GetContext(), addr, tt.giveFractionalBal) + s.network.App.GetPreciseBankKeeper().SetFractionalBalance(s.network.GetContext(), addr, tt.giveFractionalBal) // Add some locked coins - acc := suite.network.App.AccountKeeper.GetAccount(suite.network.GetContext(), addr) + acc := s.network.App.GetAccountKeeper().GetAccount(s.network.GetContext(), addr) if acc == nil { acc = authtypes.NewBaseAccount(addr, nil, 0, 0) } @@ -86,7 +86,7 @@ func (suite *KeeperIntegrationTestSuite) TestKeeper_SpendableCoin() { vestingAcc, err := vestingtypes.NewPeriodicVestingAccount( acc.(*authtypes.BaseAccount), tt.giveLockedCoins, - suite.network.GetContext().BlockTime().Unix(), + s.network.GetContext().BlockTime().Unix(), vestingtypes.Periods{ vestingtypes.Period{ Length: 100, @@ -94,19 +94,19 @@ func (suite *KeeperIntegrationTestSuite) TestKeeper_SpendableCoin() { }, }, ) - suite.Require().NoError(err) - suite.network.App.AccountKeeper.SetAccount(suite.network.GetContext(), vestingAcc) + s.Require().NoError(err) + s.network.App.GetAccountKeeper().SetAccount(s.network.GetContext(), vestingAcc) - fetchedLockedCoins := vestingAcc.LockedCoins(suite.network.GetContext().BlockTime()) - suite.Require().Equal( + fetchedLockedCoins := vestingAcc.LockedCoins(s.network.GetContext().BlockTime()) + s.Require().Equal( tt.giveLockedCoins, fetchedLockedCoins, "locked coins should be matching at current block time", ) - spendableCoinsWithLocked := suite.network.App.PreciseBankKeeper.SpendableCoin(suite.network.GetContext(), addr, tt.giveDenom) + spendableCoinsWithLocked := s.network.App.GetPreciseBankKeeper().SpendableCoin(s.network.GetContext(), addr, tt.giveDenom) - suite.Require().Equalf( + s.Require().Equalf( tt.wantSpendableBal, spendableCoinsWithLocked, "expected spendable coins of denom %s", @@ -116,7 +116,7 @@ func (suite *KeeperIntegrationTestSuite) TestKeeper_SpendableCoin() { } } -func (suite *KeeperIntegrationTestSuite) TestKeeper_HiddenReserve() { +func (s *KeeperIntegrationTestSuite) TestKeeper_HiddenReserve() { // Reserve balances should not be shown to consumers of x/precisebank, as it // represents the fractional balances of accounts. @@ -128,7 +128,7 @@ func (suite *KeeperIntegrationTestSuite) TestKeeper_HiddenReserve() { // integer coin to the reserve to back it. extCoin := sdk.NewCoin(types.ExtendedCoinDenom(), types.ConversionFactor().AddRaw(1000)) unrelatedCoin := sdk.NewCoin("unrelated", sdkmath.NewInt(1000)) - suite.MintToAccount( + s.MintToAccount( addr1, sdk.NewCoins( extCoin, @@ -137,8 +137,8 @@ func (suite *KeeperIntegrationTestSuite) TestKeeper_HiddenReserve() { ) // Check underlying x/bank balance for reserve - reserveIntCoin := suite.network.App.BankKeeper.GetBalance(suite.network.GetContext(), moduleAddr, types.IntegerCoinDenom()) - suite.Require().Equal( + reserveIntCoin := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), moduleAddr, types.IntegerCoinDenom()) + s.Require().Equal( sdkmath.NewInt(1), reserveIntCoin.Amount, "reserve should hold 1 integer coin", @@ -177,12 +177,12 @@ func (suite *KeeperIntegrationTestSuite) TestKeeper_HiddenReserve() { } for _, tt := range tests { - suite.Run(tt.name, func() { - coin := suite.network.App.PreciseBankKeeper.GetBalance(suite.network.GetContext(), tt.giveAddr, tt.giveDenom) - suite.Require().Equal(tt.wantAmount.Int64(), coin.Amount.Int64()) + s.Run(tt.name, func() { + coin := s.network.App.GetPreciseBankKeeper().GetBalance(s.network.GetContext(), tt.giveAddr, tt.giveDenom) + s.Require().Equal(tt.wantAmount.Int64(), coin.Amount.Int64()) - spendableCoin := suite.network.App.PreciseBankKeeper.SpendableCoin(suite.network.GetContext(), tt.giveAddr, tt.giveDenom) - suite.Require().Equal(tt.wantAmount.Int64(), spendableCoin.Amount.Int64()) + spendableCoin := s.network.App.GetPreciseBankKeeper().SpendableCoin(s.network.GetContext(), tt.giveAddr, tt.giveDenom) + s.Require().Equal(tt.wantAmount.Int64(), spendableCoin.Amount.Int64()) }) } } diff --git a/tests/integration/x/vm/ante_test_suite.go b/tests/integration/x/vm/ante_test_suite.go new file mode 100644 index 000000000..a0de9883b --- /dev/null +++ b/tests/integration/x/vm/ante_test_suite.go @@ -0,0 +1,21 @@ +package vm + +import ( + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/testutil/integration/evm/network" +) + +type EvmAnteTestSuite struct { + suite.Suite + + create network.CreateEvmApp + options []network.ConfigOption +} + +func NewEvmAnteTestSuite(create network.CreateEvmApp, opts ...network.ConfigOption) *EvmAnteTestSuite { + return &EvmAnteTestSuite{ + create: create, + options: opts, + } +} diff --git a/x/vm/keeper/params_benchmark_test.go b/tests/integration/x/vm/benchmark_params.go similarity index 70% rename from x/vm/keeper/params_benchmark_test.go rename to tests/integration/x/vm/benchmark_params.go index 017169114..23617a146 100644 --- a/x/vm/keeper/params_benchmark_test.go +++ b/tests/integration/x/vm/benchmark_params.go @@ -1,4 +1,4 @@ -package keeper_test +package vm import ( "testing" @@ -14,7 +14,7 @@ func BenchmarkSetParams(b *testing.B) { b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { - _ = suite.network.App.EVMKeeper.SetParams(suite.network.GetContext(), params) + _ = suite.Network.App.GetEVMKeeper().SetParams(suite.Network.GetContext(), params) } } @@ -25,6 +25,6 @@ func BenchmarkGetParams(b *testing.B) { b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { - _ = suite.network.App.EVMKeeper.GetParams(suite.network.GetContext()) + _ = suite.Network.App.GetEVMKeeper().GetParams(suite.Network.GetContext()) } } diff --git a/x/vm/keeper/statedb_benchmark_test.go b/tests/integration/x/vm/benchmark_statedb.go similarity index 89% rename from x/vm/keeper/statedb_benchmark_test.go rename to tests/integration/x/vm/benchmark_statedb.go index 4c5bf6cfc..9006a6439 100644 --- a/x/vm/keeper/statedb_benchmark_test.go +++ b/tests/integration/x/vm/benchmark_statedb.go @@ -1,4 +1,4 @@ -package keeper_test +package vm import ( "testing" @@ -38,7 +38,7 @@ func BenchmarkCreateAccountExisting(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { - vmdb.CreateAccount(suite.keyring.GetAddr(0)) + vmdb.CreateAccount(suite.Keyring.GetAddr(0)) } } @@ -53,7 +53,7 @@ func BenchmarkAddBalance(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { - vmdb.AddBalance(suite.keyring.GetAddr(0), amt, tracing.BalanceChangeUnspecified) + vmdb.AddBalance(suite.Keyring.GetAddr(0), amt, tracing.BalanceChangeUnspecified) } } @@ -68,7 +68,7 @@ func BenchmarkSetCode(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { - vmdb.SetCode(suite.keyring.GetAddr(0), hash) + vmdb.SetCode(suite.Keyring.GetAddr(0), hash) } } @@ -83,7 +83,7 @@ func BenchmarkSetState(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { - vmdb.SetCode(suite.keyring.GetAddr(0), hash) + vmdb.SetCode(suite.Keyring.GetAddr(0), hash) } } @@ -101,7 +101,7 @@ func BenchmarkAddLog(b *testing.B) { for i := 0; i < b.N; i++ { vmdb.AddLog(ðtypes.Log{ - Address: suite.keyring.GetAddr(0), + Address: suite.Keyring.GetAddr(0), Topics: []common.Hash{topic}, Data: []byte("data"), BlockNumber: 1, @@ -145,7 +145,7 @@ func BenchmarkSubBalance(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { - vmdb.SubBalance(suite.keyring.GetAddr(0), amt, tracing.BalanceChangeUnspecified) + vmdb.SubBalance(suite.Keyring.GetAddr(0), amt, tracing.BalanceChangeUnspecified) } } @@ -158,7 +158,7 @@ func BenchmarkSetNonce(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { - vmdb.SetNonce(suite.keyring.GetAddr(0), 1, tracing.NonceChangeUnspecified) + vmdb.SetNonce(suite.Keyring.GetAddr(0), 1, tracing.NonceChangeUnspecified) } } diff --git a/tests/integration/x/vm/genesis_test_suite.go b/tests/integration/x/vm/genesis_test_suite.go new file mode 100644 index 000000000..31bb774be --- /dev/null +++ b/tests/integration/x/vm/genesis_test_suite.go @@ -0,0 +1,44 @@ +package vm + +import ( + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + testkeyring "github.com/cosmos/evm/testutil/keyring" +) + +// GenesisTestSuite defines a testify suite for genesis integration tests. +type GenesisTestSuite struct { + suite.Suite + + create network.CreateEvmApp + options []network.ConfigOption + keyring testkeyring.Keyring + network *network.UnitTestNetwork + handler grpc.Handler + factory factory.TxFactory +} + +func NewGenesisTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *GenesisTestSuite { + return &GenesisTestSuite{ + create: create, + options: options, + } +} + +// SetupTest resets state before each test method +func (s *GenesisTestSuite) SetupTest() { + // initialize a fresh network, keyring, handler, and factory + s.keyring = testkeyring.New(1) + if s.options == nil { + s.options = []network.ConfigOption{} + } + options := append(s.options, + network.WithPreFundedAccounts(s.keyring.GetAllAccAddrs()...), + ) + s.network = network.NewUnitTestNetwork(s.create, options...) + s.handler = grpc.NewIntegrationHandler(s.network) + s.factory = factory.New(s.network, s.handler) +} diff --git a/x/vm/keeper/setup_test.go b/tests/integration/x/vm/keeper_test_suite.go similarity index 67% rename from x/vm/keeper/setup_test.go rename to tests/integration/x/vm/keeper_test_suite.go index 451bb802b..ade6f3112 100644 --- a/x/vm/keeper/setup_test.go +++ b/tests/integration/x/vm/keeper_test_suite.go @@ -1,16 +1,15 @@ -package keeper_test +package vm import ( "math" - "testing" "github.com/ethereum/go-ethereum/params" "github.com/stretchr/testify/suite" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/keyring" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -24,39 +23,33 @@ import ( type KeeperTestSuite struct { suite.Suite - network *network.UnitTestNetwork - handler grpc.Handler - keyring keyring.Keyring - factory factory.TxFactory + Network *network.UnitTestNetwork + Create network.CreateEvmApp + Options []network.ConfigOption + Handler grpc.Handler + Keyring keyring.Keyring + Factory factory.TxFactory - enableFeemarket bool - enableLondonHF bool - mintFeeCollector bool + EnableFeemarket bool + EnableLondonHF bool + MintFeeCollector bool } -type UnitTestSuite struct { - suite.Suite -} - -var s *KeeperTestSuite - -func TestKeeperTestSuite(t *testing.T) { - s = new(KeeperTestSuite) - s.enableFeemarket = false - s.enableLondonHF = true - suite.Run(t, s) - - // Run UnitTestSuite - unitTestSuite := new(UnitTestSuite) - suite.Run(t, unitTestSuite) +func NewKeeperTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *KeeperTestSuite { + return &KeeperTestSuite{ + Create: create, + Options: options, + EnableFeemarket: false, + EnableLondonHF: true, + } } -func (suite *KeeperTestSuite) SetupTest() { +func (s *KeeperTestSuite) SetupTest() { keys := keyring.New(2) // Set custom balance based on test params customGenesis := network.CustomGenesisState{} feemarketGenesis := feemarkettypes.DefaultGenesisState() - if s.enableFeemarket { + if s.EnableFeemarket { feemarketGenesis.Params.EnableHeight = 1 feemarketGenesis.Params.NoBaseFee = false } else { @@ -64,7 +57,7 @@ func (suite *KeeperTestSuite) SetupTest() { } customGenesis[feemarkettypes.ModuleName] = feemarketGenesis - if s.mintFeeCollector { + if s.MintFeeCollector { // mint some coin to fee collector coins := sdk.NewCoins(sdk.NewCoin(evmtypes.GetEVMCoinDenom(), sdkmath.NewInt(int64(params.TxGas)-1))) balances := []banktypes.Balance{ @@ -78,20 +71,24 @@ func (suite *KeeperTestSuite) SetupTest() { customGenesis[banktypes.ModuleName] = bankGenesis } - nw := network.NewUnitTestNetwork( + if s.Options == nil { + s.Options = []network.ConfigOption{} + } + options := append(s.Options, network.WithPreFundedAccounts(keys.GetAllAccAddrs()...), network.WithCustomGenesis(customGenesis), ) + nw := network.NewUnitTestNetwork(s.Create, options...) gh := grpc.NewIntegrationHandler(nw) tf := factory.New(nw, gh) - s.network = nw - s.factory = tf - s.handler = gh - s.keyring = keys + s.Network = nw + s.Factory = tf + s.Handler = gh + s.Keyring = keys - chainConfig := evmtypes.DefaultChainConfig(suite.network.GetEIP155ChainID().Uint64()) - if !s.enableLondonHF { + chainConfig := evmtypes.DefaultChainConfig(s.Network.GetEIP155ChainID().Uint64()) + if !s.EnableLondonHF { maxInt := sdkmath.NewInt(math.MaxInt64) chainConfig.LondonBlock = &maxInt chainConfig.ArrowGlacierBlock = &maxInt @@ -117,5 +114,5 @@ func (suite *KeeperTestSuite) SetupTest() { Decimals: decimals, }). Configure() - suite.Require().NoError(err) + s.Require().NoError(err) } diff --git a/tests/integration/x/vm/nested_evm_extension_test_suite.go b/tests/integration/x/vm/nested_evm_extension_test_suite.go new file mode 100644 index 000000000..771dbcc1d --- /dev/null +++ b/tests/integration/x/vm/nested_evm_extension_test_suite.go @@ -0,0 +1,158 @@ +package vm + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/contracts" + testcontracts "github.com/cosmos/evm/precompiles/testutil/contracts" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + testkeyring "github.com/cosmos/evm/testutil/keyring" + testutiltypes "github.com/cosmos/evm/testutil/types" + evmtypes "github.com/cosmos/evm/x/vm/types" + + "cosmossdk.io/math" +) + +// NestedEVMExtensionCallSuite covers the flash loan exploit scenarios. +type NestedEVMExtensionCallSuite struct { + suite.Suite + + create network.CreateEvmApp + options []network.ConfigOption + + keyring testkeyring.Keyring + flashLoanContract evmtypes.CompiledContract + mintAmount *big.Int + delegateAmount *big.Int + + network *network.UnitTestNetwork + handler grpc.Handler + factory factory.TxFactory + deployer testkeyring.Key + erc20Addr common.Address + flashLoanAddr common.Address + validatorToDelegateTo string + delegatedAmountPre math.Int +} + +func NewNestedEVMExtensionCallSuite(create network.CreateEvmApp, options ...network.ConfigOption) *NestedEVMExtensionCallSuite { + return &NestedEVMExtensionCallSuite{ + create: create, + options: options, + } +} + +// SetupSuite loads static data before any test +func (s *NestedEVMExtensionCallSuite) SetupSuite() { + // load keyring with two accounts + s.keyring = testkeyring.New(2) + + // Load the flash loan contract definition + var err error + s.flashLoanContract, err = testcontracts.LoadFlashLoanContract() + s.Require().NoError(err, "failed to load flash loan contract") + + // Set amounts + s.mintAmount = big.NewInt(0).Mul(big.NewInt(2), big.NewInt(1e18)) + s.delegateAmount = big.NewInt(1e18) +} + +// SetupTest resets blockchain state before each test case or entry +func (s *NestedEVMExtensionCallSuite) SetupTest() { + if s.options == nil { + s.options = []network.ConfigOption{} + } + options := append(s.options, + network.WithPreFundedAccounts(s.keyring.GetAllAccAddrs()...), + ) + // fresh network, handler, factory + s.network = network.NewUnitTestNetwork(s.create, options...) + s.handler = grpc.NewIntegrationHandler(s.network) + s.factory = factory.New(s.network, s.handler) + + // deployer is first key + s.deployer = s.keyring.GetKey(0) + + // find a validator to delegate to + valsRes, err := s.handler.GetBondedValidators() + s.Require().NoError(err, "failed to get bonded validators") + s.validatorToDelegateTo = valsRes.Validators[0].OperatorAddress + + // initial delegation is zero + s.delegatedAmountPre = math.NewInt(0) + + // Deploy an ERC20 token + var errDeploy error + s.erc20Addr, errDeploy = s.factory.DeployContract( + s.deployer.Priv, + evmtypes.EvmTxArgs{}, + testutiltypes.ContractDeploymentData{ + Contract: contracts.ERC20MinterBurnerDecimalsContract, + ConstructorArgs: []interface{}{"TestToken", "TT", uint8(18)}, + }, + ) + s.Require().NoError(errDeploy, "failed to deploy ERC20 contract") + s.Require().NoError(s.network.NextBlock(), "failed to commit block") + + // Mint tokens to deployer + _, err = s.factory.ExecuteContractCall( + s.deployer.Priv, + evmtypes.EvmTxArgs{To: &s.erc20Addr}, + testutiltypes.CallArgs{ + ContractABI: contracts.ERC20MinterBurnerDecimalsContract.ABI, + MethodName: "mint", + Args: []interface{}{s.deployer.Addr, s.mintAmount}, + }, + ) + s.Require().NoError(err, "failed to mint tokens") + s.Require().NoError(s.network.NextBlock(), "failed to commit block") + + // Deploy the flash loan contract + s.flashLoanAddr, err = s.factory.DeployContract( + s.deployer.Priv, + evmtypes.EvmTxArgs{}, + testutiltypes.ContractDeploymentData{Contract: s.flashLoanContract}, + ) + s.Require().NoError(err, "failed to deploy flash loan contract") + // commit + s.Require().NoError(s.network.NextBlock(), "failed to commit block") + + // Approve flash loan contract to spend tokens + _, err = s.factory.ExecuteContractCall( + s.deployer.Priv, + evmtypes.EvmTxArgs{To: &s.erc20Addr}, + testutiltypes.CallArgs{ + ContractABI: contracts.ERC20MinterBurnerDecimalsContract.ABI, + MethodName: "approve", + Args: []interface{}{s.flashLoanAddr, s.mintAmount}, + }, + ) + s.Require().NoError(err, "failed to approve flash loan contract") + s.Require().NoError(s.network.NextBlock(), "failed to commit block") + + // Verify allowance + res, err := s.factory.ExecuteContractCall( + s.deployer.Priv, + evmtypes.EvmTxArgs{To: &s.erc20Addr}, + testutiltypes.CallArgs{ + ContractABI: contracts.ERC20MinterBurnerDecimalsContract.ABI, + MethodName: "allowance", + Args: []interface{}{s.deployer.Addr, s.flashLoanAddr}, + }, + ) + s.Require().NoError(err, "failed to get allowance") + s.Require().NoError(s.network.NextBlock(), "failed to commit block") + + ethRes, err := evmtypes.DecodeTxResponse(res.Data) + s.Require().NoError(err, "failed to decode allowance response") + unpacked, err := contracts.ERC20MinterBurnerDecimalsContract.ABI.Unpack("allowance", ethRes.Ret) + s.Require().NoError(err, "failed to unpack allowance") + allowance, ok := unpacked[0].(*big.Int) + s.Require().True(ok, "allowance is not *big.Int") + s.Require().Equal(s.mintAmount.String(), allowance.String(), "allowance mismatch") +} diff --git a/x/vm/keeper/state_transition_benchmark_test.go b/tests/integration/x/vm/state_transition_benchmark.go similarity index 76% rename from x/vm/keeper/state_transition_benchmark_test.go rename to tests/integration/x/vm/state_transition_benchmark.go index f608381d6..1a5503420 100644 --- a/x/vm/keeper/state_transition_benchmark_test.go +++ b/tests/integration/x/vm/state_transition_benchmark.go @@ -1,4 +1,4 @@ -package keeper_test +package vm import ( "errors" @@ -162,7 +162,7 @@ func newNativeMessage( } func BenchmarkApplyTransaction(b *testing.B) { //nolint:dupl - suite := KeeperTestSuite{enableLondonHF: true} + suite := KeeperTestSuite{EnableLondonHF: true} suite.SetupTest() ethSigner := ethtypes.LatestSignerForChainID(evmtypes.GetEthChainConfig().ChainID) @@ -171,10 +171,10 @@ func BenchmarkApplyTransaction(b *testing.B) { //nolint:dupl b.ReportAllocs() for i := 0; i < b.N; i++ { b.StopTimer() - addr := suite.keyring.GetAddr(0) - krSigner := utiltx.NewSigner(suite.keyring.GetPrivKey(0)) + addr := suite.Keyring.GetAddr(0) + krSigner := utiltx.NewSigner(suite.Keyring.GetPrivKey(0)) tx, err := newSignedEthTx(templateAccessListTx, - suite.network.App.EVMKeeper.GetNonce(suite.network.GetContext(), addr), + suite.Network.App.GetEVMKeeper().GetNonce(suite.Network.GetContext(), addr), sdk.AccAddress(addr.Bytes()), krSigner, ethSigner, @@ -182,7 +182,7 @@ func BenchmarkApplyTransaction(b *testing.B) { //nolint:dupl require.NoError(b, err) b.StartTimer() - resp, err := suite.network.App.EVMKeeper.ApplyTransaction(suite.network.GetContext(), tx) + resp, err := suite.Network.App.GetEVMKeeper().ApplyTransaction(suite.Network.GetContext(), tx) b.StopTimer() require.NoError(b, err) @@ -191,7 +191,7 @@ func BenchmarkApplyTransaction(b *testing.B) { //nolint:dupl } func BenchmarkApplyTransactionWithLegacyTx(b *testing.B) { //nolint:dupl - suite := KeeperTestSuite{enableLondonHF: true} + suite := KeeperTestSuite{EnableLondonHF: true} suite.SetupTest() ethSigner := ethtypes.LatestSignerForChainID(evmtypes.GetEthChainConfig().ChainID) @@ -200,10 +200,10 @@ func BenchmarkApplyTransactionWithLegacyTx(b *testing.B) { //nolint:dupl b.ReportAllocs() for i := 0; i < b.N; i++ { b.StopTimer() - addr := suite.keyring.GetAddr(0) - krSigner := utiltx.NewSigner(suite.keyring.GetPrivKey(0)) + addr := suite.Keyring.GetAddr(0) + krSigner := utiltx.NewSigner(suite.Keyring.GetPrivKey(0)) tx, err := newSignedEthTx(templateLegacyTx, - suite.network.App.EVMKeeper.GetNonce(suite.network.GetContext(), addr), + suite.Network.App.GetEVMKeeper().GetNonce(suite.Network.GetContext(), addr), sdk.AccAddress(addr.Bytes()), krSigner, ethSigner, @@ -211,7 +211,7 @@ func BenchmarkApplyTransactionWithLegacyTx(b *testing.B) { //nolint:dupl require.NoError(b, err) b.StartTimer() - resp, err := suite.network.App.EVMKeeper.ApplyTransaction(suite.network.GetContext(), tx) + resp, err := suite.Network.App.GetEVMKeeper().ApplyTransaction(suite.Network.GetContext(), tx) b.StopTimer() require.NoError(b, err) @@ -220,7 +220,7 @@ func BenchmarkApplyTransactionWithLegacyTx(b *testing.B) { //nolint:dupl } func BenchmarkApplyTransactionWithDynamicFeeTx(b *testing.B) { - suite := KeeperTestSuite{enableFeemarket: true, enableLondonHF: true} + suite := KeeperTestSuite{EnableFeemarket: true, EnableLondonHF: true} suite.SetupTest() ethSigner := ethtypes.LatestSignerForChainID(evmtypes.GetEthChainConfig().ChainID) @@ -229,10 +229,10 @@ func BenchmarkApplyTransactionWithDynamicFeeTx(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { b.StopTimer() - addr := suite.keyring.GetAddr(0) - krSigner := utiltx.NewSigner(suite.keyring.GetPrivKey(0)) + addr := suite.Keyring.GetAddr(0) + krSigner := utiltx.NewSigner(suite.Keyring.GetPrivKey(0)) tx, err := newSignedEthTx(templateDynamicFeeTx, - suite.network.App.EVMKeeper.GetNonce(suite.network.GetContext(), addr), + suite.Network.App.GetEVMKeeper().GetNonce(suite.Network.GetContext(), addr), sdk.AccAddress(addr.Bytes()), krSigner, ethSigner, @@ -240,7 +240,7 @@ func BenchmarkApplyTransactionWithDynamicFeeTx(b *testing.B) { require.NoError(b, err) b.StartTimer() - resp, err := suite.network.App.EVMKeeper.ApplyTransaction(suite.network.GetContext(), tx) + resp, err := suite.Network.App.GetEVMKeeper().ApplyTransaction(suite.Network.GetContext(), tx) b.StopTimer() require.NoError(b, err) @@ -249,7 +249,7 @@ func BenchmarkApplyTransactionWithDynamicFeeTx(b *testing.B) { } func BenchmarkApplyMessage(b *testing.B) { - suite := KeeperTestSuite{enableLondonHF: true} + suite := KeeperTestSuite{EnableLondonHF: true} suite.SetupTest() ethCfg := evmtypes.GetEthChainConfig() @@ -259,11 +259,11 @@ func BenchmarkApplyMessage(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { b.StopTimer() - addr := suite.keyring.GetAddr(0) - krSigner := utiltx.NewSigner(suite.keyring.GetPrivKey(0)) + addr := suite.Keyring.GetAddr(0) + krSigner := utiltx.NewSigner(suite.Keyring.GetPrivKey(0)) m, err := newNativeMessage( - suite.network.App.EVMKeeper.GetNonce(suite.network.GetContext(), addr), - suite.network.GetContext().BlockHeight(), + suite.Network.App.GetEVMKeeper().GetNonce(suite.Network.GetContext(), addr), + suite.Network.GetContext().BlockHeight(), addr, ethCfg, krSigner, @@ -275,7 +275,7 @@ func BenchmarkApplyMessage(b *testing.B) { require.NoError(b, err) b.StartTimer() - resp, err := suite.network.App.EVMKeeper.ApplyMessage(suite.network.GetContext(), *m, nil, true) + resp, err := suite.Network.App.GetEVMKeeper().ApplyMessage(suite.Network.GetContext(), *m, nil, true) b.StopTimer() require.NoError(b, err) @@ -284,7 +284,7 @@ func BenchmarkApplyMessage(b *testing.B) { } func BenchmarkApplyMessageWithLegacyTx(b *testing.B) { - suite := KeeperTestSuite{enableLondonHF: true} + suite := KeeperTestSuite{EnableLondonHF: true} suite.SetupTest() ethCfg := evmtypes.GetEthChainConfig() @@ -294,11 +294,11 @@ func BenchmarkApplyMessageWithLegacyTx(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { b.StopTimer() - addr := suite.keyring.GetAddr(0) - krSigner := utiltx.NewSigner(suite.keyring.GetPrivKey(0)) + addr := suite.Keyring.GetAddr(0) + krSigner := utiltx.NewSigner(suite.Keyring.GetPrivKey(0)) m, err := newNativeMessage( - suite.network.App.EVMKeeper.GetNonce(suite.network.GetContext(), addr), - suite.network.GetContext().BlockHeight(), + suite.Network.App.GetEVMKeeper().GetNonce(suite.Network.GetContext(), addr), + suite.Network.GetContext().BlockHeight(), addr, ethCfg, krSigner, @@ -310,7 +310,7 @@ func BenchmarkApplyMessageWithLegacyTx(b *testing.B) { require.NoError(b, err) b.StartTimer() - resp, err := suite.network.App.EVMKeeper.ApplyMessage(suite.network.GetContext(), *m, nil, true) + resp, err := suite.Network.App.GetEVMKeeper().ApplyMessage(suite.Network.GetContext(), *m, nil, true) b.StopTimer() require.NoError(b, err) @@ -319,7 +319,7 @@ func BenchmarkApplyMessageWithLegacyTx(b *testing.B) { } func BenchmarkApplyMessageWithDynamicFeeTx(b *testing.B) { - suite := KeeperTestSuite{enableFeemarket: true, enableLondonHF: true} + suite := KeeperTestSuite{EnableFeemarket: true, EnableLondonHF: true} suite.SetupTest() ethCfg := evmtypes.GetEthChainConfig() @@ -329,11 +329,11 @@ func BenchmarkApplyMessageWithDynamicFeeTx(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { b.StopTimer() - addr := suite.keyring.GetAddr(0) - krSigner := utiltx.NewSigner(suite.keyring.GetPrivKey(0)) + addr := suite.Keyring.GetAddr(0) + krSigner := utiltx.NewSigner(suite.Keyring.GetPrivKey(0)) m, err := newNativeMessage( - suite.network.App.EVMKeeper.GetNonce(suite.network.GetContext(), addr), - suite.network.GetContext().BlockHeight(), + suite.Network.App.GetEVMKeeper().GetNonce(suite.Network.GetContext(), addr), + suite.Network.GetContext().BlockHeight(), addr, ethCfg, krSigner, @@ -345,7 +345,7 @@ func BenchmarkApplyMessageWithDynamicFeeTx(b *testing.B) { require.NoError(b, err) b.StartTimer() - resp, err := suite.network.App.EVMKeeper.ApplyMessage(suite.network.GetContext(), *m, nil, true) + resp, err := suite.Network.App.GetEVMKeeper().ApplyMessage(suite.Network.GetContext(), *m, nil, true) b.StopTimer() require.NoError(b, err) diff --git a/tests/integration/x/vm/test_abci.go b/tests/integration/x/vm/test_abci.go new file mode 100644 index 000000000..84f11b100 --- /dev/null +++ b/tests/integration/x/vm/test_abci.go @@ -0,0 +1,26 @@ +package vm + +import ( + "github.com/cosmos/evm/testutil/integration/evm/network" + testkeyring "github.com/cosmos/evm/testutil/keyring" + evmtypes "github.com/cosmos/evm/x/vm/types" +) + +func (s *KeeperTestSuite) TestEndBlock() { + keyring := testkeyring.New(2) + unitNetwork := network.NewUnitTestNetwork( + s.Create, + network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), + ) + ctx := unitNetwork.GetContext() + preEventManager := ctx.EventManager() + s.Require().Equal(0, len(preEventManager.Events())) + + err := unitNetwork.App.GetEVMKeeper().EndBlock(ctx) + s.Require().NoError(err) + + postEventManager := unitNetwork.GetContext().EventManager() + // should emit 1 EventTypeBlockBloom event on EndBlock + s.Require().Equal(1, len(postEventManager.Events())) + s.Require().Equal(evmtypes.EventTypeBlockBloom, postEventManager.Events()[0].Type) +} diff --git a/x/vm/keeper/benchmark_test.go b/tests/integration/x/vm/test_benchmark.go similarity index 72% rename from x/vm/keeper/benchmark_test.go rename to tests/integration/x/vm/test_benchmark.go index fde15c8e7..a268af7e6 100644 --- a/x/vm/keeper/benchmark_test.go +++ b/tests/integration/x/vm/test_benchmark.go @@ -1,4 +1,4 @@ -package keeper_test +package vm import ( "math/big" @@ -25,13 +25,13 @@ func SetupContract(b *testing.B) (*KeeperTestSuite, common.Address) { suite.SetupTest() amt := sdk.Coins{sdk.NewInt64Coin(testconstants.ExampleAttoDenom, 1000000000000000000)} - err := suite.network.App.BankKeeper.MintCoins(suite.network.GetContext(), types.ModuleName, amt) + err := suite.Network.App.GetBankKeeper().MintCoins(suite.Network.GetContext(), types.ModuleName, amt) require.NoError(b, err) - err = suite.network.App.BankKeeper.SendCoinsFromModuleToAccount(suite.network.GetContext(), types.ModuleName, suite.keyring.GetAddr(0).Bytes(), amt) + err = suite.Network.App.GetBankKeeper().SendCoinsFromModuleToAccount(suite.Network.GetContext(), types.ModuleName, suite.Keyring.GetAddr(0).Bytes(), amt) require.NoError(b, err) - contractAddr := suite.DeployTestContract(b, suite.network.GetContext(), suite.keyring.GetAddr(0), sdkmath.NewIntWithDecimal(1000, 18).BigInt()) - err = suite.network.NextBlock() + contractAddr := suite.DeployTestContract(b, suite.Network.GetContext(), suite.Keyring.GetAddr(0), sdkmath.NewIntWithDecimal(1000, 18).BigInt()) + err = suite.Network.NextBlock() require.NoError(b, err) return &suite, contractAddr @@ -43,13 +43,13 @@ func SetupTestMessageCall(b *testing.B) (*KeeperTestSuite, common.Address) { suite.SetupTest() amt := sdk.Coins{sdk.NewInt64Coin(testconstants.ExampleAttoDenom, 1000000000000000000)} - err := suite.network.App.BankKeeper.MintCoins(suite.network.GetContext(), types.ModuleName, amt) + err := suite.Network.App.GetBankKeeper().MintCoins(suite.Network.GetContext(), types.ModuleName, amt) require.NoError(b, err) - err = suite.network.App.BankKeeper.SendCoinsFromModuleToAccount(suite.network.GetContext(), types.ModuleName, suite.keyring.GetAddr(0).Bytes(), amt) + err = suite.Network.App.GetBankKeeper().SendCoinsFromModuleToAccount(suite.Network.GetContext(), types.ModuleName, suite.Keyring.GetAddr(0).Bytes(), amt) require.NoError(b, err) contractAddr := suite.DeployTestMessageCall(b) - err = suite.network.NextBlock() + err = suite.Network.NextBlock() require.NoError(b, err) return &suite, contractAddr @@ -61,26 +61,26 @@ func DoBenchmark(b *testing.B, txBuilder TxBuilder) { b.Helper() suite, contractAddr := SetupContract(b) - krSigner := utiltx.NewSigner(suite.keyring.GetPrivKey(0)) + krSigner := utiltx.NewSigner(suite.Keyring.GetPrivKey(0)) msg := txBuilder(suite, contractAddr) - msg.From = suite.keyring.GetAddr(0).Hex() + msg.From = suite.Keyring.GetAddr(0).Hex() err := msg.Sign(ethtypes.LatestSignerForChainID(types.GetEthChainConfig().ChainID), krSigner) require.NoError(b, err) b.ResetTimer() b.StartTimer() for i := 0; i < b.N; i++ { - ctx, _ := suite.network.GetContext().CacheContext() + ctx, _ := suite.Network.GetContext().CacheContext() // deduct fee first txData, err := types.UnpackTxData(msg.Data) require.NoError(b, err) fees := sdk.Coins{sdk.NewCoin(suite.EvmDenom(), sdkmath.NewIntFromBigInt(txData.Fee()))} - err = authante.DeductFees(suite.network.App.BankKeeper, suite.network.GetContext(), suite.network.App.AccountKeeper.GetAccount(ctx, msg.GetFrom()), fees) + err = authante.DeductFees(suite.Network.App.GetBankKeeper(), suite.Network.GetContext(), suite.Network.App.GetAccountKeeper().GetAccount(ctx, msg.GetFrom()), fees) require.NoError(b, err) - rsp, err := suite.network.App.EVMKeeper.EthereumTx(ctx, msg) + rsp, err := suite.Network.App.GetEVMKeeper().EthereumTx(ctx, msg) require.NoError(b, err) require.False(b, rsp.Failed()) } @@ -93,7 +93,7 @@ func BenchmarkTokenTransfer(b *testing.B) { DoBenchmark(b, func(suite *KeeperTestSuite, contract common.Address) *types.MsgEthereumTx { input, err := erc20Contract.ABI.Pack("transfer", common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), big.NewInt(1000)) require.NoError(b, err) - nonce := suite.network.App.EVMKeeper.GetNonce(suite.network.GetContext(), suite.keyring.GetAddr(0)) + nonce := suite.Network.App.GetEVMKeeper().GetNonce(suite.Network.GetContext(), suite.Keyring.GetAddr(0)) ethTxParams := &types.EvmTxArgs{ ChainID: types.GetEthChainConfig().ChainID, Nonce: nonce, @@ -114,7 +114,7 @@ func BenchmarkEmitLogs(b *testing.B) { DoBenchmark(b, func(suite *KeeperTestSuite, contract common.Address) *types.MsgEthereumTx { input, err := erc20Contract.ABI.Pack("benchmarkLogs", big.NewInt(1000)) require.NoError(b, err) - nonce := suite.network.App.EVMKeeper.GetNonce(suite.network.GetContext(), suite.keyring.GetAddr(0)) + nonce := suite.Network.App.GetEVMKeeper().GetNonce(suite.Network.GetContext(), suite.Keyring.GetAddr(0)) ethTxParams := &types.EvmTxArgs{ ChainID: types.GetEthChainConfig().ChainID, Nonce: nonce, @@ -133,9 +133,9 @@ func BenchmarkTokenTransferFrom(b *testing.B) { require.NoError(b, err) DoBenchmark(b, func(suite *KeeperTestSuite, contract common.Address) *types.MsgEthereumTx { - input, err := erc20Contract.ABI.Pack("transferFrom", suite.keyring.GetAddr(0), common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), big.NewInt(0)) + input, err := erc20Contract.ABI.Pack("transferFrom", suite.Keyring.GetAddr(0), common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), big.NewInt(0)) require.NoError(b, err) - nonce := suite.network.App.EVMKeeper.GetNonce(suite.network.GetContext(), suite.keyring.GetAddr(0)) + nonce := suite.Network.App.GetEVMKeeper().GetNonce(suite.Network.GetContext(), suite.Keyring.GetAddr(0)) ethTxParams := &types.EvmTxArgs{ ChainID: types.GetEthChainConfig().ChainID, Nonce: nonce, @@ -156,7 +156,7 @@ func BenchmarkTokenMint(b *testing.B) { DoBenchmark(b, func(suite *KeeperTestSuite, contract common.Address) *types.MsgEthereumTx { input, err := erc20Contract.ABI.Pack("mint", common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), big.NewInt(1000)) require.NoError(b, err) - nonce := suite.network.App.EVMKeeper.GetNonce(suite.network.GetContext(), suite.keyring.GetAddr(0)) + nonce := suite.Network.App.GetEVMKeeper().GetNonce(suite.Network.GetContext(), suite.Keyring.GetAddr(0)) ethTxParams := &types.EvmTxArgs{ ChainID: types.GetEthChainConfig().ChainID, Nonce: nonce, @@ -178,7 +178,7 @@ func BenchmarkMessageCall(b *testing.B) { input, err := messageCallContract.ABI.Pack("benchmarkMessageCall", big.NewInt(10000)) require.NoError(b, err) - nonce := suite.network.App.EVMKeeper.GetNonce(suite.network.GetContext(), suite.keyring.GetAddr(0)) + nonce := suite.Network.App.GetEVMKeeper().GetNonce(suite.Network.GetContext(), suite.Keyring.GetAddr(0)) ethCfg := types.GetEthChainConfig() ethTxParams := &types.EvmTxArgs{ ChainID: ethCfg.ChainID, @@ -191,25 +191,25 @@ func BenchmarkMessageCall(b *testing.B) { } msg := types.NewTx(ethTxParams) - msg.From = suite.keyring.GetAddr(0).Hex() - krSigner := utiltx.NewSigner(suite.keyring.GetPrivKey(0)) + msg.From = suite.Keyring.GetAddr(0).Hex() + krSigner := utiltx.NewSigner(suite.Keyring.GetPrivKey(0)) err = msg.Sign(ethtypes.LatestSignerForChainID(ethCfg.ChainID), krSigner) require.NoError(b, err) b.ResetTimer() b.StartTimer() for i := 0; i < b.N; i++ { - ctx, _ := suite.network.GetContext().CacheContext() + ctx, _ := suite.Network.GetContext().CacheContext() // deduct fee first txData, err := types.UnpackTxData(msg.Data) require.NoError(b, err) fees := sdk.Coins{sdk.NewCoin(suite.EvmDenom(), sdkmath.NewIntFromBigInt(txData.Fee()))} - err = authante.DeductFees(suite.network.App.BankKeeper, suite.network.GetContext(), suite.network.App.AccountKeeper.GetAccount(ctx, msg.GetFrom()), fees) + err = authante.DeductFees(suite.Network.App.GetBankKeeper(), suite.Network.GetContext(), suite.Network.App.GetAccountKeeper().GetAccount(ctx, msg.GetFrom()), fees) require.NoError(b, err) - rsp, err := suite.network.App.EVMKeeper.EthereumTx(ctx, msg) + rsp, err := suite.Network.App.GetEVMKeeper().EthereumTx(ctx, msg) require.NoError(b, err) require.False(b, rsp.Failed()) } diff --git a/x/vm/keeper/call_evm_test.go b/tests/integration/x/vm/test_call_evm.go similarity index 70% rename from x/vm/keeper/call_evm_test.go rename to tests/integration/x/vm/test_call_evm.go index c33482416..3bf26e417 100644 --- a/x/vm/keeper/call_evm_test.go +++ b/tests/integration/x/vm/test_call_evm.go @@ -1,4 +1,4 @@ -package keeper_test +package vm import ( "fmt" @@ -12,7 +12,7 @@ import ( evmtypes "github.com/cosmos/evm/x/vm/types" ) -func (suite *KeeperTestSuite) TestCallEVM() { +func (s *KeeperTestSuite) TestCallEVM() { wcosmosEVMContract := common.HexToAddress(testconstants.WEVMOSContractMainnet) testCases := []struct { name string @@ -31,21 +31,21 @@ func (suite *KeeperTestSuite) TestCallEVM() { }, } for _, tc := range testCases { - suite.SetupTest() // reset + s.SetupTest() // reset erc20 := contracts.ERC20MinterBurnerDecimalsContract.ABI account := utiltx.GenerateAddress() - res, err := suite.network.App.EVMKeeper.CallEVM(suite.network.GetContext(), erc20, types.ModuleAddress, wcosmosEVMContract, false, tc.method, account) + res, err := s.Network.App.GetEVMKeeper().CallEVM(s.Network.GetContext(), erc20, types.ModuleAddress, wcosmosEVMContract, false, tc.method, account) if tc.expPass { - suite.Require().IsTypef(&evmtypes.MsgEthereumTxResponse{}, res, tc.name) - suite.Require().NoError(err) + s.Require().IsTypef(&evmtypes.MsgEthereumTxResponse{}, res, tc.name) + s.Require().NoError(err) } else { - suite.Require().Error(err) + s.Require().Error(err) } } } -func (suite *KeeperTestSuite) TestCallEVMWithData() { +func (s *KeeperTestSuite) TestCallEVMWithData() { erc20 := contracts.ERC20MinterBurnerDecimalsContract.ABI wcosmosEVMContract := common.HexToAddress(testconstants.WEVMOSContractMainnet) testCases := []struct { @@ -111,11 +111,11 @@ func (suite *KeeperTestSuite) TestCallEVMWithData() { "fail deploy", types.ModuleAddress, func() []byte { - params := suite.network.App.EVMKeeper.GetParams(suite.network.GetContext()) + params := s.Network.App.GetEVMKeeper().GetParams(s.Network.GetContext()) params.AccessControl.Create = evmtypes.AccessControlType{ AccessType: evmtypes.AccessTypeRestricted, } - _ = suite.network.App.EVMKeeper.SetParams(suite.network.GetContext(), params) + _ = s.Network.App.GetEVMKeeper().SetParams(s.Network.GetContext(), params) ctorArgs, _ := contracts.ERC20MinterBurnerDecimalsContract.ABI.Pack("", "test", "test", uint8(18)) data := append(contracts.ERC20MinterBurnerDecimalsContract.Bin, ctorArgs...) //nolint:gocritic return data @@ -126,24 +126,24 @@ func (suite *KeeperTestSuite) TestCallEVMWithData() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() // reset + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // reset data := tc.malleate() var res *evmtypes.MsgEthereumTxResponse var err error if tc.deploy { - res, err = suite.network.App.EVMKeeper.CallEVMWithData(suite.network.GetContext(), tc.from, nil, data, true) + res, err = s.Network.App.GetEVMKeeper().CallEVMWithData(s.Network.GetContext(), tc.from, nil, data, true) } else { - res, err = suite.network.App.EVMKeeper.CallEVMWithData(suite.network.GetContext(), tc.from, &wcosmosEVMContract, data, false) + res, err = s.Network.App.GetEVMKeeper().CallEVMWithData(s.Network.GetContext(), tc.from, &wcosmosEVMContract, data, false) } if tc.expPass { - suite.Require().IsTypef(&evmtypes.MsgEthereumTxResponse{}, res, tc.name) - suite.Require().NoError(err) + s.Require().IsTypef(&evmtypes.MsgEthereumTxResponse{}, res, tc.name) + s.Require().NoError(err) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } diff --git a/x/vm/ante/ctx_test.go b/tests/integration/x/vm/test_ctx.go similarity index 75% rename from x/vm/ante/ctx_test.go rename to tests/integration/x/vm/test_ctx.go index c384fe2f2..e84b029b6 100644 --- a/x/vm/ante/ctx_test.go +++ b/tests/integration/x/vm/test_ctx.go @@ -1,14 +1,14 @@ -package ante_test +package vm import ( - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/network" evmante "github.com/cosmos/evm/x/vm/ante" storetypes "cosmossdk.io/store/types" ) func (suite *EvmAnteTestSuite) TestBuildEvmExecutionCtx() { - network := network.New() + network := network.New(suite.create, nil) ctx := evmante.BuildEvmExecutionCtx(network.GetContext()) diff --git a/x/vm/keeper/fees_test.go b/tests/integration/x/vm/test_fees.go similarity index 76% rename from x/vm/keeper/fees_test.go rename to tests/integration/x/vm/test_fees.go index 572a5f242..1cc86e2f9 100644 --- a/x/vm/keeper/fees_test.go +++ b/tests/integration/x/vm/test_fees.go @@ -1,4 +1,4 @@ -package keeper_test +package vm import ( "math/big" @@ -18,7 +18,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -func (suite *KeeperTestSuite) TestCheckSenderBalance() { +func (s *KeeperTestSuite) TestCheckSenderBalance() { hundredInt := sdkmath.NewInt(100) zeroInt := sdkmath.ZeroInt() oneInt := sdkmath.OneInt() @@ -38,11 +38,11 @@ func (suite *KeeperTestSuite) TestCheckSenderBalance() { from string accessList *ethtypes.AccessList expectPass bool - enableFeemarket bool + EnableFeemarket bool }{ { name: "Enough balance", - to: suite.keyring.GetAddr(0).String(), + to: s.Keyring.GetAddr(0).String(), gasLimit: 10, gasPrice: &oneInt, cost: &oneInt, @@ -52,7 +52,7 @@ func (suite *KeeperTestSuite) TestCheckSenderBalance() { }, { name: "Equal balance", - to: suite.keyring.GetAddr(0).String(), + to: s.Keyring.GetAddr(0).String(), gasLimit: 99, gasPrice: &oneInt, cost: &oneInt, @@ -62,7 +62,7 @@ func (suite *KeeperTestSuite) TestCheckSenderBalance() { }, { name: "negative cost", - to: suite.keyring.GetAddr(0).String(), + to: s.Keyring.GetAddr(0).String(), gasLimit: 1, gasPrice: &oneInt, cost: &negInt, @@ -72,7 +72,7 @@ func (suite *KeeperTestSuite) TestCheckSenderBalance() { }, { name: "Higher gas limit, not enough balance", - to: suite.keyring.GetAddr(0).String(), + to: s.Keyring.GetAddr(0).String(), gasLimit: 100, gasPrice: &oneInt, cost: &oneInt, @@ -82,7 +82,7 @@ func (suite *KeeperTestSuite) TestCheckSenderBalance() { }, { name: "Higher gas price, enough balance", - to: suite.keyring.GetAddr(0).String(), + to: s.Keyring.GetAddr(0).String(), gasLimit: 10, gasPrice: &fiveInt, cost: &oneInt, @@ -92,7 +92,7 @@ func (suite *KeeperTestSuite) TestCheckSenderBalance() { }, { name: "Higher gas price, not enough balance", - to: suite.keyring.GetAddr(0).String(), + to: s.Keyring.GetAddr(0).String(), gasLimit: 20, gasPrice: &fiveInt, cost: &oneInt, @@ -102,7 +102,7 @@ func (suite *KeeperTestSuite) TestCheckSenderBalance() { }, { name: "Higher cost, enough balance", - to: suite.keyring.GetAddr(0).String(), + to: s.Keyring.GetAddr(0).String(), gasLimit: 10, gasPrice: &fiveInt, cost: &fiftyInt, @@ -112,7 +112,7 @@ func (suite *KeeperTestSuite) TestCheckSenderBalance() { }, { name: "Higher cost, not enough balance", - to: suite.keyring.GetAddr(0).String(), + to: s.Keyring.GetAddr(0).String(), gasLimit: 10, gasPrice: &fiveInt, cost: &hundredInt, @@ -121,104 +121,104 @@ func (suite *KeeperTestSuite) TestCheckSenderBalance() { expectPass: false, }, { - name: "Enough balance w/ enableFeemarket", - to: suite.keyring.GetAddr(0).String(), + name: "Enough balance w/ EnableFeemarket", + to: s.Keyring.GetAddr(0).String(), gasLimit: 10, gasFeeCap: big.NewInt(1), cost: &oneInt, from: addr.String(), accessList: ðtypes.AccessList{}, expectPass: true, - enableFeemarket: true, + EnableFeemarket: true, }, { - name: "Equal balance w/ enableFeemarket", - to: suite.keyring.GetAddr(0).String(), + name: "Equal balance w/ EnableFeemarket", + to: s.Keyring.GetAddr(0).String(), gasLimit: 99, gasFeeCap: big.NewInt(1), cost: &oneInt, from: addr.String(), accessList: ðtypes.AccessList{}, expectPass: true, - enableFeemarket: true, + EnableFeemarket: true, }, { - name: "negative cost w/ enableFeemarket", - to: suite.keyring.GetAddr(0).String(), + name: "negative cost w/ EnableFeemarket", + to: s.Keyring.GetAddr(0).String(), gasLimit: 1, gasFeeCap: big.NewInt(1), cost: &negInt, from: addr.String(), accessList: ðtypes.AccessList{}, expectPass: false, - enableFeemarket: true, + EnableFeemarket: true, }, { - name: "Higher gas limit, not enough balance w/ enableFeemarket", - to: suite.keyring.GetAddr(0).String(), + name: "Higher gas limit, not enough balance w/ EnableFeemarket", + to: s.Keyring.GetAddr(0).String(), gasLimit: 100, gasFeeCap: big.NewInt(1), cost: &oneInt, from: addr.String(), accessList: ðtypes.AccessList{}, expectPass: false, - enableFeemarket: true, + EnableFeemarket: true, }, { - name: "Higher gas price, enough balance w/ enableFeemarket", - to: suite.keyring.GetAddr(0).String(), + name: "Higher gas price, enough balance w/ EnableFeemarket", + to: s.Keyring.GetAddr(0).String(), gasLimit: 10, gasFeeCap: big.NewInt(5), cost: &oneInt, from: addr.String(), accessList: ðtypes.AccessList{}, expectPass: true, - enableFeemarket: true, + EnableFeemarket: true, }, { - name: "Higher gas price, not enough balance w/ enableFeemarket", - to: suite.keyring.GetAddr(0).String(), + name: "Higher gas price, not enough balance w/ EnableFeemarket", + to: s.Keyring.GetAddr(0).String(), gasLimit: 20, gasFeeCap: big.NewInt(5), cost: &oneInt, from: addr.String(), accessList: ðtypes.AccessList{}, expectPass: false, - enableFeemarket: true, + EnableFeemarket: true, }, { - name: "Higher cost, enough balance w/ enableFeemarket", - to: suite.keyring.GetAddr(0).String(), + name: "Higher cost, enough balance w/ EnableFeemarket", + to: s.Keyring.GetAddr(0).String(), gasLimit: 10, gasFeeCap: big.NewInt(5), cost: &fiftyInt, from: addr.String(), accessList: ðtypes.AccessList{}, expectPass: true, - enableFeemarket: true, + EnableFeemarket: true, }, { - name: "Higher cost, not enough balance w/ enableFeemarket", - to: suite.keyring.GetAddr(0).String(), + name: "Higher cost, not enough balance w/ EnableFeemarket", + to: s.Keyring.GetAddr(0).String(), gasLimit: 10, gasFeeCap: big.NewInt(5), cost: &hundredInt, from: addr.String(), accessList: ðtypes.AccessList{}, expectPass: false, - enableFeemarket: true, + EnableFeemarket: true, }, } - vmdb := suite.StateDB() + vmdb := s.StateDB() vmdb.AddBalance(addr, uint256.MustFromBig(hundredInt.BigInt()), tracing.BalanceChangeUnspecified) balance := vmdb.GetBalance(addr) - suite.Require().Equal(balance.ToBig(), hundredInt.BigInt()) + s.Require().Equal(balance.ToBig(), hundredInt.BigInt()) err := vmdb.Commit() - suite.Require().NoError(err, "Unexpected error while committing to vmdb: %d", err) + s.Require().NoError(err, "Unexpected error while committing to vmdb: %d", err) for i, tc := range testCases { - suite.Run(tc.name, func() { + s.Run(tc.name, func() { to := common.HexToAddress(tc.from) var amount, gasPrice, gasFeeCap, gasTipCap *big.Int @@ -226,7 +226,7 @@ func (suite *KeeperTestSuite) TestCheckSenderBalance() { amount = tc.cost.BigInt() } - if tc.enableFeemarket { + if tc.EnableFeemarket { gasFeeCap = tc.gasFeeCap if tc.gasTipCap == nil { gasTipCap = oneInt.BigInt() @@ -253,16 +253,16 @@ func (suite *KeeperTestSuite) TestCheckSenderBalance() { txData, _ := evmtypes.UnpackTxData(tx.Data) - acct := suite.network.App.EVMKeeper.GetAccountOrEmpty(suite.network.GetContext(), addr) + acct := s.Network.App.GetEVMKeeper().GetAccountOrEmpty(s.Network.GetContext(), addr) err := keeper.CheckSenderBalance( sdkmath.NewIntFromBigInt(acct.Balance.ToBig()), txData, ) if tc.expectPass { - suite.Require().NoError(err, "valid test %d failed", i) + s.Require().NoError(err, "valid test %d failed", i) } else { - suite.Require().Error(err, "invalid test %d passed", i) + s.Require().Error(err, "invalid test %d passed", i) } }) } @@ -274,7 +274,7 @@ func (suite *KeeperTestSuite) TestCheckSenderBalance() { // NOTE: This method combines testing for both functions, because these used to be // in one function and share a lot of the same setup. // In practice, the two tested functions will also be sequentially executed. -func (suite *KeeperTestSuite) TestVerifyFeeAndDeductTxCostsFromUserBalance() { +func (s *KeeperTestSuite) TestVerifyFeeAndDeductTxCostsFromUserBalance() { hundredInt := sdkmath.NewInt(100) zeroInt := sdkmath.ZeroInt() oneInt := sdkmath.NewInt(1) @@ -295,7 +295,7 @@ func (suite *KeeperTestSuite) TestVerifyFeeAndDeductTxCostsFromUserBalance() { accessList *ethtypes.AccessList expectPassVerify bool expectPassDeduct bool - enableFeemarket bool + EnableFeemarket bool from string malleate func() }{ @@ -361,9 +361,9 @@ func (suite *KeeperTestSuite) TestVerifyFeeAndDeductTxCostsFromUserBalance() { expectPassDeduct: true, from: addr.String(), }, - // testcases with enableFeemarket enabled. + // testcases with EnableFeemarket enabled. { - name: "Invalid gasFeeCap w/ enableFeemarket", + name: "Invalid gasFeeCap w/ EnableFeemarket", gasLimit: 10, gasFeeCap: big.NewInt(1), gasTipCap: big.NewInt(1), @@ -371,7 +371,7 @@ func (suite *KeeperTestSuite) TestVerifyFeeAndDeductTxCostsFromUserBalance() { accessList: ðtypes.AccessList{}, expectPassVerify: false, expectPassDeduct: true, - enableFeemarket: true, + EnableFeemarket: true, from: addr.String(), }, { @@ -383,7 +383,7 @@ func (suite *KeeperTestSuite) TestVerifyFeeAndDeductTxCostsFromUserBalance() { accessList: ðtypes.AccessList{}, expectPassVerify: true, expectPassDeduct: true, - enableFeemarket: true, + EnableFeemarket: true, from: addr.String(), }, { @@ -394,7 +394,7 @@ func (suite *KeeperTestSuite) TestVerifyFeeAndDeductTxCostsFromUserBalance() { accessList: ðtypes.AccessList{}, expectPassVerify: true, expectPassDeduct: true, - enableFeemarket: true, + EnableFeemarket: true, from: addr.String(), }, { @@ -406,7 +406,7 @@ func (suite *KeeperTestSuite) TestVerifyFeeAndDeductTxCostsFromUserBalance() { accessList: ðtypes.AccessList{}, expectPassVerify: true, expectPassDeduct: true, - enableFeemarket: true, + EnableFeemarket: true, from: addr.String(), }, { @@ -426,7 +426,7 @@ func (suite *KeeperTestSuite) TestVerifyFeeAndDeductTxCostsFromUserBalance() { cost: &oneInt, accessList: ðtypes.AccessList{ ethtypes.AccessTuple{ - Address: suite.keyring.GetAddr(0), + Address: s.Keyring.GetAddr(0), StorageKeys: []common.Hash{}, }, }, @@ -444,16 +444,16 @@ func (suite *KeeperTestSuite) TestVerifyFeeAndDeductTxCostsFromUserBalance() { expectPassDeduct: true, from: addr.String(), malleate: func() { - suite.network.WithIsCheckTxCtx(true) + s.Network.WithIsCheckTxCtx(true) }, }, } for i, tc := range testCases { - suite.Run(tc.name, func() { - suite.enableFeemarket = tc.enableFeemarket - suite.SetupTest() - vmdb := suite.StateDB() + s.Run(tc.name, func() { + s.EnableFeemarket = tc.EnableFeemarket + s.SetupTest() + vmdb := s.StateDB() if tc.malleate != nil { tc.malleate() @@ -463,7 +463,7 @@ func (suite *KeeperTestSuite) TestVerifyFeeAndDeductTxCostsFromUserBalance() { amount = tc.cost.BigInt() } - if suite.enableFeemarket { + if s.EnableFeemarket { if tc.gasFeeCap != nil { gasFeeCap = tc.gasFeeCap } @@ -474,7 +474,7 @@ func (suite *KeeperTestSuite) TestVerifyFeeAndDeductTxCostsFromUserBalance() { } vmdb.AddBalance(addr, uint256.MustFromBig(initBalance.BigInt()), tracing.BalanceChangeUnspecified) balance := vmdb.GetBalance(addr) - suite.Require().Equal(balance.ToBig(), initBalance.BigInt()) + s.Require().Equal(balance.ToBig(), initBalance.BigInt()) } else { if tc.gasPrice != nil { gasPrice = tc.gasPrice.BigInt() @@ -482,12 +482,12 @@ func (suite *KeeperTestSuite) TestVerifyFeeAndDeductTxCostsFromUserBalance() { vmdb.AddBalance(addr, uint256.MustFromBig(hundredInt.BigInt()), tracing.BalanceChangeUnspecified) balance := vmdb.GetBalance(addr) - suite.Require().Equal(balance.ToBig(), hundredInt.BigInt()) + s.Require().Equal(balance.ToBig(), hundredInt.BigInt()) } err := vmdb.Commit() - suite.Require().NoError(err, "Unexpected error while committing to vmdb: %d", err) + s.Require().NoError(err, "Unexpected error while committing to vmdb: %d", err) - toAddr := suite.keyring.GetAddr(0) + toAddr := s.Keyring.GetAddr(0) ethTxParams := &evmtypes.EvmTxArgs{ ChainID: zeroInt.BigInt(), Nonce: 1, @@ -504,26 +504,26 @@ func (suite *KeeperTestSuite) TestVerifyFeeAndDeductTxCostsFromUserBalance() { txData, _ := evmtypes.UnpackTxData(tx.Data) - baseFee := suite.network.App.EVMKeeper.GetBaseFee(suite.network.GetContext()) + baseFee := s.Network.App.GetEVMKeeper().GetBaseFee(s.Network.GetContext()) priority := evmtypes.GetTxPriority(txData, baseFee) baseDenom := evmtypes.GetEVMCoinDenom() - fees, err := keeper.VerifyFee(txData, baseDenom, baseFee, false, false, false, suite.network.GetContext().IsCheckTx()) + fees, err := keeper.VerifyFee(txData, baseDenom, baseFee, false, false, false, s.Network.GetContext().IsCheckTx()) if tc.expectPassVerify { - suite.Require().NoError(err, "valid test %d failed - '%s'", i, tc.name) - if tc.enableFeemarket { - baseFee := suite.network.App.FeeMarketKeeper.GetBaseFee(suite.network.GetContext()) - suite.Require().Equal( + s.Require().NoError(err, "valid test %d failed - '%s'", i, tc.name) + if tc.EnableFeemarket { + baseFee := s.Network.App.GetFeeMarketKeeper().GetBaseFee(s.Network.GetContext()) + s.Require().Equal( fees, sdk.NewCoins( sdk.NewCoin(baseDenom, sdkmath.NewIntFromBigInt(txData.EffectiveFee(baseFee.TruncateInt().BigInt()))), ), "valid test %d failed, fee value is wrong - '%s'", i, tc.name, ) - suite.Require().Equal(int64(0), priority) + s.Require().Equal(int64(0), priority) } else { - suite.Require().Equal( + s.Require().Equal( fees, sdk.NewCoins( sdk.NewCoin(baseDenom, tc.gasPrice.Mul(sdkmath.NewIntFromUint64(tc.gasLimit))), @@ -532,17 +532,17 @@ func (suite *KeeperTestSuite) TestVerifyFeeAndDeductTxCostsFromUserBalance() { ) } } else { - suite.Require().Error(err, "invalid test %d passed - '%s'", i, tc.name) - suite.Require().Nil(fees, "invalid test %d passed. fees value must be nil - '%s'", i, tc.name) + s.Require().Error(err, "invalid test %d passed - '%s'", i, tc.name) + s.Require().Nil(fees, "invalid test %d passed. fees value must be nil - '%s'", i, tc.name) } - err = suite.network.App.EVMKeeper.DeductTxCostsFromUserBalance(suite.network.GetContext(), fees, common.HexToAddress(tx.From)) + err = s.Network.App.GetEVMKeeper().DeductTxCostsFromUserBalance(s.Network.GetContext(), fees, common.HexToAddress(tx.From)) if tc.expectPassDeduct { - suite.Require().NoError(err, "valid test %d failed - '%s'", i, tc.name) + s.Require().NoError(err, "valid test %d failed - '%s'", i, tc.name) } else { - suite.Require().Error(err, "invalid test %d passed - '%s'", i, tc.name) + s.Require().Error(err, "invalid test %d passed - '%s'", i, tc.name) } }) } - suite.enableFeemarket = false // reset flag + s.EnableFeemarket = false // reset flag } diff --git a/tests/integration/x/vm/test_flash_loan_exploit.go b/tests/integration/x/vm/test_flash_loan_exploit.go new file mode 100644 index 000000000..98bfdb8c2 --- /dev/null +++ b/tests/integration/x/vm/test_flash_loan_exploit.go @@ -0,0 +1,103 @@ +package vm + +import ( + "fmt" + "math/big" + "testing" + + "github.com/cosmos/evm/contracts" + testutiltypes "github.com/cosmos/evm/testutil/types" + evmtypes "github.com/cosmos/evm/x/vm/types" + + "cosmossdk.io/math" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// TestFlashLoanExploit runs the two flash loan methods +func (s *NestedEVMExtensionCallSuite) TestFlashLoanExploit() { + testCases := []struct { + method string + expDelegation bool + expSenderERC20Balance *big.Int + expContractERC20Balance *big.Int + }{ + { + method: "flashLoan", + expDelegation: true, + expSenderERC20Balance: s.mintAmount, + expContractERC20Balance: big.NewInt(0), + }, + { + method: "flashLoanWithRevert", + expDelegation: false, + expSenderERC20Balance: s.delegateAmount, + expContractERC20Balance: s.delegateAmount, + }, + } + + for _, tc := range testCases { + caseName := tc.method + s.T().Run(caseName, func(t *testing.T) { + // reset test state + s.SetupTest() + + // Execute flash loan contract call + _, err := s.factory.ExecuteContractCall( + s.deployer.Priv, + evmtypes.EvmTxArgs{To: &s.flashLoanAddr, GasPrice: big.NewInt(900_000_000), GasLimit: 400_000, Amount: s.delegateAmount}, + testutiltypes.CallArgs{ContractABI: s.flashLoanContract.ABI, MethodName: tc.method, Args: []interface{}{s.erc20Addr, s.validatorToDelegateTo}}, + ) + s.Require().NoError(err, "failed to execute flash loan") + s.Require().NoError(s.network.NextBlock(), "failed to commit block") + + flashLoanAccAddr := sdk.AccAddress(s.flashLoanAddr.Bytes()) + + if tc.expDelegation { + // Check delegation exists + delRes, err := s.handler.GetDelegation(flashLoanAccAddr.String(), s.validatorToDelegateTo) + s.Require().NoError(err, "failed to get delegation") + delAmtPost := delRes.DelegationResponse.Balance.Amount + expected := s.delegatedAmountPre.Add(math.NewIntFromBigInt(s.delegateAmount)) + s.Require().Equal(expected, delAmtPost, "delegated amount mismatch") + } else { + // Expect no delegation + _, err := s.handler.GetDelegation(flashLoanAccAddr.String(), s.validatorToDelegateTo) + s.Require().Error(err, "delegation should not exist") + s.Require().Contains(err.Error(), fmt.Sprintf("delegation with delegator %s not found for validator %s", flashLoanAccAddr.String(), s.validatorToDelegateTo)) + } + + // Verify deployer ERC20 balance + res, err := s.factory.ExecuteContractCall( + s.deployer.Priv, + evmtypes.EvmTxArgs{To: &s.erc20Addr}, + testutiltypes.CallArgs{ContractABI: contracts.ERC20MinterBurnerDecimalsContract.ABI, MethodName: "balanceOf", Args: []interface{}{s.deployer.Addr}}, + ) + s.Require().NoError(err, "failed to get deployer balance") + s.Require().NoError(s.network.NextBlock(), "failed to commit block") + ethRes, err := evmtypes.DecodeTxResponse(res.Data) + s.Require().NoError(err, "failed to decode balance response") + unpacked, err := contracts.ERC20MinterBurnerDecimalsContract.ABI.Unpack("balanceOf", ethRes.Ret) + s.Require().NoError(err, "failed to unpack balance") + bal, ok := unpacked[0].(*big.Int) + s.Require().True(ok, "balance is not *big.Int") + s.Require().Equal(tc.expSenderERC20Balance.String(), bal.String(), "deployer balance mismatch") + + // Verify flash loan contract ERC20 balance + res2, err := s.factory.ExecuteContractCall( + s.deployer.Priv, + evmtypes.EvmTxArgs{To: &s.erc20Addr}, + testutiltypes.CallArgs{ContractABI: contracts.ERC20MinterBurnerDecimalsContract.ABI, MethodName: "balanceOf", Args: []interface{}{s.flashLoanAddr}}, + ) + s.Require().NoError(err, "failed to get contract balance") + s.Require().NoError(s.network.NextBlock(), "failed to commit block") + ethRes2, err := evmtypes.DecodeTxResponse(res2.Data) + s.Require().NoError(err, "failed to decode contract balance response") + unpacked2, err := contracts.ERC20MinterBurnerDecimalsContract.ABI.Unpack("balanceOf", ethRes2.Ret) + s.Require().NoError(err, "failed to unpack contract balance") + bal2, ok := unpacked2[0].(*big.Int) + s.Require().True(ok, "contract balance is not *big.Int") + s.Require().Equal(tc.expContractERC20Balance.String(), bal2.String(), "contract balance mismatch") + }) + } +} diff --git a/tests/integration/x/vm/test_genesis.go b/tests/integration/x/vm/test_genesis.go new file mode 100644 index 000000000..058c2d8e8 --- /dev/null +++ b/tests/integration/x/vm/test_genesis.go @@ -0,0 +1,212 @@ +package vm + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/tracing" + "github.com/ethereum/go-ethereum/crypto" + "github.com/holiman/uint256" + + "github.com/cosmos/evm/contracts" + "github.com/cosmos/evm/crypto/ethsecp256k1" + "github.com/cosmos/evm/testutil/integration/evm/network" + testutiltypes "github.com/cosmos/evm/testutil/types" + "github.com/cosmos/evm/x/vm" + "github.com/cosmos/evm/x/vm/statedb" + "github.com/cosmos/evm/x/vm/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// TestInitGenesis runs various scenarios against InitGenesis +func (s *GenesisTestSuite) TestInitGenesis() { + // prepare a key and address for storage tests + privkey, err := ethsecp256k1.GenerateKey() + s.Require().NoError(err) + address := common.HexToAddress(privkey.PubKey().Address().String()) + + var ( + vmdb *statedb.StateDB + ctx sdk.Context + ) + + // table-driven cases + testCases := []struct { + name string + malleate func(*network.UnitTestNetwork) + genState *types.GenesisState + code common.Hash + expPanic bool + }{ + { + name: "pass - default", + malleate: func(_ *network.UnitTestNetwork) {}, + genState: types.DefaultGenesisState(), + expPanic: false, + }, + { + name: "valid account", + malleate: func(_ *network.UnitTestNetwork) { + vmdb.AddBalance(address, uint256.NewInt(1), tracing.BalanceChangeUnspecified) + }, + genState: &types.GenesisState{ + Params: types.DefaultParams(), + Accounts: []types.GenesisAccount{ + { + Address: address.String(), + Storage: types.Storage{ + {Key: common.BytesToHash([]byte("key")).String(), Value: common.BytesToHash([]byte("value")).String()}, + }, + }, + }, + }, + expPanic: false, + }, + { + name: "account not found", + malleate: func(_ *network.UnitTestNetwork) {}, + genState: &types.GenesisState{ + Params: types.DefaultParams(), + Accounts: []types.GenesisAccount{ + { + Address: address.String(), + }, + }, + }, + expPanic: true, + }, + { + name: "ignore empty account code checking", + malleate: func(network *network.UnitTestNetwork) { + acc := network.App.GetAccountKeeper().NewAccountWithAddress(ctx, address.Bytes()) + network.App.GetAccountKeeper().SetAccount(ctx, acc) + }, + genState: &types.GenesisState{ + Params: types.DefaultParams(), + Accounts: []types.GenesisAccount{ + { + Address: address.String(), + Code: "", + }, + }, + }, + expPanic: false, + }, + { + name: "valid account with code", + malleate: func(network *network.UnitTestNetwork) { + acc := network.App.GetAccountKeeper().NewAccountWithAddress(ctx, address.Bytes()) + network.App.GetAccountKeeper().SetAccount(ctx, acc) + }, + genState: &types.GenesisState{ + Params: types.DefaultParams(), + Accounts: []types.GenesisAccount{ + { + Address: address.String(), + Code: "1234", + }, + }, + }, + expPanic: false, + }, + } + + for _, tc := range testCases { + s.T().Run(tc.name, func(t *testing.T) { + // reinitialize suite state for each subtest + s.SetupTest() + ctx = s.network.GetContext() + vmdb = statedb.New( + ctx, s.network.App.GetEVMKeeper(), + statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash()))) + + tc.malleate(s.network) + err := vmdb.Commit() + s.Require().NoError(err) + + if tc.expPanic { + s.Require().Panics(func() { + _ = vm.InitGenesis( + s.network.GetContext(), + s.network.App.GetEVMKeeper(), + s.network.App.GetAccountKeeper(), + *tc.genState, + ) + }) + } else { + s.Require().NotPanics(func() { + _ = vm.InitGenesis( + ctx, + s.network.App.GetEVMKeeper(), + s.network.App.GetAccountKeeper(), + *tc.genState, + ) + }) + // verify state for each account + for _, acct := range tc.genState.Accounts { + s.Require().NotNil( + s.network.App.GetAccountKeeper().GetAccount(ctx, common.HexToAddress(acct.Address).Bytes()), + ) + expHash := crypto.Keccak256Hash(common.Hex2Bytes(acct.Code)) + if acct.Code == "" { + expHash = common.BytesToHash(types.EmptyCodeHash) + } + + s.Require().Equal( + expHash.String(), + s.network.App.GetEVMKeeper().GetCodeHash(ctx, common.HexToAddress(acct.Address)).String(), + ) + s.Require().Equal( + acct.Code, + common.Bytes2Hex( + s.network.App.GetEVMKeeper().GetCode(ctx, expHash), + ), + ) + + for _, storage := range acct.Storage { + s.Require().Equal( + common.HexToHash(storage.Value), + vmdb.GetState(common.HexToAddress(acct.Address), common.HexToHash(storage.Key)), + ) + } + } + } + }) + } +} + +// TestExportGenesis verifies ExportGenesis output +func (s *GenesisTestSuite) TestExportGenesis() { + contractAddr, err := s.factory.DeployContract( + s.keyring.GetPrivKey(0), + types.EvmTxArgs{}, + testutiltypes.ContractDeploymentData{ + Contract: contracts.ERC20MinterBurnerDecimalsContract, + ConstructorArgs: []interface{}{"TestToken", "TTK", uint8(18)}, + }, + ) + s.Require().NoError(err) + s.Require().NoError(s.network.NextBlock()) + + contractAddr2, err := s.factory.DeployContract( + s.keyring.GetPrivKey(0), + types.EvmTxArgs{}, + testutiltypes.ContractDeploymentData{ + Contract: contracts.ERC20MinterBurnerDecimalsContract, + ConstructorArgs: []interface{}{"AnotherToken", "ATK", uint8(18)}, + }, + ) + s.Require().NoError(err) + s.Require().NoError(s.network.NextBlock()) + + genState := vm.ExportGenesis(s.network.GetContext(), s.network.App.GetEVMKeeper()) + s.Require().Len(genState.Accounts, 3) + + addrs := make([]string, len(genState.Accounts)) + for i, acct := range genState.Accounts { + addrs[i] = acct.Address + } + s.Require().Contains(addrs, contractAddr.Hex()) + s.Require().Contains(addrs, contractAddr2.Hex()) +} diff --git a/x/vm/keeper/grpc_query_test.go b/tests/integration/x/vm/test_grpc_query.go similarity index 68% rename from x/vm/keeper/grpc_query_test.go rename to tests/integration/x/vm/test_grpc_query.go index 50854cbd8..f4b35891e 100644 --- a/x/vm/keeper/grpc_query_test.go +++ b/tests/integration/x/vm/test_grpc_query.go @@ -1,4 +1,4 @@ -package keeper_test +package vm import ( "encoding/json" @@ -15,9 +15,10 @@ import ( "github.com/cosmos/evm/server/config" testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/os/factory" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/keyring" + testutiltypes "github.com/cosmos/evm/testutil/types" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" "github.com/cosmos/evm/x/vm/keeper/testdata" "github.com/cosmos/evm/x/vm/statedb" @@ -32,7 +33,7 @@ import ( // Not valid Ethereum address const invalidAddress = "0x0000" -func (suite *KeeperTestSuite) TestQueryAccount() { +func (s *KeeperTestSuite) TestQueryAccount() { baseDenom := types.GetEVMCoinDenom() testCases := []struct { msg string @@ -56,23 +57,23 @@ func (suite *KeeperTestSuite) TestQueryAccount() { amt := sdk.Coins{sdk.NewInt64Coin(baseDenom, 100)} // Add new unfunded key - index := suite.keyring.AddKey() - addr := suite.keyring.GetAddr(index) + index := s.Keyring.AddKey() + addr := s.Keyring.GetAddr(index) - err := suite.network.App.BankKeeper.MintCoins( - suite.network.GetContext(), + err := s.Network.App.GetBankKeeper().MintCoins( + s.Network.GetContext(), types.ModuleName, amt, ) - suite.Require().NoError(err) + s.Require().NoError(err) - err = suite.network.App.BankKeeper.SendCoinsFromModuleToAccount( - suite.network.GetContext(), + err = s.Network.App.GetBankKeeper().SendCoinsFromModuleToAccount( + s.Network.GetContext(), types.ModuleName, addr.Bytes(), amt, ) - suite.Require().NoError(err) + s.Require().NoError(err) return &types.QueryAccountRequest{ Address: addr.String(), @@ -88,26 +89,26 @@ func (suite *KeeperTestSuite) TestQueryAccount() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + s.Run(fmt.Sprintf("Case %s", tc.msg), func() { req := tc.getReq() expectedResponse := tc.expResponse - ctx := suite.network.GetContext() + ctx := s.Network.GetContext() // Function under test - res, err := suite.network.GetEvmClient().Account(ctx, req) + res, err := s.Network.GetEvmClient().Account(ctx, req) - suite.Require().Equal(expectedResponse, res) + s.Require().Equal(expectedResponse, res) if tc.expPass { - suite.Require().NoError(err) + s.Require().NoError(err) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *KeeperTestSuite) TestQueryCosmosAccount() { +func (s *KeeperTestSuite) TestQueryCosmosAccount() { testCases := []struct { msg string getReqAndResp func() (*types.QueryCosmosAccountRequest, *types.QueryCosmosAccountResponse) @@ -126,7 +127,7 @@ func (suite *KeeperTestSuite) TestQueryCosmosAccount() { { "success", func() (*types.QueryCosmosAccountRequest, *types.QueryCosmosAccountResponse) { - key := suite.keyring.GetKey(0) + key := s.Keyring.GetKey(0) expAccount := &types.QueryCosmosAccountResponse{ CosmosAddress: key.AccAddr.String(), Sequence: 0, @@ -143,17 +144,17 @@ func (suite *KeeperTestSuite) TestQueryCosmosAccount() { { "success with seq and account number", func() (*types.QueryCosmosAccountRequest, *types.QueryCosmosAccountResponse) { - index := suite.keyring.AddKey() - newKey := suite.keyring.GetKey(index) + index := s.Keyring.AddKey() + newKey := s.Keyring.GetKey(index) accountNumber := uint64(100) - acc := suite.network.App.AccountKeeper.NewAccountWithAddress( - suite.network.GetContext(), + acc := s.Network.App.GetAccountKeeper().NewAccountWithAddress( + s.Network.GetContext(), newKey.AccAddr, ) - suite.Require().NoError(acc.SetSequence(10)) - suite.Require().NoError(acc.SetAccountNumber(accountNumber)) - suite.network.App.AccountKeeper.SetAccount(suite.network.GetContext(), acc) + s.Require().NoError(acc.SetSequence(10)) + s.Require().NoError(acc.SetAccountNumber(accountNumber)) + s.Network.App.GetAccountKeeper().SetAccount(s.Network.GetContext(), acc) expAccount := &types.QueryCosmosAccountResponse{ CosmosAddress: newKey.AccAddr.String(), @@ -171,26 +172,26 @@ func (suite *KeeperTestSuite) TestQueryCosmosAccount() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + s.Run(fmt.Sprintf("Case %s", tc.msg), func() { req, expectedResponse := tc.getReqAndResp() - ctx := suite.network.GetContext() + ctx := s.Network.GetContext() // Function under test - res, err := suite.network.GetEvmClient().CosmosAccount(ctx, req) + res, err := s.Network.GetEvmClient().CosmosAccount(ctx, req) - suite.Require().Equal(expectedResponse, res) + s.Require().Equal(expectedResponse, res) if tc.expPass { - suite.Require().NoError(err) + s.Require().NoError(err) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *KeeperTestSuite) TestQueryBalance() { +func (s *KeeperTestSuite) TestQueryBalance() { baseDenom := types.GetEVMCoinDenom() testCases := []struct { @@ -211,16 +212,16 @@ func (suite *KeeperTestSuite) TestQueryBalance() { { "success", func() (*types.QueryBalanceRequest, *types.QueryBalanceResponse) { - newIndex := suite.keyring.AddKey() - addr := suite.keyring.GetAddr(newIndex) + newIndex := s.Keyring.AddKey() + addr := s.Keyring.GetAddr(newIndex) balance := int64(100) amt := sdk.Coins{sdk.NewInt64Coin(baseDenom, balance)} - err := suite.network.App.BankKeeper.MintCoins(suite.network.GetContext(), types.ModuleName, amt) - suite.Require().NoError(err) - err = suite.network.App.BankKeeper.SendCoinsFromModuleToAccount(suite.network.GetContext(), types.ModuleName, addr.Bytes(), amt) - suite.Require().NoError(err) + err := s.Network.App.GetBankKeeper().MintCoins(s.Network.GetContext(), types.ModuleName, amt) + s.Require().NoError(err) + err = s.Network.App.GetBankKeeper().SendCoinsFromModuleToAccount(s.Network.GetContext(), types.ModuleName, addr.Bytes(), amt) + s.Require().NoError(err) req := &types.QueryBalanceRequest{ Address: addr.String(), @@ -234,23 +235,23 @@ func (suite *KeeperTestSuite) TestQueryBalance() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + s.Run(fmt.Sprintf("Case %s", tc.msg), func() { req, resp := tc.getReqAndResp() - ctx := suite.network.GetContext() - res, err := suite.network.GetEvmClient().Balance(ctx, req) + ctx := s.Network.GetContext() + res, err := s.Network.GetEvmClient().Balance(ctx, req) - suite.Require().Equal(resp, res) + s.Require().Equal(resp, res) if tc.expPass { - suite.Require().NoError(err) + s.Require().NoError(err) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *KeeperTestSuite) TestQueryStorage() { +func (s *KeeperTestSuite) TestQueryStorage() { testCases := []struct { msg string getReqAndResp func() (*types.QueryStorageRequest, *types.QueryStorageResponse) @@ -273,11 +274,11 @@ func (suite *KeeperTestSuite) TestQueryStorage() { value := []byte("value") expValue := common.BytesToHash(value) - newIndex := suite.keyring.AddKey() - addr := suite.keyring.GetAddr(newIndex) + newIndex := s.Keyring.AddKey() + addr := s.Keyring.GetAddr(newIndex) - suite.network.App.EVMKeeper.SetState( - suite.network.GetContext(), + s.Network.App.GetEVMKeeper().SetState( + s.Network.GetContext(), addr, key, value, @@ -296,24 +297,24 @@ func (suite *KeeperTestSuite) TestQueryStorage() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + s.Run(fmt.Sprintf("Case %s", tc.msg), func() { req, expectedResp := tc.getReqAndResp() - ctx := suite.network.GetContext() - res, err := suite.network.GetEvmClient().Storage(ctx, req) + ctx := s.Network.GetContext() + res, err := s.Network.GetEvmClient().Storage(ctx, req) - suite.Require().Equal(expectedResp, res) + s.Require().Equal(expectedResp, res) if tc.expPass { - suite.Require().NoError(err) + s.Require().NoError(err) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *KeeperTestSuite) TestQueryCode() { +func (s *KeeperTestSuite) TestQueryCode() { var ( req *types.QueryCodeRequest expCode []byte @@ -337,13 +338,13 @@ func (suite *KeeperTestSuite) TestQueryCode() { { "success", func() (*types.QueryCodeRequest, *types.QueryCodeResponse) { - newIndex := suite.keyring.AddKey() - addr := suite.keyring.GetAddr(newIndex) + newIndex := s.Keyring.AddKey() + addr := s.Keyring.GetAddr(newIndex) expCode = []byte("code") - stateDB := suite.network.GetStateDB() + stateDB := s.Network.GetStateDB() stateDB.SetCode(addr, expCode) - suite.Require().NoError(stateDB.Commit()) + s.Require().NoError(stateDB.Commit()) req = &types.QueryCodeRequest{ Address: addr.String(), @@ -357,24 +358,24 @@ func (suite *KeeperTestSuite) TestQueryCode() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + s.Run(fmt.Sprintf("Case %s", tc.msg), func() { req, expectedResponse := tc.getReqAndResp() - ctx := suite.network.GetContext() - res, err := suite.network.GetEvmClient().Code(ctx, req) + ctx := s.Network.GetContext() + res, err := s.Network.GetEvmClient().Code(ctx, req) - suite.Require().Equal(expectedResponse, res) + s.Require().Equal(expectedResponse, res) if tc.expPass { - suite.Require().NoError(err) + s.Require().NoError(err) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } // TODO: Fix this one -func (suite *KeeperTestSuite) TestQueryTxLogs() { +func (s *KeeperTestSuite) TestQueryTxLogs() { expLogs := []*types.Log{} txHash := common.BytesToHash([]byte("tx_hash")) txIndex := uint(1) @@ -393,7 +394,7 @@ func (suite *KeeperTestSuite) TestQueryTxLogs() { { "success", func(vmdb vm.StateDB) { - addr := suite.keyring.GetAddr(0) + addr := s.Keyring.GetAddr(0) expLogs = []*types.Log{ { Address: addr.String(), @@ -402,7 +403,7 @@ func (suite *KeeperTestSuite) TestQueryTxLogs() { BlockNumber: 1, TxHash: txHash.String(), TxIndex: uint64(txIndex), - BlockHash: common.BytesToHash(suite.network.GetContext().HeaderHash()).Hex(), + BlockHash: common.BytesToHash(s.Network.GetContext().HeaderHash()).Hex(), Index: uint64(logIndex), Removed: false, }, @@ -416,40 +417,40 @@ func (suite *KeeperTestSuite) TestQueryTxLogs() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + s.Run(fmt.Sprintf("Case %s", tc.msg), func() { txCfg := statedb.NewTxConfig( - common.BytesToHash(suite.network.GetContext().HeaderHash()), + common.BytesToHash(s.Network.GetContext().HeaderHash()), txHash, txIndex, logIndex, ) vmdb := statedb.New( - suite.network.GetContext(), - suite.network.App.EVMKeeper, + s.Network.GetContext(), + s.Network.App.GetEVMKeeper(), txCfg, ) tc.malleate(vmdb) - suite.Require().NoError(vmdb.Commit()) + s.Require().NoError(vmdb.Commit()) logs := vmdb.Logs() - suite.Require().Equal(expLogs, types.NewLogsFromEth(logs)) + s.Require().Equal(expLogs, types.NewLogsFromEth(logs)) }) } } -func (suite *KeeperTestSuite) TestQueryParams() { - ctx := suite.network.GetContext() +func (s *KeeperTestSuite) TestQueryParams() { + ctx := s.Network.GetContext() expParams := types.DefaultParams() expParams.ActiveStaticPrecompiles = types.AvailableStaticPrecompiles expParams.ExtraEIPs = nil - res, err := suite.network.GetEvmClient().Params(ctx, &types.QueryParamsRequest{}) - suite.Require().NoError(err) - suite.Require().Equal(expParams, res.Params) + res, err := s.Network.GetEvmClient().Params(ctx, &types.QueryParamsRequest{}) + s.Require().NoError(err) + s.Require().Equal(expParams, res.Params) } -func (suite *KeeperTestSuite) TestQueryValidatorAccount() { +func (s *KeeperTestSuite) TestQueryValidatorAccount() { testCases := []struct { msg string getReqAndResp func() (*types.QueryValidatorAccountRequest, *types.QueryValidatorAccountResponse) @@ -468,16 +469,16 @@ func (suite *KeeperTestSuite) TestQueryValidatorAccount() { { "success", func() (*types.QueryValidatorAccountRequest, *types.QueryValidatorAccountResponse) { - val := suite.network.GetValidators()[0] + val := s.Network.GetValidators()[0] consAddr, err := val.GetConsAddr() - suite.Require().NoError(err) + s.Require().NoError(err) req := &types.QueryValidatorAccountRequest{ ConsAddress: sdk.ConsAddress(consAddr).String(), } - addrBz, err := suite.network.App.StakingKeeper.ValidatorAddressCodec().StringToBytes(val.OperatorAddress) - suite.Require().NoError(err) + addrBz, err := s.Network.App.GetStakingKeeper().ValidatorAddressCodec().StringToBytes(val.OperatorAddress) + s.Require().NoError(err) resp := &types.QueryValidatorAccountResponse{ AccountAddress: sdk.AccAddress(addrBz).String(), @@ -492,24 +493,24 @@ func (suite *KeeperTestSuite) TestQueryValidatorAccount() { { "success with seq and account number", func() (*types.QueryValidatorAccountRequest, *types.QueryValidatorAccountResponse) { - val := suite.network.GetValidators()[0] + val := s.Network.GetValidators()[0] consAddr, err := val.GetConsAddr() - suite.Require().NoError(err) + s.Require().NoError(err) - // Create validator account and set sequence and account number + // create validator account and set sequence and account number accNumber := uint64(100) accSeq := uint64(10) - addrBz, err := suite.network.App.StakingKeeper.ValidatorAddressCodec().StringToBytes(val.OperatorAddress) - suite.Require().NoError(err) + addrBz, err := s.Network.App.GetStakingKeeper().ValidatorAddressCodec().StringToBytes(val.OperatorAddress) + s.Require().NoError(err) accAddrStr := sdk.AccAddress(addrBz).String() baseAcc := &authtypes.BaseAccount{Address: accAddrStr} - acc := suite.network.App.AccountKeeper.NewAccount(suite.network.GetContext(), baseAcc) - suite.Require().NoError(acc.SetSequence(accSeq)) - suite.Require().NoError(acc.SetAccountNumber(accNumber)) - suite.network.App.AccountKeeper.SetAccount(suite.network.GetContext(), acc) + acc := s.Network.App.GetAccountKeeper().NewAccount(s.Network.GetContext(), baseAcc) + s.Require().NoError(acc.SetSequence(accSeq)) + s.Require().NoError(acc.SetAccountNumber(accNumber)) + s.Network.App.GetAccountKeeper().SetAccount(s.Network.GetContext(), acc) resp := &types.QueryValidatorAccountResponse{ AccountAddress: accAddrStr, @@ -527,36 +528,36 @@ func (suite *KeeperTestSuite) TestQueryValidatorAccount() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + s.Run(fmt.Sprintf("Case %s", tc.msg), func() { req, resp := tc.getReqAndResp() - ctx := suite.network.GetContext() - res, err := suite.network.GetEvmClient().ValidatorAccount(ctx, req) + ctx := s.Network.GetContext() + res, err := s.Network.GetEvmClient().ValidatorAccount(ctx, req) - suite.Require().Equal(resp, res) + s.Require().Equal(resp, res) if tc.expPass { - suite.Require().NoError(err) + s.Require().NoError(err) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *KeeperTestSuite) TestEstimateGas() { +func (s *KeeperTestSuite) TestEstimateGas() { gasHelper := hexutil.Uint64(20000) higherGas := hexutil.Uint64(25000) // Hardcode recipient address to avoid non determinism in tests hardcodedRecipient := common.HexToAddress("0xC6Fe5D33615a1C52c08018c47E8Bc53646A0E101") erc20Contract, err := testdata.LoadERC20Contract() - suite.Require().NoError(err) + s.Require().NoError(err) testCases := []struct { msg string getArgs func() types.TransactionArgs expPass bool expGas uint64 - enableFeemarket bool + EnableFeemarket bool gasCap uint64 }{ // should success, because transfer value is zero @@ -599,7 +600,7 @@ func (suite *KeeperTestSuite) TestEstimateGas() { { "success - enough balance", func() types.TransactionArgs { - addr := suite.keyring.GetAddr(0) + addr := s.Keyring.GetAddr(0) return types.TransactionArgs{ To: &common.Address{}, From: &addr, @@ -614,9 +615,9 @@ func (suite *KeeperTestSuite) TestEstimateGas() { { "fail - not enough balance w/ gas fee cap", func() types.TransactionArgs { - addr := suite.keyring.GetAddr(0) + addr := s.Keyring.GetAddr(0) hexBigInt := hexutil.Big(*big.NewInt(1)) - balance := suite.network.App.BankKeeper.GetBalance(suite.network.GetContext(), sdk.AccAddress(addr.Bytes()), types.GetEVMCoinDenom()) + balance := s.Network.App.GetBankKeeper().GetBalance(s.Network.GetContext(), sdk.AccAddress(addr.Bytes()), types.GetEVMCoinDenom()) value := balance.Amount.Add(sdkmath.NewInt(1)) return types.TransactionArgs{ To: &common.Address{}, @@ -633,9 +634,9 @@ func (suite *KeeperTestSuite) TestEstimateGas() { { "fail - insufficient funds for gas * price + value w/ gas fee cap", func() types.TransactionArgs { - addr := suite.keyring.GetAddr(0) + addr := s.Keyring.GetAddr(0) hexBigInt := hexutil.Big(*big.NewInt(1)) - balance := suite.network.App.BankKeeper.GetBalance(suite.network.GetContext(), sdk.AccAddress(addr.Bytes()), types.GetEVMCoinDenom()) + balance := s.Network.App.GetBankKeeper().GetBalance(s.Network.GetContext(), sdk.AccAddress(addr.Bytes()), types.GetEVMCoinDenom()) value := balance.Amount.Sub(sdkmath.NewInt(1)) return types.TransactionArgs{ To: &common.Address{}, @@ -680,11 +681,11 @@ func (suite *KeeperTestSuite) TestEstimateGas() { &hardcodedRecipient, sdkmath.NewIntWithDecimal(1000, 18).BigInt(), ) - suite.Require().NoError(err) + s.Require().NoError(err) data := erc20Contract.Bin data = append(data, ctorArgs...) - addr := suite.keyring.GetAddr(0) + addr := s.Keyring.GetAddr(0) return types.TransactionArgs{ Data: (*hexutil.Bytes)(&data), From: &addr, @@ -699,19 +700,19 @@ func (suite *KeeperTestSuite) TestEstimateGas() { { "erc20 transfer", func() types.TransactionArgs { - key := suite.keyring.GetKey(0) - contractAddr, err := deployErc20Contract(key, suite.factory) - suite.Require().NoError(err) + key := s.Keyring.GetKey(0) + contractAddr, err := deployErc20Contract(key, s.Factory) + s.Require().NoError(err) - err = suite.network.NextBlock() - suite.Require().NoError(err) + err = s.Network.NextBlock() + s.Require().NoError(err) transferData, err := erc20Contract.ABI.Pack( "transfer", hardcodedRecipient, big.NewInt(1000), ) - suite.Require().NoError(err) + s.Require().NoError(err) return types.TransactionArgs{ To: &contractAddr, Data: (*hexutil.Bytes)(&transferData), @@ -723,9 +724,9 @@ func (suite *KeeperTestSuite) TestEstimateGas() { false, config.DefaultGasCap, }, - // repeated tests with enableFeemarket + // repeated tests with EnableFeemarket { - "default args w/ enableFeemarket", + "default args w/ EnableFeemarket", func() types.TransactionArgs { return types.TransactionArgs{To: &common.Address{}} }, @@ -735,7 +736,7 @@ func (suite *KeeperTestSuite) TestEstimateGas() { config.DefaultGasCap, }, { - "not enough balance w/ enableFeemarket", + "not enough balance w/ EnableFeemarket", func() types.TransactionArgs { return types.TransactionArgs{ To: &common.Address{}, @@ -748,9 +749,9 @@ func (suite *KeeperTestSuite) TestEstimateGas() { config.DefaultGasCap, }, { - "enough balance w/ enableFeemarket", + "enough balance w/ EnableFeemarket", func() types.TransactionArgs { - addr := suite.keyring.GetAddr(0) + addr := s.Keyring.GetAddr(0) return types.TransactionArgs{ To: &common.Address{}, From: &addr, @@ -763,7 +764,7 @@ func (suite *KeeperTestSuite) TestEstimateGas() { config.DefaultGasCap, }, { - "gas exceed allowance w/ enableFeemarket", + "gas exceed allowance w/ EnableFeemarket", func() types.TransactionArgs { return types.TransactionArgs{To: &common.Address{}, Gas: &gasHelper} }, @@ -773,7 +774,7 @@ func (suite *KeeperTestSuite) TestEstimateGas() { config.DefaultGasCap, }, { - "gas exceed global allowance w/ enableFeemarket", + "gas exceed global allowance w/ EnableFeemarket", func() types.TransactionArgs { return types.TransactionArgs{To: &common.Address{}} }, @@ -783,18 +784,18 @@ func (suite *KeeperTestSuite) TestEstimateGas() { 20000, }, { - "contract deployment w/ enableFeemarket", + "contract deployment w/ EnableFeemarket", func() types.TransactionArgs { ctorArgs, err := erc20Contract.ABI.Pack( "", &hardcodedRecipient, sdkmath.NewIntWithDecimal(1000, 18).BigInt(), ) - suite.Require().NoError(err) + s.Require().NoError(err) data := erc20Contract.Bin data = append(data, ctorArgs...) - sender := suite.keyring.GetAddr(0) + sender := s.Keyring.GetAddr(0) return types.TransactionArgs{ Data: (*hexutil.Bytes)(&data), From: &sender, @@ -806,22 +807,22 @@ func (suite *KeeperTestSuite) TestEstimateGas() { config.DefaultGasCap, }, { - "erc20 transfer w/ enableFeemarket", + "erc20 transfer w/ EnableFeemarket", func() types.TransactionArgs { - key := suite.keyring.GetKey(1) + key := s.Keyring.GetKey(1) - contractAddr, err := deployErc20Contract(key, suite.factory) - suite.Require().NoError(err) + contractAddr, err := deployErc20Contract(key, s.Factory) + s.Require().NoError(err) - err = suite.network.NextBlock() - suite.Require().NoError(err) + err = s.Network.NextBlock() + s.Require().NoError(err) transferData, err := erc20Contract.ABI.Pack( "transfer", hardcodedRecipient, big.NewInt(1000), ) - suite.Require().NoError(err) + s.Require().NoError(err) return types.TransactionArgs{ To: &contractAddr, @@ -837,13 +838,13 @@ func (suite *KeeperTestSuite) TestEstimateGas() { { "contract creation but 'create' param disabled", func() types.TransactionArgs { - addr := suite.keyring.GetAddr(0) + addr := s.Keyring.GetAddr(0) ctorArgs, err := erc20Contract.ABI.Pack( "", &addr, sdkmath.NewIntWithDecimal(1000, 18).BigInt(), ) - suite.Require().NoError(err) + s.Require().NoError(err) data := erc20Contract.Bin data = append(data, ctorArgs...) @@ -852,17 +853,17 @@ func (suite *KeeperTestSuite) TestEstimateGas() { From: &addr, Data: (*hexutil.Bytes)(&data), } - params := suite.network.App.EVMKeeper.GetParams(suite.network.GetContext()) + params := s.Network.App.GetEVMKeeper().GetParams(s.Network.GetContext()) params.AccessControl = types.AccessControl{ Create: types.AccessControlType{ AccessType: types.AccessTypeRestricted, }, } - err = suite.network.App.EVMKeeper.SetParams( - suite.network.GetContext(), + err = s.Network.App.GetEVMKeeper().SetParams( + s.Network.GetContext(), params, ) - suite.Require().NoError(err) + s.Require().NoError(err) return args }, @@ -916,46 +917,46 @@ func (suite *KeeperTestSuite) TestEstimateGas() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + s.Run(fmt.Sprintf("Case %s", tc.msg), func() { // Start from a clean state - suite.Require().NoError(suite.network.NextBlock()) + s.Require().NoError(s.Network.NextBlock()) // Update feemarket params per test evmParams := feemarkettypes.DefaultParams() - if !tc.enableFeemarket { - evmParams := suite.network.App.FeeMarketKeeper.GetParams( - suite.network.GetContext(), + if !tc.EnableFeemarket { + evmParams := s.Network.App.GetFeeMarketKeeper().GetParams( + s.Network.GetContext(), ) evmParams.NoBaseFee = true } - err := suite.network.App.FeeMarketKeeper.SetParams( - suite.network.GetContext(), + err := s.Network.App.GetFeeMarketKeeper().SetParams( + s.Network.GetContext(), evmParams, ) - suite.Require().NoError(err) + s.Require().NoError(err) // Get call args args := tc.getArgs() marshalArgs, err := json.Marshal(args) - suite.Require().NoError(err) + s.Require().NoError(err) req := types.EthCallRequest{ Args: marshalArgs, GasCap: tc.gasCap, - ProposerAddress: suite.network.GetContext().BlockHeader().ProposerAddress, + ProposerAddress: s.Network.GetContext().BlockHeader().ProposerAddress, } // Function under test - rsp, err := suite.network.GetEvmClient().EstimateGas( - suite.network.GetContext(), + rsp, err := s.Network.GetEvmClient().EstimateGas( + s.Network.GetContext(), &req, ) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(int64(tc.expGas), int64(rsp.Gas)) //#nosec G115 + s.Require().NoError(err) + s.Require().Equal(int64(tc.expGas), int64(rsp.Gas)) //#nosec G115 } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } @@ -972,16 +973,16 @@ func getDefaultTraceTxRequest(unitNetwork network.Network) types.QueryTraceTxReq } } -func (suite *KeeperTestSuite) TestTraceTx() { - suite.enableFeemarket = true - defer func() { suite.enableFeemarket = false }() - suite.SetupTest() +func (s *KeeperTestSuite) TestTraceTx() { + s.EnableFeemarket = true + defer func() { s.EnableFeemarket = false }() + s.SetupTest() // Hardcode recipient address to avoid non determinism in tests hardcodedRecipient := common.HexToAddress("0xC6Fe5D33615a1C52c08018c47E8Bc53646A0E101") erc20Contract, err := testdata.LoadERC20Contract() - suite.Require().NoError(err) + s.Require().NoError(err) testCases := []struct { msg string @@ -994,7 +995,7 @@ func (suite *KeeperTestSuite) TestTraceTx() { { msg: "default trace", getRequest: func() types.QueryTraceTxRequest { - return getDefaultTraceTxRequest(suite.network) + return getDefaultTraceTxRequest(s.Network) }, getPredecessors: func() []*types.MsgEthereumTx { return nil @@ -1007,7 +1008,7 @@ func (suite *KeeperTestSuite) TestTraceTx() { { msg: "default trace with filtered response", getRequest: func() types.QueryTraceTxRequest { - defaultRequest := getDefaultTraceTxRequest(suite.network) + defaultRequest := getDefaultTraceTxRequest(s.Network) defaultRequest.TraceConfig = &types.TraceConfig{ DisableStack: true, DisableStorage: true, @@ -1029,7 +1030,7 @@ func (suite *KeeperTestSuite) TestTraceTx() { traceConfig := &types.TraceConfig{ Tracer: "{data: [], fault: function(log) {}, step: function(log) { if(log.op.toString() == \"CALL\") this.data.push(log.stack.peek(0)); }, result: function() { return this.data; }}", } - defaultRequest := getDefaultTraceTxRequest(suite.network) + defaultRequest := getDefaultTraceTxRequest(s.Network) defaultRequest.TraceConfig = traceConfig return defaultRequest }, @@ -1042,17 +1043,17 @@ func (suite *KeeperTestSuite) TestTraceTx() { { msg: "default tracer with predecessors", getRequest: func() types.QueryTraceTxRequest { - return getDefaultTraceTxRequest(suite.network) + return getDefaultTraceTxRequest(s.Network) }, getPredecessors: func() []*types.MsgEthereumTx { - // Create predecessor tx + // create predecessor tx // Use different address to avoid nonce collision - senderKey := suite.keyring.GetKey(1) - contractAddr, err := deployErc20Contract(senderKey, suite.factory) - suite.Require().NoError(err) + senderKey := s.Keyring.GetKey(1) + contractAddr, err := deployErc20Contract(senderKey, s.Factory) + s.Require().NoError(err) - err = suite.network.NextBlock() - suite.Require().NoError(err) + err = s.Network.NextBlock() + s.Require().NoError(err) txMsg, err := executeTransferCall( transferParams{ @@ -1060,9 +1061,9 @@ func (suite *KeeperTestSuite) TestTraceTx() { contractAddr: contractAddr, recipientAddr: hardcodedRecipient, }, - suite.factory, + s.Factory, ) - suite.Require().NoError(err) + s.Require().NoError(err) return []*types.MsgEthereumTx{txMsg} }, @@ -1074,7 +1075,7 @@ func (suite *KeeperTestSuite) TestTraceTx() { { msg: "invalid trace config - Negative Limit", getRequest: func() types.QueryTraceTxRequest { - defaultRequest := getDefaultTraceTxRequest(suite.network) + defaultRequest := getDefaultTraceTxRequest(s.Network) defaultRequest.TraceConfig = &types.TraceConfig{ DisableStack: true, DisableStorage: true, @@ -1091,7 +1092,7 @@ func (suite *KeeperTestSuite) TestTraceTx() { { msg: "invalid trace config - Invalid Tracer", getRequest: func() types.QueryTraceTxRequest { - defaultRequest := getDefaultTraceTxRequest(suite.network) + defaultRequest := getDefaultTraceTxRequest(s.Network) defaultRequest.TraceConfig = &types.TraceConfig{ Tracer: "invalid_tracer", } @@ -1105,7 +1106,7 @@ func (suite *KeeperTestSuite) TestTraceTx() { { msg: "invalid trace config - Invalid Timeout", getRequest: func() types.QueryTraceTxRequest { - defaultRequest := getDefaultTraceTxRequest(suite.network) + defaultRequest := getDefaultTraceTxRequest(s.Network) defaultRequest.TraceConfig = &types.TraceConfig{ DisableStack: true, DisableStorage: true, @@ -1122,42 +1123,42 @@ func (suite *KeeperTestSuite) TestTraceTx() { { msg: "default tracer with contract creation tx as predecessor but 'create' param disabled", getRequest: func() types.QueryTraceTxRequest { - return getDefaultTraceTxRequest(suite.network) + return getDefaultTraceTxRequest(s.Network) }, getPredecessors: func() []*types.MsgEthereumTx { // use different address to avoid nonce collision - senderKey := suite.keyring.GetKey(1) + senderKey := s.Keyring.GetKey(1) constructorArgs := []interface{}{ senderKey.Addr, sdkmath.NewIntWithDecimal(1000, 18).BigInt(), } compiledContract := erc20Contract - deploymentData := factory.ContractDeploymentData{ + deploymentData := testutiltypes.ContractDeploymentData{ Contract: compiledContract, ConstructorArgs: constructorArgs, } - txArgs, err := suite.factory.GenerateDeployContractArgs(senderKey.Addr, types.EvmTxArgs{}, deploymentData) - suite.Require().NoError(err) + txArgs, err := s.Factory.GenerateDeployContractArgs(senderKey.Addr, types.EvmTxArgs{}, deploymentData) + s.Require().NoError(err) - txMsg, err := suite.factory.GenerateMsgEthereumTx(senderKey.Priv, txArgs) - suite.Require().NoError(err) + txMsg, err := s.Factory.GenerateMsgEthereumTx(senderKey.Priv, txArgs) + s.Require().NoError(err) - _, err = suite.factory.ExecuteEthTx( + _, err = s.Factory.ExecuteEthTx( senderKey.Priv, txArgs, // Default values ) - suite.Require().NoError(err) + s.Require().NoError(err) - params := suite.network.App.EVMKeeper.GetParams(suite.network.GetContext()) + params := s.Network.App.GetEVMKeeper().GetParams(s.Network.GetContext()) params.AccessControl = types.AccessControl{ Create: types.AccessControlType{ AccessType: types.AccessTypeRestricted, }, } - err = suite.network.App.EVMKeeper.SetParams(suite.network.GetContext(), params) - suite.Require().NoError(err) + err = s.Network.App.GetEVMKeeper().SetParams(s.Network.GetContext(), params) + s.Require().NoError(err) return []*types.MsgEthereumTx{&txMsg} }, expPass: true, @@ -1169,22 +1170,22 @@ func (suite *KeeperTestSuite) TestTraceTx() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + s.Run(fmt.Sprintf("Case %s", tc.msg), func() { // Clean up per test defaultEvmParams := types.DefaultParams() - err := suite.network.App.EVMKeeper.SetParams(suite.network.GetContext(), defaultEvmParams) - suite.Require().NoError(err) + err := s.Network.App.GetEVMKeeper().SetParams(s.Network.GetContext(), defaultEvmParams) + s.Require().NoError(err) - err = suite.network.NextBlock() - suite.Require().NoError(err) + err = s.Network.NextBlock() + s.Require().NoError(err) // ----- Contract Deployment ----- - senderKey := suite.keyring.GetKey(0) - contractAddr, err := deployErc20Contract(senderKey, suite.factory) - suite.Require().NoError(err) + senderKey := s.Keyring.GetKey(0) + contractAddr, err := deployErc20Contract(senderKey, s.Factory) + s.Require().NoError(err) - err = suite.network.NextBlock() - suite.Require().NoError(err) + err = s.Network.NextBlock() + s.Require().NoError(err) // --- Add predecessor --- predecessors := tc.getPredecessors() @@ -1196,11 +1197,11 @@ func (suite *KeeperTestSuite) TestTraceTx() { contractAddr: contractAddr, recipientAddr: hardcodedRecipient, }, - suite.factory, + s.Factory, ) - suite.Require().NoError(err) + s.Require().NoError(err) - suite.Require().NoError(suite.network.NextBlock()) + s.Require().NoError(s.Network.NextBlock()) // Get the trace request traceReq := tc.getRequest() @@ -1209,36 +1210,36 @@ func (suite *KeeperTestSuite) TestTraceTx() { traceReq.Msg = msgToTrace // Function under test - res, err := suite.network.GetEvmClient().TraceTx( - suite.network.GetContext(), + res, err := s.Network.GetEvmClient().TraceTx( + s.Network.GetContext(), &traceReq, ) if tc.expPass { - suite.Require().NoError(err) + s.Require().NoError(err) // if data is to big, slice the result if len(res.Data) > 150 { - suite.Require().Equal(tc.expectedTrace, string(res.Data[:150])) + s.Require().Equal(tc.expectedTrace, string(res.Data[:150])) } else { - suite.Require().Equal(tc.expectedTrace, string(res.Data)) + s.Require().Equal(tc.expectedTrace, string(res.Data)) } if traceReq.TraceConfig == nil || traceReq.TraceConfig.Tracer == "" { var result ethlogger.ExecutionResult - suite.Require().NoError(json.Unmarshal(res.Data, &result)) - suite.Require().Positive(result.Gas) + s.Require().NoError(json.Unmarshal(res.Data, &result)) + s.Require().Positive(result.Gas) } } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *KeeperTestSuite) TestTraceBlock() { - suite.enableFeemarket = true - defer func() { suite.enableFeemarket = false }() - suite.SetupTest() +func (s *KeeperTestSuite) TestTraceBlock() { + s.EnableFeemarket = true + defer func() { s.EnableFeemarket = false }() + s.SetupTest() // Hardcode recipient to make gas estimation deterministic hardcodedTransferRecipient := common.HexToAddress("0xC6Fe5D33615a1C52c08018c47E8Bc53646A0E101") @@ -1253,7 +1254,7 @@ func (suite *KeeperTestSuite) TestTraceBlock() { { msg: "default trace", getRequest: func() types.QueryTraceBlockRequest { - return getDefaultTraceBlockRequest(suite.network) + return getDefaultTraceBlockRequest(s.Network) }, getAdditionalTxs: func() []*types.MsgEthereumTx { return nil @@ -1266,7 +1267,7 @@ func (suite *KeeperTestSuite) TestTraceBlock() { { msg: "filtered trace", getRequest: func() types.QueryTraceBlockRequest { - defaultReq := getDefaultTraceBlockRequest(suite.network) + defaultReq := getDefaultTraceBlockRequest(s.Network) defaultReq.TraceConfig = &types.TraceConfig{ DisableStack: true, DisableStorage: true, @@ -1285,7 +1286,7 @@ func (suite *KeeperTestSuite) TestTraceBlock() { { msg: "javascript tracer", getRequest: func() types.QueryTraceBlockRequest { - defaultReq := getDefaultTraceBlockRequest(suite.network) + defaultReq := getDefaultTraceBlockRequest(s.Network) defaultReq.TraceConfig = &types.TraceConfig{ Tracer: "{data: [], fault: function(log) {}, step: function(log) { if(log.op.toString() == \"CALL\") this.data.push(log.stack.peek(0)); }, result: function() { return this.data; }}", } @@ -1300,27 +1301,27 @@ func (suite *KeeperTestSuite) TestTraceBlock() { { msg: "tracer with multiple transactions", getRequest: func() types.QueryTraceBlockRequest { - return getDefaultTraceBlockRequest(suite.network) + return getDefaultTraceBlockRequest(s.Network) }, getAdditionalTxs: func() []*types.MsgEthereumTx { - // Create predecessor tx + // create predecessor tx // Use different address to avoid nonce collision - senderKey := suite.keyring.GetKey(1) - contractAddr, err := deployErc20Contract(senderKey, suite.factory) - suite.Require().NoError(err) + senderKey := s.Keyring.GetKey(1) + contractAddr, err := deployErc20Contract(senderKey, s.Factory) + s.Require().NoError(err) - err = suite.network.NextBlock() - suite.Require().NoError(err) + err = s.Network.NextBlock() + s.Require().NoError(err) firstTransferMessage, err := executeTransferCall( transferParams{ - senderKey: suite.keyring.GetKey(1), + senderKey: s.Keyring.GetKey(1), contractAddr: contractAddr, recipientAddr: hardcodedTransferRecipient, }, - suite.factory, + s.Factory, ) - suite.Require().NoError(err) + s.Require().NoError(err) return []*types.MsgEthereumTx{firstTransferMessage} }, expPass: true, @@ -1331,7 +1332,7 @@ func (suite *KeeperTestSuite) TestTraceBlock() { { msg: "invalid trace config - Negative Limit", getRequest: func() types.QueryTraceBlockRequest { - defaultReq := getDefaultTraceBlockRequest(suite.network) + defaultReq := getDefaultTraceBlockRequest(s.Network) defaultReq.TraceConfig = &types.TraceConfig{ Limit: -1, } @@ -1345,7 +1346,7 @@ func (suite *KeeperTestSuite) TestTraceBlock() { { msg: "invalid trace config - Invalid Tracer", getRequest: func() types.QueryTraceBlockRequest { - defaultReq := getDefaultTraceBlockRequest(suite.network) + defaultReq := getDefaultTraceBlockRequest(s.Network) defaultReq.TraceConfig = &types.TraceConfig{ Tracer: "invalid_tracer", } @@ -1361,17 +1362,17 @@ func (suite *KeeperTestSuite) TestTraceBlock() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + s.Run(fmt.Sprintf("Case %s", tc.msg), func() { // Start from fresh block - suite.Require().NoError(suite.network.NextBlock()) + s.Require().NoError(s.Network.NextBlock()) // ----- Contract Deployment ----- - senderKey := suite.keyring.GetKey(0) - contractAddr, err := deployErc20Contract(senderKey, suite.factory) - suite.Require().NoError(err) + senderKey := s.Keyring.GetKey(0) + contractAddr, err := deployErc20Contract(senderKey, s.Factory) + s.Require().NoError(err) - err = suite.network.NextBlock() - suite.Require().NoError(err) + err = s.Network.NextBlock() + s.Require().NoError(err) // --- Add predecessor --- txs := tc.getAdditionalTxs() @@ -1383,57 +1384,57 @@ func (suite *KeeperTestSuite) TestTraceBlock() { contractAddr: contractAddr, recipientAddr: hardcodedTransferRecipient, }, - suite.factory, + s.Factory, ) - suite.Require().NoError(err) + s.Require().NoError(err) txs = append(txs, msgToTrace) - suite.Require().NoError(suite.network.NextBlock()) + s.Require().NoError(s.Network.NextBlock()) // Get the trace request traceReq := tc.getRequest() // Add txs to trace request traceReq.Txs = txs - res, err := suite.network.GetEvmClient().TraceBlock(suite.network.GetContext(), &traceReq) + res, err := s.Network.GetEvmClient().TraceBlock(s.Network.GetContext(), &traceReq) if tc.expPass { - suite.Require().NoError(err) + s.Require().NoError(err) // if data is too big, slice the result if len(res.Data) > 200 { - suite.Require().Contains(string(res.Data[:200]), tc.traceResponse) + s.Require().Contains(string(res.Data[:200]), tc.traceResponse) } else { - suite.Require().Contains(string(res.Data), tc.traceResponse) + s.Require().Contains(string(res.Data), tc.traceResponse) } } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *KeeperTestSuite) TestNonceInQuery() { - suite.enableFeemarket = true - defer func() { suite.enableFeemarket = false }() - suite.SetupTest() +func (s *KeeperTestSuite) TestNonceInQuery() { + s.EnableFeemarket = true + defer func() { s.EnableFeemarket = false }() + s.SetupTest() - senderKey := suite.keyring.GetKey(0) - nonce := suite.network.App.EVMKeeper.GetNonce( - suite.network.GetContext(), + senderKey := s.Keyring.GetKey(0) + nonce := s.Network.App.GetEVMKeeper().GetNonce( + s.Network.GetContext(), senderKey.Addr, ) - suite.Require().Equal(uint64(0), nonce) + s.Require().Equal(uint64(0), nonce) // accupy nonce 0 - contractAddr, err := deployErc20Contract(suite.keyring.GetKey(0), suite.factory) - suite.Require().NoError(err) + contractAddr, err := deployErc20Contract(s.Keyring.GetKey(0), s.Factory) + s.Require().NoError(err) erc20Contract, err := testdata.LoadERC20Contract() - suite.Require().NoError(err, "failed to load erc20 contract") + s.Require().NoError(err, "failed to load erc20 contract") // do an EthCall/EstimateGas with nonce 0 ctorArgs, err := erc20Contract.ABI.Pack("", senderKey.Addr, big.NewInt(1000)) - suite.Require().NoError(err) + s.Require().NoError(err) data := erc20Contract.Bin data = append(data, ctorArgs...) @@ -1442,34 +1443,34 @@ func (suite *KeeperTestSuite) TestNonceInQuery() { To: &contractAddr, Data: (*hexutil.Bytes)(&data), }) - suite.Require().NoError(err) + s.Require().NoError(err) - proposerAddress := suite.network.GetContext().BlockHeader().ProposerAddress - _, err = suite.network.GetEvmClient().EstimateGas( - suite.network.GetContext(), + proposerAddress := s.Network.GetContext().BlockHeader().ProposerAddress + _, err = s.Network.GetEvmClient().EstimateGas( + s.Network.GetContext(), &types.EthCallRequest{ Args: args, GasCap: config.DefaultGasCap, ProposerAddress: proposerAddress, }, ) - suite.Require().NoError(err) + s.Require().NoError(err) - _, err = suite.network.GetEvmClient().EthCall( - suite.network.GetContext(), + _, err = s.Network.GetEvmClient().EthCall( + s.Network.GetContext(), &types.EthCallRequest{ Args: args, GasCap: config.DefaultGasCap, ProposerAddress: proposerAddress, }, ) - suite.Require().NoError(err) + s.Require().NoError(err) } -func (suite *KeeperTestSuite) TestQueryBaseFee() { - suite.enableFeemarket = true - defer func() { suite.enableFeemarket = false }() - suite.SetupTest() +func (s *KeeperTestSuite) TestQueryBaseFee() { + s.EnableFeemarket = true + defer func() { s.EnableFeemarket = false }() + s.SetupTest() testCases := []struct { name string @@ -1485,10 +1486,10 @@ func (suite *KeeperTestSuite) TestQueryBaseFee() { }, func() { feemarketDefault := feemarkettypes.DefaultParams() - suite.Require().NoError(suite.network.App.FeeMarketKeeper.SetParams(suite.network.GetContext(), feemarketDefault)) + s.Require().NoError(s.Network.App.GetFeeMarketKeeper().SetParams(s.Network.GetContext(), feemarketDefault)) evmDefault := types.DefaultParams() - suite.Require().NoError(suite.network.App.EVMKeeper.SetParams(suite.network.GetContext(), evmDefault)) + s.Require().NoError(s.Network.App.GetEVMKeeper().SetParams(s.Network.GetContext(), evmDefault)) }, true, @@ -1500,9 +1501,9 @@ func (suite *KeeperTestSuite) TestQueryBaseFee() { }, func() { feemarketDefault := feemarkettypes.DefaultParams() - suite.Require().NoError(suite.network.App.FeeMarketKeeper.SetParams(suite.network.GetContext(), feemarketDefault)) + s.Require().NoError(s.Network.App.GetFeeMarketKeeper().SetParams(s.Network.GetContext(), feemarketDefault)) - chainConfig := types.DefaultChainConfig(suite.network.GetEIP155ChainID().Uint64()) + chainConfig := types.DefaultChainConfig(s.Network.GetEIP155ChainID().Uint64()) maxInt := sdkmath.NewInt(math.MaxInt64) chainConfig.LondonBlock = &maxInt chainConfig.ArrowGlacierBlock = &maxInt @@ -1518,7 +1519,7 @@ func (suite *KeeperTestSuite) TestQueryBaseFee() { WithChainConfig(chainConfig). WithEVMCoinInfo(testconstants.ExampleChainCoinInfo[testconstants.ExampleChainID]). Configure() - suite.Require().NoError(err) + s.Require().NoError(err) }, true, }, @@ -1531,10 +1532,10 @@ func (suite *KeeperTestSuite) TestQueryBaseFee() { func() { feemarketDefault := feemarkettypes.DefaultParams() feemarketDefault.NoBaseFee = true - suite.Require().NoError(suite.network.App.FeeMarketKeeper.SetParams(suite.network.GetContext(), feemarketDefault)) + s.Require().NoError(s.Network.App.GetFeeMarketKeeper().SetParams(s.Network.GetContext(), feemarketDefault)) evmDefault := types.DefaultParams() - suite.Require().NoError(suite.network.App.EVMKeeper.SetParams(suite.network.GetContext(), evmDefault)) + s.Require().NoError(s.Network.App.GetEVMKeeper().SetParams(s.Network.GetContext(), evmDefault)) }, true, }, @@ -1546,49 +1547,49 @@ func (suite *KeeperTestSuite) TestQueryBaseFee() { ExtendedDenom: types.GetEVMCoinExtendedDenom(), Decimals: types.GetEVMCoinDecimals(), } - chainConfig := types.DefaultChainConfig(suite.network.GetEIP155ChainID().Uint64()) + chainConfig := types.DefaultChainConfig(s.Network.GetEIP155ChainID().Uint64()) for _, tc := range testCases { - suite.Run(tc.name, func() { + s.Run(tc.name, func() { // Set necessary params tc.setParams() // Get the expected response expResp := tc.getExpResp() // Function under test - res, err := suite.network.GetEvmClient().BaseFee( - suite.network.GetContext(), + res, err := s.Network.GetEvmClient().BaseFee( + s.Network.GetContext(), &types.QueryBaseFeeRequest{}, ) if tc.expPass { - suite.Require().NotNil(res) - suite.Require().Equal(expResp, res, tc.name) - suite.Require().NoError(err) + s.Require().NotNil(res) + s.Require().Equal(expResp, res, tc.name) + s.Require().NoError(err) } else { - suite.Require().Error(err) + s.Require().Error(err) } - suite.Require().NoError(suite.network.NextBlock()) + s.Require().NoError(s.Network.NextBlock()) configurator := types.NewEVMConfigurator() configurator.ResetTestConfig() err = configurator. WithChainConfig(chainConfig). WithEVMCoinInfo(coinInfo). Configure() - suite.Require().NoError(err) + s.Require().NoError(err) }) } } -func (suite *KeeperTestSuite) TestEthCall() { - suite.SetupTest() +func (s *KeeperTestSuite) TestEthCall() { + s.SetupTest() erc20Contract, err := testdata.LoadERC20Contract() - suite.Require().NoError(err) + s.Require().NoError(err) // Generate common data for requests - sender := suite.keyring.GetAddr(0) + sender := s.Keyring.GetAddr(0) supply := sdkmath.NewIntWithDecimal(1000, 18).BigInt() ctorArgs, err := erc20Contract.ABI.Pack("", sender, supply) - suite.Require().NoError(err) + s.Require().NoError(err) data := erc20Contract.Bin data = append(data, ctorArgs...) @@ -1614,7 +1615,7 @@ func (suite *KeeperTestSuite) TestEthCall() { GasPrice: &hexBigInt, MaxFeePerGas: &hexBigInt, }) - suite.Require().NoError(err) + s.Require().NoError(err) return &types.EthCallRequest{Args: args, GasCap: config.DefaultGasCap} }, @@ -1628,17 +1629,17 @@ func (suite *KeeperTestSuite) TestEthCall() { Data: (*hexutil.Bytes)(&data), }) - suite.Require().NoError(err) + s.Require().NoError(err) req := &types.EthCallRequest{Args: args, GasCap: config.DefaultGasCap} - params := suite.network.App.EVMKeeper.GetParams(suite.network.GetContext()) + params := s.Network.App.GetEVMKeeper().GetParams(s.Network.GetContext()) params.AccessControl = types.AccessControl{ Create: types.AccessControlType{ AccessType: types.AccessTypeRestricted, }, } - err = suite.network.App.EVMKeeper.SetParams(suite.network.GetContext(), params) - suite.Require().NoError(err) + err = s.Network.App.GetEVMKeeper().SetParams(s.Network.GetContext(), params) + s.Require().NoError(err) return req }, true, @@ -1651,45 +1652,45 @@ func (suite *KeeperTestSuite) TestEthCall() { Data: (*hexutil.Bytes)(&data), }) - suite.Require().NoError(err) + s.Require().NoError(err) req := &types.EthCallRequest{Args: args, GasCap: config.DefaultGasCap} - params := suite.network.App.EVMKeeper.GetParams(suite.network.GetContext()) + params := s.Network.App.GetEVMKeeper().GetParams(s.Network.GetContext()) params.AccessControl = types.AccessControl{ Create: types.AccessControlType{ AccessType: types.AccessTypePermissioned, }, } - err = suite.network.App.EVMKeeper.SetParams(suite.network.GetContext(), params) - suite.Require().NoError(err) + err = s.Network.App.GetEVMKeeper().SetParams(s.Network.GetContext(), params) + s.Require().NoError(err) return req }, true, }, } for _, tc := range testCases { - suite.Run(tc.name, func() { + s.Run(tc.name, func() { req := tc.getReq() - res, err := suite.network.GetEvmClient().EthCall(suite.network.GetContext(), req) + res, err := s.Network.GetEvmClient().EthCall(s.Network.GetContext(), req) if tc.expVMError { - suite.Require().NotNil(res) - suite.Require().Contains(res.VmError, "does not have permission to deploy contracts") + s.Require().NotNil(res) + s.Require().Contains(res.VmError, "does not have permission to deploy contracts") } else { - suite.Require().Error(err) + s.Require().Error(err) } // Reset params defaultEvmParams := types.DefaultParams() - err = suite.network.App.EVMKeeper.SetParams(suite.network.GetContext(), defaultEvmParams) - suite.Require().NoError(err) + err = s.Network.App.GetEVMKeeper().SetParams(s.Network.GetContext(), defaultEvmParams) + s.Require().NoError(err) }) } } -func (suite *KeeperTestSuite) TestEmptyRequest() { - suite.SetupTest() - k := suite.network.App.EVMKeeper +func (s *KeeperTestSuite) TestEmptyRequest() { + s.SetupTest() + k := s.Network.App.GetEVMKeeper() testCases := []struct { name string @@ -1698,69 +1699,69 @@ func (suite *KeeperTestSuite) TestEmptyRequest() { { "Account method", func() (interface{}, error) { - return k.Account(suite.network.GetContext(), nil) + return k.Account(s.Network.GetContext(), nil) }, }, { "CosmosAccount method", func() (interface{}, error) { - return k.CosmosAccount(suite.network.GetContext(), nil) + return k.CosmosAccount(s.Network.GetContext(), nil) }, }, { "ValidatorAccount method", func() (interface{}, error) { - return k.ValidatorAccount(suite.network.GetContext(), nil) + return k.ValidatorAccount(s.Network.GetContext(), nil) }, }, { "Balance method", func() (interface{}, error) { - return k.Balance(suite.network.GetContext(), nil) + return k.Balance(s.Network.GetContext(), nil) }, }, { "Storage method", func() (interface{}, error) { - return k.Storage(suite.network.GetContext(), nil) + return k.Storage(s.Network.GetContext(), nil) }, }, { "Code method", func() (interface{}, error) { - return k.Code(suite.network.GetContext(), nil) + return k.Code(s.Network.GetContext(), nil) }, }, { "EthCall method", func() (interface{}, error) { - return k.EthCall(suite.network.GetContext(), nil) + return k.EthCall(s.Network.GetContext(), nil) }, }, { "EstimateGas method", func() (interface{}, error) { - return k.EstimateGas(suite.network.GetContext(), nil) + return k.EstimateGas(s.Network.GetContext(), nil) }, }, { "TraceTx method", func() (interface{}, error) { - return k.TraceTx(suite.network.GetContext(), nil) + return k.TraceTx(s.Network.GetContext(), nil) }, }, { "TraceBlock method", func() (interface{}, error) { - return k.TraceBlock(suite.network.GetContext(), nil) + return k.TraceBlock(s.Network.GetContext(), nil) }, }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.Run(fmt.Sprintf("Case %s", tc.name), func() { _, err := tc.queryFunc() - suite.Require().Error(err) + s.Require().Error(err) }) } } @@ -1775,7 +1776,7 @@ func getDefaultTraceBlockRequest(unitNetwork network.Network) types.QueryTraceBl } } -func deployErc20Contract(from testkeyring.Key, txFactory factory.TxFactory) (common.Address, error) { +func deployErc20Contract(from keyring.Key, txFactory factory.TxFactory) (common.Address, error) { erc20Contract, err := testdata.LoadERC20Contract() if err != nil { return common.Address{}, err @@ -1789,7 +1790,7 @@ func deployErc20Contract(from testkeyring.Key, txFactory factory.TxFactory) (com contractAddr, err := txFactory.DeployContract( from.Priv, types.EvmTxArgs{}, // Default values - factory.ContractDeploymentData{ + testutiltypes.ContractDeploymentData{ Contract: compiledContract, ConstructorArgs: constructorArgs, }, @@ -1801,7 +1802,7 @@ func deployErc20Contract(from testkeyring.Key, txFactory factory.TxFactory) (com } type transferParams struct { - senderKey testkeyring.Key + senderKey keyring.Key contractAddr common.Address recipientAddr common.Address } @@ -1818,7 +1819,7 @@ func executeTransferCall( transferArgs := types.EvmTxArgs{ To: &transferParams.contractAddr, } - callArgs := factory.CallArgs{ + callArgs := testutiltypes.CallArgs{ ContractABI: erc20Contract.ABI, MethodName: "transfer", Args: []interface{}{transferParams.recipientAddr, big.NewInt(1000)}, diff --git a/x/vm/keeper/hooks_test.go b/tests/integration/x/vm/test_hooks.go similarity index 77% rename from x/vm/keeper/hooks_test.go rename to tests/integration/x/vm/test_hooks.go index 8329f0328..c9ebd9689 100644 --- a/x/vm/keeper/hooks_test.go +++ b/tests/integration/x/vm/test_hooks.go @@ -1,4 +1,4 @@ -package keeper_test +package vm import ( "errors" @@ -32,7 +32,7 @@ func (dh FailureHook) PostTxProcessing(ctx sdk.Context, sender common.Address, m return errors.New("post tx processing failed") } -func (suite *KeeperTestSuite) TestEvmHooks() { +func (s *KeeperTestSuite) TestEvmHooks() { testCases := []struct { msg string setupHook func() types.EvmHooks @@ -44,8 +44,8 @@ func (suite *KeeperTestSuite) TestEvmHooks() { return &LogRecordHook{} }, func(hook types.EvmHooks, result error) { - suite.Require().NoError(result) - suite.Require().Equal(1, len((hook.(*LogRecordHook).Logs))) + s.Require().NoError(result) + s.Require().Equal(1, len((hook.(*LogRecordHook).Logs))) }, }, { @@ -54,18 +54,18 @@ func (suite *KeeperTestSuite) TestEvmHooks() { return &FailureHook{} }, func(hook types.EvmHooks, result error) { - suite.Require().Error(result) + s.Require().Error(result) }, }, } for _, tc := range testCases { - suite.SetupTest() + s.SetupTest() hook := tc.setupHook() - suite.network.App.EVMKeeper.SetHooks(keeper.NewMultiEvmHooks(hook)) + s.Network.App.GetEVMKeeper().SetHooks(keeper.NewMultiEvmHooks(hook)) - k := suite.network.App.EVMKeeper - ctx := suite.network.GetContext() + k := s.Network.App.GetEVMKeeper() + ctx := s.Network.GetContext() txHash := common.BigToHash(big.NewInt(1)) vmdb := statedb.New(ctx, k, statedb.NewTxConfig( common.BytesToHash(ctx.HeaderHash()), @@ -76,14 +76,14 @@ func (suite *KeeperTestSuite) TestEvmHooks() { vmdb.AddLog(ðtypes.Log{ Topics: []common.Hash{}, - Address: suite.keyring.GetAddr(0), + Address: s.Keyring.GetAddr(0), }) logs := vmdb.Logs() receipt := ðtypes.Receipt{ TxHash: txHash, Logs: logs, } - result := k.PostTxProcessing(ctx, suite.keyring.GetAddr(0), core.Message{}, receipt) + result := k.PostTxProcessing(ctx, s.Keyring.GetAddr(0), core.Message{}, receipt) tc.expFunc(hook, result) } diff --git a/x/vm/keeper/keeper_test.go b/tests/integration/x/vm/test_keeper.go similarity index 64% rename from x/vm/keeper/keeper_test.go rename to tests/integration/x/vm/test_keeper.go index 1f3f924e7..c31b3bb7f 100644 --- a/x/vm/keeper/keeper_test.go +++ b/tests/integration/x/vm/test_keeper.go @@ -1,4 +1,4 @@ -package keeper_test +package vm import ( "fmt" @@ -15,11 +15,11 @@ import ( authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) -func (suite *KeeperTestSuite) TestBaseFee() { +func (s *KeeperTestSuite) TestBaseFee() { testCases := []struct { name string - enableLondonHF bool - enableFeemarket bool + EnableLondonHF bool + EnableFeemarket bool expectBaseFee *big.Int }{ {"not enable london HF, not enable feemarket", false, false, nil}, @@ -29,20 +29,20 @@ func (suite *KeeperTestSuite) TestBaseFee() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.enableFeemarket = tc.enableFeemarket - suite.enableLondonHF = tc.enableLondonHF - suite.SetupTest() + s.Run(tc.name, func() { + s.EnableFeemarket = tc.EnableFeemarket + s.EnableLondonHF = tc.EnableLondonHF + s.SetupTest() - baseFee := suite.network.App.EVMKeeper.GetBaseFee(suite.network.GetContext()) - suite.Require().Equal(tc.expectBaseFee, baseFee) + baseFee := s.Network.App.GetEVMKeeper().GetBaseFee(s.Network.GetContext()) + s.Require().Equal(tc.expectBaseFee, baseFee) }) } - suite.enableFeemarket = false - suite.enableLondonHF = true + s.EnableFeemarket = false + s.EnableLondonHF = true } -func (suite *KeeperTestSuite) TestGetAccountStorage() { +func (s *KeeperTestSuite) TestGetAccountStorage() { var ctx sdk.Context testCases := []struct { name string @@ -56,16 +56,16 @@ func (suite *KeeperTestSuite) TestGetAccountStorage() { name: "One contract (with storage) and other EOAs", malleate: func() common.Address { supply := big.NewInt(100) - contractAddr := suite.DeployTestContract(suite.T(), ctx, suite.keyring.GetAddr(0), supply) + contractAddr := s.DeployTestContract(s.T(), ctx, s.Keyring.GetAddr(0), supply) return contractAddr }, }, } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() - ctx = suite.network.GetContext() + s.Run(tc.name, func() { + s.SetupTest() + ctx = s.Network.GetContext() var contractAddr common.Address if tc.malleate != nil { @@ -73,7 +73,7 @@ func (suite *KeeperTestSuite) TestGetAccountStorage() { } i := 0 - suite.network.App.AccountKeeper.IterateAccounts(ctx, func(account sdk.AccountI) bool { + s.Network.App.GetAccountKeeper().IterateAccounts(ctx, func(account sdk.AccountI) bool { acc, ok := account.(*authtypes.BaseAccount) if !ok { // Ignore e.g. module accounts @@ -87,15 +87,15 @@ func (suite *KeeperTestSuite) TestGetAccountStorage() { panic(fmt.Sprintf("failed to convert %s to hex address", err)) } - storage := suite.network.App.EVMKeeper.GetAccountStorage(ctx, address) + storage := s.Network.App.GetEVMKeeper().GetAccountStorage(ctx, address) if address == contractAddr { - suite.Require().NotEqual(0, len(storage), + s.Require().NotEqual(0, len(storage), "expected account %d to have non-zero amount of storage slots, got %d", i, len(storage), ) } else { - suite.Require().Len(storage, 0, + s.Require().Len(storage, 0, "expected account %d to have %d storage slots, got %d", i, 0, len(storage), ) @@ -108,15 +108,15 @@ func (suite *KeeperTestSuite) TestGetAccountStorage() { } } -func (suite *KeeperTestSuite) TestGetAccountOrEmpty() { - ctx := suite.network.GetContext() +func (s *KeeperTestSuite) TestGetAccountOrEmpty() { + ctx := s.Network.GetContext() empty := statedb.Account{ Balance: new(uint256.Int), CodeHash: evmtypes.EmptyCodeHash, } supply := big.NewInt(100) - contractAddr := suite.DeployTestContract(suite.T(), ctx, suite.keyring.GetAddr(0), supply) + contractAddr := s.DeployTestContract(s.T(), ctx, s.Keyring.GetAddr(0), supply) testCases := []struct { name string @@ -136,12 +136,12 @@ func (suite *KeeperTestSuite) TestGetAccountOrEmpty() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - res := suite.network.App.EVMKeeper.GetAccountOrEmpty(ctx, tc.addr) + s.Run(tc.name, func() { + res := s.Network.App.GetEVMKeeper().GetAccountOrEmpty(ctx, tc.addr) if tc.expEmpty { - suite.Require().Equal(empty, res) + s.Require().Equal(empty, res) } else { - suite.Require().NotEqual(empty, res) + s.Require().NotEqual(empty, res) } }) } diff --git a/x/vm/keeper/msg_server_test.go b/tests/integration/x/vm/test_msg_server.go similarity index 51% rename from x/vm/keeper/msg_server_test.go rename to tests/integration/x/vm/test_msg_server.go index 1602945e1..3c9f87d4a 100644 --- a/x/vm/keeper/msg_server_test.go +++ b/tests/integration/x/vm/test_msg_server.go @@ -1,9 +1,9 @@ -package keeper_test +package vm import ( "math/big" - "github.com/cosmos/evm/testutil/integration/os/utils" + "github.com/cosmos/evm/testutil/integration/evm/utils" "github.com/cosmos/evm/x/vm/types" sdktypes "github.com/cosmos/cosmos-sdk/types" @@ -11,10 +11,10 @@ import ( govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) -func (suite *KeeperTestSuite) TestEthereumTx() { - suite.enableFeemarket = true - defer func() { suite.enableFeemarket = false }() - suite.SetupTest() +func (s *KeeperTestSuite) TestEthereumTx() { + s.EnableFeemarket = true + defer func() { s.EnableFeemarket = false }() + s.SetupTest() testCases := []struct { name string getMsg func() *types.MsgEthereumTx @@ -27,8 +27,8 @@ func (suite *KeeperTestSuite) TestEthereumTx() { // Have insufficient gas GasLimit: 10, } - tx, err := suite.factory.GenerateSignedEthTx(suite.keyring.GetPrivKey(0), args) - suite.Require().NoError(err) + tx, err := s.Factory.GenerateSignedEthTx(s.Keyring.GetPrivKey(0), args) + s.Require().NoError(err) return tx.GetMsgs()[0].(*types.MsgEthereumTx) }, types.ErrInvalidGasCap, @@ -36,13 +36,13 @@ func (suite *KeeperTestSuite) TestEthereumTx() { { "success - transfer funds tx", func() *types.MsgEthereumTx { - recipient := suite.keyring.GetAddr(1) + recipient := s.Keyring.GetAddr(1) args := types.EvmTxArgs{ To: &recipient, Amount: big.NewInt(1e18), } - tx, err := suite.factory.GenerateSignedEthTx(suite.keyring.GetPrivKey(0), args) - suite.Require().NoError(err) + tx, err := s.Factory.GenerateSignedEthTx(s.Keyring.GetPrivKey(0), args) + s.Require().NoError(err) return tx.GetMsgs()[0].(*types.MsgEthereumTx) }, nil, @@ -50,37 +50,37 @@ func (suite *KeeperTestSuite) TestEthereumTx() { } for _, tc := range testCases { - suite.Run(tc.name, func() { + s.Run(tc.name, func() { msg := tc.getMsg() // Function to be tested - res, err := suite.network.App.EVMKeeper.EthereumTx(suite.network.GetContext(), msg) + res, err := s.Network.App.GetEVMKeeper().EthereumTx(s.Network.GetContext(), msg) - events := suite.network.GetContext().EventManager().Events() + events := s.Network.GetContext().EventManager().Events() if tc.expectedErr != nil { - suite.Require().Error(err) + s.Require().Error(err) // no events should have been emitted - suite.Require().Empty(events) + s.Require().Empty(events) } else { - suite.Require().NoError(err) - suite.Require().False(res.Failed()) + s.Require().NoError(err) + s.Require().False(res.Failed()) // check expected events were emitted - suite.Require().NotEmpty(events) - suite.Require().True(utils.ContainsEventType(events.ToABCIEvents(), types.EventTypeEthereumTx)) - suite.Require().True(utils.ContainsEventType(events.ToABCIEvents(), types.EventTypeTxLog)) - suite.Require().True(utils.ContainsEventType(events.ToABCIEvents(), sdktypes.EventTypeMessage)) + s.Require().NotEmpty(events) + s.Require().True(utils.ContainsEventType(events.ToABCIEvents(), types.EventTypeEthereumTx)) + s.Require().True(utils.ContainsEventType(events.ToABCIEvents(), types.EventTypeTxLog)) + s.Require().True(utils.ContainsEventType(events.ToABCIEvents(), sdktypes.EventTypeMessage)) } - err = suite.network.NextBlock() - suite.Require().NoError(err) + err = s.Network.NextBlock() + s.Require().NoError(err) }) } - suite.enableFeemarket = false + s.EnableFeemarket = false } -func (suite *KeeperTestSuite) TestUpdateParams() { - suite.SetupTest() +func (s *KeeperTestSuite) TestUpdateParams() { + s.SetupTest() testCases := []struct { name string getMsg func() *types.MsgUpdateParams @@ -106,18 +106,18 @@ func (suite *KeeperTestSuite) TestUpdateParams() { } for _, tc := range testCases { - suite.Run("MsgUpdateParams", func() { + s.Run("MsgUpdateParams", func() { msg := tc.getMsg() - _, err := suite.network.App.EVMKeeper.UpdateParams(suite.network.GetContext(), msg) + _, err := s.Network.App.GetEVMKeeper().UpdateParams(s.Network.GetContext(), msg) if tc.expectedErr != nil { - suite.Require().Error(err) - suite.Contains(err.Error(), tc.expectedErr.Error()) + s.Require().Error(err) + s.Contains(err.Error(), tc.expectedErr.Error()) } else { - suite.Require().NoError(err) + s.Require().NoError(err) } }) - err := suite.network.NextBlock() - suite.Require().NoError(err) + err := s.Network.NextBlock() + s.Require().NoError(err) } } diff --git a/x/vm/keeper/params_test.go b/tests/integration/x/vm/test_params.go similarity index 65% rename from x/vm/keeper/params_test.go rename to tests/integration/x/vm/test_params.go index aa59ddc59..067cb40f2 100644 --- a/x/vm/keeper/params_test.go +++ b/tests/integration/x/vm/test_params.go @@ -1,11 +1,12 @@ -package keeper_test +package vm import ( - exampleapp "github.com/cosmos/evm/evmd" + exampleapp "cosmosevm.io/evmd" + "github.com/cosmos/evm/x/vm/types" ) -func (suite *KeeperTestSuite) TestParams() { +func (s *KeeperTestSuite) TestParams() { defaultChainEVMParams := exampleapp.NewEVMGenesisState().Params defaultChainEVMParams.ActiveStaticPrecompiles = types.AvailableStaticPrecompiles @@ -21,12 +22,12 @@ func (suite *KeeperTestSuite) TestParams() { return defaultChainEVMParams }, func() interface{} { - return suite.network.App.EVMKeeper.GetParams(suite.network.GetContext()) + return s.Network.App.GetEVMKeeper().GetParams(s.Network.GetContext()) }, true, }, { - "success - Check Access Control Create param is set to restricted and can be retrieved correctly", + "success - Check Access Control create param is set to restricted and can be retrieved correctly", func() interface{} { params := defaultChainEVMParams params.AccessControl = types.AccessControl{ @@ -34,12 +35,12 @@ func (suite *KeeperTestSuite) TestParams() { AccessType: types.AccessTypeRestricted, }, } - err := suite.network.App.EVMKeeper.SetParams(suite.network.GetContext(), params) - suite.Require().NoError(err) + err := s.Network.App.GetEVMKeeper().SetParams(s.Network.GetContext(), params) + s.Require().NoError(err) return types.AccessTypeRestricted }, func() interface{} { - evmParams := suite.network.App.EVMKeeper.GetParams(suite.network.GetContext()) + evmParams := s.Network.App.GetEVMKeeper().GetParams(s.Network.GetContext()) return evmParams.GetAccessControl().Create.AccessType }, true, @@ -53,12 +54,12 @@ func (suite *KeeperTestSuite) TestParams() { AccessType: types.AccessTypeRestricted, }, } - err := suite.network.App.EVMKeeper.SetParams(suite.network.GetContext(), params) - suite.Require().NoError(err) + err := s.Network.App.GetEVMKeeper().SetParams(s.Network.GetContext(), params) + s.Require().NoError(err) return types.AccessTypeRestricted }, func() interface{} { - evmParams := suite.network.App.EVMKeeper.GetParams(suite.network.GetContext()) + evmParams := s.Network.App.GetEVMKeeper().GetParams(s.Network.GetContext()) return evmParams.GetAccessControl().Call.AccessType }, true, @@ -68,12 +69,12 @@ func (suite *KeeperTestSuite) TestParams() { func() interface{} { params := defaultChainEVMParams params.AllowUnprotectedTxs = false - err := suite.network.App.EVMKeeper.SetParams(suite.network.GetContext(), params) - suite.Require().NoError(err) + err := s.Network.App.GetEVMKeeper().SetParams(s.Network.GetContext(), params) + s.Require().NoError(err) return params.AllowUnprotectedTxs }, func() interface{} { - evmParams := suite.network.App.EVMKeeper.GetParams(suite.network.GetContext()) + evmParams := s.Network.App.GetEVMKeeper().GetParams(s.Network.GetContext()) return evmParams.GetAllowUnprotectedTxs() }, true, @@ -86,8 +87,8 @@ func (suite *KeeperTestSuite) TestParams() { "0x0000000000000000000000000000000000000801", "0x0000000000000000000000000000000000000800", } - err := suite.network.App.EVMKeeper.SetParams(suite.network.GetContext(), params) - suite.Require().NoError(err, "expected no error when setting params") + err := s.Network.App.GetEVMKeeper().SetParams(s.Network.GetContext(), params) + s.Require().NoError(err, "expected no error when setting params") // NOTE: return sorted slice here because the precompiles should be sorted when setting the params return []string{ @@ -96,17 +97,17 @@ func (suite *KeeperTestSuite) TestParams() { } }, getFun: func() interface{} { - evmParams := suite.network.App.EVMKeeper.GetParams(suite.network.GetContext()) + evmParams := s.Network.App.GetEVMKeeper().GetParams(s.Network.GetContext()) return evmParams.GetActiveStaticPrecompiles() }, expected: true, }, } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() + s.Run(tc.name, func() { + s.SetupTest() - suite.Require().Equal(tc.paramsFun(), tc.getFun(), "expected different params") + s.Require().Equal(tc.paramsFun(), tc.getFun(), "expected different params") }) } } diff --git a/x/vm/keeper/state_transition_test.go b/tests/integration/x/vm/test_state_transition.go similarity index 61% rename from x/vm/keeper/state_transition_test.go rename to tests/integration/x/vm/test_state_transition.go index 0779086d8..3b94e5d38 100644 --- a/x/vm/keeper/state_transition_test.go +++ b/tests/integration/x/vm/test_state_transition.go @@ -1,10 +1,11 @@ -package keeper_test +package vm import ( "fmt" "math" "math/big" + exampleapp "cosmosevm.io/evmd" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" gethtypes "github.com/ethereum/go-ethereum/core/types" @@ -14,12 +15,11 @@ import ( tmproto "github.com/cometbft/cometbft/proto/tendermint/types" cmttypes "github.com/cometbft/cometbft/types" - exampleapp "github.com/cosmos/evm/evmd" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" - "github.com/cosmos/evm/testutil/integration/os/utils" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/integration/evm/utils" + testKeyring "github.com/cosmos/evm/testutil/keyring" utiltx "github.com/cosmos/evm/testutil/tx" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" "github.com/cosmos/evm/x/vm/keeper" @@ -34,9 +34,9 @@ import ( stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) -func (suite *KeeperTestSuite) TestGetHashFn() { - suite.SetupTest() - header := suite.network.GetContext().BlockHeader() +func (s *KeeperTestSuite) TestGetHashFn() { + s.SetupTest() + header := s.Network.GetContext().BlockHeader() h, _ := cmttypes.HeaderFromProto(&header) hash := h.Hash() @@ -48,9 +48,9 @@ func (suite *KeeperTestSuite) TestGetHashFn() { }{ { "case 1.1: context hash cached", - uint64(suite.network.GetContext().BlockHeight()), //nolint:gosec // G115 + uint64(s.Network.GetContext().BlockHeight()), //nolint:gosec // G115 func() sdk.Context { - return suite.network.GetContext().WithHeaderHash( + return s.Network.GetContext().WithHeaderHash( tmhash.Sum([]byte("header")), ) }, @@ -58,19 +58,19 @@ func (suite *KeeperTestSuite) TestGetHashFn() { }, { "case 1.2: failed to cast Tendermint header", - uint64(suite.network.GetContext().BlockHeight()), //nolint:gosec // G115 + uint64(s.Network.GetContext().BlockHeight()), //nolint:gosec // G115 func() sdk.Context { header := tmproto.Header{} - header.Height = suite.network.GetContext().BlockHeight() - return suite.network.GetContext().WithBlockHeader(header) + header.Height = s.Network.GetContext().BlockHeight() + return s.Network.GetContext().WithBlockHeader(header) }, common.Hash{}, }, { "case 1.3: hash calculated from Tendermint header", - uint64(suite.network.GetContext().BlockHeight()), //nolint:gosec // G115 + uint64(s.Network.GetContext().BlockHeight()), //nolint:gosec // G115 func() sdk.Context { - return suite.network.GetContext().WithBlockHeader(header) + return s.Network.GetContext().WithBlockHeader(header) }, common.BytesToHash(hash), }, @@ -78,7 +78,7 @@ func (suite *KeeperTestSuite) TestGetHashFn() { "case 2.1: height lower than current one, hist info not found", 1, func() sdk.Context { - return suite.network.GetContext().WithBlockHeight(10) + return s.Network.GetContext().WithBlockHeight(10) }, common.Hash{}, }, @@ -86,8 +86,8 @@ func (suite *KeeperTestSuite) TestGetHashFn() { "case 2.2: height lower than current one, invalid hist info header", 1, func() sdk.Context { - suite.Require().NoError(suite.network.App.StakingKeeper.SetHistoricalInfo(suite.network.GetContext(), 1, &stakingtypes.HistoricalInfo{})) - return suite.network.GetContext().WithBlockHeight(10) + s.Require().NoError(s.Network.App.GetStakingKeeper().SetHistoricalInfo(s.Network.GetContext(), 1, &stakingtypes.HistoricalInfo{})) + return s.Network.GetContext().WithBlockHeight(10) }, common.Hash{}, }, @@ -98,36 +98,36 @@ func (suite *KeeperTestSuite) TestGetHashFn() { histInfo := &stakingtypes.HistoricalInfo{ Header: header, } - suite.Require().NoError(suite.network.App.StakingKeeper.SetHistoricalInfo(suite.network.GetContext(), 1, histInfo)) - return suite.network.GetContext().WithBlockHeight(10) + s.Require().NoError(s.Network.App.GetStakingKeeper().SetHistoricalInfo(s.Network.GetContext(), 1, histInfo)) + return s.Network.GetContext().WithBlockHeight(10) }, common.BytesToHash(hash), }, { "case 3: height greater than current one", 200, - func() sdk.Context { return suite.network.GetContext() }, + func() sdk.Context { return s.Network.GetContext() }, common.Hash{}, }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + s.Run(fmt.Sprintf("Case %s", tc.msg), func() { ctx := tc.malleate() // Function being tested - hash := suite.network.App.EVMKeeper.GetHashFn(ctx)(tc.height) - suite.Require().Equal(tc.expHash, hash) + hash := s.Network.App.GetEVMKeeper().GetHashFn(ctx)(tc.height) + s.Require().Equal(tc.expHash, hash) - err := suite.network.NextBlock() - suite.Require().NoError(err) + err := s.Network.NextBlock() + s.Require().NoError(err) }) } } -func (suite *KeeperTestSuite) TestGetCoinbaseAddress() { - suite.SetupTest() - validators := suite.network.GetValidators() +func (s *KeeperTestSuite) TestGetCoinbaseAddress() { + s.SetupTest() + validators := s.Network.GetValidators() proposerAddressHex := utils.ValidatorConsAddressToHex( validators[0].OperatorAddress, ) @@ -140,44 +140,44 @@ func (suite *KeeperTestSuite) TestGetCoinbaseAddress() { { "validator not found", func() sdk.Context { - header := suite.network.GetContext().BlockHeader() + header := s.Network.GetContext().BlockHeader() header.ProposerAddress = []byte{} - return suite.network.GetContext().WithBlockHeader(header) + return s.Network.GetContext().WithBlockHeader(header) }, false, }, { "success", func() sdk.Context { - return suite.network.GetContext() + return s.Network.GetContext() }, true, }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + s.Run(fmt.Sprintf("Case %s", tc.msg), func() { ctx := tc.malleate() proposerAddress := ctx.BlockHeader().ProposerAddress // Function being tested - coinbase, err := suite.network.App.EVMKeeper.GetCoinbaseAddress( + coinbase, err := s.Network.App.GetEVMKeeper().GetCoinbaseAddress( ctx, sdk.ConsAddress(proposerAddress), ) if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(proposerAddressHex, coinbase) + s.Require().NoError(err) + s.Require().Equal(proposerAddressHex, coinbase) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *KeeperTestSuite) TestGetEthIntrinsicGas() { - suite.SetupTest() +func (s *KeeperTestSuite) TestGetEthIntrinsicGas() { + s.SetupTest() testCases := []struct { name string data []byte @@ -257,21 +257,21 @@ func (suite *KeeperTestSuite) TestGetEthIntrinsicGas() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.Run(fmt.Sprintf("Case %s", tc.name), func() { ethCfg := types.GetEthChainConfig() ethCfg.HomesteadBlock = big.NewInt(2) ethCfg.IstanbulBlock = big.NewInt(3) signer := gethtypes.LatestSignerForChainID(ethCfg.ChainID) // in the future, fork not enabled - shanghaiTime := uint64(suite.network.GetContext().BlockTime().Unix()) + 10000 //#nosec G115 -- int overflow is not a concern here + shanghaiTime := uint64(s.Network.GetContext().BlockTime().Unix()) + 10000 //#nosec G115 -- int overflow is not a concern here ethCfg.ShanghaiTime = &shanghaiTime - ctx := suite.network.GetContext().WithBlockHeight(tc.height) + ctx := s.Network.GetContext().WithBlockHeight(tc.height) - addr := suite.keyring.GetAddr(0) - krSigner := utiltx.NewSigner(suite.keyring.GetPrivKey(0)) - nonce := suite.network.App.EVMKeeper.GetNonce(ctx, addr) + addr := s.Keyring.GetAddr(0) + krSigner := utiltx.NewSigner(s.Keyring.GetPrivKey(0)) + nonce := s.Network.App.GetEVMKeeper().GetNonce(ctx, addr) m, err := newNativeMessage( nonce, ctx.BlockHeight(), @@ -283,10 +283,10 @@ func (suite *KeeperTestSuite) TestGetEthIntrinsicGas() { tc.data, tc.accessList, ) - suite.Require().NoError(err) + s.Require().NoError(err) // Function being tested - gas, err := suite.network.App.EVMKeeper.GetEthIntrinsicGas( + gas, err := s.Network.App.GetEVMKeeper().GetEthIntrinsicGas( ctx, *m, ethCfg, @@ -294,18 +294,18 @@ func (suite *KeeperTestSuite) TestGetEthIntrinsicGas() { ) if tc.noError { - suite.Require().NoError(err) + s.Require().NoError(err) } else { - suite.Require().Error(err) + s.Require().Error(err) } - suite.Require().Equal(tc.expGas, gas) + s.Require().Equal(tc.expGas, gas) }) } } -func (suite *KeeperTestSuite) TestGasToRefund() { - suite.SetupTest() +func (s *KeeperTestSuite) TestGasToRefund() { + s.SetupTest() testCases := []struct { name string gasconsumed uint64 @@ -344,8 +344,8 @@ func (suite *KeeperTestSuite) TestGasToRefund() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - vmdb := suite.network.GetStateDB() + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + vmdb := s.Network.GetStateDB() vmdb.AddRefund(10) if tc.expPanic { @@ -353,16 +353,16 @@ func (suite *KeeperTestSuite) TestGasToRefund() { //nolint:staticcheck keeper.GasToRefund(vmdb.GetRefund(), tc.gasconsumed, tc.refundQuotient) } - suite.Require().Panics(panicF) + s.Require().Panics(panicF) } else { gr := keeper.GasToRefund(vmdb.GetRefund(), tc.gasconsumed, tc.refundQuotient) - suite.Require().Equal(tc.expGasRefund, gr) + s.Require().Equal(tc.expGasRefund, gr) } }) } } -func (suite *KeeperTestSuite) TestRefundGas() { +func (s *KeeperTestSuite) TestRefundGas() { // FeeCollector account is pre-funded with enough tokens // for refund to work // NOTE: everything should happen within the same block for @@ -384,16 +384,17 @@ func (suite *KeeperTestSuite) TestRefundGas() { customGenesis := network.CustomGenesisState{} customGenesis[banktypes.ModuleName] = bankGenesis - keyring := testkeyring.New(2) + Keyring := testKeyring.New(2) unitNetwork := network.NewUnitTestNetwork( - network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), + s.Create, + network.WithPreFundedAccounts(Keyring.GetAllAccAddrs()...), network.WithCustomGenesis(customGenesis), ) grpcHandler := grpc.NewIntegrationHandler(unitNetwork) txFactory := factory.New(unitNetwork, grpcHandler) - sender := keyring.GetKey(0) - recipient := keyring.GetAddr(1) + sender := Keyring.GetKey(0) + recipient := Keyring.GetAddr(1) testCases := []struct { name string @@ -442,7 +443,7 @@ func (suite *KeeperTestSuite) TestRefundGas() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.Run(fmt.Sprintf("Case %s", tc.name), func() { coreMsg, err := txFactory.GenerateGethCoreMsg( sender.Priv, types.EvmTxArgs{ @@ -451,7 +452,7 @@ func (suite *KeeperTestSuite) TestRefundGas() { GasPrice: tc.gasPrice, }, ) - suite.Require().NoError(err) + s.Require().NoError(err) transactionGas := coreMsg.GasLimit vmdb := unitNetwork.GetStateDB() @@ -463,9 +464,9 @@ func (suite *KeeperTestSuite) TestRefundGas() { gasUsed := transactionGas - tc.leftoverGas refund := keeper.GasToRefund(vmdb.GetRefund(), gasUsed, tc.refundQuotient) - suite.Require().Equal(tc.expGasRefund, refund) + s.Require().Equal(tc.expGasRefund, refund) - err = unitNetwork.App.EVMKeeper.RefundGas( + err = unitNetwork.App.GetEVMKeeper().RefundGas( unitNetwork.GetContext(), *coreMsg, refund, @@ -473,16 +474,16 @@ func (suite *KeeperTestSuite) TestRefundGas() { ) if tc.noError { - suite.Require().NoError(err) + s.Require().NoError(err) } else { - suite.Require().Error(err) + s.Require().Error(err) } }) } } -func (suite *KeeperTestSuite) TestResetGasMeterAndConsumeGas() { - suite.SetupTest() +func (s *KeeperTestSuite) TestResetGasMeterAndConsumeGas() { + s.SetupTest() testCases := []struct { name string gasConsumed uint64 @@ -522,57 +523,57 @@ func (suite *KeeperTestSuite) TestResetGasMeterAndConsumeGas() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.Run(fmt.Sprintf("Case %s", tc.name), func() { panicF := func() { gm := storetypes.NewGasMeter(10) gm.ConsumeGas(tc.gasConsumed, "") - ctx := suite.network.GetContext().WithGasMeter(gm) - suite.network.App.EVMKeeper.ResetGasMeterAndConsumeGas(ctx, tc.gasUsed) + ctx := s.Network.GetContext().WithGasMeter(gm) + s.Network.App.GetEVMKeeper().ResetGasMeterAndConsumeGas(ctx, tc.gasUsed) } if tc.expPanic { - suite.Require().Panics(panicF) + s.Require().Panics(panicF) } else { - suite.Require().NotPanics(panicF) + s.Require().NotPanics(panicF) } }) } } -func (suite *KeeperTestSuite) TestEVMConfig() { - suite.SetupTest() +func (s *KeeperTestSuite) TestEVMConfig() { + s.SetupTest() defaultChainEVMParams := exampleapp.NewEVMGenesisState().Params - proposerAddress := suite.network.GetContext().BlockHeader().ProposerAddress - cfg, err := suite.network.App.EVMKeeper.EVMConfig( - suite.network.GetContext(), + proposerAddress := s.Network.GetContext().BlockHeader().ProposerAddress + cfg, err := s.Network.App.GetEVMKeeper().EVMConfig( + s.Network.GetContext(), proposerAddress, ) - suite.Require().NoError(err) - suite.Require().Equal(defaultChainEVMParams, cfg.Params) + s.Require().NoError(err) + s.Require().Equal(defaultChainEVMParams, cfg.Params) // london hardfork is enabled by default - suite.Require().Equal(big.NewInt(0), cfg.BaseFee) + s.Require().Equal(big.NewInt(0), cfg.BaseFee) - validators := suite.network.GetValidators() + validators := s.Network.GetValidators() proposerHextAddress := utils.ValidatorConsAddressToHex(validators[0].OperatorAddress) - suite.Require().Equal(proposerHextAddress, cfg.CoinBase) + s.Require().Equal(proposerHextAddress, cfg.CoinBase) } -func (suite *KeeperTestSuite) TestApplyTransaction() { - suite.enableFeemarket = true - defer func() { suite.enableFeemarket = false }() +func (s *KeeperTestSuite) TestApplyTransaction() { + s.EnableFeemarket = true + defer func() { s.EnableFeemarket = false }() // FeeCollector account is pre-funded with enough tokens // for refund to work // NOTE: everything should happen within the same block for // feecollector account to remain funded - suite.SetupTest() + s.SetupTest() // set bounded cosmos block gas limit - ctx := suite.network.GetContext().WithBlockGasMeter(storetypes.NewGasMeter(1e6)) - err := suite.network.App.BankKeeper.MintCoins(ctx, "mint", sdk.NewCoins(sdk.NewCoin("aatom", sdkmath.NewInt(3e18)))) - suite.Require().NoError(err) - err = suite.network.App.BankKeeper.SendCoinsFromModuleToModule(ctx, "mint", "fee_collector", sdk.NewCoins(sdk.NewCoin("aatom", sdkmath.NewInt(3e18)))) - suite.Require().NoError(err) + ctx := s.Network.GetContext().WithBlockGasMeter(storetypes.NewGasMeter(1e6)) + err := s.Network.App.GetBankKeeper().MintCoins(ctx, "mint", sdk.NewCoins(sdk.NewCoin("aatom", sdkmath.NewInt(3e18)))) + s.Require().NoError(err) + err = s.Network.App.GetBankKeeper().SendCoinsFromModuleToModule(ctx, "mint", "fee_collector", sdk.NewCoins(sdk.NewCoin("aatom", sdkmath.NewInt(3e18)))) + s.Require().NoError(err) testCases := []struct { name string gasLimit uint64 @@ -588,68 +589,68 @@ func (suite *KeeperTestSuite) TestApplyTransaction() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - tx, err := suite.factory.GenerateSignedEthTx(suite.keyring.GetPrivKey(0), types.EvmTxArgs{ + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + tx, err := s.Factory.GenerateSignedEthTx(s.Keyring.GetPrivKey(0), types.EvmTxArgs{ GasLimit: tc.gasLimit, }) - suite.Require().NoError(err) - initialBalance := suite.network.App.BankKeeper.GetBalance(ctx, suite.keyring.GetAccAddr(0), "aatom") + s.Require().NoError(err) + initialBalance := s.Network.App.GetBankKeeper().GetBalance(ctx, s.Keyring.GetAccAddr(0), "aatom") ethTx := tx.GetMsgs()[0].(*types.MsgEthereumTx).AsTransaction() - res, err := suite.network.App.EVMKeeper.ApplyTransaction(ctx, ethTx) - suite.Require().NoError(err) - suite.Require().Equal(res.GasUsed, uint64(3e6)) + res, err := s.Network.App.GetEVMKeeper().ApplyTransaction(ctx, ethTx) + s.Require().NoError(err) + s.Require().Equal(res.GasUsed, uint64(3e6)) // Half of the gas should be refunded based on the protocol refund cap. // Note that the balance should only increment by the refunded amount // because ApplyTransaction does not consume and take the gas from the user. - balanceAfterRefund := suite.network.App.BankKeeper.GetBalance(ctx, suite.keyring.GetAccAddr(0), "aatom") - expectedRefund := new(big.Int).Mul(new(big.Int).SetUint64(6e6/2), suite.network.App.EVMKeeper.GetBaseFee(ctx)) - suite.Require().Equal(balanceAfterRefund.Sub(initialBalance).Amount, sdkmath.NewIntFromBigInt(expectedRefund)) + balanceAfterRefund := s.Network.App.GetBankKeeper().GetBalance(ctx, s.Keyring.GetAccAddr(0), "aatom") + expectedRefund := new(big.Int).Mul(new(big.Int).SetUint64(6e6/2), s.Network.App.GetEVMKeeper().GetBaseFee(ctx)) + s.Require().Equal(balanceAfterRefund.Sub(initialBalance).Amount, sdkmath.NewIntFromBigInt(expectedRefund)) }) } } -func (suite *KeeperTestSuite) TestApplyMessage() { - suite.enableFeemarket = true - defer func() { suite.enableFeemarket = false }() - suite.SetupTest() +func (s *KeeperTestSuite) TestApplyMessage() { + s.EnableFeemarket = true + defer func() { s.EnableFeemarket = false }() + s.SetupTest() // Generate a transfer tx message - sender := suite.keyring.GetKey(0) - recipient := suite.keyring.GetAddr(1) + sender := s.Keyring.GetKey(0) + recipient := s.Keyring.GetAddr(1) transferArgs := types.EvmTxArgs{ To: &recipient, Amount: big.NewInt(100), } - coreMsg, err := suite.factory.GenerateGethCoreMsg( + coreMsg, err := s.Factory.GenerateGethCoreMsg( sender.Priv, transferArgs, ) - suite.Require().NoError(err) + s.Require().NoError(err) - tracer := suite.network.App.EVMKeeper.Tracer( - suite.network.GetContext(), + tracer := s.Network.App.GetEVMKeeper().Tracer( + s.Network.GetContext(), *coreMsg, types.GetEthChainConfig(), ) - res, err := suite.network.App.EVMKeeper.ApplyMessage( - suite.network.GetContext(), + res, err := s.Network.App.GetEVMKeeper().ApplyMessage( + s.Network.GetContext(), *coreMsg, tracer, true, ) - suite.Require().NoError(err) - suite.Require().False(res.Failed()) + s.Require().NoError(err) + s.Require().False(res.Failed()) // Compare gas to a transfer tx gas expectedGasUsed := params.TxGas - suite.Require().Equal(expectedGasUsed, res.GasUsed) + s.Require().Equal(expectedGasUsed, res.GasUsed) } -func (suite *KeeperTestSuite) TestApplyMessageWithConfig() { - suite.enableFeemarket = true - defer func() { suite.enableFeemarket = false }() - suite.SetupTest() +func (s *KeeperTestSuite) TestApplyMessageWithConfig() { + s.EnableFeemarket = true + defer func() { s.EnableFeemarket = false }() + s.SetupTest() testCases := []struct { name string getMessage func() core.Message @@ -662,13 +663,13 @@ func (suite *KeeperTestSuite) TestApplyMessageWithConfig() { { "success - messsage applied ok with default params", func() core.Message { - sender := suite.keyring.GetKey(0) - recipient := suite.keyring.GetAddr(1) - msg, err := suite.factory.GenerateGethCoreMsg(sender.Priv, types.EvmTxArgs{ + sender := s.Keyring.GetKey(0) + recipient := s.Keyring.GetAddr(1) + msg, err := s.Factory.GenerateGethCoreMsg(sender.Priv, types.EvmTxArgs{ To: &recipient, Amount: big.NewInt(100), }) - suite.Require().NoError(err) + s.Require().NoError(err) return *msg }, types.DefaultParams, @@ -680,14 +681,14 @@ func (suite *KeeperTestSuite) TestApplyMessageWithConfig() { { "call contract tx with config param EnableCall = false", func() core.Message { - sender := suite.keyring.GetKey(0) - recipient := suite.keyring.GetAddr(1) - msg, err := suite.factory.GenerateGethCoreMsg(sender.Priv, types.EvmTxArgs{ + sender := s.Keyring.GetKey(0) + recipient := s.Keyring.GetAddr(1) + msg, err := s.Factory.GenerateGethCoreMsg(sender.Priv, types.EvmTxArgs{ To: &recipient, Amount: big.NewInt(100), Input: []byte("contract_data"), }) - suite.Require().NoError(err) + s.Require().NoError(err) return *msg }, func() types.Params { @@ -707,12 +708,12 @@ func (suite *KeeperTestSuite) TestApplyMessageWithConfig() { { "create contract tx with config param EnableCreate = false", func() core.Message { - sender := suite.keyring.GetKey(0) - msg, err := suite.factory.GenerateGethCoreMsg(sender.Priv, types.EvmTxArgs{ + sender := s.Keyring.GetKey(0) + msg, err := s.Factory.GenerateGethCoreMsg(sender.Priv, types.EvmTxArgs{ Amount: big.NewInt(100), Input: []byte("contract_data"), }) - suite.Require().NoError(err) + s.Require().NoError(err) return *msg }, func() types.Params { @@ -732,19 +733,19 @@ func (suite *KeeperTestSuite) TestApplyMessageWithConfig() { { "fail - fix panic when minimumGasUsed is not uint64", func() core.Message { - sender := suite.keyring.GetKey(0) - recipient := suite.keyring.GetAddr(1) - msg, err := suite.factory.GenerateGethCoreMsg(sender.Priv, types.EvmTxArgs{ + sender := s.Keyring.GetKey(0) + recipient := s.Keyring.GetAddr(1) + msg, err := s.Factory.GenerateGethCoreMsg(sender.Priv, types.EvmTxArgs{ To: &recipient, Amount: big.NewInt(100), }) - suite.Require().NoError(err) + s.Require().NoError(err) return *msg }, types.DefaultParams, func() feemarkettypes.Params { - paramsRes, err := suite.handler.GetFeeMarketParams() - suite.Require().NoError(err) + paramsRes, err := s.Handler.GetFeeMarketParams() + s.Require().NoError(err) params := paramsRes.GetParams() params.MinGasMultiplier = sdkmath.LegacyNewDec(math.MaxInt64).MulInt64(100) return params @@ -756,35 +757,35 @@ func (suite *KeeperTestSuite) TestApplyMessageWithConfig() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.Run(fmt.Sprintf("Case %s", tc.name), func() { msg := tc.getMessage() evmParams := tc.getEVMParams() - err := suite.network.App.EVMKeeper.SetParams( - suite.network.GetContext(), + err := s.Network.App.GetEVMKeeper().SetParams( + s.Network.GetContext(), evmParams, ) - suite.Require().NoError(err) + s.Require().NoError(err) feeMarketparams := tc.getFeeMarketParams() - err = suite.network.App.FeeMarketKeeper.SetParams( - suite.network.GetContext(), + err = s.Network.App.GetFeeMarketKeeper().SetParams( + s.Network.GetContext(), feeMarketparams, ) - suite.Require().NoError(err) + s.Require().NoError(err) - txConfig := suite.network.App.EVMKeeper.TxConfig( - suite.network.GetContext(), + txConfig := s.Network.App.GetEVMKeeper().TxConfig( + s.Network.GetContext(), common.Hash{}, ) - proposerAddress := suite.network.GetContext().BlockHeader().ProposerAddress - config, err := suite.network.App.EVMKeeper.EVMConfig( - suite.network.GetContext(), + proposerAddress := s.Network.GetContext().BlockHeader().ProposerAddress + config, err := s.Network.App.GetEVMKeeper().EVMConfig( + s.Network.GetContext(), proposerAddress, ) - suite.Require().NoError(err) + s.Require().NoError(err) // Function being tested - res, err := suite.network.App.EVMKeeper.ApplyMessageWithConfig( - suite.network.GetContext(), + res, err := s.Network.App.GetEVMKeeper().ApplyMessageWithConfig( + s.Network.GetContext(), msg, nil, true, @@ -793,33 +794,33 @@ func (suite *KeeperTestSuite) TestApplyMessageWithConfig() { ) if tc.expErr { - suite.Require().Error(err) + s.Require().Error(err) } else if !tc.expVMErr { - suite.Require().NoError(err) - suite.Require().False(res.Failed()) - suite.Require().Equal(tc.expectedGasUsed, res.GasUsed) + s.Require().NoError(err) + s.Require().False(res.Failed()) + s.Require().Equal(tc.expectedGasUsed, res.GasUsed) } - err = suite.network.NextBlock() + err = s.Network.NextBlock() if tc.expVMErr { - suite.Require().NotEmpty(res.VmError) + s.Require().NotEmpty(res.VmError) return } if tc.expVMErr { - suite.Require().NotEmpty(res.VmError) + s.Require().NotEmpty(res.VmError) return } - suite.Require().NoError(err) + s.Require().NoError(err) }) } } -func (suite *KeeperTestSuite) TestGetProposerAddress() { - suite.SetupTest() - address := sdk.ConsAddress(suite.keyring.GetAddr(0).Bytes()) - proposerAddress := sdk.ConsAddress(suite.network.GetContext().BlockHeader().ProposerAddress) +func (s *KeeperTestSuite) TestGetProposerAddress() { + s.SetupTest() + address := sdk.ConsAddress(s.Keyring.GetAddr(0).Bytes()) + proposerAddress := sdk.ConsAddress(s.Network.GetContext().BlockHeader().ProposerAddress) testCases := []struct { msg string addr sdk.ConsAddress @@ -842,10 +843,10 @@ func (suite *KeeperTestSuite) TestGetProposerAddress() { }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.Require().Equal( + s.Run(fmt.Sprintf("Case %s", tc.msg), func() { + s.Require().Equal( tc.expAdr, - keeper.GetProposerAddress(suite.network.GetContext(), tc.addr), + keeper.GetProposerAddress(s.Network.GetContext(), tc.addr), ) }) } diff --git a/x/vm/keeper/statedb_test.go b/tests/integration/x/vm/test_statedb.go similarity index 56% rename from x/vm/keeper/statedb_test.go rename to tests/integration/x/vm/test_statedb.go index ff1d098df..963143a4f 100644 --- a/x/vm/keeper/statedb_test.go +++ b/tests/integration/x/vm/test_statedb.go @@ -1,10 +1,8 @@ -package keeper_test +package vm import ( - "bytes" "fmt" "math/big" - "testing" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/tracing" @@ -13,14 +11,10 @@ import ( "github.com/ethereum/go-ethereum/crypto" ethparams "github.com/ethereum/go-ethereum/params" "github.com/holiman/uint256" - "github.com/stretchr/testify/require" - "github.com/cosmos/evm/contracts" testconstants "github.com/cosmos/evm/testutil/constants" - testfactory "github.com/cosmos/evm/testutil/integration/os/factory" - testhandler "github.com/cosmos/evm/testutil/integration/os/grpc" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/network" + testKeyring "github.com/cosmos/evm/testutil/keyring" utiltx "github.com/cosmos/evm/testutil/tx" "github.com/cosmos/evm/x/vm/statedb" "github.com/cosmos/evm/x/vm/types" @@ -36,7 +30,7 @@ import ( authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) -func (suite *KeeperTestSuite) TestCreateAccount() { +func (s *KeeperTestSuite) TestCreateAccount() { testCases := []struct { name string addr common.Address @@ -48,27 +42,27 @@ func (suite *KeeperTestSuite) TestCreateAccount() { utiltx.GenerateAddress(), func(vmdb vm.StateDB, addr common.Address) { vmdb.AddBalance(addr, uint256.NewInt(100), tracing.BalanceChangeUnspecified) - suite.Require().NotZero(vmdb.GetBalance(addr).Uint64()) + s.Require().NotZero(vmdb.GetBalance(addr).Uint64()) }, func(vmdb vm.StateDB, addr common.Address) { - suite.Require().Equal(vmdb.GetBalance(addr).Uint64(), uint64(100)) + s.Require().Equal(vmdb.GetBalance(addr).Uint64(), uint64(100)) }, }, { "create account", utiltx.GenerateAddress(), func(vmdb vm.StateDB, addr common.Address) { - suite.Require().False(vmdb.Exist(addr)) + s.Require().False(vmdb.Exist(addr)) }, func(vmdb vm.StateDB, addr common.Address) { - suite.Require().True(vmdb.Exist(addr)) + s.Require().True(vmdb.Exist(addr)) }, }, } for _, tc := range testCases { - suite.Run(tc.name, func() { - vmdb := suite.StateDB() + s.Run(tc.name, func() { + vmdb := s.StateDB() tc.malleate(vmdb, tc.addr) vmdb.CreateAccount(tc.addr) tc.callback(vmdb, tc.addr) @@ -76,7 +70,7 @@ func (suite *KeeperTestSuite) TestCreateAccount() { } } -func (suite *KeeperTestSuite) TestAddBalance() { +func (s *KeeperTestSuite) TestAddBalance() { testCases := []struct { name string amount *uint256.Int @@ -95,22 +89,22 @@ func (suite *KeeperTestSuite) TestAddBalance() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - vmdb := suite.StateDB() - prev := vmdb.GetBalance(suite.keyring.GetAddr(0)) - vmdb.AddBalance(suite.keyring.GetAddr(0), tc.amount, tracing.BalanceChangeUnspecified) - post := vmdb.GetBalance(suite.keyring.GetAddr(0)) + s.Run(tc.name, func() { + vmdb := s.StateDB() + prev := vmdb.GetBalance(s.Keyring.GetAddr(0)) + vmdb.AddBalance(s.Keyring.GetAddr(0), tc.amount, tracing.BalanceChangeUnspecified) + post := vmdb.GetBalance(s.Keyring.GetAddr(0)) if tc.isNoOp { - suite.Require().Equal(prev, post) + s.Require().Equal(prev, post) } else { - suite.Require().Equal(new(uint256.Int).Add(prev, tc.amount), post) + s.Require().Equal(new(uint256.Int).Add(prev, tc.amount), post) } }) } } -func (suite *KeeperTestSuite) TestSubBalance() { +func (s *KeeperTestSuite) TestSubBalance() { testCases := []struct { name string amount *uint256.Int @@ -127,7 +121,7 @@ func (suite *KeeperTestSuite) TestSubBalance() { "positive amount, above zero", uint256.NewInt(50), func(vmdb vm.StateDB) { - vmdb.AddBalance(suite.keyring.GetAddr(0), uint256.NewInt(100), tracing.BalanceChangeUnspecified) + vmdb.AddBalance(s.Keyring.GetAddr(0), uint256.NewInt(100), tracing.BalanceChangeUnspecified) }, false, }, @@ -140,24 +134,24 @@ func (suite *KeeperTestSuite) TestSubBalance() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - vmdb := suite.StateDB() + s.Run(tc.name, func() { + vmdb := s.StateDB() tc.malleate(vmdb) - prev := vmdb.GetBalance(suite.keyring.GetAddr(0)) - vmdb.SubBalance(suite.keyring.GetAddr(0), tc.amount, tracing.BalanceChangeUnspecified) - post := vmdb.GetBalance(suite.keyring.GetAddr(0)) + prev := vmdb.GetBalance(s.Keyring.GetAddr(0)) + vmdb.SubBalance(s.Keyring.GetAddr(0), tc.amount, tracing.BalanceChangeUnspecified) + post := vmdb.GetBalance(s.Keyring.GetAddr(0)) if tc.isNoOp { - suite.Require().Equal(prev, post) + s.Require().Equal(prev, post) } else { - suite.Require().Equal(new(uint256.Int).Sub(prev, tc.amount), post) + s.Require().Equal(new(uint256.Int).Sub(prev, tc.amount), post) } }) } } -func (suite *KeeperTestSuite) TestGetNonce() { +func (s *KeeperTestSuite) TestGetNonce() { testCases := []struct { name string address common.Address @@ -172,26 +166,26 @@ func (suite *KeeperTestSuite) TestGetNonce() { }, { "existing account", - suite.keyring.GetAddr(0), + s.Keyring.GetAddr(0), 1, func(vmdb vm.StateDB) { - vmdb.SetNonce(suite.keyring.GetAddr(0), 1, tracing.NonceChangeUnspecified) + vmdb.SetNonce(s.Keyring.GetAddr(0), 1, tracing.NonceChangeUnspecified) }, }, } for _, tc := range testCases { - suite.Run(tc.name, func() { - vmdb := suite.StateDB() + s.Run(tc.name, func() { + vmdb := s.StateDB() tc.malleate(vmdb) nonce := vmdb.GetNonce(tc.address) - suite.Require().Equal(tc.expectedNonce, nonce) + s.Require().Equal(tc.expectedNonce, nonce) }) } } -func (suite *KeeperTestSuite) TestSetNonce() { +func (s *KeeperTestSuite) TestSetNonce() { testCases := []struct { name string address common.Address @@ -206,27 +200,27 @@ func (suite *KeeperTestSuite) TestSetNonce() { }, { "existing account", - suite.keyring.GetAddr(0), + s.Keyring.GetAddr(0), 99, func() {}, }, } for _, tc := range testCases { - suite.Run(tc.name, func() { - vmdb := suite.StateDB() + s.Run(tc.name, func() { + vmdb := s.StateDB() vmdb.SetNonce(tc.address, tc.nonce, tracing.NonceChangeUnspecified) nonce := vmdb.GetNonce(tc.address) - suite.Require().Equal(tc.nonce, nonce) + s.Require().Equal(tc.nonce, nonce) }) } } -func (suite *KeeperTestSuite) TestGetCodeHash() { +func (s *KeeperTestSuite) TestGetCodeHash() { addr := utiltx.GenerateAddress() baseAcc := &authtypes.BaseAccount{Address: sdk.AccAddress(addr.Bytes()).String()} - newAcc := suite.network.App.AccountKeeper.NewAccount(suite.network.GetContext(), baseAcc) - suite.network.App.AccountKeeper.SetAccount(suite.network.GetContext(), newAcc) + newAcc := s.Network.App.GetAccountKeeper().NewAccount(s.Network.GetContext(), baseAcc) + s.Network.App.GetAccountKeeper().SetAccount(s.Network.GetContext(), newAcc) testCases := []struct { name string @@ -248,30 +242,30 @@ func (suite *KeeperTestSuite) TestGetCodeHash() { }, { "existing account", - suite.keyring.GetAddr(0), + s.Keyring.GetAddr(0), crypto.Keccak256Hash([]byte("codeHash")), func(vmdb vm.StateDB) { - vmdb.SetCode(suite.keyring.GetAddr(0), []byte("codeHash")) + vmdb.SetCode(s.Keyring.GetAddr(0), []byte("codeHash")) }, }, } for _, tc := range testCases { - suite.Run(tc.name, func() { - vmdb := suite.StateDB() + s.Run(tc.name, func() { + vmdb := s.StateDB() tc.malleate(vmdb) hash := vmdb.GetCodeHash(tc.address) - suite.Require().Equal(tc.expHash, hash) + s.Require().Equal(tc.expHash, hash) }) } } -func (suite *KeeperTestSuite) TestSetCode() { +func (s *KeeperTestSuite) TestSetCode() { addr := utiltx.GenerateAddress() baseAcc := &authtypes.BaseAccount{Address: sdk.AccAddress(addr.Bytes()).String()} - newAcc := suite.network.App.AccountKeeper.NewAccount(suite.network.GetContext(), baseAcc) - suite.network.App.AccountKeeper.SetAccount(suite.network.GetContext(), newAcc) + newAcc := s.Network.App.GetAccountKeeper().NewAccount(s.Network.GetContext(), baseAcc) + s.Network.App.GetAccountKeeper().SetAccount(s.Network.GetContext(), newAcc) testCases := []struct { name string @@ -293,37 +287,37 @@ func (suite *KeeperTestSuite) TestSetCode() { }, { "existing account", - suite.keyring.GetAddr(0), + s.Keyring.GetAddr(0), []byte("code"), false, }, { "existing account, code deleted from store", - suite.keyring.GetAddr(0), + s.Keyring.GetAddr(0), nil, false, }, } for _, tc := range testCases { - suite.Run(tc.name, func() { - vmdb := suite.StateDB() + s.Run(tc.name, func() { + vmdb := s.StateDB() prev := vmdb.GetCode(tc.address) vmdb.SetCode(tc.address, tc.code) post := vmdb.GetCode(tc.address) if tc.isNoOp { - suite.Require().Equal(prev, post) + s.Require().Equal(prev, post) } else { - suite.Require().Equal(tc.code, post) + s.Require().Equal(tc.code, post) } - suite.Require().Equal(len(post), vmdb.GetCodeSize(tc.address)) + s.Require().Equal(len(post), vmdb.GetCodeSize(tc.address)) }) } } -func (suite *KeeperTestSuite) TestKeeperSetOrDeleteCode() { +func (s *KeeperTestSuite) TestKeeperSetOrDeleteCode() { testCases := []struct { name string codeHash []byte @@ -342,80 +336,81 @@ func (suite *KeeperTestSuite) TestKeeperSetOrDeleteCode() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() + s.Run(tc.name, func() { + s.SetupTest() addr := utiltx.GenerateAddress() - baseAcc := suite.network.App.AccountKeeper.NewAccountWithAddress(suite.network.GetContext(), addr.Bytes()) - suite.network.App.AccountKeeper.SetAccount(suite.network.GetContext(), baseAcc) - ctx := suite.network.GetContext() + baseAcc := s.Network.App.GetAccountKeeper().NewAccountWithAddress(s.Network.GetContext(), addr.Bytes()) + s.Network.App.GetAccountKeeper().SetAccount(s.Network.GetContext(), baseAcc) + ctx := s.Network.GetContext() if len(tc.code) == 0 { - suite.network.App.EVMKeeper.DeleteCode(ctx, tc.codeHash) + s.Network.App.GetEVMKeeper().DeleteCode(ctx, tc.codeHash) } else { - suite.network.App.EVMKeeper.SetCode(ctx, tc.codeHash, tc.code) + s.Network.App.GetEVMKeeper().SetCode(ctx, tc.codeHash, tc.code) } - key := suite.network.App.GetKey(types.StoreKey) + key := s.Network.App.GetKey(types.StoreKey) store := prefix.NewStore(ctx.KVStore(key), types.KeyPrefixCode) code := store.Get(tc.codeHash) - suite.Require().Equal(tc.code, code) + s.Require().Equal(tc.code, code) }) } } -func TestIterateContracts(t *testing.T) { - keyring := testkeyring.New(1) - network := network.NewUnitTestNetwork( - network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), - ) - handler := testhandler.NewIntegrationHandler(network) - factory := testfactory.New(network, handler) - - contractAddr, err := factory.DeployContract( - keyring.GetPrivKey(0), - types.EvmTxArgs{}, - testfactory.ContractDeploymentData{ - Contract: contracts.ERC20MinterBurnerDecimalsContract, - ConstructorArgs: []interface{}{"TestToken", "TTK", uint8(18)}, - }, - ) - require.NoError(t, err, "failed to deploy contract") - require.NoError(t, network.NextBlock(), "failed to advance block") - - contractAddr2, err := factory.DeployContract( - keyring.GetPrivKey(0), - types.EvmTxArgs{}, - testfactory.ContractDeploymentData{ - Contract: contracts.ERC20MinterBurnerDecimalsContract, - ConstructorArgs: []interface{}{"AnotherToken", "ATK", uint8(18)}, - }, - ) - require.NoError(t, err, "failed to deploy contract") - require.NoError(t, network.NextBlock(), "failed to advance block") - - var ( - foundAddrs []common.Address - foundHashes []common.Hash - ) - - network.App.EVMKeeper.IterateContracts(network.GetContext(), func(addr common.Address, codeHash common.Hash) bool { - // NOTE: we only care about the 2 contracts deployed above, not the ERC20 native precompile for the aatom denomination - if bytes.Equal(addr.Bytes(), common.HexToAddress(testconstants.WEVMOSContractMainnet).Bytes()) { - return false - } - - foundAddrs = append(foundAddrs, addr) - foundHashes = append(foundHashes, codeHash) - return false - }) - - require.Len(t, foundAddrs, 2, "expected 2 contracts to be found when iterating") - require.Contains(t, foundAddrs, contractAddr, "expected contract 1 to be found when iterating") - require.Contains(t, foundAddrs, contractAddr2, "expected contract 2 to be found when iterating") - require.Equal(t, foundHashes[0], foundHashes[1], "expected both contracts to have the same code hash") - require.NotEqual(t, types.EmptyCodeHash, foundHashes[0], "expected store code hash not to be the keccak256 of empty code") -} - -func (suite *KeeperTestSuite) TestRefund() { +// TODO: Move to evmd +//func TestIterateContracts(t *testing.T) { +// Keyring := testKeyring.New(1) +// Network := network.NewUnitTestNetwork( +// network.WithPreFundedAccounts(Keyring.GetAllAccAddrs()...), +// ) +// handler := grpc.NewIntegrationHandler(Network) +// factory := factory2.New(Network, handler) +// +// contractAddr, err := factory.DeployContract( +// Keyring.GetPrivKey(0), +// types.EvmTxArgs{}, +// factory2.ContractDeploymentData{ +// Contract: contracts.ERC20MinterBurnerDecimalsContract, +// ConstructorArgs: []interface{}{"TestToken", "TTK", uint8(18)}, +// }, +// ) +// require.NoError(t, err, "failed to deploy contract") +// require.NoError(t, Network.NextBlock(), "failed to advance block") +// +// contractAddr2, err := factory.DeployContract( +// Keyring.GetPrivKey(0), +// types.EvmTxArgs{}, +// factory2.ContractDeploymentData{ +// Contract: contracts.ERC20MinterBurnerDecimalsContract, +// ConstructorArgs: []interface{}{"AnotherToken", "ATK", uint8(18)}, +// }, +// ) +// require.NoError(t, err, "failed to deploy contract") +// require.NoError(t, Network.NextBlock(), "failed to advance block") +// +// var ( +// foundAddrs []common.Address +// foundHashes []common.Hash +// ) +// +// Network.App.GetEVMKeeper().IterateContracts(Network.GetContext(), func(addr common.Address, codeHash common.Hash) bool { +// // NOTE: we only care about the 2 contracts deployed above, not the ERC20 native precompile for the aatom denomination +// if bytes.Equal(addr.Bytes(), common.HexToAddress(testconstants.WEVMOSContractMainnet).Bytes()) { +// return false +// } +// +// foundAddrs = append(foundAddrs, addr) +// foundHashes = append(foundHashes, codeHash) +// return false +// }) +// +// require.Len(t, foundAddrs, 2, "expected 2 contracts to be found when iterating") +// require.Contains(t, foundAddrs, contractAddr, "expected contract 1 to be found when iterating") +// require.Contains(t, foundAddrs, contractAddr2, "expected contract 2 to be found when iterating") +// require.Equal(t, foundHashes[0], foundHashes[1], "expected both contracts to have the same code hash") +// require.NotEqual(t, types.EmptyCodeHash, foundHashes[0], "expected store code hash not to be the keccak256 of empty code") +//} + +func (s *KeeperTestSuite) TestRefund() { testCases := []struct { name string malleate func(vm.StateDB) @@ -440,21 +435,21 @@ func (suite *KeeperTestSuite) TestRefund() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - vmdb := suite.StateDB() + s.Run(tc.name, func() { + vmdb := s.StateDB() tc.malleate(vmdb) if tc.expPanic { - suite.Require().Panics(func() { vmdb.SubRefund(10) }) + s.Require().Panics(func() { vmdb.SubRefund(10) }) } else { vmdb.SubRefund(10) - suite.Require().Equal(tc.expRefund, vmdb.GetRefund()) + s.Require().Equal(tc.expRefund, vmdb.GetRefund()) } }) } } -func (suite *KeeperTestSuite) TestState() { +func (s *KeeperTestSuite) TestState() { testCases := []struct { name string key, value common.Hash @@ -472,59 +467,60 @@ func (suite *KeeperTestSuite) TestState() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - vmdb := suite.StateDB() - vmdb.SetState(suite.keyring.GetAddr(0), tc.key, tc.value) - value := vmdb.GetState(suite.keyring.GetAddr(0), tc.key) - suite.Require().Equal(tc.value, value) + s.Run(tc.name, func() { + vmdb := s.StateDB() + vmdb.SetState(s.Keyring.GetAddr(0), tc.key, tc.value) + value := vmdb.GetState(s.Keyring.GetAddr(0), tc.key) + s.Require().Equal(tc.value, value) }) } } -func (suite *KeeperTestSuite) TestCommittedState() { +func (s *KeeperTestSuite) TestCommittedState() { key := common.BytesToHash([]byte("key")) value1 := common.BytesToHash([]byte("value1")) value2 := common.BytesToHash([]byte("value2")) - vmdb := suite.StateDB() - vmdb.SetState(suite.keyring.GetAddr(0), key, value1) + vmdb := s.StateDB() + vmdb.SetState(s.Keyring.GetAddr(0), key, value1) err := vmdb.Commit() - suite.Require().NoError(err) - - vmdb = suite.StateDB() - vmdb.SetState(suite.keyring.GetAddr(0), key, value2) - tmp := vmdb.GetState(suite.keyring.GetAddr(0), key) - suite.Require().Equal(value2, tmp) - tmp = vmdb.GetCommittedState(suite.keyring.GetAddr(0), key) - suite.Require().Equal(value1, tmp) + s.Require().NoError(err) + + vmdb = s.StateDB() + vmdb.SetState(s.Keyring.GetAddr(0), key, value2) + tmp := vmdb.GetState(s.Keyring.GetAddr(0), key) + s.Require().Equal(value2, tmp) + tmp = vmdb.GetCommittedState(s.Keyring.GetAddr(0), key) + s.Require().Equal(value1, tmp) err = vmdb.Commit() - suite.Require().NoError(err) + s.Require().NoError(err) - vmdb = suite.StateDB() - tmp = vmdb.GetCommittedState(suite.keyring.GetAddr(0), key) - suite.Require().Equal(value2, tmp) + vmdb = s.StateDB() + tmp = vmdb.GetCommittedState(s.Keyring.GetAddr(0), key) + s.Require().Equal(value2, tmp) } -func (suite *KeeperTestSuite) TestSetAndGetCodeHash() { - suite.SetupTest() +func (s *KeeperTestSuite) TestSetAndGetCodeHash() { + s.SetupTest() } -func (suite *KeeperTestSuite) TestSuicide() { - keyring := testkeyring.New(1) +func (s *KeeperTestSuite) TestSuicide() { + Keyring := testKeyring.New(1) unitNetwork := network.NewUnitTestNetwork( - network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), + s.Create, + network.WithPreFundedAccounts(Keyring.GetAllAccAddrs()...), ) - firstAddressIndex := keyring.AddKey() - firstAddress := keyring.GetAddr(firstAddressIndex) - secondAddressIndex := keyring.AddKey() - secondAddress := keyring.GetAddr(secondAddressIndex) + firstAddressIndex := Keyring.AddKey() + firstAddress := Keyring.GetAddr(firstAddressIndex) + secondAddressIndex := Keyring.AddKey() + secondAddress := Keyring.GetAddr(secondAddressIndex) code := []byte("code") db := unitNetwork.GetStateDB() // Add code to account db.SetCode(firstAddress, code) - suite.Require().Equal(code, db.GetCode(firstAddress)) + s.Require().Equal(code, db.GetCode(firstAddress)) // Add state to account for i := 0; i < 5; i++ { db.SetState( @@ -533,12 +529,12 @@ func (suite *KeeperTestSuite) TestSuicide() { common.BytesToHash([]byte(fmt.Sprintf("value%d", i))), ) } - suite.Require().NoError(db.Commit()) + s.Require().NoError(db.Commit()) db = unitNetwork.GetStateDB() // Add code and state to account 2 db.SetCode(secondAddress, code) - suite.Require().Equal(code, db.GetCode(secondAddress)) + s.Require().Equal(code, db.GetCode(secondAddress)) for i := 0; i < 5; i++ { db.SetState( secondAddress, @@ -551,56 +547,56 @@ func (suite *KeeperTestSuite) TestSuicide() { db.SelfDestruct(firstAddress) // Check suicided is marked - suite.Require().True(db.HasSelfDestructed(firstAddress)) + s.Require().True(db.HasSelfDestructed(firstAddress)) // Commit state - suite.Require().NoError(db.Commit()) + s.Require().NoError(db.Commit()) db = unitNetwork.GetStateDB() // Check code is deleted - suite.Require().Nil(db.GetCode(firstAddress)) + s.Require().Nil(db.GetCode(firstAddress)) // Check state is deleted var storage types.Storage - unitNetwork.App.EVMKeeper.ForEachStorage(unitNetwork.GetContext(), firstAddress, func(key, value common.Hash) bool { + unitNetwork.App.GetEVMKeeper().ForEachStorage(unitNetwork.GetContext(), firstAddress, func(key, value common.Hash) bool { storage = append(storage, types.NewState(key, value)) return true }) - suite.Require().Equal(0, len(storage)) + s.Require().Equal(0, len(storage)) // Check account is deleted - suite.Require().Equal(common.Hash{}, db.GetCodeHash(firstAddress)) + s.Require().Equal(common.Hash{}, db.GetCodeHash(firstAddress)) // Check code is still present in addr2 and suicided is false - suite.Require().NotNil(db.GetCode(secondAddress)) - suite.Require().False(db.HasSelfDestructed(secondAddress)) + s.Require().NotNil(db.GetCode(secondAddress)) + s.Require().False(db.HasSelfDestructed(secondAddress)) } -func (suite *KeeperTestSuite) TestExist() { +func (s *KeeperTestSuite) TestExist() { testCases := []struct { name string address common.Address malleate func(vm.StateDB) exists bool }{ - {"success, account exists", suite.keyring.GetAddr(0), func(vm.StateDB) {}, true}, - {"success, has suicided", suite.keyring.GetAddr(0), func(vmdb vm.StateDB) { - vmdb.SelfDestruct(suite.keyring.GetAddr(0)) + {"success, account exists", s.Keyring.GetAddr(0), func(vm.StateDB) {}, true}, + {"success, has suicided", s.Keyring.GetAddr(0), func(vmdb vm.StateDB) { + vmdb.SelfDestruct(s.Keyring.GetAddr(0)) }, true}, {"success, account doesn't exist", utiltx.GenerateAddress(), func(vm.StateDB) {}, false}, } for _, tc := range testCases { - suite.Run(tc.name, func() { - vmdb := suite.StateDB() + s.Run(tc.name, func() { + vmdb := s.StateDB() tc.malleate(vmdb) - suite.Require().Equal(tc.exists, vmdb.Exist(tc.address)) + s.Require().Equal(tc.exists, vmdb.Exist(tc.address)) }) } } -func (suite *KeeperTestSuite) TestEmpty() { +func (s *KeeperTestSuite) TestEmpty() { testCases := []struct { name string address common.Address @@ -620,17 +616,17 @@ func (suite *KeeperTestSuite) TestEmpty() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() - vmdb := suite.StateDB() + s.Run(tc.name, func() { + s.SetupTest() + vmdb := s.StateDB() tc.malleate(vmdb, tc.address) - suite.Require().Equal(tc.empty, vmdb.Empty(tc.address)) + s.Require().Equal(tc.empty, vmdb.Empty(tc.address)) }) } } -func (suite *KeeperTestSuite) TestSnapshot() { +func (s *KeeperTestSuite) TestSnapshot() { key := common.BytesToHash([]byte("key")) value1 := common.BytesToHash([]byte("value1")) value2 := common.BytesToHash([]byte("value2")) @@ -641,77 +637,77 @@ func (suite *KeeperTestSuite) TestSnapshot() { }{ {"simple revert", func(vmdb vm.StateDB) { revision := vmdb.Snapshot() - suite.Require().Zero(revision) + s.Require().Zero(revision) - vmdb.SetState(suite.keyring.GetAddr(0), key, value1) - suite.Require().Equal(value1, vmdb.GetState(suite.keyring.GetAddr(0), key)) + vmdb.SetState(s.Keyring.GetAddr(0), key, value1) + s.Require().Equal(value1, vmdb.GetState(s.Keyring.GetAddr(0), key)) vmdb.RevertToSnapshot(revision) // reverted - suite.Require().Equal(common.Hash{}, vmdb.GetState(suite.keyring.GetAddr(0), key)) + s.Require().Equal(common.Hash{}, vmdb.GetState(s.Keyring.GetAddr(0), key)) }}, {"nested snapshot/revert", func(vmdb vm.StateDB) { revision1 := vmdb.Snapshot() - suite.Require().Zero(revision1) + s.Require().Zero(revision1) - vmdb.SetState(suite.keyring.GetAddr(0), key, value1) + vmdb.SetState(s.Keyring.GetAddr(0), key, value1) revision2 := vmdb.Snapshot() - vmdb.SetState(suite.keyring.GetAddr(0), key, value2) - suite.Require().Equal(value2, vmdb.GetState(suite.keyring.GetAddr(0), key)) + vmdb.SetState(s.Keyring.GetAddr(0), key, value2) + s.Require().Equal(value2, vmdb.GetState(s.Keyring.GetAddr(0), key)) vmdb.RevertToSnapshot(revision2) - suite.Require().Equal(value1, vmdb.GetState(suite.keyring.GetAddr(0), key)) + s.Require().Equal(value1, vmdb.GetState(s.Keyring.GetAddr(0), key)) vmdb.RevertToSnapshot(revision1) - suite.Require().Equal(common.Hash{}, vmdb.GetState(suite.keyring.GetAddr(0), key)) + s.Require().Equal(common.Hash{}, vmdb.GetState(s.Keyring.GetAddr(0), key)) }}, {"jump revert", func(vmdb vm.StateDB) { revision1 := vmdb.Snapshot() - vmdb.SetState(suite.keyring.GetAddr(0), key, value1) + vmdb.SetState(s.Keyring.GetAddr(0), key, value1) vmdb.Snapshot() - vmdb.SetState(suite.keyring.GetAddr(0), key, value2) + vmdb.SetState(s.Keyring.GetAddr(0), key, value2) vmdb.RevertToSnapshot(revision1) - suite.Require().Equal(common.Hash{}, vmdb.GetState(suite.keyring.GetAddr(0), key)) + s.Require().Equal(common.Hash{}, vmdb.GetState(s.Keyring.GetAddr(0), key)) }}, } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() - vmdb := suite.StateDB() + s.Run(tc.name, func() { + s.SetupTest() + vmdb := s.StateDB() tc.malleate(vmdb) }) } } -func (suite *KeeperTestSuite) CreateTestTx(msg *types.MsgEthereumTx, priv cryptotypes.PrivKey) authsigning.Tx { +func (s *KeeperTestSuite) CreateTestTx(msg *types.MsgEthereumTx, priv cryptotypes.PrivKey) authsigning.Tx { option, err := codectypes.NewAnyWithValue(&types.ExtensionOptionsEthereumTx{}) - suite.Require().NoError(err) + s.Require().NoError(err) - clientCtx := client.Context{}.WithTxConfig(suite.network.App.GetTxConfig()) + clientCtx := client.Context{}.WithTxConfig(s.Network.App.GetTxConfig()) ethSigner := ethtypes.LatestSignerForChainID(types.GetEthChainConfig().ChainID) txBuilder := clientCtx.TxConfig.NewTxBuilder() builder, ok := txBuilder.(authtx.ExtensionOptionsTxBuilder) - suite.Require().True(ok) + s.Require().True(ok) builder.SetExtensionOptions(option) err = msg.Sign(ethSigner, utiltx.NewSigner(priv)) - suite.Require().NoError(err) + s.Require().NoError(err) err = txBuilder.SetMsgs(msg) - suite.Require().NoError(err) + s.Require().NoError(err) return txBuilder.GetTx() } -func (suite *KeeperTestSuite) TestAddLog() { +func (s *KeeperTestSuite) TestAddLog() { addr, privKey := utiltx.NewAddrKey() - toAddr := suite.keyring.GetAddr(0) + toAddr := s.Keyring.GetAddr(0) ethTxParams := &types.EvmTxArgs{ ChainID: common.Big1, Nonce: 0, @@ -724,7 +720,7 @@ func (suite *KeeperTestSuite) TestAddLog() { msg := types.NewTx(ethTxParams) msg.From = addr.Hex() - tx := suite.CreateTestTx(msg, privKey) + tx := s.CreateTestTx(msg, privKey) msg, _ = tx.GetMsgs()[0].(*types.MsgEthereumTx) txHash := msg.AsTransaction().Hash() @@ -753,7 +749,7 @@ func (suite *KeeperTestSuite) TestAddLog() { msg3 := types.NewTx(ethTx3Params) msg3.From = addr.Hex() - tx3 := suite.CreateTestTx(msg3, privKey) + tx3 := s.CreateTestTx(msg3, privKey) msg3, _ = tx3.GetMsgs()[0].(*types.MsgEthereumTx) txHash3 := msg3.AsTransaction().Hash() @@ -807,10 +803,10 @@ func (suite *KeeperTestSuite) TestAddLog() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() - vmdb := statedb.New(suite.network.GetContext(), suite.network.App.EVMKeeper, statedb.NewTxConfig( - common.BytesToHash(suite.network.GetContext().HeaderHash()), + s.Run(tc.name, func() { + s.SetupTest() + vmdb := statedb.New(s.Network.GetContext(), s.Network.App.GetEVMKeeper(), statedb.NewTxConfig( + common.BytesToHash(s.Network.GetContext().HeaderHash()), tc.hash, 0, 0, )) @@ -818,13 +814,13 @@ func (suite *KeeperTestSuite) TestAddLog() { vmdb.AddLog(tc.log) logs := vmdb.Logs() - suite.Require().Equal(1, len(logs)) - suite.Require().Equal(tc.expLog, logs[0]) + s.Require().Equal(1, len(logs)) + s.Require().Equal(tc.expLog, logs[0]) }) } } -func (suite *KeeperTestSuite) TestPrepareAccessList() { +func (s *KeeperTestSuite) TestPrepareAccessList() { dest := utiltx.GenerateAddress() precompiles := []common.Address{utiltx.GenerateAddress(), utiltx.GenerateAddress()} accesses := ethtypes.AccessList{ @@ -833,7 +829,7 @@ func (suite *KeeperTestSuite) TestPrepareAccessList() { } rules := ethparams.Rules{ - ChainID: suite.network.GetEVMChainConfig().ChainID, + ChainID: s.Network.GetEVMChainConfig().ChainID, IsHomestead: true, IsEIP150: true, IsEIP155: true, @@ -850,45 +846,45 @@ func (suite *KeeperTestSuite) TestPrepareAccessList() { IsEIP2929: true, } - vmdb := suite.StateDB() - vmdb.Prepare(rules, suite.keyring.GetAddr(0), common.Address{}, &dest, precompiles, accesses) + vmdb := s.StateDB() + vmdb.Prepare(rules, s.Keyring.GetAddr(0), common.Address{}, &dest, precompiles, accesses) - suite.Require().True(vmdb.AddressInAccessList(suite.keyring.GetAddr(0))) - suite.Require().True(vmdb.AddressInAccessList(dest)) + s.Require().True(vmdb.AddressInAccessList(s.Keyring.GetAddr(0))) + s.Require().True(vmdb.AddressInAccessList(dest)) for _, precompile := range precompiles { - suite.Require().True(vmdb.AddressInAccessList(precompile)) + s.Require().True(vmdb.AddressInAccessList(precompile)) } for _, access := range accesses { for _, key := range access.StorageKeys { addrOK, slotOK := vmdb.SlotInAccessList(access.Address, key) - suite.Require().True(addrOK, access.Address.Hex()) - suite.Require().True(slotOK, key.Hex()) + s.Require().True(addrOK, access.Address.Hex()) + s.Require().True(slotOK, key.Hex()) } } } -func (suite *KeeperTestSuite) TestAddAddressToAccessList() { +func (s *KeeperTestSuite) TestAddAddressToAccessList() { testCases := []struct { name string addr common.Address }{ {"new address", utiltx.GenerateAddress()}, - {"existing address", suite.keyring.GetAddr(0)}, + {"existing address", s.Keyring.GetAddr(0)}, } for _, tc := range testCases { - suite.Run(tc.name, func() { - vmdb := suite.StateDB() + s.Run(tc.name, func() { + vmdb := s.StateDB() vmdb.AddAddressToAccessList(tc.addr) addrOk := vmdb.AddressInAccessList(tc.addr) - suite.Require().True(addrOk, tc.addr.Hex()) + s.Require().True(addrOk, tc.addr.Hex()) }) } } -func (suite *KeeperTestSuite) TestAddSlotToAccessList() { +func (s *KeeperTestSuite) TestAddSlotToAccessList() { testCases := []struct { name string addr common.Address @@ -896,17 +892,17 @@ func (suite *KeeperTestSuite) TestAddSlotToAccessList() { }{ {"new address and slot (1)", utiltx.GenerateAddress(), common.BytesToHash([]byte("hash"))}, {"new address and slot (2)", utiltx.GenerateAddress(), common.Hash{}}, - {"existing address and slot", suite.keyring.GetAddr(0), common.Hash{}}, - {"existing address, new slot", suite.keyring.GetAddr(0), common.BytesToHash([]byte("hash"))}, + {"existing address and slot", s.Keyring.GetAddr(0), common.Hash{}}, + {"existing address, new slot", s.Keyring.GetAddr(0), common.BytesToHash([]byte("hash"))}, } for _, tc := range testCases { - suite.Run(tc.name, func() { - vmdb := suite.StateDB() + s.Run(tc.name, func() { + vmdb := s.StateDB() vmdb.AddSlotToAccessList(tc.addr, tc.slot) addrOk, slotOk := vmdb.SlotInAccessList(tc.addr, tc.slot) - suite.Require().True(addrOk, tc.addr.Hex()) - suite.Require().True(slotOk, tc.slot.Hex()) + s.Require().True(addrOk, tc.addr.Hex()) + s.Require().True(slotOk, tc.slot.Hex()) }) } } @@ -925,7 +921,7 @@ func (suite *KeeperTestSuite) TestAddSlotToAccessList() { // "aggregate state", // func(vmdb vm.StateDB) { // for i := 0; i < 5; i++ { -// vmdb.SetState(suite.keyring.GetAddr(0), common.BytesToHash([]byte(fmt.Sprintf("key%d", i))), common.BytesToHash([]byte(fmt.Sprintf("value%d", i)))) +// vmdb.SetState(suite.Keyring.GetAddr(0), common.BytesToHash([]byte(fmt.Sprintf("key%d", i))), common.BytesToHash([]byte(fmt.Sprintf("value%d", i)))) // } // }, // func(key, value common.Hash) bool { @@ -943,8 +939,8 @@ func (suite *KeeperTestSuite) TestAddSlotToAccessList() { // { // "filter state", // func(vmdb vm.StateDB) { -// vmdb.SetState(suite.keyring.GetAddr(0), common.BytesToHash([]byte("key")), common.BytesToHash([]byte("value"))) -// vmdb.SetState(suite.keyring.GetAddr(0), common.BytesToHash([]byte("filterkey")), common.BytesToHash([]byte("filtervalue"))) +// vmdb.SetState(suite.Keyring.GetAddr(0), common.BytesToHash([]byte("key")), common.BytesToHash([]byte("value"))) +// vmdb.SetState(suite.Keyring.GetAddr(0), common.BytesToHash([]byte("filterkey")), common.BytesToHash([]byte("filtervalue"))) // }, // func(key, value common.Hash) bool { // if value == common.BytesToHash([]byte("filtervalue")) { @@ -965,7 +961,7 @@ func (suite *KeeperTestSuite) TestAddSlotToAccessList() { // vmdb := suite.StateDB() // tc.malleate(vmdb) // -// err := vmdb.ForEachStorage(suite.keyring.GetAddr(0), tc.callback) +// err := vmdb.ForEachStorage(suite.Keyring.GetAddr(0), tc.callback) // suite.Require().NoError(err) // suite.Require().Equal(len(tc.expValues), len(storage), fmt.Sprintf("Expected values:\n%v\nStorage Values\n%v", tc.expValues, storage)) // @@ -981,7 +977,7 @@ func (suite *KeeperTestSuite) TestAddSlotToAccessList() { // } // } -func (suite *KeeperTestSuite) TestSetBalance() { +func (s *KeeperTestSuite) TestSetBalance() { amount := common.U2560 addr := utiltx.GenerateAddress() @@ -1010,22 +1006,22 @@ func (suite *KeeperTestSuite) TestSetBalance() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() + s.Run(tc.name, func() { + s.SetupTest() tc.malleate() - err := suite.network.App.EVMKeeper.SetBalance(suite.network.GetContext(), tc.addr, amount) + err := s.Network.App.GetEVMKeeper().SetBalance(s.Network.GetContext(), tc.addr, amount) if tc.expErr { - suite.Require().Error(err) + s.Require().Error(err) } else { - balance := suite.network.App.EVMKeeper.GetBalance(suite.network.GetContext(), tc.addr) - suite.Require().NoError(err) - suite.Require().Equal(amount, balance) + balance := s.Network.App.GetEVMKeeper().GetBalance(s.Network.GetContext(), tc.addr) + s.Require().NoError(err) + s.Require().Equal(amount, balance) } }) } } -func (suite *KeeperTestSuite) TestDeleteAccount() { +func (s *KeeperTestSuite) TestDeleteAccount() { var ( ctx sdk.Context contractAddr common.Address @@ -1040,7 +1036,7 @@ func (suite *KeeperTestSuite) TestDeleteAccount() { }{ { name: "remove address", - malleate: func() common.Address { return suite.keyring.GetAddr(0) }, + malleate: func() common.Address { return s.Keyring.GetAddr(0) }, errContains: "only smart contracts can be self-destructed", }, { @@ -1056,27 +1052,27 @@ func (suite *KeeperTestSuite) TestDeleteAccount() { } for _, tc := range testCases { - suite.Run(tc.name, func() { - suite.SetupTest() - ctx = suite.network.GetContext() - contractAddr = suite.DeployTestContract(suite.T(), ctx, suite.keyring.GetAddr(0), supply) + s.Run(tc.name, func() { + s.SetupTest() + ctx = s.Network.GetContext() + contractAddr = s.DeployTestContract(s.T(), ctx, s.Keyring.GetAddr(0), supply) addr := tc.malleate() - err := suite.network.App.EVMKeeper.DeleteAccount(ctx, addr) + err := s.Network.App.GetEVMKeeper().DeleteAccount(ctx, addr) if tc.expPass { - suite.Require().NoError(err, "expected deleting account to succeed") + s.Require().NoError(err, "expected deleting account to succeed") - acc := suite.network.App.EVMKeeper.GetAccount(ctx, addr) - suite.Require().Nil(acc, "expected no account to be found after deleting") + acc := s.Network.App.GetEVMKeeper().GetAccount(ctx, addr) + s.Require().Nil(acc, "expected no account to be found after deleting") - balance := suite.network.App.EVMKeeper.GetBalance(ctx, addr) - suite.Require().Equal(new(uint256.Int), balance, "expected balance to be zero after deleting account") + balance := s.Network.App.GetEVMKeeper().GetBalance(ctx, addr) + s.Require().Equal(new(uint256.Int), balance, "expected balance to be zero after deleting account") } else { - suite.Require().ErrorContains(err, tc.errContains, "expected error to contain message") + s.Require().ErrorContains(err, tc.errContains, "expected error to contain message") - acc := suite.network.App.EVMKeeper.GetAccount(ctx, addr) - suite.Require().NotNil(acc, "expected account to still be found after failing to delete") + acc := s.Network.App.GetEVMKeeper().GetAccount(ctx, addr) + s.Require().NotNil(acc, "expected account to still be found after failing to delete") } }) } diff --git a/x/vm/keeper/utils_test.go b/tests/integration/x/vm/utils.go similarity index 66% rename from x/vm/keeper/utils_test.go rename to tests/integration/x/vm/utils.go index 5e2c3d1d6..0c3a61909 100644 --- a/x/vm/keeper/utils_test.go +++ b/tests/integration/x/vm/utils.go @@ -1,4 +1,4 @@ -package keeper_test +package vm import ( "encoding/json" @@ -19,16 +19,16 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -func (suite *KeeperTestSuite) EvmDenom() string { +func (s *KeeperTestSuite) EvmDenom() string { return evmtypes.GetEVMCoinDenom() } -func (suite *KeeperTestSuite) StateDB() *statedb.StateDB { - return statedb.New(suite.network.GetContext(), suite.network.App.EVMKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(suite.network.GetContext().HeaderHash()))) +func (s *KeeperTestSuite) StateDB() *statedb.StateDB { + return statedb.New(s.Network.GetContext(), s.Network.App.GetEVMKeeper(), statedb.NewEmptyTxConfig(common.BytesToHash(s.Network.GetContext().HeaderHash()))) } // DeployTestContract deploy a test erc20 contract and returns the contract address -func (suite *KeeperTestSuite) DeployTestContract(t require.TestingT, ctx sdk.Context, owner common.Address, supply *big.Int) common.Address { +func (s *KeeperTestSuite) DeployTestContract(t require.TestingT, ctx sdk.Context, owner common.Address, supply *big.Int) common.Address { chainID := evmtypes.GetEthChainConfig().ChainID erc20Contract, err := testdata.LoadERC20Contract() @@ -37,8 +37,8 @@ func (suite *KeeperTestSuite) DeployTestContract(t require.TestingT, ctx sdk.Con ctorArgs, err := erc20Contract.ABI.Pack("", owner, supply) require.NoError(t, err) - addr := suite.keyring.GetAddr(0) - nonce := suite.network.App.EVMKeeper.GetNonce(suite.network.GetContext(), addr) + addr := s.Keyring.GetAddr(0) + nonce := s.Network.App.GetEVMKeeper().GetNonce(s.Network.GetContext(), addr) data := erc20Contract.Bin data = append(data, ctorArgs...) @@ -47,18 +47,18 @@ func (suite *KeeperTestSuite) DeployTestContract(t require.TestingT, ctx sdk.Con Data: (*hexutil.Bytes)(&data), }) require.NoError(t, err) - res, err := suite.network.GetEvmClient().EstimateGas(ctx, &evmtypes.EthCallRequest{ + res, err := s.Network.GetEvmClient().EstimateGas(ctx, &evmtypes.EthCallRequest{ Args: args, GasCap: servercfg.DefaultGasCap, - ProposerAddress: suite.network.GetContext().BlockHeader().ProposerAddress, + ProposerAddress: s.Network.GetContext().BlockHeader().ProposerAddress, }) require.NoError(t, err) - baseFeeRes, err := suite.network.GetEvmClient().BaseFee(ctx, &evmtypes.QueryBaseFeeRequest{}) + baseFeeRes, err := s.Network.GetEvmClient().BaseFee(ctx, &evmtypes.QueryBaseFeeRequest{}) require.NoError(t, err) var erc20DeployTx *evmtypes.MsgEthereumTx - if suite.enableFeemarket { + if s.EnableFeemarket { ethTxParams := &evmtypes.EvmTxArgs{ ChainID: chainID, Nonce: nonce, @@ -79,18 +79,18 @@ func (suite *KeeperTestSuite) DeployTestContract(t require.TestingT, ctx sdk.Con erc20DeployTx = evmtypes.NewTx(ethTxParams) } - krSigner := utiltx.NewSigner(suite.keyring.GetPrivKey(0)) + krSigner := utiltx.NewSigner(s.Keyring.GetPrivKey(0)) erc20DeployTx.From = addr.Hex() err = erc20DeployTx.Sign(ethtypes.LatestSignerForChainID(chainID), krSigner) require.NoError(t, err) - rsp, err := suite.network.App.EVMKeeper.EthereumTx(ctx, erc20DeployTx) + rsp, err := s.Network.App.GetEVMKeeper().EthereumTx(ctx, erc20DeployTx) require.NoError(t, err) require.Empty(t, rsp.VmError) return crypto.CreateAddress(addr, nonce) } -func (suite *KeeperTestSuite) TransferERC20Token(t require.TestingT, contractAddr, from, to common.Address, amount *big.Int) *evmtypes.MsgEthereumTx { - ctx := suite.network.GetContext() +func (s *KeeperTestSuite) TransferERC20Token(t require.TestingT, contractAddr, from, to common.Address, amount *big.Int) *evmtypes.MsgEthereumTx { + ctx := s.Network.GetContext() chainID := evmtypes.GetEthChainConfig().ChainID erc20Contract, err := testdata.LoadERC20Contract() @@ -100,19 +100,19 @@ func (suite *KeeperTestSuite) TransferERC20Token(t require.TestingT, contractAdd require.NoError(t, err) args, err := json.Marshal(&evmtypes.TransactionArgs{To: &contractAddr, From: &from, Data: (*hexutil.Bytes)(&transferData)}) require.NoError(t, err) - res, err := suite.network.GetEvmClient().EstimateGas(ctx, &evmtypes.EthCallRequest{ + res, err := s.Network.GetEvmClient().EstimateGas(ctx, &evmtypes.EthCallRequest{ Args: args, GasCap: 25_000_000, - ProposerAddress: suite.network.GetContext().BlockHeader().ProposerAddress, + ProposerAddress: s.Network.GetContext().BlockHeader().ProposerAddress, }) require.NoError(t, err) - nonce := suite.network.App.EVMKeeper.GetNonce(suite.network.GetContext(), suite.keyring.GetAddr(0)) - baseFeeRes, err := suite.network.GetEvmClient().BaseFee(ctx, &evmtypes.QueryBaseFeeRequest{}) + nonce := s.Network.App.GetEVMKeeper().GetNonce(s.Network.GetContext(), s.Keyring.GetAddr(0)) + baseFeeRes, err := s.Network.GetEvmClient().BaseFee(ctx, &evmtypes.QueryBaseFeeRequest{}) require.NoError(t, err, "failed to get base fee") var ercTransferTx *evmtypes.MsgEthereumTx - if suite.enableFeemarket { + if s.EnableFeemarket { ethTxParams := &evmtypes.EvmTxArgs{ ChainID: chainID, Nonce: nonce, @@ -135,46 +135,46 @@ func (suite *KeeperTestSuite) TransferERC20Token(t require.TestingT, contractAdd ercTransferTx = evmtypes.NewTx(ethTxParams) } - addr := suite.keyring.GetAddr(0) - krSigner := utiltx.NewSigner(suite.keyring.GetPrivKey(0)) + addr := s.Keyring.GetAddr(0) + krSigner := utiltx.NewSigner(s.Keyring.GetPrivKey(0)) ercTransferTx.From = addr.Hex() err = ercTransferTx.Sign(ethtypes.LatestSignerForChainID(chainID), krSigner) require.NoError(t, err) - rsp, err := suite.network.App.EVMKeeper.EthereumTx(ctx, ercTransferTx) + rsp, err := s.Network.App.GetEVMKeeper().EthereumTx(ctx, ercTransferTx) require.NoError(t, err) require.Empty(t, rsp.VmError) return ercTransferTx } // DeployTestMessageCall deploy a test erc20 contract and returns the contract address -func (suite *KeeperTestSuite) DeployTestMessageCall(t require.TestingT) common.Address { - ctx := suite.network.GetContext() +func (s *KeeperTestSuite) DeployTestMessageCall(t require.TestingT) common.Address { + ctx := s.Network.GetContext() chainID := evmtypes.GetEthChainConfig().ChainID testMsgCall, err := testdata.LoadMessageCallContract() require.NoError(t, err) data := testMsgCall.Bin - addr := suite.keyring.GetAddr(0) + addr := s.Keyring.GetAddr(0) args, err := json.Marshal(&evmtypes.TransactionArgs{ From: &addr, Data: (*hexutil.Bytes)(&data), }) require.NoError(t, err) - res, err := suite.network.GetEvmClient().EstimateGas(ctx, &evmtypes.EthCallRequest{ + res, err := s.Network.GetEvmClient().EstimateGas(ctx, &evmtypes.EthCallRequest{ Args: args, GasCap: servercfg.DefaultGasCap, - ProposerAddress: suite.network.GetContext().BlockHeader().ProposerAddress, + ProposerAddress: s.Network.GetContext().BlockHeader().ProposerAddress, }) require.NoError(t, err) - nonce := suite.network.App.EVMKeeper.GetNonce(suite.network.GetContext(), addr) - baseFeeRes, err := suite.network.GetEvmClient().BaseFee(ctx, &evmtypes.QueryBaseFeeRequest{}) + nonce := s.Network.App.GetEVMKeeper().GetNonce(s.Network.GetContext(), addr) + baseFeeRes, err := s.Network.GetEvmClient().BaseFee(ctx, &evmtypes.QueryBaseFeeRequest{}) require.NoError(t, err, "failed to get base fee") var erc20DeployTx *evmtypes.MsgEthereumTx - if suite.enableFeemarket { + if s.EnableFeemarket { ethTxParams := &evmtypes.EvmTxArgs{ ChainID: chainID, Nonce: nonce, @@ -195,11 +195,11 @@ func (suite *KeeperTestSuite) DeployTestMessageCall(t require.TestingT) common.A erc20DeployTx = evmtypes.NewTx(ethTxParams) } - krSigner := utiltx.NewSigner(suite.keyring.GetPrivKey(0)) + krSigner := utiltx.NewSigner(s.Keyring.GetPrivKey(0)) erc20DeployTx.From = addr.Hex() err = erc20DeployTx.Sign(ethtypes.LatestSignerForChainID(chainID), krSigner) require.NoError(t, err) - rsp, err := suite.network.App.EVMKeeper.EthereumTx(ctx, erc20DeployTx) + rsp, err := s.Network.App.GetEVMKeeper().EthereumTx(ctx, erc20DeployTx) require.NoError(t, err) require.Empty(t, rsp.VmError) return crypto.CreateAddress(addr, nonce) diff --git a/evmd/testutil/gas.go b/testutil/gas.go similarity index 100% rename from evmd/testutil/gas.go rename to testutil/gas.go diff --git a/testutil/integration/common/factory/base.go b/testutil/integration/base/factory/base.go similarity index 97% rename from testutil/integration/common/factory/base.go rename to testutil/integration/base/factory/base.go index e3ccc3496..fe74f0eda 100644 --- a/testutil/integration/common/factory/base.go +++ b/testutil/integration/base/factory/base.go @@ -5,8 +5,8 @@ import ( abcitypes "github.com/cometbft/cometbft/abci/types" - "github.com/cosmos/evm/testutil/integration/os/grpc" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/base/network" + "github.com/cosmos/evm/testutil/integration/evm/grpc" errorsmod "cosmossdk.io/errors" diff --git a/testutil/integration/common/factory/distribution.go b/testutil/integration/base/factory/distribution.go similarity index 100% rename from testutil/integration/common/factory/distribution.go rename to testutil/integration/base/factory/distribution.go diff --git a/testutil/integration/common/factory/factory.go b/testutil/integration/base/factory/factory.go similarity index 89% rename from testutil/integration/common/factory/factory.go rename to testutil/integration/base/factory/factory.go index 178590f1d..b3c4f4e61 100644 --- a/testutil/integration/common/factory/factory.go +++ b/testutil/integration/base/factory/factory.go @@ -1,8 +1,8 @@ package factory import ( - "github.com/cosmos/evm/testutil/integration/os/grpc" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" ) const ( diff --git a/testutil/integration/common/factory/fund.go b/testutil/integration/base/factory/fund.go similarity index 95% rename from testutil/integration/common/factory/fund.go rename to testutil/integration/base/factory/fund.go index d0d18592c..7977bf30e 100644 --- a/testutil/integration/common/factory/fund.go +++ b/testutil/integration/base/factory/fund.go @@ -3,7 +3,7 @@ package factory import ( "fmt" - "github.com/cosmos/evm/testutil/integration/os/keyring" + "github.com/cosmos/evm/testutil/keyring" sdktypes "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" diff --git a/testutil/integration/common/factory/helper.go b/testutil/integration/base/factory/helper.go similarity index 100% rename from testutil/integration/common/factory/helper.go rename to testutil/integration/base/factory/helper.go diff --git a/testutil/integration/common/factory/sign.go b/testutil/integration/base/factory/sign.go similarity index 100% rename from testutil/integration/common/factory/sign.go rename to testutil/integration/base/factory/sign.go diff --git a/testutil/integration/common/factory/staking.go b/testutil/integration/base/factory/staking.go similarity index 100% rename from testutil/integration/common/factory/staking.go rename to testutil/integration/base/factory/staking.go diff --git a/testutil/integration/common/factory/types.go b/testutil/integration/base/factory/types.go similarity index 100% rename from testutil/integration/common/factory/types.go rename to testutil/integration/base/factory/types.go diff --git a/testutil/integration/common/grpc/account.go b/testutil/integration/base/grpc/account.go similarity index 100% rename from testutil/integration/common/grpc/account.go rename to testutil/integration/base/grpc/account.go diff --git a/testutil/integration/common/grpc/authz.go b/testutil/integration/base/grpc/authz.go similarity index 100% rename from testutil/integration/common/grpc/authz.go rename to testutil/integration/base/grpc/authz.go diff --git a/testutil/integration/common/grpc/bank.go b/testutil/integration/base/grpc/bank.go similarity index 100% rename from testutil/integration/common/grpc/bank.go rename to testutil/integration/base/grpc/bank.go diff --git a/testutil/integration/common/grpc/distribution.go b/testutil/integration/base/grpc/distribution.go similarity index 100% rename from testutil/integration/common/grpc/distribution.go rename to testutil/integration/base/grpc/distribution.go diff --git a/testutil/integration/common/grpc/grpc.go b/testutil/integration/base/grpc/grpc.go similarity index 98% rename from testutil/integration/common/grpc/grpc.go rename to testutil/integration/base/grpc/grpc.go index ef5296890..af27a4d40 100644 --- a/testutil/integration/common/grpc/grpc.go +++ b/testutil/integration/base/grpc/grpc.go @@ -1,7 +1,7 @@ package grpc import ( - "github.com/cosmos/evm/testutil/integration/common/network" + "github.com/cosmos/evm/testutil/integration/base/network" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/authz" diff --git a/testutil/integration/common/grpc/staking.go b/testutil/integration/base/grpc/staking.go similarity index 100% rename from testutil/integration/common/grpc/staking.go rename to testutil/integration/base/grpc/staking.go diff --git a/testutil/integration/common/network/network.go b/testutil/integration/base/network/network.go similarity index 100% rename from testutil/integration/common/network/network.go rename to testutil/integration/base/network/network.go diff --git a/evmd/testutil/contract.go b/testutil/integration/contract.go similarity index 94% rename from evmd/testutil/contract.go rename to testutil/integration/contract.go index 74085343d..532b447d9 100644 --- a/evmd/testutil/contract.go +++ b/testutil/integration/contract.go @@ -1,4 +1,4 @@ -package testutil +package integration import ( "fmt" @@ -11,7 +11,7 @@ import ( abci "github.com/cometbft/cometbft/abci/types" - exampleapp "github.com/cosmos/evm/evmd" + "github.com/cosmos/evm" "github.com/cosmos/evm/testutil/tx" evmtypes "github.com/cosmos/evm/x/vm/types" "github.com/cosmos/gogoproto/proto" @@ -51,7 +51,7 @@ type ContractCallArgs struct { // compiled contract data and constructor arguments func DeployContract( ctx sdk.Context, - app *exampleapp.EVMD, + app evm.EvmApp, priv cryptotypes.PrivKey, queryClientEvm evmtypes.QueryClient, contract evmtypes.CompiledContract, @@ -59,7 +59,7 @@ func DeployContract( ) (common.Address, error) { chainID := evmtypes.GetEthChainConfig().ChainID from := common.BytesToAddress(priv.PubKey().Address().Bytes()) - nonce := app.EVMKeeper.GetNonce(ctx, from) + nonce := app.GetEVMKeeper().GetNonce(ctx, from) ctorArgs, err := contract.ABI.Pack("", constructorArgs...) if err != nil { @@ -104,14 +104,14 @@ func DeployContract( // with the provided factoryAddress func DeployContractWithFactory( ctx sdk.Context, - exampleApp *exampleapp.EVMD, + exampleApp evm.EvmApp, priv cryptotypes.PrivKey, factoryAddress common.Address, ) (common.Address, abci.ExecTxResult, error) { chainID := evmtypes.GetEthChainConfig().ChainID from := common.BytesToAddress(priv.PubKey().Address().Bytes()) - factoryNonce := exampleApp.EVMKeeper.GetNonce(ctx, factoryAddress) - nonce := exampleApp.EVMKeeper.GetNonce(ctx, from) + factoryNonce := exampleApp.GetEVMKeeper().GetNonce(ctx, factoryAddress) + nonce := exampleApp.GetEVMKeeper().GetNonce(ctx, from) msgEthereumTx := evmtypes.NewTx(&evmtypes.EvmTxArgs{ ChainID: chainID, diff --git a/testutil/integration/os/factory/broadcast.go b/testutil/integration/evm/factory/broadcast.go similarity index 93% rename from testutil/integration/os/factory/broadcast.go rename to testutil/integration/evm/factory/broadcast.go index 6a9ee61f1..32a7b88ff 100644 --- a/testutil/integration/os/factory/broadcast.go +++ b/testutil/integration/evm/factory/broadcast.go @@ -7,6 +7,7 @@ import ( abcitypes "github.com/cometbft/cometbft/abci/types" "github.com/cosmos/evm/precompiles/testutil" + testutiltypes "github.com/cosmos/evm/testutil/types" evmtypes "github.com/cosmos/evm/x/vm/types" errorsmod "cosmossdk.io/errors" @@ -42,7 +43,7 @@ func (tf *IntegrationTxFactory) ExecuteEthTx( } // ExecuteContractCall executes a contract call with the provided private key. -func (tf *IntegrationTxFactory) ExecuteContractCall(privKey cryptotypes.PrivKey, txArgs evmtypes.EvmTxArgs, callArgs CallArgs) (abcitypes.ExecTxResult, error) { +func (tf *IntegrationTxFactory) ExecuteContractCall(privKey cryptotypes.PrivKey, txArgs evmtypes.EvmTxArgs, callArgs testutiltypes.CallArgs) (abcitypes.ExecTxResult, error) { completeTxArgs, err := tf.GenerateContractCallArgs(txArgs, callArgs) if err != nil { return abcitypes.ExecTxResult{}, errorsmod.Wrap(err, "failed to generate contract call args") @@ -57,7 +58,7 @@ func (tf *IntegrationTxFactory) ExecuteContractCall(privKey cryptotypes.PrivKey, func (tf *IntegrationTxFactory) DeployContract( priv cryptotypes.PrivKey, txArgs evmtypes.EvmTxArgs, - deploymentData ContractDeploymentData, + deploymentData testutiltypes.ContractDeploymentData, ) (common.Address, error) { // Get account's nonce to create contract hash from := common.BytesToAddress(priv.PubKey().Address().Bytes()) @@ -81,7 +82,7 @@ func (tf *IntegrationTxFactory) DeployContract( func (tf *IntegrationTxFactory) CallContractAndCheckLogs( priv cryptotypes.PrivKey, txArgs evmtypes.EvmTxArgs, - callArgs CallArgs, + callArgs testutiltypes.CallArgs, logCheckArgs testutil.LogCheckArgs, ) (abcitypes.ExecTxResult, *evmtypes.MsgEthereumTxResponse, error) { res, err := tf.ExecuteContractCall(priv, txArgs, callArgs) diff --git a/testutil/integration/os/factory/build.go b/testutil/integration/evm/factory/build.go similarity index 97% rename from testutil/integration/os/factory/build.go rename to testutil/integration/evm/factory/build.go index 5404149b3..59a6e3350 100644 --- a/testutil/integration/os/factory/build.go +++ b/testutil/integration/evm/factory/build.go @@ -11,6 +11,7 @@ import ( gethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/cosmos/evm/server/config" + testutiltypes "github.com/cosmos/evm/testutil/types" evmtypes "github.com/cosmos/evm/x/vm/types" errorsmod "cosmossdk.io/errors" @@ -154,7 +155,7 @@ func (tf *IntegrationTxFactory) GenerateGethCoreMsg( // GenerateContractCallArgs generates the txArgs for a contract call. func (tf *IntegrationTxFactory) GenerateContractCallArgs( txArgs evmtypes.EvmTxArgs, - callArgs CallArgs, + callArgs testutiltypes.CallArgs, ) (evmtypes.EvmTxArgs, error) { input, err := callArgs.ContractABI.Pack(callArgs.MethodName, callArgs.Args...) if err != nil { @@ -168,7 +169,7 @@ func (tf *IntegrationTxFactory) GenerateContractCallArgs( func (tf *IntegrationTxFactory) GenerateDeployContractArgs( from common.Address, txArgs evmtypes.EvmTxArgs, - deploymentData ContractDeploymentData, + deploymentData testutiltypes.ContractDeploymentData, ) (evmtypes.EvmTxArgs, error) { account, err := tf.grpcHandler.GetEvmAccount(from) if err != nil { diff --git a/testutil/integration/os/factory/factory.go b/testutil/integration/evm/factory/factory.go similarity index 91% rename from testutil/integration/os/factory/factory.go rename to testutil/integration/evm/factory/factory.go index 430f2cb61..999797ab0 100644 --- a/testutil/integration/os/factory/factory.go +++ b/testutil/integration/evm/factory/factory.go @@ -12,9 +12,10 @@ import ( abcitypes "github.com/cometbft/cometbft/abci/types" "github.com/cosmos/evm/precompiles/testutil" - commonfactory "github.com/cosmos/evm/testutil/integration/common/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - "github.com/cosmos/evm/testutil/integration/os/network" + basefactory "github.com/cosmos/evm/testutil/integration/base/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/types" evmtypes "github.com/cosmos/evm/x/vm/types" "github.com/cosmos/gogoproto/proto" @@ -30,7 +31,7 @@ import ( // network. // Methods are organized by build sign and broadcast type methods. type TxFactory interface { - commonfactory.CoreTxFactory + basefactory.CoreTxFactory // GenerateDefaultTxTypeArgs generates a default ETH tx args for the desired tx type GenerateDefaultTxTypeArgs(sender common.Address, txType int) (evmtypes.EvmTxArgs, error) @@ -52,20 +53,20 @@ type TxFactory interface { // If the txArgs are not provided, they will be populated with default values or gas estimations. ExecuteEthTx(privKey cryptotypes.PrivKey, txArgs evmtypes.EvmTxArgs) (abcitypes.ExecTxResult, error) // ExecuteContractCall executes a contract call with the provided private key - ExecuteContractCall(privKey cryptotypes.PrivKey, txArgs evmtypes.EvmTxArgs, callArgs CallArgs) (abcitypes.ExecTxResult, error) + ExecuteContractCall(privKey cryptotypes.PrivKey, txArgs evmtypes.EvmTxArgs, callArgs types.CallArgs) (abcitypes.ExecTxResult, error) // DeployContract deploys a contract with the provided private key, // compiled contract data and constructor arguments - DeployContract(privKey cryptotypes.PrivKey, txArgs evmtypes.EvmTxArgs, deploymentData ContractDeploymentData) (common.Address, error) + DeployContract(privKey cryptotypes.PrivKey, txArgs evmtypes.EvmTxArgs, deploymentData types.ContractDeploymentData) (common.Address, error) // CallContractAndCheckLogs is a helper function to call a contract and check the logs using // the integration test utilities. // // It returns the Cosmos Tx response, the decoded Ethereum Tx response and an error. This error value // is nil, if the expected logs are found and the VM error is the expected one, should one be expected. - CallContractAndCheckLogs(privKey cryptotypes.PrivKey, txArgs evmtypes.EvmTxArgs, callArgs CallArgs, logCheckArgs testutil.LogCheckArgs) (abcitypes.ExecTxResult, *evmtypes.MsgEthereumTxResponse, error) + CallContractAndCheckLogs(privKey cryptotypes.PrivKey, txArgs evmtypes.EvmTxArgs, callArgs types.CallArgs, logCheckArgs testutil.LogCheckArgs) (abcitypes.ExecTxResult, *evmtypes.MsgEthereumTxResponse, error) // GenerateDeployContractArgs generates the txArgs for a contract deployment. - GenerateDeployContractArgs(from common.Address, txArgs evmtypes.EvmTxArgs, deploymentData ContractDeploymentData) (evmtypes.EvmTxArgs, error) + GenerateDeployContractArgs(from common.Address, txArgs evmtypes.EvmTxArgs, deploymentData types.ContractDeploymentData) (evmtypes.EvmTxArgs, error) // GenerateContractCallArgs generates the txArgs for a contract call. - GenerateContractCallArgs(txArgs evmtypes.EvmTxArgs, callArgs CallArgs) (evmtypes.EvmTxArgs, error) + GenerateContractCallArgs(txArgs evmtypes.EvmTxArgs, callArgs types.CallArgs) (evmtypes.EvmTxArgs, error) // GenerateMsgEthereumTx creates a new MsgEthereumTx with the provided arguments. GenerateMsgEthereumTx(privKey cryptotypes.PrivKey, txArgs evmtypes.EvmTxArgs) (evmtypes.MsgEthereumTx, error) // GenerateGethCoreMsg creates a new GethCoreMsg with the provided arguments. @@ -81,7 +82,7 @@ var _ TxFactory = (*IntegrationTxFactory)(nil) // IntegrationTxFactory is a helper struct to build and broadcast transactions // to the network on integration tests. This is to simulate the behavior of a real user. type IntegrationTxFactory struct { - commonfactory.CoreTxFactory + basefactory.CoreTxFactory grpcHandler grpc.Handler network network.Network @@ -93,7 +94,7 @@ func New( network network.Network, grpcHandler grpc.Handler, ) TxFactory { - cf := commonfactory.New(network, grpcHandler) + cf := basefactory.New(network, grpcHandler) return &IntegrationTxFactory{ CoreTxFactory: cf, grpcHandler: grpcHandler, diff --git a/testutil/integration/os/factory/helpers.go b/testutil/integration/evm/factory/helpers.go similarity index 100% rename from testutil/integration/os/factory/helpers.go rename to testutil/integration/evm/factory/helpers.go diff --git a/testutil/integration/os/factory/sign.go b/testutil/integration/evm/factory/sign.go similarity index 100% rename from testutil/integration/os/factory/sign.go rename to testutil/integration/evm/factory/sign.go diff --git a/testutil/integration/os/grpc/evm.go b/testutil/integration/evm/grpc/evm.go similarity index 100% rename from testutil/integration/os/grpc/evm.go rename to testutil/integration/evm/grpc/evm.go diff --git a/testutil/integration/os/grpc/feemarket.go b/testutil/integration/evm/grpc/feemarket.go similarity index 100% rename from testutil/integration/os/grpc/feemarket.go rename to testutil/integration/evm/grpc/feemarket.go diff --git a/testutil/integration/os/grpc/gov.go b/testutil/integration/evm/grpc/gov.go similarity index 100% rename from testutil/integration/os/grpc/gov.go rename to testutil/integration/evm/grpc/gov.go diff --git a/testutil/integration/os/grpc/grpc.go b/testutil/integration/evm/grpc/grpc.go similarity index 87% rename from testutil/integration/os/grpc/grpc.go rename to testutil/integration/evm/grpc/grpc.go index 7712054ad..dc2a79578 100644 --- a/testutil/integration/os/grpc/grpc.go +++ b/testutil/integration/evm/grpc/grpc.go @@ -3,8 +3,8 @@ package grpc import ( "github.com/ethereum/go-ethereum/common" - commongrpc "github.com/cosmos/evm/testutil/integration/common/grpc" - "github.com/cosmos/evm/testutil/integration/os/network" + basegrpc "github.com/cosmos/evm/testutil/integration/base/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -15,7 +15,7 @@ import ( // Handler is an interface that defines the methods that are used to query // the network's modules via gRPC. type Handler interface { - commongrpc.Handler + basegrpc.Handler // EVM methods GetEvmAccount(address common.Address) (*evmtypes.QueryAccountResponse, error) @@ -40,7 +40,7 @@ var _ Handler = (*IntegrationHandler)(nil) // the modules directly. type IntegrationHandler struct { // We take the IntegrationHandler from common/grpc to get the common methods. - *commongrpc.IntegrationHandler + *basegrpc.IntegrationHandler network network.Network } @@ -48,7 +48,7 @@ type IntegrationHandler struct { func NewIntegrationHandler(network network.Network) Handler { return &IntegrationHandler{ // Is there a better way to do this? - IntegrationHandler: commongrpc.NewIntegrationHandler(network), + IntegrationHandler: basegrpc.NewIntegrationHandler(network), network: network, } } diff --git a/testutil/integration/os/network/abci.go b/testutil/integration/evm/network/abci.go similarity index 98% rename from testutil/integration/os/network/abci.go rename to testutil/integration/evm/network/abci.go index 3c50ee383..2050bc253 100644 --- a/testutil/integration/os/network/abci.go +++ b/testutil/integration/evm/network/abci.go @@ -50,7 +50,7 @@ func (n *IntegrationNetwork) finalizeBlockAndCommit(duration time.Duration, txBy return nil, err } - newCtx := n.app.BaseApp.NewContextLegacy(false, header) + newCtx := n.app.GetBaseApp().NewContextLegacy(false, header) // Update context header newCtx = newCtx.WithMinGasPrices(n.ctx.MinGasPrices()) diff --git a/testutil/integration/os/network/amounts.go b/testutil/integration/evm/network/amounts.go similarity index 100% rename from testutil/integration/os/network/amounts.go rename to testutil/integration/evm/network/amounts.go diff --git a/testutil/integration/os/network/chain_id_modifiers.go b/testutil/integration/evm/network/chain_id_modifiers.go similarity index 100% rename from testutil/integration/os/network/chain_id_modifiers.go rename to testutil/integration/evm/network/chain_id_modifiers.go diff --git a/testutil/integration/os/network/clients.go b/testutil/integration/evm/network/clients.go similarity index 87% rename from testutil/integration/os/network/clients.go rename to testutil/integration/evm/network/clients.go index 8e4c3477f..965ade62b 100644 --- a/testutil/integration/os/network/clients.go +++ b/testutil/integration/evm/network/clients.go @@ -34,66 +34,67 @@ func getQueryHelper(ctx sdktypes.Context, encCfg testutil.TestEncodingConfig) *b func (n *IntegrationNetwork) GetERC20Client() erc20types.QueryClient { queryHelper := getQueryHelper(n.GetContext(), n.GetEncodingConfig()) - erc20types.RegisterQueryServer(queryHelper, n.app.Erc20Keeper) + erc20types.RegisterQueryServer(queryHelper, n.app.GetErc20Keeper()) return erc20types.NewQueryClient(queryHelper) } func (n *IntegrationNetwork) GetEvmClient() evmtypes.QueryClient { queryHelper := getQueryHelper(n.GetContext(), n.GetEncodingConfig()) - evmtypes.RegisterQueryServer(queryHelper, n.app.EVMKeeper) + evmtypes.RegisterQueryServer(queryHelper, n.app.GetEVMKeeper()) return evmtypes.NewQueryClient(queryHelper) } func (n *IntegrationNetwork) GetGovClient() govtypes.QueryClient { queryHelper := getQueryHelper(n.GetContext(), n.GetEncodingConfig()) - govtypes.RegisterQueryServer(queryHelper, govkeeper.NewQueryServer(&n.app.GovKeeper)) + govKeeper := n.app.GetGovKeeper() + govtypes.RegisterQueryServer(queryHelper, govkeeper.NewQueryServer(&govKeeper)) return govtypes.NewQueryClient(queryHelper) } func (n *IntegrationNetwork) GetBankClient() banktypes.QueryClient { queryHelper := getQueryHelper(n.GetContext(), n.GetEncodingConfig()) - banktypes.RegisterQueryServer(queryHelper, n.app.BankKeeper) + banktypes.RegisterQueryServer(queryHelper, n.app.GetBankKeeper()) return banktypes.NewQueryClient(queryHelper) } func (n *IntegrationNetwork) GetFeeMarketClient() feemarkettypes.QueryClient { queryHelper := getQueryHelper(n.GetContext(), n.GetEncodingConfig()) - feemarkettypes.RegisterQueryServer(queryHelper, n.app.FeeMarketKeeper) + feemarkettypes.RegisterQueryServer(queryHelper, n.app.GetFeeMarketKeeper()) return feemarkettypes.NewQueryClient(queryHelper) } func (n *IntegrationNetwork) GetAuthClient() authtypes.QueryClient { queryHelper := getQueryHelper(n.GetContext(), n.GetEncodingConfig()) - authtypes.RegisterQueryServer(queryHelper, authkeeper.NewQueryServer(n.app.AccountKeeper)) + authtypes.RegisterQueryServer(queryHelper, authkeeper.NewQueryServer(n.app.GetAccountKeeper())) return authtypes.NewQueryClient(queryHelper) } func (n *IntegrationNetwork) GetAuthzClient() authz.QueryClient { queryHelper := getQueryHelper(n.GetContext(), n.GetEncodingConfig()) - authz.RegisterQueryServer(queryHelper, n.app.AuthzKeeper) + authz.RegisterQueryServer(queryHelper, n.app.GetAuthzKeeper()) return authz.NewQueryClient(queryHelper) } func (n *IntegrationNetwork) GetStakingClient() stakingtypes.QueryClient { queryHelper := getQueryHelper(n.GetContext(), n.GetEncodingConfig()) - stakingtypes.RegisterQueryServer(queryHelper, stakingkeeper.Querier{Keeper: n.app.StakingKeeper}) + stakingtypes.RegisterQueryServer(queryHelper, stakingkeeper.Querier{Keeper: n.app.GetStakingKeeper()}) return stakingtypes.NewQueryClient(queryHelper) } func (n *IntegrationNetwork) GetDistrClient() distrtypes.QueryClient { queryHelper := getQueryHelper(n.GetContext(), n.GetEncodingConfig()) - distrtypes.RegisterQueryServer(queryHelper, distrkeeper.Querier{Keeper: n.app.DistrKeeper}) + distrtypes.RegisterQueryServer(queryHelper, distrkeeper.Querier{Keeper: n.app.GetDistrKeeper()}) return distrtypes.NewQueryClient(queryHelper) } func (n *IntegrationNetwork) GetMintClient() minttypes.QueryClient { queryHelper := getQueryHelper(n.GetContext(), n.GetEncodingConfig()) - minttypes.RegisterQueryServer(queryHelper, mintkeeper.NewQueryServerImpl(n.app.MintKeeper)) + minttypes.RegisterQueryServer(queryHelper, mintkeeper.NewQueryServerImpl(n.app.GetMintKeeper())) return minttypes.NewQueryClient(queryHelper) } func (n *IntegrationNetwork) GetPreciseBankClient() precisebanktypes.QueryClient { queryHelper := getQueryHelper(n.GetContext(), n.GetEncodingConfig()) - precisebanktypes.RegisterQueryServer(queryHelper, precisebankkeeper.NewQueryServerImpl(n.app.PreciseBankKeeper)) + precisebanktypes.RegisterQueryServer(queryHelper, precisebankkeeper.NewQueryServerImpl(*n.app.GetPreciseBankKeeper())) return precisebanktypes.NewQueryClient(queryHelper) } diff --git a/testutil/integration/os/network/coins.go b/testutil/integration/evm/network/coins.go similarity index 100% rename from testutil/integration/os/network/coins.go rename to testutil/integration/evm/network/coins.go diff --git a/testutil/integration/os/network/config.go b/testutil/integration/evm/network/config.go similarity index 98% rename from testutil/integration/os/network/config.go rename to testutil/integration/evm/network/config.go index 92d0d42e0..a2699911f 100644 --- a/testutil/integration/os/network/config.go +++ b/testutil/integration/evm/network/config.go @@ -67,6 +67,10 @@ func DefaultConfig() Config { } } +func (cfg Config) GetChainCoins() ChainCoins { + return cfg.chainCoins +} + // getGenAccountsAndBalances takes the network configuration and returns the used // genesis accounts and balances. // diff --git a/testutil/integration/os/network/example_contracts.go b/testutil/integration/evm/network/example_contracts.go similarity index 100% rename from testutil/integration/os/network/example_contracts.go rename to testutil/integration/evm/network/example_contracts.go diff --git a/testutil/integration/os/network/ibc.go b/testutil/integration/evm/network/ibc.go similarity index 100% rename from testutil/integration/os/network/ibc.go rename to testutil/integration/evm/network/ibc.go diff --git a/testutil/integration/os/network/network.go b/testutil/integration/evm/network/network.go similarity index 84% rename from testutil/integration/os/network/network.go rename to testutil/integration/evm/network/network.go index 8f2537c2c..d8a188cc0 100644 --- a/testutil/integration/os/network/network.go +++ b/testutil/integration/evm/network/network.go @@ -15,9 +15,9 @@ import ( cmttypes "github.com/cometbft/cometbft/types" "github.com/cometbft/cometbft/version" - app "github.com/cosmos/evm/evmd" - chainutil "github.com/cosmos/evm/evmd/testutil" - commonnetwork "github.com/cosmos/evm/testutil/integration/common/network" + "github.com/cosmos/evm" + "github.com/cosmos/evm/testutil/integration" + basenetwork "github.com/cosmos/evm/testutil/integration/base/network" "github.com/cosmos/evm/types" erc20types "github.com/cosmos/evm/x/erc20/types" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" @@ -25,6 +25,7 @@ import ( sdkmath "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/baseapp" sdktypes "github.com/cosmos/cosmos-sdk/types" sdktestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" txtypes "github.com/cosmos/cosmos-sdk/types/tx" @@ -38,8 +39,9 @@ import ( // It was designed to avoid users to access module's keepers directly and force integration tests // to be closer to the real user's behavior. type Network interface { - commonnetwork.Network + basenetwork.Network + GetBaseDecimal() evmtypes.Decimals GetEIP155ChainID() *big.Int GetEVMChainConfig() *gethparams.ChainConfig @@ -51,14 +53,17 @@ type Network interface { GetMintClient() minttypes.QueryClient } +type CreateEvmApp func(chainID string, evmChainID uint64, customBaseAppOptions ...func(*baseapp.BaseApp)) evm.EvmApp + var _ Network = (*IntegrationNetwork)(nil) // IntegrationNetwork is the implementation of the Network interface for integration tests. type IntegrationNetwork struct { - cfg Config - ctx sdktypes.Context - validators []stakingtypes.Validator - app *app.EVMD + cfg Config + ctx sdktypes.Context + validators []stakingtypes.Validator + app evm.EvmApp + baseDecimal evmtypes.Decimals // This is only needed for IBC chain testing setup valSet *cmttypes.ValidatorSet @@ -70,7 +75,7 @@ type IntegrationNetwork struct { // it uses the default configuration. // // It panics if an error occurs. -func New(opts ...ConfigOption) *IntegrationNetwork { +func New(createEvmApp CreateEvmApp, opts ...ConfigOption) *IntegrationNetwork { cfg := DefaultConfig() // Modify the default config with the given options for _, opt := range opts { @@ -84,7 +89,9 @@ func New(opts ...ConfigOption) *IntegrationNetwork { validators: []stakingtypes.Validator{}, } - err := network.configureAndInitChain() + // create a new testing app with the following params + evmApp := createEvmApp(cfg.chainID, cfg.eip155ChainID.Uint64(), cfg.customBaseAppOpts...) + err := network.configureAndInitChain(evmApp) if err != nil { panic(err) } @@ -98,7 +105,7 @@ var PrefundedAccountInitialBalance, _ = sdkmath.NewIntFromString("100_000_000_00 // configureAndInitChain initializes the network with the given configuration. // It creates the genesis state and starts the network. -func (n *IntegrationNetwork) configureAndInitChain() error { +func (n *IntegrationNetwork) configureAndInitChain(evmApp evm.EvmApp) error { // -------------------------------------------------------------------------------------------- // Apply changes deriving from possible config options // FIX: for sure there exists a better way to achieve that. @@ -106,9 +113,10 @@ func (n *IntegrationNetwork) configureAndInitChain() error { // The bonded amount should be updated to reflect the actual base denom baseDecimals := n.cfg.chainCoins.BaseDecimals() + n.baseDecimal = baseDecimals bondedAmount := GetInitialBondedAmount(baseDecimals) - // Create validator set with the amount of validators specified in the config + // create validator set with the amount of validators specified in the config // with the default power of 1. valSet, valSigners := createValidatorSetAndSigners(n.cfg.amountOfValidators) totalBonded := bondedAmount.Mul(sdkmath.NewInt(int64(n.cfg.amountOfValidators))) @@ -119,7 +127,7 @@ func (n *IntegrationNetwork) configureAndInitChain() error { return err } - // Create genesis accounts and funded balances based on the config. + // create genesis accounts and funded balances based on the config. genAccounts, fundedAccountBalances := getGenAccountsAndBalances(n.cfg, validators) fundedAccountBalances = addBondedModuleAccountToFundedBalances( @@ -129,9 +137,6 @@ func (n *IntegrationNetwork) configureAndInitChain() error { delegations := createDelegations(validators, genAccounts[0].GetAddress()) - // Create a new testing app with the following params - exampleApp := createTestingApp(n.cfg.chainID, n.cfg.eip155ChainID.Uint64(), n.cfg.customBaseAppOpts...) - stakingParams := StakingCustomGenesisState{ denom: n.cfg.chainCoins.BaseDenom(), validators: validators, @@ -159,14 +164,14 @@ func (n *IntegrationNetwork) configureAndInitChain() error { // Get the corresponding slashing info and missed block info // for the created validators - slashingParams, err := getValidatorsSlashingGen(validators, exampleApp.StakingKeeper) + slashingParams, err := getValidatorsSlashingGen(validators, evmApp.GetStakingKeeper()) if err != nil { return err } // Configure Genesis state genesisState := newDefaultGenesisState( - exampleApp, + evmApp, n.cfg.eip155ChainID.Uint64(), defaultGenesisParams{ genAccounts: genAccounts, @@ -181,7 +186,7 @@ func (n *IntegrationNetwork) configureAndInitChain() error { // modify genesis state if there're any custom genesis state // for specific modules - genesisState, err = customizeGenesis(exampleApp, n.cfg.customGenesisState, genesisState) + genesisState, err = customizeGenesis(evmApp, n.cfg.customGenesisState, genesisState) if err != nil { return err } @@ -192,10 +197,10 @@ func (n *IntegrationNetwork) configureAndInitChain() error { return err } - consensusParams := chainutil.DefaultConsensusParams + consensusParams := integration.DefaultConsensusParams now := time.Now() - if _, err = exampleApp.InitChain( + if _, err = evmApp.InitChain( &abcitypes.RequestInitChain{ Time: now, ChainId: n.cfg.chainID, @@ -209,8 +214,8 @@ func (n *IntegrationNetwork) configureAndInitChain() error { header := cmtproto.Header{ ChainID: n.cfg.chainID, - Height: exampleApp.LastBlockHeight() + 1, - AppHash: exampleApp.LastCommitID().Hash, + Height: evmApp.LastBlockHeight() + 1, + AppHash: evmApp.LastCommitID().Hash, Time: now, ValidatorsHash: valSet.Hash(), NextValidatorsHash: valSet.Hash(), @@ -221,15 +226,15 @@ func (n *IntegrationNetwork) configureAndInitChain() error { } req := buildFinalizeBlockReq(header, valSet.Validators) - if _, err := exampleApp.FinalizeBlock(req); err != nil { + if _, err := evmApp.FinalizeBlock(req); err != nil { return err } // TODO - this might not be the best way to initilize the context - n.ctx = exampleApp.BaseApp.NewContextLegacy(false, header) + n.ctx = evmApp.GetBaseApp().NewContextLegacy(false, header) // Commit genesis changes - if _, err := exampleApp.Commit(); err != nil { + if _, err := evmApp.Commit(); err != nil { return err } @@ -239,7 +244,7 @@ func (n *IntegrationNetwork) configureAndInitChain() error { blockMaxGas = uint64(consensusParams.Block.MaxGas) //#nosec G115 -- max gas will not exceed uint64 } - n.app = exampleApp + n.app = evmApp n.ctx = n.ctx.WithConsensusParams(*consensusParams) n.ctx = n.ctx.WithBlockGasMeter(types.NewInfiniteGasMeterWithLimit(blockMaxGas)) @@ -250,6 +255,11 @@ func (n *IntegrationNetwork) configureAndInitChain() error { return nil } +// GetConfig returns the network's configuration +func (n *IntegrationNetwork) GetBaseDecimal() evmtypes.Decimals { + return n.baseDecimal +} + // GetContext returns the network's context func (n *IntegrationNetwork) GetContext() sdktypes.Context { return n.ctx @@ -324,7 +334,7 @@ func (n *IntegrationNetwork) BroadcastTxSync(txBytes []byte) (abcitypes.ExecTxRe // NextBlock or NextBlockAfter functions req.DecidedLastCommit = abcitypes.CommitInfo{} - blockRes, err := n.app.BaseApp.FinalizeBlock(req) + blockRes, err := n.app.GetBaseApp().FinalizeBlock(req) if err != nil { return abcitypes.ExecTxResult{}, err } @@ -337,7 +347,7 @@ func (n *IntegrationNetwork) BroadcastTxSync(txBytes []byte) (abcitypes.ExecTxRe // Simulate simulates the given txBytes to the network and returns the simulated response. // TODO - this should be change to gRPC func (n *IntegrationNetwork) Simulate(txBytes []byte) (*txtypes.SimulateResponse, error) { - gas, result, err := n.app.BaseApp.Simulate(txBytes) + gas, result, err := n.app.GetBaseApp().Simulate(txBytes) if err != nil { return nil, err } @@ -350,7 +360,7 @@ func (n *IntegrationNetwork) Simulate(txBytes []byte) (*txtypes.SimulateResponse // CheckTx calls the BaseApp's CheckTx method with the given txBytes to the network and returns the response. func (n *IntegrationNetwork) CheckTx(txBytes []byte) (*abcitypes.ResponseCheckTx, error) { req := &abcitypes.RequestCheckTx{Tx: txBytes} - res, err := n.app.BaseApp.CheckTx(req) + res, err := n.app.GetBaseApp().CheckTx(req) if err != nil { return nil, err } diff --git a/testutil/integration/os/network/setup.go b/testutil/integration/evm/network/setup.go similarity index 84% rename from testutil/integration/os/network/setup.go rename to testutil/integration/evm/network/setup.go index f7b4e1cff..13e280dcd 100644 --- a/testutil/integration/os/network/setup.go +++ b/testutil/integration/evm/network/setup.go @@ -9,8 +9,7 @@ import ( cmttypes "github.com/cometbft/cometbft/types" - dbm "github.com/cosmos/cosmos-db" - exampleapp "github.com/cosmos/evm/evmd" + "github.com/cosmos/evm" testconstants "github.com/cosmos/evm/testutil/constants" cosmosevmtypes "github.com/cosmos/evm/types" erc20types "github.com/cosmos/evm/x/erc20/types" @@ -19,14 +18,11 @@ import ( "github.com/cosmos/gogoproto/proto" capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types" - "cosmossdk.io/log" sdkmath "cosmossdk.io/math" - "github.com/cosmos/cosmos-sdk/baseapp" codectypes "github.com/cosmos/cosmos-sdk/codec/types" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" "github.com/cosmos/cosmos-sdk/testutil/mock" - simutils "github.com/cosmos/cosmos-sdk/testutil/sims" sdktypes "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -40,7 +36,7 @@ import ( ) // genSetupFn is the type for the module genesis setup functions -type genSetupFn func(cosmosEVMApp *exampleapp.EVMD, genesisState cosmosevmtypes.GenesisState, customGenesis interface{}) (cosmosevmtypes.GenesisState, error) +type genSetupFn func(cosmosEVMApp evm.EvmApp, genesisState cosmosevmtypes.GenesisState, customGenesis interface{}) (cosmosevmtypes.GenesisState, error) // defaultGenesisParams contains the params that are needed to // setup the default genesis for the testing setup @@ -65,7 +61,7 @@ var genesisSetupFunctions = map[string]genSetupFn{ minttypes.ModuleName: genStateSetter[*minttypes.GenesisState](minttypes.ModuleName), banktypes.ModuleName: setBankGenesisState, authtypes.ModuleName: setAuthGenesisState, - consensustypes.ModuleName: func(_ *exampleapp.EVMD, genesisState cosmosevmtypes.GenesisState, _ interface{}) (cosmosevmtypes.GenesisState, error) { + consensustypes.ModuleName: func(_ evm.EvmApp, genesisState cosmosevmtypes.GenesisState, _ interface{}) (cosmosevmtypes.GenesisState, error) { // no-op. Consensus does not have a genesis state on the application // but the params are used on it // (e.g. block max gas, max bytes). @@ -77,7 +73,7 @@ var genesisSetupFunctions = map[string]genSetupFn{ // genStateSetter is a generic function to set module-specific genesis state func genStateSetter[T proto.Message](moduleName string) genSetupFn { - return func(cosmosEVMApp *exampleapp.EVMD, genesisState cosmosevmtypes.GenesisState, customGenesis interface{}) (cosmosevmtypes.GenesisState, error) { + return func(cosmosEVMApp evm.EvmApp, genesisState cosmosevmtypes.GenesisState, customGenesis interface{}) (cosmosevmtypes.GenesisState, error) { moduleGenesis, ok := customGenesis.(T) if !ok { return nil, fmt.Errorf("invalid type %T for %s module genesis state", customGenesis, moduleName) @@ -91,7 +87,7 @@ func genStateSetter[T proto.Message](moduleName string) genSetupFn { // createValidatorSetAndSigners creates validator set with the amount of validators specified // with the default power of 1. func createValidatorSetAndSigners(numberOfValidators int) (*cmttypes.ValidatorSet, map[string]cmttypes.PrivValidator) { - // Create validator set + // create validator set tmValidators := make([]*cmttypes.Validator, 0, numberOfValidators) signers := make(map[string]cmttypes.PrivValidator, numberOfValidators) @@ -159,27 +155,6 @@ func createBalances( return fundedAccountBalances } -// createTestingApp creates an evmos app -func createTestingApp(chainID string, evmChainID uint64, customBaseAppOptions ...func(*baseapp.BaseApp)) *exampleapp.EVMD { - // Create evmos app - db := dbm.NewMemDB() - logger := log.NewNopLogger() - loadLatest := true - appOptions := simutils.NewAppOptionsWithFlagHome(exampleapp.DefaultNodeHome) - baseAppOptions := append(customBaseAppOptions, baseapp.SetChainID(chainID)) //nolint:gocritic - - return exampleapp.NewExampleApp( - logger, - db, - nil, - loadLatest, - appOptions, - evmChainID, - exampleapp.EvmAppOptions, - baseAppOptions..., - ) -} - // createStakingValidator creates a staking validator from the given tm validator and bonded func createStakingValidator(val *cmttypes.Validator, bondedAmt sdkmath.Int, operatorAddr *sdktypes.AccAddress) (stakingtypes.Validator, error) { pk, err := cryptocodec.FromTmPubKeyInterface(val.PubKey) //nolint:staticcheck @@ -308,7 +283,7 @@ type StakingCustomGenesisState struct { } // setDefaultStakingGenesisState sets the default staking genesis state -func setDefaultStakingGenesisState(cosmosEVMApp *exampleapp.EVMD, genesisState cosmosevmtypes.GenesisState, overwriteParams StakingCustomGenesisState) cosmosevmtypes.GenesisState { +func setDefaultStakingGenesisState(cosmosEVMApp evm.EvmApp, genesisState cosmosevmtypes.GenesisState, overwriteParams StakingCustomGenesisState) cosmosevmtypes.GenesisState { // Set staking params stakingParams := stakingtypes.DefaultParams() stakingParams.BondDenom = overwriteParams.denom @@ -328,7 +303,7 @@ type BankCustomGenesisState struct { } // setDefaultBankGenesisState sets the default bank genesis state -func setDefaultBankGenesisState(cosmosEVMApp *exampleapp.EVMD, genesisState cosmosevmtypes.GenesisState, overwriteParams BankCustomGenesisState) cosmosevmtypes.GenesisState { +func setDefaultBankGenesisState(cosmosEVMApp evm.EvmApp, genesisState cosmosevmtypes.GenesisState, overwriteParams BankCustomGenesisState) cosmosevmtypes.GenesisState { bankGenesis := banktypes.NewGenesisState( banktypes.DefaultGenesisState().Params, overwriteParams.balances, @@ -349,7 +324,7 @@ type SlashingCustomGenesisState struct { } // setDefaultSlashingGenesisState sets the default slashing genesis state -func setDefaultSlashingGenesisState(cosmosEVMApp *exampleapp.EVMD, genesisState cosmosevmtypes.GenesisState, overwriteParams SlashingCustomGenesisState) cosmosevmtypes.GenesisState { +func setDefaultSlashingGenesisState(cosmosEVMApp evm.EvmApp, genesisState cosmosevmtypes.GenesisState, overwriteParams SlashingCustomGenesisState) cosmosevmtypes.GenesisState { slashingGen := slashingtypes.DefaultGenesisState() slashingGen.SigningInfos = overwriteParams.signingInfo slashingGen.MissedBlocks = overwriteParams.missedBlocks @@ -359,7 +334,7 @@ func setDefaultSlashingGenesisState(cosmosEVMApp *exampleapp.EVMD, genesisState } // setBankGenesisState updates the bank genesis state with custom genesis state -func setBankGenesisState(cosmosEVMApp *exampleapp.EVMD, genesisState cosmosevmtypes.GenesisState, customGenesis interface{}) (cosmosevmtypes.GenesisState, error) { +func setBankGenesisState(cosmosEVMApp evm.EvmApp, genesisState cosmosevmtypes.GenesisState, customGenesis interface{}) (cosmosevmtypes.GenesisState, error) { customGen, ok := customGenesis.(*banktypes.GenesisState) if !ok { return nil, fmt.Errorf("invalid type %T for bank module genesis state", customGenesis) @@ -411,14 +386,14 @@ func addBondedModuleAccountToFundedBalances( } // setDefaultAuthGenesisState sets the default auth genesis state -func setDefaultAuthGenesisState(cosmosEVMApp *exampleapp.EVMD, genesisState cosmosevmtypes.GenesisState, genAccs []authtypes.GenesisAccount) cosmosevmtypes.GenesisState { +func setDefaultAuthGenesisState(cosmosEVMApp evm.EvmApp, genesisState cosmosevmtypes.GenesisState, genAccs []authtypes.GenesisAccount) cosmosevmtypes.GenesisState { defaultAuthGen := authtypes.NewGenesisState(authtypes.DefaultParams(), genAccs) genesisState[authtypes.ModuleName] = cosmosEVMApp.AppCodec().MustMarshalJSON(defaultAuthGen) return genesisState } // setAuthGenesisState updates the bank genesis state with custom genesis state -func setAuthGenesisState(cosmosEVMApp *exampleapp.EVMD, genesisState cosmosevmtypes.GenesisState, customGenesis interface{}) (cosmosevmtypes.GenesisState, error) { +func setAuthGenesisState(cosmosEVMApp evm.EvmApp, genesisState cosmosevmtypes.GenesisState, customGenesis interface{}) (cosmosevmtypes.GenesisState, error) { customGen, ok := customGenesis.(*authtypes.GenesisState) if !ok { return nil, fmt.Errorf("invalid type %T for auth module genesis state", customGenesis) @@ -443,7 +418,7 @@ type GovCustomGenesisState struct { } // setDefaultGovGenesisState sets the default gov genesis state -func setDefaultGovGenesisState(cosmosEVMApp *exampleapp.EVMD, genesisState cosmosevmtypes.GenesisState, overwriteParams GovCustomGenesisState) cosmosevmtypes.GenesisState { +func setDefaultGovGenesisState(cosmosEVMApp evm.EvmApp, genesisState cosmosevmtypes.GenesisState, overwriteParams GovCustomGenesisState) cosmosevmtypes.GenesisState { govGen := govtypesv1.DefaultGenesisState() updatedParams := govGen.Params minDepositAmt := sdkmath.NewInt(1e18).Quo(evmtypes.GetEVMCoinDecimals().ConversionFactor()) @@ -460,7 +435,7 @@ type FeeMarketCustomGenesisState struct { } // setDefaultFeeMarketGenesisState sets the default fee market genesis state -func setDefaultFeeMarketGenesisState(cosmosEVMApp *exampleapp.EVMD, genesisState cosmosevmtypes.GenesisState, overwriteParams FeeMarketCustomGenesisState) cosmosevmtypes.GenesisState { +func setDefaultFeeMarketGenesisState(cosmosEVMApp evm.EvmApp, genesisState cosmosevmtypes.GenesisState, overwriteParams FeeMarketCustomGenesisState) cosmosevmtypes.GenesisState { fmGen := feemarkettypes.DefaultGenesisState() fmGen.Params.BaseFee = overwriteParams.baseFee genesisState[feemarkettypes.ModuleName] = cosmosEVMApp.AppCodec().MustMarshalJSON(fmGen) @@ -477,7 +452,7 @@ type MintCustomGenesisState struct { // setDefaultGovGenesisState sets the default gov genesis state // // NOTE: for the testing network we don't want to have any minting -func setDefaultMintGenesisState(cosmosEVMApp *exampleapp.EVMD, genesisState cosmosevmtypes.GenesisState, overwriteParams MintCustomGenesisState) cosmosevmtypes.GenesisState { +func setDefaultMintGenesisState(cosmosEVMApp evm.EvmApp, genesisState cosmosevmtypes.GenesisState, overwriteParams MintCustomGenesisState) cosmosevmtypes.GenesisState { mintGen := minttypes.DefaultGenesisState() updatedParams := mintGen.Params updatedParams.MintDenom = overwriteParams.denom @@ -489,13 +464,16 @@ func setDefaultMintGenesisState(cosmosEVMApp *exampleapp.EVMD, genesisState cosm return genesisState } -func setDefaultErc20GenesisState(cosmosEVMApp *exampleapp.EVMD, evmChainID uint64, genesisState cosmosevmtypes.GenesisState) cosmosevmtypes.GenesisState { +func setDefaultErc20GenesisState(cosmosEVMApp evm.EvmApp, evmChainID uint64, genesisState cosmosevmtypes.GenesisState) cosmosevmtypes.GenesisState { // NOTE: here we are using the setup from the example chain - erc20Gen := exampleapp.NewErc20GenesisState() + erc20GenState := erc20types.DefaultGenesisState() + erc20GenState.TokenPairs = testconstants.ExampleTokenPairs + erc20GenState.Params.NativePrecompiles = append(erc20GenState.Params.NativePrecompiles, testconstants.WEVMOSContractMainnet) + updatedErc20Gen := updateErc20GenesisStateForChainID(testconstants.ChainID{ ChainID: cosmosEVMApp.ChainID(), EVMChainID: evmChainID, - }, *erc20Gen) + }, *erc20GenState) genesisState[erc20types.ModuleName] = cosmosEVMApp.AppCodec().MustMarshalJSON(&updatedErc20Gen) return genesisState @@ -503,7 +481,7 @@ func setDefaultErc20GenesisState(cosmosEVMApp *exampleapp.EVMD, evmChainID uint6 // defaultAuthGenesisState sets the default genesis state // for the testing setup -func newDefaultGenesisState(cosmosEVMApp *exampleapp.EVMD, evmChainID uint64, params defaultGenesisParams) cosmosevmtypes.GenesisState { +func newDefaultGenesisState(cosmosEVMApp evm.EvmApp, evmChainID uint64, params defaultGenesisParams) cosmosevmtypes.GenesisState { genesisState := cosmosEVMApp.DefaultGenesis() genesisState = setDefaultAuthGenesisState(cosmosEVMApp, genesisState, params.genAccounts) @@ -520,7 +498,7 @@ func newDefaultGenesisState(cosmosEVMApp *exampleapp.EVMD, evmChainID uint64, pa // customizeGenesis modifies genesis state if there are any custom genesis state // for specific modules -func customizeGenesis(cosmosEVMApp *exampleapp.EVMD, customGen CustomGenesisState, genesisState cosmosevmtypes.GenesisState) (cosmosevmtypes.GenesisState, error) { +func customizeGenesis(cosmosEVMApp evm.EvmApp, customGen CustomGenesisState, genesisState cosmosevmtypes.GenesisState) (cosmosevmtypes.GenesisState, error) { var err error for mod, modGenState := range customGen { if fn, found := genesisSetupFunctions[mod]; found { diff --git a/testutil/integration/os/network/unit_network.go b/testutil/integration/evm/network/unit_network.go similarity index 77% rename from testutil/integration/os/network/unit_network.go rename to testutil/integration/evm/network/unit_network.go index cb91499b3..9e23559f7 100644 --- a/testutil/integration/os/network/unit_network.go +++ b/testutil/integration/evm/network/unit_network.go @@ -3,7 +3,7 @@ package network import ( "github.com/ethereum/go-ethereum/common" - exampleapp "github.com/cosmos/evm/evmd" + "github.com/cosmos/evm" "github.com/cosmos/evm/x/vm/statedb" sdktypes "github.com/cosmos/cosmos-sdk/types" @@ -15,7 +15,7 @@ import ( // makes the App public for easier testing. type UnitTestNetwork struct { IntegrationNetwork - App *exampleapp.EVMD + App evm.EvmApp } var _ Network = (*UnitTestNetwork)(nil) @@ -26,8 +26,8 @@ var _ Network = (*UnitTestNetwork)(nil) // // It panics if an error occurs. // Note: Only uses for Unit Tests -func NewUnitTestNetwork(opts ...ConfigOption) *UnitTestNetwork { - network := New(opts...) +func NewUnitTestNetwork(createEvmApp CreateEvmApp, opts ...ConfigOption) *UnitTestNetwork { + network := New(createEvmApp, opts...) return &UnitTestNetwork{ IntegrationNetwork: *network, App: network.app, @@ -39,7 +39,7 @@ func (n *UnitTestNetwork) GetStateDB() *statedb.StateDB { headerHash := n.GetContext().HeaderHash() return statedb.New( n.GetContext(), - n.app.EVMKeeper, + n.app.GetEVMKeeper(), statedb.NewEmptyTxConfig(common.BytesToHash(headerHash)), ) } @@ -48,9 +48,9 @@ func (n *UnitTestNetwork) GetStateDB() *statedb.StateDB { func (n *UnitTestNetwork) FundAccount(addr sdktypes.AccAddress, coins sdktypes.Coins) error { ctx := n.GetContext() - if err := n.app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, coins); err != nil { + if err := n.app.GetBankKeeper().MintCoins(ctx, minttypes.ModuleName, coins); err != nil { return err } - return n.app.BankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, coins) + return n.app.GetBankKeeper().SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, coins) } diff --git a/testutil/integration/os/utils/bank.go b/testutil/integration/evm/utils/bank.go similarity index 85% rename from testutil/integration/os/utils/bank.go rename to testutil/integration/evm/utils/bank.go index eb9a153da..edd91f31c 100644 --- a/testutil/integration/os/utils/bank.go +++ b/testutil/integration/evm/utils/bank.go @@ -4,9 +4,9 @@ import ( "context" "fmt" - cmnfactory "github.com/cosmos/evm/testutil/integration/common/factory" - cmnnet "github.com/cosmos/evm/testutil/integration/common/network" - "github.com/cosmos/evm/testutil/integration/os/keyring" + cmnfactory "github.com/cosmos/evm/testutil/integration/base/factory" + cmnnet "github.com/cosmos/evm/testutil/integration/base/network" + "github.com/cosmos/evm/testutil/keyring" "cosmossdk.io/math" diff --git a/testutil/integration/os/utils/contracts.go b/testutil/integration/evm/utils/contracts.go similarity index 88% rename from testutil/integration/os/utils/contracts.go rename to testutil/integration/evm/utils/contracts.go index 8a85c6a11..b98b0a236 100644 --- a/testutil/integration/os/utils/contracts.go +++ b/testutil/integration/evm/utils/contracts.go @@ -6,7 +6,7 @@ import ( abcitypes "github.com/cometbft/cometbft/abci/types" - "github.com/cosmos/evm/testutil/integration/os/factory" + testutiltypes "github.com/cosmos/evm/testutil/types" evmtypes "github.com/cosmos/evm/x/vm/types" ) @@ -33,7 +33,7 @@ func CheckTxTopics(res abcitypes.ExecTxResult, expectedTopics []string) error { } // DecodeContractCallResponse decodes the response of a contract call query -func DecodeContractCallResponse(response interface{}, callArgs factory.CallArgs, res abcitypes.ExecTxResult) error { +func DecodeContractCallResponse(response interface{}, callArgs testutiltypes.CallArgs, res abcitypes.ExecTxResult) error { msgEthResponse, err := DecodeExecTxResult(res) if err != nil { return err diff --git a/testutil/integration/os/utils/erc20.go b/testutil/integration/evm/utils/erc20.go similarity index 96% rename from testutil/integration/os/utils/erc20.go rename to testutil/integration/evm/utils/erc20.go index 281087ab0..89d34c27d 100644 --- a/testutil/integration/os/utils/erc20.go +++ b/testutil/integration/evm/utils/erc20.go @@ -5,8 +5,8 @@ import ( "github.com/ethereum/go-ethereum/common" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/network" erc20types "github.com/cosmos/evm/x/erc20/types" errorsmod "cosmossdk.io/errors" diff --git a/testutil/integration/os/utils/events.go b/testutil/integration/evm/utils/events.go similarity index 100% rename from testutil/integration/os/utils/events.go rename to testutil/integration/evm/utils/events.go diff --git a/testutil/integration/os/utils/evm.go b/testutil/integration/evm/utils/evm.go similarity index 95% rename from testutil/integration/os/utils/evm.go rename to testutil/integration/evm/utils/evm.go index a05bcf91c..0ae12b85a 100644 --- a/testutil/integration/os/utils/evm.go +++ b/testutil/integration/evm/utils/evm.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/cosmos/evm/contracts" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/network" evmtypes "github.com/cosmos/evm/x/vm/types" ) diff --git a/testutil/integration/os/utils/genesis.go b/testutil/integration/evm/utils/genesis.go similarity index 79% rename from testutil/integration/os/utils/genesis.go rename to testutil/integration/evm/utils/genesis.go index 9472c2b58..e2493a0ff 100644 --- a/testutil/integration/os/utils/genesis.go +++ b/testutil/integration/evm/utils/genesis.go @@ -1,10 +1,10 @@ package utils import ( - exampleapp "github.com/cosmos/evm/evmd" "github.com/cosmos/evm/testutil/constants" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" + testconstants "github.com/cosmos/evm/testutil/constants" + "github.com/cosmos/evm/testutil/integration/evm/network" + testkeyring "github.com/cosmos/evm/testutil/keyring" utiltx "github.com/cosmos/evm/testutil/tx" erc20types "github.com/cosmos/evm/x/erc20/types" @@ -69,7 +69,7 @@ func CreateGenesisWithTokenPairs(keyring testkeyring.Keyring, denoms ...string) // STR v2: update the NativePrecompiles and DynamicPrecompiles // with the WEVMOS (default is mainnet) and 'xmpl' tokens in the erc20 params - erc20GenesisState := exampleapp.NewErc20GenesisState() + erc20GenesisState := NewErc20GenesisState() erc20GenesisState.TokenPairs = tokenPairs erc20GenesisState.Params.NativePrecompiles = []string{constants.WEVMOSContractMainnet} erc20GenesisState.Params.DynamicPrecompiles = dynPrecAddr @@ -80,3 +80,15 @@ func CreateGenesisWithTokenPairs(keyring testkeyring.Keyring, denoms ...string) erc20types.ModuleName: erc20GenesisState, } } + +// NewErc20GenesisState returns the default genesis state for the ERC20 module. +// +// NOTE: for the example chain implementation we are also adding a default token pair, +// which is the base denomination of the chain (i.e. the WEVMOS contract). +func NewErc20GenesisState() *erc20types.GenesisState { + erc20GenState := erc20types.DefaultGenesisState() + erc20GenState.TokenPairs = testconstants.ExampleTokenPairs + erc20GenState.Params.NativePrecompiles = append(erc20GenState.Params.NativePrecompiles, testconstants.WEVMOSContractMainnet) + + return erc20GenState +} diff --git a/testutil/integration/os/utils/gov.go b/testutil/integration/evm/utils/gov.go similarity index 96% rename from testutil/integration/os/utils/gov.go rename to testutil/integration/evm/utils/gov.go index efae3e92e..4da565ba3 100644 --- a/testutil/integration/os/utils/gov.go +++ b/testutil/integration/evm/utils/gov.go @@ -7,9 +7,9 @@ import ( abcitypes "github.com/cometbft/cometbft/abci/types" - commonfactory "github.com/cosmos/evm/testutil/integration/common/factory" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/network" + commonfactory "github.com/cosmos/evm/testutil/integration/base/factory" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/network" evmtypes "github.com/cosmos/evm/x/vm/types" errorsmod "cosmossdk.io/errors" diff --git a/testutil/integration/os/utils/params.go b/testutil/integration/evm/utils/params.go similarity index 96% rename from testutil/integration/os/utils/params.go rename to testutil/integration/evm/utils/params.go index 5ed7d2ea3..76f62b380 100644 --- a/testutil/integration/os/utils/params.go +++ b/testutil/integration/evm/utils/params.go @@ -3,8 +3,8 @@ package utils import ( "fmt" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/network" erc20types "github.com/cosmos/evm/x/erc20/types" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" evmtypes "github.com/cosmos/evm/x/vm/types" diff --git a/testutil/integration/os/utils/staking.go b/testutil/integration/evm/utils/staking.go similarity index 96% rename from testutil/integration/os/utils/staking.go rename to testutil/integration/evm/utils/staking.go index 07734312a..7f09fbb7c 100644 --- a/testutil/integration/os/utils/staking.go +++ b/testutil/integration/evm/utils/staking.go @@ -4,8 +4,8 @@ import ( "errors" "time" - "github.com/cosmos/evm/testutil/integration/os/grpc" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" errorsmod "cosmossdk.io/errors" diff --git a/testutil/integration/os/utils/types.go b/testutil/integration/evm/utils/types.go similarity index 100% rename from testutil/integration/os/utils/types.go rename to testutil/integration/evm/utils/types.go diff --git a/testutil/integration/os/utils/unit.go b/testutil/integration/evm/utils/unit.go similarity index 73% rename from testutil/integration/os/utils/unit.go rename to testutil/integration/evm/utils/unit.go index 2f0de9d8c..24780d0b5 100644 --- a/testutil/integration/os/utils/unit.go +++ b/testutil/integration/evm/utils/unit.go @@ -7,7 +7,7 @@ package utils import ( "fmt" - "github.com/cosmos/evm/testutil/integration/os/network" + "github.com/cosmos/evm/testutil/integration/evm/network" erc20types "github.com/cosmos/evm/x/erc20/types" transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" @@ -30,13 +30,13 @@ func RegisterEvmosERC20Coins( network network.UnitTestNetwork, tokenReceiver sdk.AccAddress, ) (erc20types.TokenPair, error) { - bondDenom, err := network.App.StakingKeeper.BondDenom(network.GetContext()) + bondDenom, err := network.App.GetStakingKeeper().BondDenom(network.GetContext()) if err != nil { return erc20types.TokenPair{}, err } coin := sdk.NewCoin(bondDenom, math.NewInt(TokenToMint)) - err = network.App.BankKeeper.MintCoins( + err = network.App.GetBankKeeper().MintCoins( network.GetContext(), minttypes.ModuleName, sdk.NewCoins(coin), @@ -44,7 +44,7 @@ func RegisterEvmosERC20Coins( if err != nil { return erc20types.TokenPair{}, err } - err = network.App.BankKeeper.SendCoinsFromModuleToAccount( + err = network.App.GetBankKeeper().SendCoinsFromModuleToAccount( network.GetContext(), minttypes.ModuleName, tokenReceiver, @@ -54,18 +54,18 @@ func RegisterEvmosERC20Coins( return erc20types.TokenPair{}, err } - cosmosEVMMetadata, found := network.App.BankKeeper.GetDenomMetaData(network.GetContext(), bondDenom) + cosmosEVMMetadata, found := network.App.GetBankKeeper().GetDenomMetaData(network.GetContext(), bondDenom) if !found { return erc20types.TokenPair{}, fmt.Errorf("expected evmos denom metadata") } - _, err = network.App.Erc20Keeper.RegisterERC20Extension(network.GetContext(), cosmosEVMMetadata.Base) + _, err = network.App.GetErc20Keeper().RegisterERC20Extension(network.GetContext(), cosmosEVMMetadata.Base) if err != nil { return erc20types.TokenPair{}, err } - cosmosEVMDenomID := network.App.Erc20Keeper.GetDenomMap(network.GetContext(), bondDenom) - tokenPair, ok := network.App.Erc20Keeper.GetTokenPair(network.GetContext(), cosmosEVMDenomID) + cosmosEVMDenomID := network.App.GetErc20Keeper().GetDenomMap(network.GetContext(), bondDenom) + tokenPair, ok := network.App.GetErc20Keeper().GetTokenPair(network.GetContext(), cosmosEVMDenomID) if !ok { return erc20types.TokenPair{}, fmt.Errorf("expected evmos erc20 token pair") } @@ -85,7 +85,7 @@ func RegisterIBCERC20Coins( denom transfertypes.Denom, ) (erc20types.TokenPair, error) { ibcDenom := denom.IBCDenom() - network.App.TransferKeeper.SetDenom(network.GetContext(), denom) + network.App.GetTransferKeeper().SetDenom(network.GetContext(), denom) ibcMetadata := banktypes.Metadata{ Name: "Generic IBC name", Symbol: "IBC", @@ -106,7 +106,7 @@ func RegisterIBCERC20Coins( } coin := sdk.NewCoin(ibcMetadata.Base, math.NewInt(TokenToMint)) - err := network.App.BankKeeper.MintCoins( + err := network.App.GetBankKeeper().MintCoins( network.GetContext(), minttypes.ModuleName, sdk.NewCoins(coin), @@ -115,7 +115,7 @@ func RegisterIBCERC20Coins( return erc20types.TokenPair{}, err } - err = network.App.BankKeeper.SendCoinsFromModuleToAccount( + err = network.App.GetBankKeeper().SendCoinsFromModuleToAccount( network.GetContext(), minttypes.ModuleName, tokenReceiver, @@ -125,16 +125,16 @@ func RegisterIBCERC20Coins( return erc20types.TokenPair{}, err } - _, err = network.App.Erc20Keeper.RegisterERC20Extension(network.GetContext(), ibcMetadata.Base) + _, err = network.App.GetErc20Keeper().RegisterERC20Extension(network.GetContext(), ibcMetadata.Base) if err != nil { return erc20types.TokenPair{}, err } - ibcDenomID := network.App.Erc20Keeper.GetDenomMap( + ibcDenomID := network.App.GetErc20Keeper().GetDenomMap( network.GetContext(), denom.IBCDenom(), ) - tokenPair, ok := network.App.Erc20Keeper.GetTokenPair(network.GetContext(), ibcDenomID) + tokenPair, ok := network.App.GetErc20Keeper().GetTokenPair(network.GetContext(), ibcDenomID) if !ok { return erc20types.TokenPair{}, fmt.Errorf("expected %s erc20 token pair", ibcDenom) } diff --git a/testutil/integration/os/network/config_test.go b/testutil/integration/os/network/config_test.go deleted file mode 100644 index 8826ae39f..000000000 --- a/testutil/integration/os/network/config_test.go +++ /dev/null @@ -1,136 +0,0 @@ -package network_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - testconstants "github.com/cosmos/evm/testutil/constants" - grpchandler "github.com/cosmos/evm/testutil/integration/os/grpc" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" - evmtypes "github.com/cosmos/evm/x/vm/types" - - "cosmossdk.io/math" - - sdk "github.com/cosmos/cosmos-sdk/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" -) - -func TestWithChainID(t *testing.T) { - eighteenDecimalsCoinInfo := testconstants.ExampleChainCoinInfo[testconstants.ExampleChainID] - sixDecimalsCoinInfo := testconstants.ExampleChainCoinInfo[testconstants.SixDecimalsChainID] - - testCases := []struct { - name string - chainID testconstants.ChainID - evmChainID uint64 - coinInfo evmtypes.EvmCoinInfo - expBaseFee math.LegacyDec - expCosmosAmount math.Int - }{ - { - name: "18 decimals", - chainID: testconstants.ExampleChainID, - coinInfo: eighteenDecimalsCoinInfo, - expBaseFee: math.LegacyNewDec(875_000_000), - expCosmosAmount: network.GetInitialAmount(evmtypes.EighteenDecimals), - }, - { - name: "6 decimals", - chainID: testconstants.SixDecimalsChainID, - coinInfo: sixDecimalsCoinInfo, - expBaseFee: math.LegacyNewDecWithPrec(875, 6), - expCosmosAmount: network.GetInitialAmount(evmtypes.SixDecimals), - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - // Create a new network with 2 pre-funded accounts - keyring := testkeyring.New(1) - - opts := []network.ConfigOption{ - network.WithChainID(tc.chainID), - network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), - } - - nw := network.New(opts...) - - handler := grpchandler.NewIntegrationHandler(nw) - - // ------------------------------------------------------------------------------------ - // Checks on initial balances. - // ------------------------------------------------------------------------------------ - - // Evm balance should always be in 18 decimals regardless of the - // chain ID. - - // Evm balance should always be in 18 decimals - req, err := handler.GetBalanceFromEVM(keyring.GetAccAddr(0)) - require.NoError(t, err, "error getting balances") - require.Equal(t, - network.GetInitialAmount(evmtypes.EighteenDecimals).String(), - req.Balance, - "expected amount to be in 18 decimals", - ) - - // Bank balance should always be in the original amount. - cReq, err := handler.GetBalanceFromBank(keyring.GetAccAddr(0), tc.coinInfo.Denom) - require.NoError(t, err, "error getting balances") - require.Equal(t, - tc.expCosmosAmount.String(), - cReq.Balance.Amount.String(), - "expected amount to be in original decimals", - ) - - // ------------------------------------------------------------------------------------ - // Checks on the base fee. - // ------------------------------------------------------------------------------------ - // Base fee should always be represented with the decimal - // representation of the EVM denom coin. - bfResp, err := handler.GetBaseFee() - require.NoError(t, err, "error getting base fee") - require.Equal(t, - tc.expBaseFee.String(), - bfResp.BaseFee.String(), - "expected amount to be in 18 decimals", - ) - }) - } -} - -func TestWithBalances(t *testing.T) { - key1Balance := sdk.NewCoins(sdk.NewInt64Coin(testconstants.ExampleAttoDenom, 1e18)) - key2Balance := sdk.NewCoins( - sdk.NewInt64Coin(testconstants.ExampleAttoDenom, 2e18), - sdk.NewInt64Coin("other", 3e18), - ) - - // Create a new network with 2 pre-funded accounts - keyring := testkeyring.New(2) - balances := []banktypes.Balance{ - { - Address: keyring.GetAccAddr(0).String(), - Coins: key1Balance, - }, - { - Address: keyring.GetAccAddr(1).String(), - Coins: key2Balance, - }, - } - nw := network.New( - network.WithBalances(balances...), - ) - handler := grpchandler.NewIntegrationHandler(nw) - - req, err := handler.GetAllBalances(keyring.GetAccAddr(0)) - require.NoError(t, err, "error getting balances") - require.Len(t, req.Balances, 1, "wrong number of balances") - require.Equal(t, balances[0].Coins, req.Balances, "wrong balances") - - req, err = handler.GetAllBalances(keyring.GetAccAddr(1)) - require.NoError(t, err, "error getting balances") - require.Len(t, req.Balances, 2, "wrong number of balances") - require.Equal(t, balances[1].Coins, req.Balances, "wrong balances") -} diff --git a/testutil/integration/os/utils/bank_test.go b/testutil/integration/os/utils/bank_test.go deleted file mode 100644 index 011ccffed..000000000 --- a/testutil/integration/os/utils/bank_test.go +++ /dev/null @@ -1,74 +0,0 @@ -package utils_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" - "github.com/cosmos/evm/testutil/integration/os/utils" - evmtypes "github.com/cosmos/evm/x/vm/types" - - "cosmossdk.io/math" - - sdk "github.com/cosmos/cosmos-sdk/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" -) - -func TestCheckBalances(t *testing.T) { - testDenom := "atest" - keyring := testkeyring.New(1) - address := keyring.GetAccAddr(0).String() - - testcases := []struct { - name string - decimals uint8 - expAmount math.Int - expPass bool - errContains string - }{ - { - name: "pass - eighteen decimals", - decimals: 18, - expAmount: network.GetInitialAmount(evmtypes.EighteenDecimals), - expPass: true, - }, - { - name: "pass - six decimals", - decimals: 6, - expAmount: network.GetInitialAmount(evmtypes.SixDecimals), - expPass: true, - }, - { - name: "fail - wrong amount", - decimals: 18, - expAmount: math.NewInt(1), - errContains: "expected balance", - }, - } - - for _, tc := range testcases { - t.Run(tc.name, func(t *testing.T) { - balances := []banktypes.Balance{{ - Address: address, - Coins: sdk.NewCoins( - sdk.NewCoin(testDenom, tc.expAmount), - ), - }} - - nw := network.New( - network.WithBaseCoin(testDenom, tc.decimals), - network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), - ) - - err := utils.CheckBalances(nw.GetContext(), nw.GetBankClient(), balances) - if tc.expPass { - require.NoError(t, err, "unexpected error checking balances") - } else { - require.Error(t, err, "expected error checking balances") - require.ErrorContains(t, err, tc.errContains, "expected different error checking balances") - } - }) - } -} diff --git a/testutil/integration/os/utils/evm_test.go b/testutil/integration/os/utils/evm_test.go deleted file mode 100644 index f44a30ec8..000000000 --- a/testutil/integration/os/utils/evm_test.go +++ /dev/null @@ -1,65 +0,0 @@ -package utils_test - -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" - - "github.com/cosmos/evm/contracts" - testfactory "github.com/cosmos/evm/testutil/integration/os/factory" - testhandler "github.com/cosmos/evm/testutil/integration/os/grpc" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - testnetwork "github.com/cosmos/evm/testutil/integration/os/network" - "github.com/cosmos/evm/testutil/integration/os/utils" - evmtypes "github.com/cosmos/evm/x/vm/types" -) - -func TestGetERC20Balance(t *testing.T) { - keyring := testkeyring.New(1) - network := testnetwork.NewUnitTestNetwork( - testnetwork.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), - ) - handler := testhandler.NewIntegrationHandler(network) - factory := testfactory.New(network, handler) - - sender := keyring.GetKey(0) - mintAmount := big.NewInt(100) - - // Deploy an ERC-20 contract - erc20Addr, err := factory.DeployContract( - sender.Priv, - evmtypes.EvmTxArgs{}, - testfactory.ContractDeploymentData{ - Contract: contracts.ERC20MinterBurnerDecimalsContract, - ConstructorArgs: []interface{}{"TestToken", "TT", uint8(18)}, - }, - ) - require.NoError(t, err, "failed to deploy contract") - require.NoError(t, network.NextBlock(), "failed to advance block") - - balance, err := utils.GetERC20Balance(network, erc20Addr, sender.Addr) - require.NoError(t, err, "failed to get ERC20 balance") - require.Equal(t, common.Big0.Int64(), balance.Int64(), "expected no balance before minting") - - // Mint some tokens - _, err = factory.ExecuteContractCall( - sender.Priv, - evmtypes.EvmTxArgs{ - To: &erc20Addr, - }, - testfactory.CallArgs{ - ContractABI: contracts.ERC20MinterBurnerDecimalsContract.ABI, - MethodName: "mint", - Args: []interface{}{sender.Addr, mintAmount}, - }, - ) - require.NoError(t, err, "failed to mint tokens") - - require.NoError(t, network.NextBlock(), "failed to advance block") - - balance, err = utils.GetERC20Balance(network, erc20Addr, sender.Addr) - require.NoError(t, err, "failed to get ERC20 balance") - require.Equal(t, mintAmount.Int64(), balance.Int64(), "expected different balance after minting") -} diff --git a/testutil/integration/params.go b/testutil/integration/params.go new file mode 100644 index 000000000..de3382bae --- /dev/null +++ b/testutil/integration/params.go @@ -0,0 +1,27 @@ +package integration + +import ( + "time" + + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + cmtypes "github.com/cometbft/cometbft/types" +) + +// DefaultConsensusParams defines the default Tendermint consensus params used in +// Cosmos EVM testing. +var DefaultConsensusParams = &tmproto.ConsensusParams{ + Block: &tmproto.BlockParams{ + MaxBytes: 200000, + MaxGas: -1, // no limit + }, + Evidence: &tmproto.EvidenceParams{ + MaxAgeNumBlocks: 302400, + MaxAgeDuration: 504 * time.Hour, // 3 weeks is the max duration + MaxBytes: 10000, + }, + Validator: &tmproto.ValidatorParams{ + PubKeyTypes: []string{ + cmtypes.ABCIPubKeyTypeEd25519, + }, + }, +} diff --git a/testutil/integration/utils.go b/testutil/integration/utils.go new file mode 100644 index 000000000..7ec44baa4 --- /dev/null +++ b/testutil/integration/utils.go @@ -0,0 +1,67 @@ +package integration + +import ( + "fmt" + + abci "github.com/cometbft/cometbft/abci/types" + + "github.com/cosmos/evm" + "github.com/cosmos/evm/testutil/tx" + + errorsmod "cosmossdk.io/errors" + + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + errortypes "github.com/cosmos/cosmos-sdk/types/errors" +) + +// DeliverEthTx generates and broadcasts a Cosmos Tx populated with MsgEthereumTx messages. +// If a private key is provided, it will attempt to sign all messages with the given private key, +// otherwise, it will assume the messages have already been signed. +func DeliverEthTx( + evmApp evm.EvmApp, + priv cryptotypes.PrivKey, + msgs ...sdk.Msg, +) (abci.ExecTxResult, error) { + txConfig := evmApp.GetTxConfig() + + tx, err := tx.PrepareEthTx(txConfig, priv, msgs...) + if err != nil { + return abci.ExecTxResult{}, err + } + res, err := BroadcastTxBytes(evmApp, txConfig.TxEncoder(), tx) + if err != nil { + return res, err + } + + codec := evmApp.AppCodec() + if _, err := CheckEthTxResponse(res, codec); err != nil { + return res, err + } + return res, nil +} + +// BroadcastTxBytes encodes a transaction and calls DeliverTx on the app. +func BroadcastTxBytes(app evm.EvmApp, txEncoder sdk.TxEncoder, tx sdk.Tx) (abci.ExecTxResult, error) { + // bz are bytes to be broadcasted over the network + bz, err := txEncoder(tx) + if err != nil { + return abci.ExecTxResult{}, err + } + + req := abci.RequestFinalizeBlock{Txs: [][]byte{bz}} + + res, err := app.GetBaseApp().FinalizeBlock(&req) + if err != nil { + return abci.ExecTxResult{}, err + } + if len(res.TxResults) != 1 { + return abci.ExecTxResult{}, fmt.Errorf("unexpected transaction results. Expected 1, got: %d", len(res.TxResults)) + } + txRes := res.TxResults[0] + if txRes.Code != 0 { + return abci.ExecTxResult{}, errorsmod.Wrapf(errortypes.ErrInvalidRequest, "log: %s", txRes.Log) + } + + return *txRes, nil +} diff --git a/testutil/integration/os/keyring/keyring.go b/testutil/keyring/keyring.go similarity index 100% rename from testutil/integration/os/keyring/keyring.go rename to testutil/keyring/keyring.go diff --git a/testutil/network/network.go b/testutil/network/network.go index 7c0ed83fa..d226c009b 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -17,6 +17,7 @@ import ( "testing" "time" + exampleapp "cosmosevm.io/evmd" "github.com/ethereum/go-ethereum/ethclient" "github.com/spf13/cobra" "golang.org/x/sync/errgroup" @@ -29,7 +30,6 @@ import ( dbm "github.com/cosmos/cosmos-db" chaincmd "github.com/cosmos/evm/cmd/evmd/cmd" "github.com/cosmos/evm/crypto/hd" - exampleapp "github.com/cosmos/evm/evmd" "github.com/cosmos/evm/server/config" testconstants "github.com/cosmos/evm/testutil/constants" cosmosevmtypes "github.com/cosmos/evm/types" diff --git a/testutil/staking_rewards.go b/testutil/staking_rewards.go deleted file mode 100644 index fdd9cab33..000000000 --- a/testutil/staking_rewards.go +++ /dev/null @@ -1,126 +0,0 @@ -package testutil - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/require" - - app "github.com/cosmos/evm/evmd" - "github.com/cosmos/evm/testutil/constants" - testutiltx "github.com/cosmos/evm/testutil/tx" - - "cosmossdk.io/math" - - "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" - sdk "github.com/cosmos/cosmos-sdk/types" - teststaking "github.com/cosmos/cosmos-sdk/x/staking/testutil" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" -) - -// PrepareAccountsForDelegationRewards prepares the test suite for testing to withdraw delegation rewards. -// -// Balance is the amount of tokens that will be left in the account after the setup is done. -// For each defined reward, a validator is created and tokens are allocated to it using the distribution keeper, -// such that the given amount of tokens is outstanding as a staking reward for the account. -// -// The setup is done in the following way: -// - Fund the account with the given address with the given balance. -// - If the given balance is zero, the account will be created with zero balance. -// -// For every reward defined in the rewards argument, the following steps are executed: -// - Set up a validator with zero commission and delegate to it -> the account delegation will be 50% of the total delegation. -// - Allocate rewards to the validator. -// -// The function returns the updated context along with a potential error. -func PrepareAccountsForDelegationRewards(t *testing.T, ctx sdk.Context, app *app.EVMD, addr sdk.AccAddress, balance math.Int, rewards ...math.Int) (sdk.Context, error) { - t.Helper() - // Calculate the necessary amount of tokens to fund the account in order for the desired residual balance to - // be left after creating validators and delegating to them. - totalRewards := math.ZeroInt() - for _, reward := range rewards { - totalRewards = totalRewards.Add(reward) - } - totalNeededBalance := balance.Add(totalRewards) - - if totalNeededBalance.IsZero() { - app.AccountKeeper.SetAccount(ctx, app.AccountKeeper.NewAccountWithAddress(ctx, addr)) - } else { - // Fund account with enough tokens to stake them - err := FundAccountWithBaseDenom(ctx, app.BankKeeper, addr, totalNeededBalance.Int64()) - if err != nil { - return sdk.Context{}, fmt.Errorf("failed to fund account: %s", err.Error()) - } - } - - if totalRewards.IsZero() { - return ctx, nil - } - - // reset historical count in distribution keeper which is necessary - // for the delegation rewards to be calculated correctly - app.DistrKeeper.DeleteAllValidatorHistoricalRewards(ctx) - - // set distribution module account balance which pays out the rewards - distrAcc := app.DistrKeeper.GetDistributionAccount(ctx) - err := FundModuleAccount(ctx, app.BankKeeper, distrAcc.GetName(), sdk.NewCoins(sdk.NewCoin(constants.ExampleAttoDenom, totalRewards))) - if err != nil { - return sdk.Context{}, fmt.Errorf("failed to fund distribution module account: %s", err.Error()) - } - app.AccountKeeper.SetModuleAccount(ctx, distrAcc) - - for _, reward := range rewards { - if reward.IsZero() { - continue - } - - // Set up validator and delegate to it - privKey := ed25519.GenPrivKey() - addr2, _ := testutiltx.NewAccAddressAndKey() - err := FundAccountWithBaseDenom(ctx, app.BankKeeper, addr2, reward.Int64()) - if err != nil { - return sdk.Context{}, fmt.Errorf("failed to fund validator account: %s", err.Error()) - } - - zeroDec := math.LegacyZeroDec() - stakingParams, err := app.StakingKeeper.GetParams(ctx) - if err != nil { - return sdk.Context{}, fmt.Errorf("failed to get staking params: %s", err.Error()) - } - stakingParams.BondDenom = constants.ExampleAttoDenom - stakingParams.MinCommissionRate = zeroDec - err = app.StakingKeeper.SetParams(ctx, stakingParams) - require.NoError(t, err) - - stakingHelper := teststaking.NewHelper(t, ctx, app.StakingKeeper) - stakingHelper.Commission = stakingtypes.NewCommissionRates(zeroDec, zeroDec, zeroDec) - stakingHelper.Denom = constants.ExampleAttoDenom - - valAddr := sdk.ValAddress(addr2.Bytes()) - // self-delegate the same amount of tokens as the delegate address also stakes - // this ensures, that the delegation rewards are 50% of the total rewards - stakingHelper.CreateValidator(valAddr, privKey.PubKey(), reward, true) - stakingHelper.Delegate(addr, valAddr, reward) - - // end block to bond validator and increase block height - // Not using Commit() here because code panics due to invalid block height - _, err = app.StakingKeeper.EndBlocker(ctx) - require.NoError(t, err) - - // allocate rewards to validator (of these 50% will be paid out to the delegator) - validator, err := app.StakingKeeper.Validator(ctx, valAddr) - if err != nil { - return sdk.Context{}, fmt.Errorf("failed to get validator: %s", err.Error()) - } - allocatedRewards := sdk.NewDecCoins(sdk.NewDecCoin(constants.ExampleAttoDenom, reward.Mul(math.NewInt(2)))) - if err = app.DistrKeeper.AllocateTokensToValidator(ctx, validator, allocatedRewards); err != nil { - return sdk.Context{}, fmt.Errorf("failed to allocate tokens to validator: %s", err.Error()) - } - } - - // Increase block height in ctx for the rewards calculation - // NOTE: this will only work for unit tests that use the context - // returned by this function - currentHeight := ctx.BlockHeight() - return ctx.WithBlockHeight(currentHeight + 1), nil -} diff --git a/testutil/tx/cosmos.go b/testutil/tx/cosmos.go index d4f0376d8..f130c360c 100644 --- a/testutil/tx/cosmos.go +++ b/testutil/tx/cosmos.go @@ -3,7 +3,7 @@ package tx import ( protov2 "google.golang.org/protobuf/proto" - exampleapp "github.com/cosmos/evm/evmd" + "github.com/cosmos/evm" "github.com/cosmos/evm/testutil/constants" sdkmath "cosmossdk.io/math" @@ -42,7 +42,7 @@ type CosmosTxArgs struct { // It returns the signed transaction and an error func PrepareCosmosTx( ctx sdk.Context, - exampleApp *exampleapp.EVMD, + evmApp evm.EvmApp, args CosmosTxArgs, ) (authsigning.Tx, error) { txBuilder := args.TxCfg.NewTxBuilder() @@ -65,7 +65,7 @@ func PrepareCosmosTx( return signCosmosTx( ctx, - exampleApp, + evmApp, args, txBuilder, ) @@ -75,12 +75,12 @@ func PrepareCosmosTx( // the provided private key func signCosmosTx( ctx sdk.Context, - exampleApp *exampleapp.EVMD, + evmApp evm.EvmApp, args CosmosTxArgs, txBuilder client.TxBuilder, ) (authsigning.Tx, error) { addr := sdk.AccAddress(args.Priv.PubKey().Address().Bytes()) - seq, err := exampleApp.AccountKeeper.GetSequence(ctx, addr) + seq, err := evmApp.GetAccountKeeper().GetSequence(ctx, addr) if err != nil { return nil, err } @@ -108,7 +108,7 @@ func signCosmosTx( } // Second round: all signer infos are set, so each signer can sign. - accNumber := exampleApp.AccountKeeper.GetAccount(ctx, addr).GetAccountNumber() + accNumber := evmApp.GetAccountKeeper().GetAccount(ctx, addr).GetAccountNumber() signerData := authsigning.SignerData{ ChainID: args.ChainID, AccountNumber: accNumber, diff --git a/testutil/tx/eip712.go b/testutil/tx/eip712.go index b0de5b5c7..009a658ed 100644 --- a/testutil/tx/eip712.go +++ b/testutil/tx/eip712.go @@ -6,9 +6,9 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/signer/core/apitypes" + "github.com/cosmos/evm" cryptocodec "github.com/cosmos/evm/crypto/codec" "github.com/cosmos/evm/ethereum/eip712" - exampleapp "github.com/cosmos/evm/evmd" "github.com/cosmos/evm/types" "github.com/cosmos/cosmos-sdk/client" @@ -45,12 +45,12 @@ type signatureV2Args struct { // It returns the signed transaction and an error func CreateEIP712CosmosTx( ctx sdk.Context, - exampleApp *exampleapp.EVMD, + evmApp evm.EvmApp, args EIP712TxArgs, ) (sdk.Tx, error) { builder, err := PrepareEIP712CosmosTx( ctx, - exampleApp, + evmApp, args, ) return builder.GetTx(), err @@ -61,15 +61,15 @@ func CreateEIP712CosmosTx( // It returns the tx builder with the signed transaction and an error func PrepareEIP712CosmosTx( ctx sdk.Context, - exampleApp *exampleapp.EVMD, + evmApp evm.EvmApp, args EIP712TxArgs, ) (client.TxBuilder, error) { txArgs := args.CosmosTxArgs from := sdk.AccAddress(txArgs.Priv.PubKey().Address().Bytes()) - accNumber := exampleApp.AccountKeeper.GetAccount(ctx, from).GetAccountNumber() + accNumber := evmApp.GetAccountKeeper().GetAccount(ctx, from).GetAccountNumber() - nonce, err := exampleApp.AccountKeeper.GetSequence(ctx, from) + nonce, err := evmApp.GetAccountKeeper().GetSequence(ctx, from) if err != nil { return nil, err } @@ -107,7 +107,7 @@ func PrepareEIP712CosmosTx( return signCosmosEIP712Tx( ctx, - exampleApp, + evmApp, args, builder, typedData, @@ -118,7 +118,7 @@ func PrepareEIP712CosmosTx( // the provided private key and the typed data func signCosmosEIP712Tx( ctx sdk.Context, - exampleApp *exampleapp.EVMD, + evmApp evm.EvmApp, args EIP712TxArgs, builder authtx.ExtensionOptionsTxBuilder, data apitypes.TypedData, @@ -126,7 +126,7 @@ func signCosmosEIP712Tx( priv := args.CosmosTxArgs.Priv from := sdk.AccAddress(priv.PubKey().Address().Bytes()) - nonce, err := exampleApp.AccountKeeper.GetSequence(ctx, from) + nonce, err := evmApp.GetAccountKeeper().GetSequence(ctx, from) if err != nil { return nil, err } diff --git a/testutil/tx/eth.go b/testutil/tx/eth.go index 8f9ceacc2..5cddc7480 100644 --- a/testutil/tx/eth.go +++ b/testutil/tx/eth.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" ethtypes "github.com/ethereum/go-ethereum/core/types" - exampleapp "github.com/cosmos/evm/evmd" + "github.com/cosmos/evm" "github.com/cosmos/evm/server/config" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -92,7 +92,7 @@ func PrepareEthTx( // Should this not be the case, just pass in zero. func CreateEthTx( ctx sdk.Context, - exampleApp *exampleapp.EVMD, + evmApp evm.EvmApp, privKey cryptotypes.PrivKey, dest []byte, amount *big.Int, @@ -103,14 +103,14 @@ func CreateEthTx( fromAddr := common.BytesToAddress(privKey.PubKey().Address().Bytes()) chainID := evmtypes.GetEthChainConfig().ChainID - baseFeeRes, err := exampleApp.EVMKeeper.BaseFee(ctx, &evmtypes.QueryBaseFeeRequest{}) + baseFeeRes, err := evmApp.GetEVMKeeper().BaseFee(ctx, &evmtypes.QueryBaseFeeRequest{}) if err != nil { return nil, err } baseFee := baseFeeRes.BaseFee.BigInt() // When we send multiple Ethereum Tx's in one Cosmos Tx, we need to increment the nonce for each one. - nonce := exampleApp.EVMKeeper.GetNonce(ctx, fromAddr) + uint64(nonceIncrement) //#nosec G115 -- will not exceed uint64 + nonce := evmApp.GetEVMKeeper().GetNonce(ctx, fromAddr) + uint64(nonceIncrement) //#nosec G115 -- will not exceed uint64 evmTxParams := &evmtypes.EvmTxArgs{ ChainID: chainID, Nonce: nonce, diff --git a/testutil/integration/os/factory/types.go b/testutil/types/types.go similarity index 98% rename from testutil/integration/os/factory/types.go rename to testutil/types/types.go index 87790f602..359a410bb 100644 --- a/testutil/integration/os/factory/types.go +++ b/testutil/types/types.go @@ -1,4 +1,4 @@ -package factory +package types import ( "github.com/ethereum/go-ethereum/accounts/abi" diff --git a/ante/cosmos/utils_test.go b/testutil/util.go similarity index 65% rename from ante/cosmos/utils_test.go rename to testutil/util.go index 6be766d2c..2a86ef032 100644 --- a/ante/cosmos/utils_test.go +++ b/testutil/util.go @@ -1,14 +1,11 @@ -package cosmos_test +package testutil import ( "context" "time" - "github.com/cosmos/evm/ante/testutils" "github.com/cosmos/evm/crypto/ethsecp256k1" - sdkmath "cosmossdk.io/math" - "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/tx" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" @@ -18,32 +15,29 @@ import ( "github.com/cosmos/cosmos-sdk/x/authz" ) -func (suite *AnteTestSuite) CreateTestCosmosTxBuilder(gasPrice sdkmath.Int, denom string, msgs ...sdk.Msg) client.TxBuilder { - txBuilder := suite.GetClientCtx().TxConfig.NewTxBuilder() - - txBuilder.SetGasLimit(testutils.TestGasLimit) - fees := &sdk.Coins{{Denom: denom, Amount: gasPrice.MulRaw(int64(testutils.TestGasLimit))}} - txBuilder.SetFeeAmount(*fees) - err := txBuilder.SetMsgs(msgs...) - suite.Require().NoError(err) - return txBuilder -} +func GeneratePrivKeyAddressPairs(accCount int) ([]*ethsecp256k1.PrivKey, []sdk.AccAddress, error) { + var ( + err error + testPrivKeys = make([]*ethsecp256k1.PrivKey, accCount) + testAddresses = make([]sdk.AccAddress, accCount) + ) -func (suite *AnteTestSuite) CreateTestCosmosTxBuilderWithFees(fees sdk.Coins, msgs ...sdk.Msg) client.TxBuilder { - txBuilder := suite.GetClientCtx().TxConfig.NewTxBuilder() - txBuilder.SetGasLimit(testutils.TestGasLimit) - txBuilder.SetFeeAmount(fees) - err := txBuilder.SetMsgs(msgs...) - suite.Require().NoError(err) - return txBuilder + for i := range testPrivKeys { + testPrivKeys[i], err = ethsecp256k1.GenerateKey() + if err != nil { + return nil, nil, err + } + testAddresses[i] = testPrivKeys[i].PubKey().Address().Bytes() + } + return testPrivKeys, testAddresses, nil } -func newMsgExec(grantee sdk.AccAddress, msgs []sdk.Msg) *authz.MsgExec { +func NewMsgExec(grantee sdk.AccAddress, msgs []sdk.Msg) *authz.MsgExec { msg := authz.NewMsgExec(grantee, msgs) return &msg } -func newMsgGrant(granter sdk.AccAddress, grantee sdk.AccAddress, a authz.Authorization, expiration *time.Time) *authz.MsgGrant { +func NewMsgGrant(granter sdk.AccAddress, grantee sdk.AccAddress, a authz.Authorization, expiration *time.Time) *authz.MsgGrant { msg, err := authz.NewMsgGrant(granter, grantee, a, expiration) if err != nil { panic(err) @@ -51,36 +45,19 @@ func newMsgGrant(granter sdk.AccAddress, grantee sdk.AccAddress, a authz.Authori return msg } -func createNestedMsgExec(a sdk.AccAddress, nestedLvl int, lastLvlMsgs []sdk.Msg) *authz.MsgExec { +func CreateNestedMsgExec(a sdk.AccAddress, nestedLvl int, lastLvlMsgs []sdk.Msg) *authz.MsgExec { msgs := make([]*authz.MsgExec, nestedLvl) for i := range msgs { if i == 0 { - msgs[i] = newMsgExec(a, lastLvlMsgs) + msgs[i] = NewMsgExec(a, lastLvlMsgs) continue } - msgs[i] = newMsgExec(a, []sdk.Msg{msgs[i-1]}) + msgs[i] = NewMsgExec(a, []sdk.Msg{msgs[i-1]}) } return msgs[nestedLvl-1] } -func generatePrivKeyAddressPairs(accCount int) ([]*ethsecp256k1.PrivKey, []sdk.AccAddress, error) { - var ( - err error - testPrivKeys = make([]*ethsecp256k1.PrivKey, accCount) - testAddresses = make([]sdk.AccAddress, accCount) - ) - - for i := range testPrivKeys { - testPrivKeys[i], err = ethsecp256k1.GenerateKey() - if err != nil { - return nil, nil, err - } - testAddresses[i] = testPrivKeys[i].PubKey().Address().Bytes() - } - return testPrivKeys, testAddresses, nil -} - -func createTx(ctx context.Context, txCfg client.TxConfig, priv cryptotypes.PrivKey, msgs ...sdk.Msg) (sdk.Tx, error) { +func CreateTx(ctx context.Context, txCfg client.TxConfig, priv cryptotypes.PrivKey, msgs ...sdk.Msg) (sdk.Tx, error) { txBuilder := txCfg.NewTxBuilder() defaultSignMode, err := authsigning.APISignModeToInternal(txCfg.SignModeHandler().DefaultMode()) if err != nil { diff --git a/utils/utils.go b/utils/utils.go index 067094c50..b771e05e4 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -22,6 +22,34 @@ import ( errortypes "github.com/cosmos/cosmos-sdk/types/errors" ) +// EthHexToCosmosAddr takes a given Hex string and derives a Cosmos SDK account address +// from it. +func EthHexToCosmosAddr(hexAddr string) sdk.AccAddress { + return EthToCosmosAddr(common.HexToAddress(hexAddr)) +} + +// EthToCosmosAddr converts a given Ethereum style address to an SDK address. +func EthToCosmosAddr(addr common.Address) sdk.AccAddress { + return sdk.AccAddress(addr.Bytes()) +} + +// Bech32ToHexAddr converts a given Bech32 address string and converts it to +// an Ethereum address. +func Bech32ToHexAddr(bech32Addr string) (common.Address, error) { + accAddr, err := sdk.AccAddressFromBech32(bech32Addr) + if err != nil { + return common.Address{}, errorsmod.Wrapf(err, "failed to convert bech32 string to address") + } + + return CosmosToEthAddr(accAddr), nil +} + +// CosmosToEthAddr converts a given SDK account address to +// an Ethereum address. +func CosmosToEthAddr(accAddr sdk.AccAddress) common.Address { + return common.BytesToAddress(accAddr.Bytes()) +} + // Bech32StringFromHexAddress takes a given Hex string and derives a Cosmos SDK account address // from it. func Bech32StringFromHexAddress(hexAddr string) string { diff --git a/wallets/usbwallet/ledger.go b/wallets/usbwallet/ledger.go index d40716adc..6a738775f 100644 --- a/wallets/usbwallet/ledger.go +++ b/wallets/usbwallet/ledger.go @@ -299,7 +299,7 @@ func (w *ledgerDriver) ledgerSignTypedMessage(derivationPath gethaccounts.Deriva for i, component := range derivationPath { binary.BigEndian.PutUint32(path[1+4*i:], component) } - // Create the 712 message + // create the 712 message var payload []byte payload = append(payload, path...) payload = append(payload, domainHash...) diff --git a/x/erc20/ibc_middleware.go b/x/erc20/ibc_middleware.go index 5607419de..5efcc0c24 100644 --- a/x/erc20/ibc_middleware.go +++ b/x/erc20/ibc_middleware.go @@ -22,11 +22,11 @@ var _ porttypes.IBCModule = &IBCMiddleware{} // the erc20 keeper and the underlying application. type IBCMiddleware struct { *ibc.Module - keeper erc20types.ERC20Keeper + keeper erc20types.Erc20Keeper } // NewIBCMiddleware creates a new IBCMiddleware given the keeper and underlying application -func NewIBCMiddleware(k erc20types.ERC20Keeper, app porttypes.IBCModule) IBCMiddleware { +func NewIBCMiddleware(k erc20types.Erc20Keeper, app porttypes.IBCModule) IBCMiddleware { if app == nil { panic(errors.New("underlying application cannot be nil")) } diff --git a/x/erc20/keeper/integration_test.go b/x/erc20/keeper/integration_test.go deleted file mode 100644 index 264fce594..000000000 --- a/x/erc20/keeper/integration_test.go +++ /dev/null @@ -1,193 +0,0 @@ -package keeper_test - -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" - - "github.com/cosmos/evm/testutil/integration/common/factory" - testutils "github.com/cosmos/evm/testutil/integration/os/utils" - "github.com/cosmos/evm/x/erc20/types" - - "cosmossdk.io/math" - - sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" -) - -func TestPrecompileIntegrationTestSuite(t *testing.T) { - // Run Ginkgo integration tests - RegisterFailHandler(Fail) - RunSpecs(t, "ERC20 Module Integration Tests") -} - -var _ = Describe("Performing EVM transactions", Ordered, func() { - var s *KeeperTestSuite - BeforeEach(func() { - s = new(KeeperTestSuite) - s.SetupTest() - }) - - Context("with the ERC20 module disabled", func() { - BeforeEach(func() { - params := types.DefaultParams() - params.EnableErc20 = false - err := testutils.UpdateERC20Params(testutils.UpdateParamsInput{ - Tf: s.factory, - Network: s.network, - Pk: s.keyring.GetPrivKey(0), - Params: params, - }) - Expect(err).To(BeNil()) - }) - It("should be successful", func() { - _, err := s.DeployContract("coin", "token", erc20Decimals) - Expect(err).To(BeNil()) - }) - }) - - Context("with the ERC20 module and EVM Hook enabled", func() { - It("should be successful", func() { - _, err := s.DeployContract("coin", "token", erc20Decimals) - Expect(err).To(BeNil()) - }) - }) -}) - -var _ = Describe("ERC20:", Ordered, func() { - var ( - s *KeeperTestSuite - contract common.Address - contract2 common.Address - - // moduleAcc is the address of the ERC-20 module account - moduleAcc = authtypes.NewModuleAddress(types.ModuleName) - amt = math.NewInt(100) - ) - - BeforeEach(func() { - s = new(KeeperTestSuite) - s.SetupTest() - }) - - Describe("Submitting a token pair proposal through governance", func() { - Context("with deployed contracts", func() { - BeforeEach(func() { - var err error - contract, err = s.DeployContract(erc20Name, erc20Symbol, erc20Decimals) - Expect(err).To(BeNil()) - contract2, err = s.DeployContract(erc20Name, erc20Symbol, erc20Decimals) - Expect(err).To(BeNil()) - }) - - Describe("for a single ERC20 token", func() { - BeforeEach(func() { - // register erc20 - _, err := testutils.RegisterERC20( - s.factory, - s.network, - testutils.ERC20RegistrationData{ - Addresses: []string{contract.Hex()}, - ProposerPriv: s.keyring.GetPrivKey(0), - }, - ) - Expect(err).To(BeNil()) - }) - - It("should create a token pair owned by the contract deployer", func() { - qc := s.network.GetERC20Client() - - res, err := qc.TokenPairs(s.network.GetContext(), &types.QueryTokenPairsRequest{}) - Expect(err).To(BeNil()) - - tokenPairs := res.TokenPairs - Expect(tokenPairs).To(HaveLen(2)) - for i, tokenPair := range tokenPairs { - if tokenPair.Erc20Address == contract.Hex() { - Expect(tokenPairs[i].ContractOwner).To(Equal(types.OWNER_EXTERNAL)) - } - } - }) - }) - - Describe("for multiple ERC20 tokens", func() { - BeforeEach(func() { - // register erc20 tokens - _, err := testutils.RegisterERC20( - s.factory, - s.network, - testutils.ERC20RegistrationData{ - Addresses: []string{contract.Hex(), contract2.Hex()}, - ProposerPriv: s.keyring.GetPrivKey(0), - }, - ) - Expect(err).To(BeNil()) - }) - - It("should create a token pairs owned by the contract deployer", func() { - qc := s.network.GetERC20Client() - res, err := qc.TokenPairs(s.network.GetContext(), &types.QueryTokenPairsRequest{}) - Expect(err).To(BeNil()) - - tokenPairs := res.TokenPairs - Expect(tokenPairs).To(HaveLen(3)) - for i, tokenPair := range tokenPairs { - if tokenPair.Erc20Address == contract2.Hex() { - Expect(tokenPairs[i].ContractOwner).To(Equal(types.OWNER_EXTERNAL)) - } - } - }) - }) - }) - }) - - Describe("Converting", func() { - Context("with a registered ERC20", func() { - BeforeEach(func() { - var err error - contract, err = s.setupRegisterERC20Pair(contractMinterBurner) - Expect(err).To(BeNil()) - - res, err := s.MintERC20Token(contract, s.keyring.GetAddr(0), big.NewInt(amt.Int64())) - Expect(err).To(BeNil()) - Expect(res.IsOK()).To(BeTrue()) - }) - - Describe("an ERC20 token into a Cosmos coin", func() { - BeforeEach(func() { - // convert ERC20 to cosmos coin - msg := types.NewMsgConvertERC20(amt, s.keyring.GetAccAddr(0), contract, s.keyring.GetAddr(0)) - res, err := s.factory.CommitCosmosTx(s.keyring.GetPrivKey(0), factory.CosmosTxArgs{Msgs: []sdk.Msg{msg}}) - Expect(err).To(BeNil()) - Expect(res.IsOK()).To(BeTrue()) - }) - - It("should decrease tokens on the sender account", func() { - balanceERC20, err := s.BalanceOf(contract, s.keyring.GetAddr(0)) - Expect(err).To(BeNil()) - Expect(balanceERC20.(*big.Int).Int64()).To(Equal(int64(0))) - }) - - It("should escrow tokens on the module account", func() { - moduleAddr := common.BytesToAddress(moduleAcc.Bytes()) - balanceERC20, err := s.BalanceOf(contract, moduleAddr) - Expect(err).To(BeNil()) - Expect(balanceERC20.(*big.Int).Int64()).To(Equal(amt.Int64())) - }) - - It("should send coins to the receiver account", func() { - balRes, err := s.handler.GetBalanceFromBank(s.keyring.GetAccAddr(0), types.CreateDenom(contract.Hex())) - Expect(err).To(BeNil()) - balanceCoin := balRes.Balance - Expect(balanceCoin.Amount).To(Equal(amt)) - }) - }) - }) - }) -}) diff --git a/x/erc20/keeper/mint_test.go b/x/erc20/keeper/mint_test.go deleted file mode 100644 index 79e3659f7..000000000 --- a/x/erc20/keeper/mint_test.go +++ /dev/null @@ -1,109 +0,0 @@ -package keeper_test - -import ( - "fmt" - - utiltx "github.com/cosmos/evm/testutil/tx" - "github.com/cosmos/evm/x/erc20/types" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -func (suite *KeeperTestSuite) TestMintingEnabled() { - var ctx sdk.Context - sender := sdk.AccAddress(utiltx.GenerateAddress().Bytes()) - receiver := sdk.AccAddress(utiltx.GenerateAddress().Bytes()) - expPair := types.NewTokenPair(utiltx.GenerateAddress(), "coin", types.OWNER_MODULE) - id := expPair.GetID() - - testCases := []struct { - name string - malleate func() - expPass bool - }{ - { - "conversion is disabled globally", - func() { - params := types.DefaultParams() - params.EnableErc20 = false - suite.network.App.Erc20Keeper.SetParams(ctx, params) //nolint:errcheck - }, - false, - }, - { - "token pair not found", - func() {}, - false, - }, - { - "conversion is disabled for the given pair", - func() { - expPair.Enabled = false - suite.network.App.Erc20Keeper.SetTokenPair(ctx, expPair) - suite.network.App.Erc20Keeper.SetDenomMap(ctx, expPair.Denom, id) - suite.network.App.Erc20Keeper.SetERC20Map(ctx, expPair.GetERC20Contract(), id) - }, - false, - }, - { - "token transfers are disabled", - func() { - expPair.Enabled = true - suite.network.App.Erc20Keeper.SetTokenPair(ctx, expPair) - suite.network.App.Erc20Keeper.SetDenomMap(ctx, expPair.Denom, id) - suite.network.App.Erc20Keeper.SetERC20Map(ctx, expPair.GetERC20Contract(), id) - - suite.network.App.BankKeeper.SetSendEnabled(ctx, expPair.Denom, false) - }, - false, - }, - { - "token not registered", - func() { - suite.network.App.Erc20Keeper.SetDenomMap(ctx, expPair.Denom, id) - suite.network.App.Erc20Keeper.SetERC20Map(ctx, expPair.GetERC20Contract(), id) - }, - false, - }, - { - "receiver address is blocked (module account)", - func() { - suite.network.App.Erc20Keeper.SetTokenPair(ctx, expPair) - suite.network.App.Erc20Keeper.SetDenomMap(ctx, expPair.Denom, id) - suite.network.App.Erc20Keeper.SetERC20Map(ctx, expPair.GetERC20Contract(), id) - - acc := suite.network.App.AccountKeeper.GetModuleAccount(ctx, types.ModuleName) - receiver = acc.GetAddress() - }, - false, - }, - { - "ok", - func() { - suite.network.App.Erc20Keeper.SetTokenPair(ctx, expPair) - suite.network.App.Erc20Keeper.SetDenomMap(ctx, expPair.Denom, id) - suite.network.App.Erc20Keeper.SetERC20Map(ctx, expPair.GetERC20Contract(), id) - - receiver = sdk.AccAddress(utiltx.GenerateAddress().Bytes()) - }, - true, - }, - } - - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() // reset - ctx = suite.network.GetContext() - - tc.malleate() - - pair, err := suite.network.App.Erc20Keeper.MintingEnabled(ctx, sender, receiver, expPair.Erc20Address) - if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(expPair, pair) - } else { - suite.Require().Error(err) - } - }) - } -} diff --git a/x/erc20/keeper/token_pairs.go b/x/erc20/keeper/token_pairs.go index fcf8d943a..20310f8c1 100644 --- a/x/erc20/keeper/token_pairs.go +++ b/x/erc20/keeper/token_pairs.go @@ -14,7 +14,7 @@ import ( ) // CreateNewTokenPair creates a new token pair and stores it in the state. -func (k *Keeper) CreateNewTokenPair(ctx sdk.Context, denom string) (types.TokenPair, error) { +func (k Keeper) CreateNewTokenPair(ctx sdk.Context, denom string) (types.TokenPair, error) { pair, err := types.NewTokenPairSTRv2(denom) if err != nil { return types.TokenPair{}, err @@ -24,7 +24,7 @@ func (k *Keeper) CreateNewTokenPair(ctx sdk.Context, denom string) (types.TokenP } // SetToken stores a token pair, denom map and erc20 map. -func (k *Keeper) SetToken(ctx sdk.Context, pair types.TokenPair) { +func (k Keeper) SetToken(ctx sdk.Context, pair types.TokenPair) { k.SetTokenPair(ctx, pair) k.SetDenomMap(ctx, pair.Denom, pair.GetID()) k.SetERC20Map(ctx, pair.GetERC20Contract(), pair.GetID()) diff --git a/x/erc20/keeper/utils_test.go b/x/erc20/keeper/utils_test.go deleted file mode 100644 index 69e27f564..000000000 --- a/x/erc20/keeper/utils_test.go +++ /dev/null @@ -1,80 +0,0 @@ -package keeper_test - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/common" - - "github.com/cosmos/evm/contracts" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/x/erc20/keeper/testdata" - "github.com/cosmos/evm/x/erc20/types" - evm "github.com/cosmos/evm/x/vm/types" - - sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" -) - -// MintFeeCollector mints some coins to the fee collector address. -// Use this only for unit tests. For integration tests, you can use the -// mintFeeCollector flag to setup some balance on genesis -func (suite *KeeperTestSuite) MintFeeCollector(coins sdk.Coins) { - err := suite.network.App.BankKeeper.MintCoins(suite.network.GetContext(), types.ModuleName, coins) - suite.Require().NoError(err) - err = suite.network.App.BankKeeper.SendCoinsFromModuleToModule(suite.network.GetContext(), types.ModuleName, authtypes.FeeCollectorName, coins) - suite.Require().NoError(err) -} - -func (suite *KeeperTestSuite) DeployContract(name, symbol string, decimals uint8) (common.Address, error) { - addr, err := suite.factory.DeployContract( - suite.keyring.GetPrivKey(0), - evm.EvmTxArgs{}, - factory.ContractDeploymentData{ - Contract: contracts.ERC20MinterBurnerDecimalsContract, - ConstructorArgs: []interface{}{name, symbol, decimals}, - }, - ) - if err != nil { - return common.Address{}, err - } - - return addr, suite.network.NextBlock() -} - -func (suite *KeeperTestSuite) DeployContractMaliciousDelayed() (common.Address, error) { - maliciousDelayedContract, err := testdata.LoadMaliciousDelayedContract() - suite.Require().NoError(err, "failed to load malicious delayed contract") - - addr, err := suite.factory.DeployContract( - suite.keyring.GetPrivKey(0), - evm.EvmTxArgs{}, - factory.ContractDeploymentData{ - Contract: maliciousDelayedContract, - ConstructorArgs: []interface{}{big.NewInt(1000000000000000000)}, - }, - ) - if err != nil { - return common.Address{}, err - } - - return addr, suite.network.NextBlock() -} - -func (suite *KeeperTestSuite) DeployContractDirectBalanceManipulation() (common.Address, error) { - balanceManipulationContract, err := testdata.LoadBalanceManipulationContract() - suite.Require().NoError(err, "failed to load balance manipulation contract") - - addr, err := suite.factory.DeployContract( - suite.keyring.GetPrivKey(0), - evm.EvmTxArgs{}, - factory.ContractDeploymentData{ - Contract: balanceManipulationContract, - ConstructorArgs: []interface{}{big.NewInt(1000000000000000000)}, - }, - ) - if err != nil { - return common.Address{}, err - } - - return addr, suite.network.NextBlock() -} diff --git a/x/erc20/types/interfaces.go b/x/erc20/types/interfaces.go index dfec77840..f3543fb9f 100644 --- a/x/erc20/types/interfaces.go +++ b/x/erc20/types/interfaces.go @@ -50,7 +50,7 @@ type EVMKeeper interface { GetAccount(ctx sdk.Context, address common.Address) *statedb.Account } -type ERC20Keeper interface { +type Erc20Keeper interface { OnRecvPacket(ctx sdk.Context, packet channeltypes.Packet, ack exported.Acknowledgement) exported.Acknowledgement OnAcknowledgementPacket(ctx sdk.Context, packet channeltypes.Packet, data transfertypes.FungibleTokenPacketData, ack channeltypes.Acknowledgement) error OnTimeoutPacket(ctx sdk.Context, packet channeltypes.Packet, data transfertypes.FungibleTokenPacketData) error diff --git a/x/erc20/v2/ibc_middleware.go b/x/erc20/v2/ibc_middleware.go index e69f079af..e3a0f35f4 100644 --- a/x/erc20/v2/ibc_middleware.go +++ b/x/erc20/v2/ibc_middleware.go @@ -23,13 +23,13 @@ var _ ibcapi.IBCModule = &IBCMiddleware{} // The logics are same as the IBCMiddleware, but this is a v2 version of the middleware type IBCMiddleware struct { app ibcapi.IBCModule - keeper erc20types.ERC20Keeper + keeper erc20types.Erc20Keeper } // NewIBCMiddleware creates a new IBCMiddleware given the keeper and underlying application func NewIBCMiddleware( app ibcapi.IBCModule, - k erc20types.ERC20Keeper, + k erc20types.Erc20Keeper, ) IBCMiddleware { if app == nil { panic(errors.New("underlying application cannot be nil")) diff --git a/x/feemarket/keeper/integration_test.go b/x/feemarket/keeper/integration_test.go deleted file mode 100644 index 83af3d942..000000000 --- a/x/feemarket/keeper/integration_test.go +++ /dev/null @@ -1,688 +0,0 @@ -package keeper_test - -import ( - "math/big" - "testing" - - ethtypes "github.com/ethereum/go-ethereum/core/types" - - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" - - "github.com/cosmos/evm/testutil/integration/common/factory" - testutils "github.com/cosmos/evm/testutil/integration/os/utils" - fmkttypes "github.com/cosmos/evm/x/feemarket/types" - evmtypes "github.com/cosmos/evm/x/vm/types" - - "cosmossdk.io/math" - - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - sdk "github.com/cosmos/cosmos-sdk/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" -) - -type txParams struct { - gasPrice *big.Int - gasFeeCap *big.Int - gasTipCap *big.Int - accesses *ethtypes.AccessList -} -type getprices func() txParams - -func TestKeeperIntegrationTestSuite(t *testing.T) { - // Run Ginkgo integration tests - RegisterFailHandler(Fail) - RunSpecs(t, "Keeper Suite") -} - -var _ = Describe("Feemarket", func() { - var ( - s *KeeperTestSuite - privKey cryptotypes.PrivKey - ) - - BeforeEach(func() { - s = new(KeeperTestSuite) - s.SetupTest() - privKey = s.keyring.GetPrivKey(0) - }) - - Describe("Performing Cosmos transactions", func() { - var ( - txArgs factory.CosmosTxArgs - gasWanted uint64 = 200_000 - ) - - BeforeEach(func() { - msg := banktypes.MsgSend{ - FromAddress: s.keyring.GetAccAddr(0).String(), - ToAddress: s.keyring.GetAccAddr(1).String(), - Amount: sdk.Coins{sdk.Coin{ - Denom: s.denom, - Amount: math.NewInt(10000), - }}, - } - txArgs = factory.CosmosTxArgs{ - ChainID: s.network.GetChainID(), - Msgs: []sdk.Msg{&msg}, - Gas: &gasWanted, - } - }) - - Context("with min-gas-prices (local) < MinGasPrices (feemarket param)", func() { - // minGasPrices is the feemarket MinGasPrices - const minGasPrices int64 = 15 - - BeforeEach(func() { - // local min-gas-prices is 10aatom - params := fmkttypes.DefaultParams() - params.MinGasPrice = math.LegacyNewDec(minGasPrices) - params.BaseFee = math.LegacyNewDec(0) - err := testutils.UpdateFeeMarketParams( - testutils.UpdateParamsInput{ - Tf: s.factory, - Network: s.network, - Pk: privKey, - Params: params, - }, - ) - Expect(err).To(BeNil()) - }) - - Context("during CheckTx", func() { - It("should reject transactions with gasPrice < MinGasPrices", func() { - gasPrice := math.NewInt(minGasPrices - 3) - txArgs.GasPrice = &gasPrice - tx, err := s.factory.BuildCosmosTx(privKey, txArgs) - Expect(err).To(BeNil()) - bz, err := s.factory.EncodeTx(tx) - Expect(err).To(BeNil()) - - res, err := s.network.CheckTx(bz) - Expect(err).To(BeNil()) - Expect(res.IsOK()).To(BeFalse()) - Expect(res.Log).To(ContainSubstring("provided fee < minimum global fee")) - }) - - It("should accept transactions with gasPrice >= MinGasPrices", func() { - gasPrice := math.NewInt(minGasPrices) - txArgs.GasPrice = &gasPrice - tx, err := s.factory.BuildCosmosTx(privKey, txArgs) - Expect(err).To(BeNil()) - bz, err := s.factory.EncodeTx(tx) - Expect(err).To(BeNil()) - - res, err := s.network.CheckTx(bz) - Expect(err).To(BeNil()) - Expect(res.IsOK()).To(BeTrue(), "transaction should have succeeded", res.GetLog()) - }) - }) - - Context("during DeliverTx", func() { - It("should reject transactions with gasPrice < MinGasPrices", func() { - gasPrice := math.NewInt(minGasPrices - 2) - txArgs.GasPrice = &gasPrice - res, err := s.factory.ExecuteCosmosTx(privKey, txArgs) - Expect(err).To(BeNil()) - Expect(res.IsOK()).To(BeFalse()) - Expect(res.Log).To(ContainSubstring("provided fee < minimum global fee")) - }) - - It("should accept transactions with gasPrice >= MinGasPrices", func() { - gasPrice := math.NewInt(minGasPrices) - txArgs.GasPrice = &gasPrice - res, err := s.factory.ExecuteCosmosTx(privKey, txArgs) - Expect(err).To(BeNil()) - Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog()) - }) - }) - }) - - Context("with min-gas-prices (local) == MinGasPrices (feemarket param)", func() { - // minGasPrices is the feemarket MinGasPrices - const minGasPrices int64 = 10 - BeforeEach(func() { - // local min-gas-prices is 10aatom - params := fmkttypes.DefaultParams() - params.MinGasPrice = math.LegacyNewDec(minGasPrices) - params.BaseFee = math.LegacyNewDec(0) - - err := testutils.UpdateFeeMarketParams( - testutils.UpdateParamsInput{ - Tf: s.factory, - Network: s.network, - Pk: privKey, - Params: params, - }, - ) - Expect(err).To(BeNil()) - }) - - Context("during CheckTx", func() { - It("should reject transactions with gasPrice < min-gas-prices", func() { - gasPrice := math.NewInt(minGasPrices - 3) - txArgs.GasPrice = &gasPrice - tx, err := s.factory.BuildCosmosTx(privKey, txArgs) - Expect(err).To(BeNil()) - bz, err := s.factory.EncodeTx(tx) - Expect(err).To(BeNil()) - - res, err := s.network.CheckTx(bz) - Expect(err).To(BeNil()) - Expect(res.IsOK()).To(BeFalse()) - Expect(res.Log).To(ContainSubstring("insufficient fee")) - }) - - It("should accept transactions with gasPrice >= MinGasPrices", func() { - gasPrice := math.NewInt(minGasPrices) - txArgs.GasPrice = &gasPrice - tx, err := s.factory.BuildCosmosTx(privKey, txArgs) - Expect(err).To(BeNil()) - bz, err := s.factory.EncodeTx(tx) - Expect(err).To(BeNil()) - - res, err := s.network.CheckTx(bz) - Expect(err).To(BeNil()) - Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog()) - }) - }) - - Context("during DeliverTx", func() { - It("should reject transactions with gasPrice < MinGasPrices", func() { - gasPrice := math.NewInt(minGasPrices - 2) - txArgs.GasPrice = &gasPrice - res, err := s.factory.ExecuteCosmosTx(privKey, txArgs) - Expect(err).To(BeNil()) - Expect(res.IsOK()).To(BeFalse()) - Expect(res.Log).To(ContainSubstring("provided fee < minimum global fee")) - }) - - It("should accept transactions with gasPrice >= MinGasPrices", func() { - gasPrice := math.NewInt(minGasPrices) - txArgs.GasPrice = &gasPrice - res, err := s.factory.ExecuteCosmosTx(privKey, txArgs) - Expect(err).To(BeNil()) - Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog()) - }) - }) - }) - - Context("with MinGasPrices (feemarket param) < min-gas-prices (local)", func() { - // minGasPrices is the feemarket MinGasPrices - const minGasPrices int64 = 7 - baseFee := math.LegacyNewDec(15) - - BeforeEach(func() { - // local min-gas-prices is 10aatom - params := fmkttypes.DefaultParams() - params.MinGasPrice = math.LegacyNewDec(minGasPrices) - params.BaseFee = baseFee - - err := testutils.UpdateFeeMarketParams( - testutils.UpdateParamsInput{ - Tf: s.factory, - Network: s.network, - Pk: privKey, - Params: params, - }, - ) - Expect(err).To(BeNil()) - }) - - Context("during CheckTx", func() { - It("should reject transactions with gasPrice < MinGasPrices", func() { - gasPrice := math.NewInt(minGasPrices - 3) - txArgs.GasPrice = &gasPrice - tx, err := s.factory.BuildCosmosTx(privKey, txArgs) - Expect(err).To(BeNil()) - bz, err := s.factory.EncodeTx(tx) - Expect(err).To(BeNil()) - - res, err := s.network.CheckTx(bz) - Expect(err).To(BeNil()) - Expect(res.IsOK()).To(BeFalse()) - Expect(res.Log).To(ContainSubstring("insufficient fee")) - }) - - It("should reject transactions with MinGasPrices < gasPrice < baseFee", func() { - gasPrice := math.NewInt(minGasPrices + 1) - txArgs.GasPrice = &gasPrice - tx, err := s.factory.BuildCosmosTx(privKey, txArgs) - Expect(err).To(BeNil()) - bz, err := s.factory.EncodeTx(tx) - Expect(err).To(BeNil()) - - res, err := s.network.CheckTx(bz) - Expect(err).To(BeNil()) - Expect(res.IsOK()).To(BeFalse()) - Expect(res.Log).To(ContainSubstring("insufficient fee")) - }) - - It("should accept transactions with gasPrice >= baseFee", func() { - gasPrice := baseFee.TruncateInt() - txArgs.GasPrice = &gasPrice - tx, err := s.factory.BuildCosmosTx(privKey, txArgs) - Expect(err).To(BeNil()) - bz, err := s.factory.EncodeTx(tx) - Expect(err).To(BeNil()) - - res, err := s.network.CheckTx(bz) - Expect(err).To(BeNil()) - Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog()) - }) - }) - - Context("during DeliverTx", func() { - It("should reject transactions with gasPrice < MinGasPrices", func() { - gasPrice := math.NewInt(minGasPrices - 2) - txArgs.GasPrice = &gasPrice - res, err := s.factory.ExecuteCosmosTx(privKey, txArgs) - Expect(err).To(BeNil()) - Expect(res.IsOK()).To(BeFalse()) - Expect(res.Log).To(ContainSubstring("provided fee < minimum global fee")) - }) - - It("should reject transactions with MinGasPrices < gasPrice < baseFee", func() { - gasPrice := math.NewInt(minGasPrices + 1) - txArgs.GasPrice = &gasPrice - res, err := s.factory.ExecuteCosmosTx(privKey, txArgs) - Expect(err).To(BeNil()) - Expect(res.IsOK()).To(BeFalse()) - Expect(res.Log).To(ContainSubstring("insufficient fee")) - }) - It("should accept transactions with gasPrice >= baseFee", func() { - gasPrice := baseFee.TruncateInt() - txArgs.GasPrice = &gasPrice - res, err := s.factory.ExecuteCosmosTx(privKey, txArgs) - Expect(err).To(BeNil()) - Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog()) - }) - }) - }) - }) - - Describe("Performing EVM transactions", func() { - var ( - txArgs evmtypes.EvmTxArgs - gasWanted uint64 = 200_000 - ) - - BeforeEach(func() { - toAddr := s.keyring.GetAddr(1) - txArgs = evmtypes.EvmTxArgs{ - ChainID: s.network.GetEIP155ChainID(), - GasLimit: gasWanted, - To: &toAddr, - Amount: big.NewInt(10000), - } - }) - - Context("with MinGasPrices (feemarket param) < BaseFee (feemarket)", func() { - var ( - baseFee int64 - minGasPrices int64 - ) - - BeforeEach(func() { - baseFee = 10_000_000_000 - minGasPrices = baseFee - 5_000_000_000 - - params := fmkttypes.DefaultParams() - params.MinGasPrice = math.LegacyNewDec(minGasPrices) - params.BaseFee = math.LegacyNewDec(baseFee) - - // Note that the tests run the same transactions with `gasLimit = - // 200_000`. With the fee calculation `Fee = (baseFee + tip) * gasLimit`, - // a `minGasPrices = 5_000_000_000` results in `minGlobalFee = - // 1_000_000_000_000_000` - err := testutils.UpdateFeeMarketParams( - testutils.UpdateParamsInput{ - Tf: s.factory, - Network: s.network, - Pk: privKey, - Params: params, - }, - ) - Expect(err).To(BeNil()) - }) - - Context("during CheckTx", func() { - DescribeTable("should reject transactions with gasPrice < MinGasPrices", - func(malleate getprices) { - p := malleate() - - txArgs.GasPrice = p.gasPrice - txArgs.GasFeeCap = p.gasFeeCap - txArgs.GasTipCap = p.gasTipCap - txArgs.Accesses = p.accesses - - tx, err := s.factory.GenerateSignedEthTx(privKey, txArgs) - Expect(err).To(BeNil()) - - Expect(err).To(BeNil()) - bz, err := s.factory.EncodeTx(tx) - Expect(err).To(BeNil()) - - res, err := s.network.CheckTx(bz) - Expect(err).To(BeNil()) - Expect(res.IsOK()).To(BeFalse()) - Expect(res.Log).To(ContainSubstring("provided fee < minimum global fee")) - }, - Entry("legacy tx", func() txParams { - return txParams{big.NewInt(minGasPrices - 1_000_000_000), nil, nil, nil} - }), - Entry("dynamic tx with GasFeeCap < MinGasPrices, no gasTipCap", func() txParams { - return txParams{nil, big.NewInt(minGasPrices - 1_000_000_000), big.NewInt(0), ðtypes.AccessList{}} - }), - Entry("dynamic tx with GasFeeCap < MinGasPrices, max gasTipCap", func() txParams { - return txParams{nil, big.NewInt(minGasPrices - 1_000_000_000), big.NewInt(minGasPrices - 1_000_000_000), ðtypes.AccessList{}} - }), - ) - - DescribeTable("should reject transactions with MinGasPrices < tx gasPrice < EffectivePrice", - func(malleate getprices) { - p := malleate() - - txArgs.GasPrice = p.gasPrice - txArgs.GasFeeCap = p.gasFeeCap - txArgs.GasTipCap = p.gasTipCap - txArgs.Accesses = p.accesses - - tx, err := s.factory.GenerateSignedEthTx(privKey, txArgs) - Expect(err).To(BeNil()) - - Expect(err).To(BeNil()) - bz, err := s.factory.EncodeTx(tx) - Expect(err).To(BeNil()) - - err = s.network.NextBlock() - Expect(err).To(BeNil()) - - res, err := s.network.CheckTx(bz) - Expect(err).To(BeNil()) - Expect(res.IsOK()).To(BeFalse()) - Expect(res.Log).To(ContainSubstring("insufficient fee")) - }, - Entry("legacy tx", func() txParams { - currBaseFee := s.network.App.FeeMarketKeeper.GetBaseFee(s.network.GetContext()) - return txParams{big.NewInt(currBaseFee.Sub(currBaseFee.Sub(math.LegacyNewDec(minGasPrices)).QuoInt64(2)).RoundInt64()), nil, nil, nil} - }), - Entry("dynamic tx", func() txParams { - currBaseFee := s.network.App.FeeMarketKeeper.GetBaseFee(s.network.GetContext()) - return txParams{nil, big.NewInt(currBaseFee.Sub(currBaseFee.Sub(math.LegacyNewDec(minGasPrices)).QuoInt64(2)).RoundInt64()), big.NewInt(0), ðtypes.AccessList{}} - }), - ) - - DescribeTable("should accept transactions with gasPrice >= EffectivePrice", - func(malleate getprices) { - p := malleate() - txArgs.GasPrice = p.gasPrice - txArgs.GasFeeCap = p.gasFeeCap - txArgs.GasTipCap = p.gasTipCap - txArgs.Accesses = p.accesses - - tx, err := s.factory.GenerateSignedEthTx(privKey, txArgs) - Expect(err).To(BeNil()) - - Expect(err).To(BeNil()) - bz, err := s.factory.EncodeTx(tx) - Expect(err).To(BeNil()) - - res, err := s.network.CheckTx(bz) - Expect(err).To(BeNil(), "transaction should have succeeded") - Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog()) - }, - Entry("legacy tx", func() txParams { - return txParams{big.NewInt(baseFee), nil, nil, nil} - }), - Entry("dynamic tx", func() txParams { - return txParams{nil, big.NewInt(baseFee), big.NewInt(0), ðtypes.AccessList{}} - }), - ) - }) - - Context("during DeliverTx", func() { - DescribeTable("should reject transactions with gasPrice < MinGasPrices", - func(malleate getprices) { - p := malleate() - - txArgs.GasPrice = p.gasPrice - txArgs.GasFeeCap = p.gasFeeCap - txArgs.GasTipCap = p.gasTipCap - txArgs.Accesses = p.accesses - - res, err := s.factory.ExecuteEthTx(privKey, txArgs) - Expect(err).NotTo(BeNil()) - Expect(res.IsOK()).To(BeFalse()) - Expect(res.Log).To(ContainSubstring("provided fee < minimum global fee")) - }, - Entry("legacy tx", func() txParams { - return txParams{big.NewInt(minGasPrices - 1_000_000_000), nil, nil, nil} - }), - Entry("dynamic tx", func() txParams { - return txParams{nil, big.NewInt(minGasPrices - 1_000_000_000), nil, ðtypes.AccessList{}} - }), - ) - - DescribeTable("should reject transactions with MinGasPrices < gasPrice < EffectivePrice", - func(malleate getprices) { - p := malleate() - - txArgs.GasPrice = p.gasPrice - txArgs.GasFeeCap = p.gasFeeCap - txArgs.GasTipCap = p.gasTipCap - txArgs.Accesses = p.accesses - - res, err := s.factory.ExecuteEthTx(privKey, txArgs) - Expect(err).NotTo(BeNil()) - Expect(res.IsOK()).To(BeFalse()) - Expect(res.Log).To(ContainSubstring("insufficient fee")) - }, - // Note that the baseFee is not 10_000_000_000 anymore but updates to 7_656_250_000 because of the s.Commit - Entry("legacy tx", func() txParams { - return txParams{big.NewInt(baseFee - 2_500_000_000), nil, nil, nil} - }), - Entry("dynamic tx", func() txParams { - return txParams{nil, big.NewInt(baseFee - 2_500_000_000), big.NewInt(0), ðtypes.AccessList{}} - }), - ) - - DescribeTable("should accept transactions with gasPrice >= EffectivePrice", - func(malleate getprices) { - p := malleate() - - txArgs.GasPrice = p.gasPrice - txArgs.GasFeeCap = p.gasFeeCap - txArgs.GasTipCap = p.gasTipCap - txArgs.Accesses = p.accesses - - res, err := s.factory.ExecuteEthTx(privKey, txArgs) - Expect(err).To(BeNil()) - Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog()) - }, - Entry("legacy tx", func() txParams { - return txParams{big.NewInt(baseFee), nil, nil, nil} - }), - Entry("dynamic tx", func() txParams { - return txParams{nil, big.NewInt(baseFee), big.NewInt(0), ðtypes.AccessList{}} - }), - ) - }) - }) - - Context("with BaseFee (feemarket) < MinGasPrices (feemarket param)", func() { - var ( - baseFee int64 - minGasPrices int64 - ) - - Context("during CheckTx", func() { - BeforeEach(func() { - baseFee = 10_000_000_000 - minGasPrices = baseFee + 30_000_000_000 - - // Note that the tests run the same transactions with `gasLimit = - // 200000`. With the fee calculation `Fee = (baseFee + tip) * gasLimit`, - // with `minGasPrices = 40_000_000_000` results in `minGlobalFee = - // 8000000000000000` - // local min-gas-prices is 10aatom - params := fmkttypes.DefaultParams() - params.MinGasPrice = math.LegacyNewDec(minGasPrices) - params.BaseFee = math.LegacyNewDec(baseFee) - - // Note that the tests run the same transactions with `gasLimit = - // 200_000`. With the fee calculation `Fee = (baseFee + tip) * gasLimit`, - // a `minGasPrices = 5_000_000_000` results in `minGlobalFee = - // 1_000_000_000_000_000` - err := testutils.UpdateFeeMarketParams( - testutils.UpdateParamsInput{ - Tf: s.factory, - Network: s.network, - Pk: privKey, - Params: params, - }, - ) - Expect(err).To(BeNil()) - }) - - DescribeTable("should reject transactions with EffectivePrice < MinGasPrices", - func(malleate getprices) { - p := malleate() - - txArgs.GasPrice = p.gasPrice - txArgs.GasFeeCap = p.gasFeeCap - txArgs.GasTipCap = p.gasTipCap - txArgs.Accesses = p.accesses - - tx, err := s.factory.GenerateSignedEthTx(privKey, txArgs) - Expect(err).To(BeNil()) - - Expect(err).To(BeNil()) - bz, err := s.factory.EncodeTx(tx) - Expect(err).To(BeNil()) - - res, err := s.network.CheckTx(bz) - Expect(err).To(BeNil()) - Expect(res.IsOK()).To(BeFalse()) - Expect(res.Log).To(ContainSubstring("provided fee < minimum global fee")) - }, - Entry("legacy tx", func() txParams { - return txParams{big.NewInt(minGasPrices - 10_000_000_000), nil, nil, nil} - }), - Entry("dynamic tx with GasFeeCap < MinGasPrices, no gasTipCap", func() txParams { - return txParams{nil, big.NewInt(minGasPrices - 10_000_000_000), big.NewInt(0), ðtypes.AccessList{}} - }), - Entry("dynamic tx with GasFeeCap < MinGasPrices, max gasTipCap", func() txParams { - // Note that max priority fee per gas can't be higher than the max fee per gas (gasFeeCap), i.e. 30_000_000_000) - return txParams{nil, big.NewInt(minGasPrices - 10_000_000_000), big.NewInt(30_000_000_000), ðtypes.AccessList{}} - }), - ) - - DescribeTable("should accept transactions with gasPrice >= MinGasPrices", - func(malleate getprices) { - p := malleate() - - txArgs.GasPrice = p.gasPrice - txArgs.GasFeeCap = p.gasFeeCap - txArgs.GasTipCap = p.gasTipCap - txArgs.Accesses = p.accesses - - tx, err := s.factory.GenerateSignedEthTx(privKey, txArgs) - Expect(err).To(BeNil()) - - Expect(err).To(BeNil()) - bz, err := s.factory.EncodeTx(tx) - Expect(err).To(BeNil()) - - res, err := s.network.CheckTx(bz) - Expect(err).To(BeNil()) - Expect(res.IsOK()).To(BeTrue(), "transaction should have succeeded", res.GetLog()) - }, - Entry("legacy tx", func() txParams { - return txParams{big.NewInt(minGasPrices), nil, nil, nil} - }), - // Note that this tx is not rejected on CheckTx, but not on DeliverTx, - // as the baseFee is set to minGasPrices during DeliverTx when baseFee - // < minGasPrices - Entry("dynamic tx with GasFeeCap > MinGasPrices, EffectivePrice > MinGasPrices", func() txParams { - return txParams{nil, big.NewInt(minGasPrices), big.NewInt(30_000_000_000), ðtypes.AccessList{}} - }), - ) - }) - - Context("during DeliverTx", func() { - BeforeEach(func() { - baseFee = 10_000_000_000 - minGasPrices = baseFee + 30_000_000_000 - - // Note that the tests run the same transactions with `gasLimit = - // 200000`. With the fee calculation `Fee = (baseFee + tip) * gasLimit`, - // with `minGasPrices = 40_000_000_000` results in `minGlobalFee = - // 8000000000000000` - // local min-gas-prices is 10aatom - params := fmkttypes.DefaultParams() - params.MinGasPrice = math.LegacyNewDec(minGasPrices) - params.BaseFee = math.LegacyNewDec(baseFee) - - err := testutils.UpdateFeeMarketParams( - testutils.UpdateParamsInput{ - Tf: s.factory, - Network: s.network, - Pk: privKey, - Params: params, - }, - ) - Expect(err).To(BeNil()) - }) - DescribeTable("should reject transactions with gasPrice < MinGasPrices", - func(malleate getprices) { - p := malleate() - - txArgs.GasPrice = p.gasPrice - txArgs.GasFeeCap = p.gasFeeCap - txArgs.GasTipCap = p.gasTipCap - txArgs.Accesses = p.accesses - - res, err := s.factory.ExecuteEthTx(privKey, txArgs) - Expect(err).NotTo(BeNil()) - Expect(res.IsOK()).To(BeFalse()) - Expect(res.Log).To(ContainSubstring("provided fee < minimum global fee")) - }, - Entry("legacy tx", func() txParams { - return txParams{big.NewInt(minGasPrices - 10_000_000_000), nil, nil, nil} - }), - Entry("dynamic tx with GasFeeCap < MinGasPrices, no gasTipCap", func() txParams { - return txParams{nil, big.NewInt(minGasPrices - 10_000_000_000), big.NewInt(0), ðtypes.AccessList{}} - }), - Entry("dynamic tx with GasFeeCap < MinGasPrices, max gasTipCap", func() txParams { - // Note that max priority fee per gas can't be higher than the max fee per gas (gasFeeCap), i.e. 30_000_000_000) - return txParams{nil, big.NewInt(minGasPrices - 10_000_000_000), big.NewInt(30_000_000_000), ðtypes.AccessList{}} - }), - ) - - DescribeTable("should accept transactions with gasPrice >= MinGasPrices", - func(malleate getprices) { - p := malleate() - - txArgs.GasPrice = p.gasPrice - txArgs.GasFeeCap = p.gasFeeCap - txArgs.GasTipCap = p.gasTipCap - txArgs.Accesses = p.accesses - - res, err := s.factory.ExecuteEthTx(privKey, txArgs) - Expect(err).To(BeNil(), "transaction should have succeeded") - Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog()) - }, - Entry("legacy tx", func() txParams { - return txParams{big.NewInt(minGasPrices + 1), nil, nil, nil} - }), - Entry("dynamic tx, EffectivePrice > MinGasPrices", func() txParams { - return txParams{nil, big.NewInt(minGasPrices + 10_000_000_000), big.NewInt(30_000_000_000), ðtypes.AccessList{}} - }), - ) - }) - }) - }) -}) diff --git a/x/feemarket/keeper/setup_test.go b/x/feemarket/keeper/setup_test.go deleted file mode 100644 index aa0acf6a1..000000000 --- a/x/feemarket/keeper/setup_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package keeper_test - -import ( - "github.com/stretchr/testify/suite" - - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" - - "github.com/cosmos/cosmos-sdk/baseapp" -) - -type KeeperTestSuite struct { - suite.Suite - - network *network.UnitTestNetwork - factory factory.TxFactory - grpcHandler grpc.Handler - keyring testkeyring.Keyring - - denom string -} - -// SetupTest setup test environment -func (suite *KeeperTestSuite) SetupTest() { - keyring := testkeyring.New(2) - nw := network.NewUnitTestNetwork( - network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), - network.WithCustomBaseAppOpts(baseapp.SetMinGasPrices("10aatom")), - ) - grpcHandler := grpc.NewIntegrationHandler(nw) - txFactory := factory.New(nw, grpcHandler) - - ctx := nw.GetContext() - sk := nw.App.StakingKeeper - bondDenom, err := sk.BondDenom(ctx) - if err != nil { - panic(err) - } - - suite.denom = bondDenom - suite.factory = txFactory - suite.grpcHandler = grpcHandler - suite.keyring = keyring - suite.network = nw -} diff --git a/x/precisebank/keeper/keeper_test.go b/x/precisebank/keeper/keeper_test.go index d0b3f8b4d..1ae52d647 100644 --- a/x/precisebank/keeper/keeper_test.go +++ b/x/precisebank/keeper/keeper_test.go @@ -3,8 +3,10 @@ package keeper_test import ( "testing" + "cosmosevm.io/evmd" + + evmosencoding "github.com/cosmos/evm/encoding" testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/os/network" "github.com/cosmos/evm/x/precisebank/keeper" "github.com/cosmos/evm/x/precisebank/types" "github.com/cosmos/evm/x/precisebank/types/mocks" @@ -39,11 +41,14 @@ func newMockedTestData(t *testing.T) testData { bk := mocks.NewMockBankKeeper(t) ak := mocks.NewMockAccountKeeper(t) - nw := network.NewUnitTestNetwork( - network.WithChainID(testconstants.SixDecimalsChainID), - ) - cdc := nw.App.AppCodec() + chainId := testconstants.SixDecimalsChainID.EVMChainID + cfg := evmosencoding.MakeConfig(chainId) + cdc := cfg.Codec k := keeper.NewKeeper(cdc, storeKey, bk, ak) + err := evmd.EvmAppOptions(chainId) + if err != nil { + return testData{} + } return testData{ ctx: ctx, diff --git a/x/precisebank/keeper/setup_test.go b/x/precisebank/keeper/setup_test.go deleted file mode 100644 index df41a5c79..000000000 --- a/x/precisebank/keeper/setup_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package keeper_test - -import ( - "testing" - - "github.com/stretchr/testify/suite" - - testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" -) - -const SEED = int64(42) - -type KeeperIntegrationTestSuite struct { - suite.Suite - - network *network.UnitTestNetwork - factory factory.TxFactory - keyring keyring.Keyring -} - -func TestKeeperIntegrationTestSuite(t *testing.T) { - suite.Run(t, new(KeeperIntegrationTestSuite)) -} - -func (suite *KeeperIntegrationTestSuite) SetupTest() { - suite.SetupTestWithChainID(testconstants.SixDecimalsChainID) -} - -func (suite *KeeperIntegrationTestSuite) SetupTestWithChainID(chainID testconstants.ChainID) { - suite.keyring = keyring.New(2) - - nw := network.NewUnitTestNetwork( - network.WithChainID(chainID), - network.WithPreFundedAccounts(suite.keyring.GetAllAccAddrs()...), - ) - gh := grpc.NewIntegrationHandler(nw) - tf := factory.New(nw, gh) - - suite.network = nw - suite.factory = tf -} diff --git a/x/vm/ante/suite_test.go b/x/vm/ante/suite_test.go deleted file mode 100644 index 4c080aa1b..000000000 --- a/x/vm/ante/suite_test.go +++ /dev/null @@ -1,15 +0,0 @@ -package ante_test - -import ( - "testing" - - "github.com/stretchr/testify/suite" -) - -type EvmAnteTestSuite struct { - suite.Suite -} - -func TestEvmAnteTestSuite(t *testing.T) { - suite.Run(t, &EvmAnteTestSuite{}) -} diff --git a/x/vm/genesis_test.go b/x/vm/genesis_test.go deleted file mode 100644 index d6d5ceb48..000000000 --- a/x/vm/genesis_test.go +++ /dev/null @@ -1,250 +0,0 @@ -package vm_test - -import ( - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/tracing" - "github.com/ethereum/go-ethereum/crypto" - "github.com/holiman/uint256" - "github.com/stretchr/testify/require" - - "github.com/cosmos/evm/contracts" - "github.com/cosmos/evm/crypto/ethsecp256k1" - testconstants "github.com/cosmos/evm/testutil/constants" - testfactory "github.com/cosmos/evm/testutil/integration/os/factory" - testhandler "github.com/cosmos/evm/testutil/integration/os/grpc" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - testnetwork "github.com/cosmos/evm/testutil/integration/os/network" - "github.com/cosmos/evm/x/vm" - "github.com/cosmos/evm/x/vm/statedb" - "github.com/cosmos/evm/x/vm/types" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -type GenesisTestSuite struct { - keyring testkeyring.Keyring - network *testnetwork.UnitTestNetwork - handler testhandler.Handler - factory testfactory.TxFactory -} - -func SetupTest() *GenesisTestSuite { - keyring := testkeyring.New(1) - network := testnetwork.NewUnitTestNetwork( - testnetwork.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), - ) - handler := testhandler.NewIntegrationHandler(network) - factory := testfactory.New(network, handler) - - return &GenesisTestSuite{ - keyring: keyring, - network: network, - handler: handler, - factory: factory, - } -} - -func TestInitGenesis(t *testing.T) { - privkey, err := ethsecp256k1.GenerateKey() - require.NoError(t, err, "failed to generate private key") - - address := common.HexToAddress(privkey.PubKey().Address().String()) - - var ( - vmdb *statedb.StateDB - ctx sdk.Context - ) - - testCases := []struct { - name string - malleate func(*testnetwork.UnitTestNetwork) - genState *types.GenesisState - code common.Hash - expPanic bool - }{ - { - name: "pass - default", - malleate: func(_ *testnetwork.UnitTestNetwork) {}, - genState: types.DefaultGenesisState(), - expPanic: false, - }, - { - name: "valid account", - malleate: func(_ *testnetwork.UnitTestNetwork) { - vmdb.AddBalance(address, uint256.NewInt(1), tracing.BalanceChangeUnspecified) - }, - genState: &types.GenesisState{ - Params: types.DefaultParams(), - Accounts: []types.GenesisAccount{ - { - Address: address.String(), - Storage: types.Storage{ - {Key: common.BytesToHash([]byte("key")).String(), Value: common.BytesToHash([]byte("value")).String()}, - }, - }, - }, - }, - expPanic: false, - }, - { - name: "account not found", - malleate: func(_ *testnetwork.UnitTestNetwork) {}, - genState: &types.GenesisState{ - Params: types.DefaultParams(), - Accounts: []types.GenesisAccount{ - { - Address: address.String(), - }, - }, - }, - expPanic: true, - }, - { - name: "ignore empty account code checking", - malleate: func(network *testnetwork.UnitTestNetwork) { - acc := network.App.AccountKeeper.NewAccountWithAddress(ctx, address.Bytes()) - network.App.AccountKeeper.SetAccount(ctx, acc) - }, - genState: &types.GenesisState{ - Params: types.DefaultParams(), - Accounts: []types.GenesisAccount{ - { - Address: address.String(), - Code: "", - }, - }, - }, - expPanic: false, - }, - { - name: "valid account with code", - malleate: func(network *testnetwork.UnitTestNetwork) { - acc := network.App.AccountKeeper.NewAccountWithAddress(ctx, address.Bytes()) - network.App.AccountKeeper.SetAccount(ctx, acc) - }, - genState: &types.GenesisState{ - Params: types.DefaultParams(), - Accounts: []types.GenesisAccount{ - { - Address: address.String(), - Code: "1234", - }, - }, - }, - expPanic: false, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - ts := SetupTest() - ctx = ts.network.GetContext() - - vmdb = statedb.New( - ctx, - ts.network.App.EVMKeeper, - statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash())), - ) - - tc.malleate(ts.network) - err := vmdb.Commit() - require.NoError(t, err, "failed to commit to state db") - - if tc.expPanic { - require.Panics(t, func() { - _ = vm.InitGenesis( - ts.network.GetContext(), - ts.network.App.EVMKeeper, - ts.network.App.AccountKeeper, - *tc.genState, - ) - }) - } else { - require.NotPanics(t, func() { - _ = vm.InitGenesis( - ctx, - ts.network.App.EVMKeeper, - ts.network.App.AccountKeeper, - *tc.genState, - ) - }) - - // If the initialization has not panicked we're checking the state - for _, account := range tc.genState.Accounts { - acc := ts.network.App.AccountKeeper.GetAccount(ctx, common.HexToAddress(account.Address).Bytes()) - require.NotNil(t, acc, "account not found in account keeper") - - expHash := crypto.Keccak256Hash(common.Hex2Bytes(account.Code)) - if account.Code == "" { - expHash = common.BytesToHash(types.EmptyCodeHash) - } - - require.Equal(t, - expHash.String(), - ts.network.App.EVMKeeper.GetCodeHash( - ts.network.GetContext(), - common.HexToAddress(account.Address), - ).String(), - "code hash mismatch", - ) - - require.Equal(t, - account.Code, - common.Bytes2Hex( - ts.network.App.EVMKeeper.GetCode( - ts.network.GetContext(), - expHash, - ), - ), - "code mismatch", - ) - - for _, storage := range account.Storage { - key := common.HexToHash(storage.Key) - value := common.HexToHash(storage.Value) - require.Equal(t, value, vmdb.GetState(common.HexToAddress(account.Address), key), "storage mismatch") - } - } - } - }) - } -} - -func TestExportGenesis(t *testing.T) { - ts := SetupTest() - - contractAddr, err := ts.factory.DeployContract( - ts.keyring.GetPrivKey(0), - types.EvmTxArgs{}, - testfactory.ContractDeploymentData{ - Contract: contracts.ERC20MinterBurnerDecimalsContract, - ConstructorArgs: []interface{}{"TestToken", "TTK", uint8(18)}, - }, - ) - require.NoError(t, err, "failed to deploy contract") - require.NoError(t, ts.network.NextBlock(), "failed to advance block") - - contractAddr2, err := ts.factory.DeployContract( - ts.keyring.GetPrivKey(0), - types.EvmTxArgs{}, - testfactory.ContractDeploymentData{ - Contract: contracts.ERC20MinterBurnerDecimalsContract, - ConstructorArgs: []interface{}{"AnotherToken", "ATK", uint8(18)}, - }, - ) - require.NoError(t, err, "failed to deploy contract") - require.NoError(t, ts.network.NextBlock(), "failed to advance block") - - genState := vm.ExportGenesis(ts.network.GetContext(), ts.network.App.EVMKeeper) - require.Len(t, genState.Accounts, 3, "expected 3 smart contracts in the exported genesis") // NOTE: 2 deployed above + 1 for the aatom denomination ERC-20 pair - - genAddresses := make([]string, 0, len(genState.Accounts)) - for _, acc := range genState.Accounts { - genAddresses = append(genAddresses, acc.Address) - } - require.Contains(t, genAddresses, contractAddr.Hex(), "expected contract 1 address in exported genesis") - require.Contains(t, genAddresses, contractAddr2.Hex(), "expected contract 2 address in exported genesis") - require.Contains(t, genAddresses, testconstants.WEVMOSContractMainnet, "expected mainnet aatom contract address in exported genesis") -} diff --git a/x/vm/keeper/abci_test.go b/x/vm/keeper/abci_test.go deleted file mode 100644 index 7966d87a4..000000000 --- a/x/vm/keeper/abci_test.go +++ /dev/null @@ -1,25 +0,0 @@ -package keeper_test - -import ( - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" - evmtypes "github.com/cosmos/evm/x/vm/types" -) - -func (suite *KeeperTestSuite) TestEndBlock() { - keyring := testkeyring.New(2) - unitNetwork := network.NewUnitTestNetwork( - network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), - ) - ctx := unitNetwork.GetContext() - preEventManager := ctx.EventManager() - suite.Require().Equal(0, len(preEventManager.Events())) - - err := unitNetwork.App.EVMKeeper.EndBlock(ctx) - suite.Require().NoError(err) - - postEventManager := unitNetwork.GetContext().EventManager() - // should emit 1 EventTypeBlockBloom event on EndBlock - suite.Require().Equal(1, len(postEventManager.Events())) - suite.Require().Equal(evmtypes.EventTypeBlockBloom, postEventManager.Events()[0].Type) -} diff --git a/x/vm/keeper/grpc_query.go b/x/vm/keeper/grpc_query.go index 044b0b549..729587289 100644 --- a/x/vm/keeper/grpc_query.go +++ b/x/vm/keeper/grpc_query.go @@ -357,7 +357,7 @@ func (k Keeper) EstimateGasInternal(c context.Context, req *types.EthCallRequest // NOTE: the errors from the executable below should be consistent with go-ethereum, // so we don't wrap them with the gRPC status code - // Create a helper to check if a gas allowance results in an executable transaction + // create a helper to check if a gas allowance results in an executable transaction executable := func(gas uint64) (vmError bool, rsp *types.MsgEthereumTxResponse, err error) { // update the message with the new gas value msg = core.Message{ diff --git a/x/vm/keeper/integration_test.go b/x/vm/keeper/integration_test.go deleted file mode 100644 index d70dd1ad6..000000000 --- a/x/vm/keeper/integration_test.go +++ /dev/null @@ -1,673 +0,0 @@ -package keeper_test - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/common" - ethtypes "github.com/ethereum/go-ethereum/core/types" - - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" - - abcitypes "github.com/cometbft/cometbft/abci/types" - - "github.com/cosmos/evm/contracts" - "github.com/cosmos/evm/precompiles/staking" - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" - integrationutils "github.com/cosmos/evm/testutil/integration/os/utils" - evmtypes "github.com/cosmos/evm/x/vm/types" - - "cosmossdk.io/math" - - sdktypes "github.com/cosmos/cosmos-sdk/types" -) - -type IntegrationTestSuite struct { - network network.Network - factory factory.TxFactory - grpcHandler grpc.Handler - keyring testkeyring.Keyring -} - -// This test suite is meant to test the EVM module in the context of the ATOM. -// It uses the integration test framework to spin up a local ATOM network and -// perform transactions on it. -// The test suite focus on testing how the MsgEthereumTx message is handled under the -// different params configuration of the module while testing the different Tx types -// Ethereum supports (LegacyTx, AccessListTx, DynamicFeeTx) and the different types of -// transactions (transfer, contract deployment, contract call). -// Note that more in depth testing of the EVM and solidity execution is done through the -// hardhat and the nix setup. -var _ = Describe("Handling a MsgEthereumTx message", Label("EVM"), Ordered, func() { - var s *IntegrationTestSuite - - BeforeAll(func() { - keyring := testkeyring.New(4) - integrationNetwork := network.New( - network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), - ) - grpcHandler := grpc.NewIntegrationHandler(integrationNetwork) - txFactory := factory.New(integrationNetwork, grpcHandler) - s = &IntegrationTestSuite{ - network: integrationNetwork, - factory: txFactory, - grpcHandler: grpcHandler, - keyring: keyring, - } - }) - - AfterEach(func() { - // Start each test with a fresh block - err := s.network.NextBlock() - Expect(err).To(BeNil()) - }) - - When("the params have default values", Ordered, func() { - BeforeAll(func() { - // Set params to default values - defaultParams := evmtypes.DefaultParams() - err := integrationutils.UpdateEvmParams( - integrationutils.UpdateParamsInput{ - Tf: s.factory, - Network: s.network, - Pk: s.keyring.GetPrivKey(0), - Params: defaultParams, - }, - ) - Expect(err).To(BeNil()) - }) - DescribeTable("Executes a transfer transaction", func(getTxArgs func() evmtypes.EvmTxArgs) { - senderKey := s.keyring.GetKey(0) - receiverKey := s.keyring.GetKey(1) - denom := s.network.GetBaseDenom() - - senderPrevBalanceResponse, err := s.grpcHandler.GetBalanceFromBank(senderKey.AccAddr, denom) - Expect(err).To(BeNil()) - senderPrevBalance := senderPrevBalanceResponse.GetBalance().Amount - - receiverPrevBalanceResponse, err := s.grpcHandler.GetBalanceFromBank(receiverKey.AccAddr, denom) - Expect(err).To(BeNil()) - receiverPrevBalance := receiverPrevBalanceResponse.GetBalance().Amount - - transferAmount := int64(1000) - - // Taking custom args from the table entry - txArgs := getTxArgs() - txArgs.Amount = big.NewInt(transferAmount) - txArgs.To = &receiverKey.Addr - - res, err := s.factory.ExecuteEthTx(senderKey.Priv, txArgs) - Expect(err).To(BeNil()) - Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog()) - - err = s.network.NextBlock() - Expect(err).To(BeNil()) - - // Check sender balance after transaction - senderBalanceResultBeforeFees := senderPrevBalance.Sub(math.NewInt(transferAmount)) - senderAfterBalance, err := s.grpcHandler.GetBalanceFromBank(senderKey.AccAddr, denom) - Expect(err).To(BeNil()) - Expect(senderAfterBalance.GetBalance().Amount.LTE(senderBalanceResultBeforeFees)).To(BeTrue()) - - // Check receiver balance after transaction - receiverBalanceResult := receiverPrevBalance.Add(math.NewInt(transferAmount)) - receverAfterBalanceResponse, err := s.grpcHandler.GetBalanceFromBank(receiverKey.AccAddr, denom) - Expect(err).To(BeNil()) - Expect(receverAfterBalanceResponse.GetBalance().Amount).To(Equal(receiverBalanceResult)) - }, - Entry("as a DynamicFeeTx", func() evmtypes.EvmTxArgs { return evmtypes.EvmTxArgs{} }), - Entry("as an AccessListTx", - func() evmtypes.EvmTxArgs { - return evmtypes.EvmTxArgs{ - Accesses: ðtypes.AccessList{{ - Address: s.keyring.GetAddr(1), - StorageKeys: []common.Hash{{0}}, - }}, - } - }, - ), - Entry("as a LegacyTx", func() evmtypes.EvmTxArgs { - return evmtypes.EvmTxArgs{ - GasPrice: big.NewInt(1e9), - } - }), - ) - - DescribeTable("Executes a contract deployment", func(getTxArgs func() evmtypes.EvmTxArgs) { - // Deploy contract - senderPriv := s.keyring.GetPrivKey(0) - constructorArgs := []interface{}{"coin", "token", uint8(18)} - compiledContract := contracts.ERC20MinterBurnerDecimalsContract - - txArgs := getTxArgs() - contractAddr, err := s.factory.DeployContract( - senderPriv, - txArgs, - factory.ContractDeploymentData{ - Contract: compiledContract, - ConstructorArgs: constructorArgs, - }, - ) - Expect(err).To(BeNil()) - Expect(contractAddr).ToNot(Equal(common.Address{})) - - err = s.network.NextBlock() - Expect(err).To(BeNil()) - - // Check contract account got created correctly - contractBechAddr := sdktypes.AccAddress(contractAddr.Bytes()).String() - contractAccount, err := s.grpcHandler.GetAccount(contractBechAddr) - Expect(err).To(BeNil()) - Expect(contractAccount).ToNot(BeNil(), "expected account to be retrievable via auth query") - - ethAccountRes, err := s.grpcHandler.GetEvmAccount(contractAddr) - Expect(err).To(BeNil(), "expected no error retrieving account from the state db") - Expect(ethAccountRes.CodeHash).ToNot(Equal(common.BytesToHash(evmtypes.EmptyCodeHash).Hex()), - "expected code hash not to be the empty code hash", - ) - }, - Entry("as a DynamicFeeTx", func() evmtypes.EvmTxArgs { return evmtypes.EvmTxArgs{} }), - Entry("as an AccessListTx", - func() evmtypes.EvmTxArgs { - return evmtypes.EvmTxArgs{ - Accesses: ðtypes.AccessList{{ - Address: s.keyring.GetAddr(1), - StorageKeys: []common.Hash{{0}}, - }}, - } - }, - ), - Entry("as a LegacyTx", func() evmtypes.EvmTxArgs { - return evmtypes.EvmTxArgs{ - GasPrice: big.NewInt(1e9), - } - }), - ) - - Context("With a predeployed ERC20MinterBurnerDecimalsContract", func() { - var contractAddr common.Address - - BeforeEach(func() { - // Deploy contract - senderPriv := s.keyring.GetPrivKey(0) - constructorArgs := []interface{}{"coin", "token", uint8(18)} - compiledContract := contracts.ERC20MinterBurnerDecimalsContract - - var err error // Avoid shadowing - contractAddr, err = s.factory.DeployContract( - senderPriv, - evmtypes.EvmTxArgs{}, // Default values - factory.ContractDeploymentData{ - Contract: compiledContract, - ConstructorArgs: constructorArgs, - }, - ) - Expect(err).To(BeNil()) - Expect(contractAddr).ToNot(Equal(common.Address{})) - - err = s.network.NextBlock() - Expect(err).To(BeNil()) - }) - - DescribeTable("Executes a contract call", func(getTxArgs func() evmtypes.EvmTxArgs) { - senderPriv := s.keyring.GetPrivKey(0) - compiledContract := contracts.ERC20MinterBurnerDecimalsContract - recipientKey := s.keyring.GetKey(1) - - // Execute contract call - mintTxArgs := getTxArgs() - mintTxArgs.To = &contractAddr - - amountToMint := big.NewInt(1e18) - mintArgs := factory.CallArgs{ - ContractABI: compiledContract.ABI, - MethodName: "mint", - Args: []interface{}{recipientKey.Addr, amountToMint}, - } - mintResponse, err := s.factory.ExecuteContractCall(senderPriv, mintTxArgs, mintArgs) - Expect(err).To(BeNil()) - Expect(mintResponse.IsOK()).To(Equal(true), "transaction should have succeeded", mintResponse.GetLog()) - - err = checkMintTopics(mintResponse) - Expect(err).To(BeNil()) - - err = s.network.NextBlock() - Expect(err).To(BeNil()) - - totalSupplyTxArgs := evmtypes.EvmTxArgs{ - To: &contractAddr, - } - totalSupplyArgs := factory.CallArgs{ - ContractABI: compiledContract.ABI, - MethodName: "totalSupply", - Args: []interface{}{}, - } - totalSupplyRes, err := s.factory.ExecuteContractCall(senderPriv, totalSupplyTxArgs, totalSupplyArgs) - Expect(err).To(BeNil()) - Expect(totalSupplyRes.IsOK()).To(Equal(true), "transaction should have succeeded", totalSupplyRes.GetLog()) - - var totalSupplyResponse *big.Int - err = integrationutils.DecodeContractCallResponse(&totalSupplyResponse, totalSupplyArgs, totalSupplyRes) - Expect(err).To(BeNil()) - Expect(totalSupplyResponse).To(Equal(amountToMint)) - }, - Entry("as a DynamicFeeTx", func() evmtypes.EvmTxArgs { return evmtypes.EvmTxArgs{} }), - Entry("as an AccessListTx", - func() evmtypes.EvmTxArgs { - return evmtypes.EvmTxArgs{ - Accesses: ðtypes.AccessList{{ - Address: s.keyring.GetAddr(1), - StorageKeys: []common.Hash{{0}}, - }}, - } - }, - ), - Entry("as a LegacyTx", func() evmtypes.EvmTxArgs { - return evmtypes.EvmTxArgs{ - GasPrice: big.NewInt(1e9), - } - }), - ) - }) - - It("should fail when ChainID is wrong", func() { - senderPriv := s.keyring.GetPrivKey(0) - receiver := s.keyring.GetKey(1) - txArgs := evmtypes.EvmTxArgs{ - To: &receiver.Addr, - Amount: big.NewInt(1000), - ChainID: big.NewInt(1), - } - - res, err := s.factory.ExecuteEthTx(senderPriv, txArgs) - Expect(err).NotTo(BeNil()) - Expect(err.Error()).To(ContainSubstring("invalid chain id")) - // Transaction fails before being broadcasted - Expect(res).To(Equal(abcitypes.ExecTxResult{})) - }) - }) - - DescribeTable("Performs transfer and contract call", func(getTestParams func() evmtypes.Params, transferParams, contractCallParams PermissionsTableTest) { - params := getTestParams() - err := integrationutils.UpdateEvmParams( - integrationutils.UpdateParamsInput{ - Tf: s.factory, - Network: s.network, - Pk: s.keyring.GetPrivKey(0), - Params: params, - }, - ) - Expect(err).To(BeNil()) - - err = s.network.NextBlock() - Expect(err).To(BeNil()) - - signer := s.keyring.GetKey(transferParams.SignerIndex) - receiver := s.keyring.GetKey(1) - txArgs := evmtypes.EvmTxArgs{ - To: &receiver.Addr, - Amount: big.NewInt(1000), - // Hard coded gas limit to avoid failure on gas estimation because - // of the param - GasLimit: 100000, - } - res, err := s.factory.ExecuteEthTx(signer.Priv, txArgs) - if transferParams.ExpFail { - Expect(err).NotTo(BeNil()) - Expect(err.Error()).To(ContainSubstring("does not have permission to perform a call")) - } else { - Expect(err).To(BeNil()) - Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog()) - } - - senderKey := s.keyring.GetKey(contractCallParams.SignerIndex) - contractAddress := common.HexToAddress(evmtypes.StakingPrecompileAddress) - validatorAddress := s.network.GetValidators()[1].OperatorAddress - contractABI, err := staking.LoadABI() - Expect(err).To(BeNil()) - - // If grpc query fails, that means there were no previous delegations - prevDelegation := big.NewInt(0) - prevDelegationRes, err := s.grpcHandler.GetDelegation(senderKey.AccAddr.String(), validatorAddress) - if err == nil { - prevDelegation = prevDelegationRes.DelegationResponse.Balance.Amount.BigInt() - } - - amountToDelegate := big.NewInt(200) - totalSupplyTxArgs := evmtypes.EvmTxArgs{ - To: &contractAddress, - } - - // Perform a delegate transaction to the staking precompile - delegateArgs := factory.CallArgs{ - ContractABI: contractABI, - MethodName: staking.DelegateMethod, - Args: []interface{}{senderKey.Addr, validatorAddress, amountToDelegate}, - } - delegateResponse, err := s.factory.ExecuteContractCall(senderKey.Priv, totalSupplyTxArgs, delegateArgs) - if contractCallParams.ExpFail { - Expect(err).NotTo(BeNil()) - Expect(err.Error()).To(ContainSubstring("does not have permission to perform a call")) - } else { - Expect(err).To(BeNil()) - Expect(delegateResponse.IsOK()).To(Equal(true), "transaction should have succeeded", delegateResponse.GetLog()) - - err = s.network.NextBlock() - Expect(err).To(BeNil()) - - // Perform query to check the delegation was successful - queryDelegationArgs := factory.CallArgs{ - ContractABI: contractABI, - MethodName: staking.DelegationMethod, - Args: []interface{}{senderKey.Addr, validatorAddress}, - } - queryDelegationResponse, err := s.factory.ExecuteContractCall(senderKey.Priv, totalSupplyTxArgs, queryDelegationArgs) - Expect(err).To(BeNil()) - Expect(queryDelegationResponse.IsOK()).To(Equal(true), "transaction should have succeeded", queryDelegationResponse.GetLog()) - - // Make sure the delegation amount is correct - var delegationOutput staking.DelegationOutput - err = integrationutils.DecodeContractCallResponse(&delegationOutput, queryDelegationArgs, queryDelegationResponse) - Expect(err).To(BeNil()) - - expectedDelegationAmt := amountToDelegate.Add(amountToDelegate, prevDelegation) - Expect(delegationOutput.Balance.Amount.String()).To(Equal(expectedDelegationAmt.String())) - } - }, - // Entry("transfer and call fail with CALL permission policy set to restricted", func() evmtypes.Params { - // // Set params to default values - // defaultParams := evmtypes.DefaultParams() - // defaultParams.AccessControl.Call = evmtypes.AccessControlType{ - // AccessType: evmtypes.AccessTypeRestricted, - // } - // return defaultParams - // }, - // OpcodeTestTable{ExpFail: true, SignerIndex: 0}, - // OpcodeTestTable{ExpFail: true, SignerIndex: 0}, - // ), - Entry("transfer and call succeed with CALL permission policy set to default and CREATE permission policy set to restricted", func() evmtypes.Params { - blockedSignerIndex := 1 - // Set params to default values - defaultParams := evmtypes.DefaultParams() - defaultParams.AccessControl.Create = evmtypes.AccessControlType{ - AccessType: evmtypes.AccessTypeRestricted, - AccessControlList: []string{s.keyring.GetAddr(blockedSignerIndex).String()}, - } - return defaultParams - }, - PermissionsTableTest{ExpFail: false, SignerIndex: 0}, - PermissionsTableTest{ExpFail: false, SignerIndex: 0}, - ), - Entry("transfer and call are successful with CALL permission policy set to permissionless and address not blocked", func() evmtypes.Params { - blockedSignerIndex := 1 - // Set params to default values - defaultParams := evmtypes.DefaultParams() - defaultParams.AccessControl.Call = evmtypes.AccessControlType{ - AccessType: evmtypes.AccessTypePermissionless, - AccessControlList: []string{s.keyring.GetAddr(blockedSignerIndex).String()}, - } - return defaultParams - }, - PermissionsTableTest{ExpFail: false, SignerIndex: 0}, - PermissionsTableTest{ExpFail: false, SignerIndex: 0}, - ), - Entry("transfer fails with signer blocked and call succeeds with signer NOT blocked permission policy set to permissionless", func() evmtypes.Params { - blockedSignerIndex := 1 - // Set params to default values - defaultParams := evmtypes.DefaultParams() - defaultParams.AccessControl.Call = evmtypes.AccessControlType{ - AccessType: evmtypes.AccessTypePermissionless, - AccessControlList: []string{s.keyring.GetAddr(blockedSignerIndex).String()}, - } - return defaultParams - }, - PermissionsTableTest{ExpFail: true, SignerIndex: 1}, - PermissionsTableTest{ExpFail: false, SignerIndex: 0}, - ), - Entry("transfer succeeds with signer NOT blocked and call fails with signer blocked permission policy set to permissionless", func() evmtypes.Params { - blockedSignerIndex := 1 - // Set params to default values - defaultParams := evmtypes.DefaultParams() - defaultParams.AccessControl.Call = evmtypes.AccessControlType{ - AccessType: evmtypes.AccessTypePermissionless, - AccessControlList: []string{s.keyring.GetAddr(blockedSignerIndex).String()}, - } - return defaultParams - }, - PermissionsTableTest{ExpFail: false, SignerIndex: 0}, - PermissionsTableTest{ExpFail: true, SignerIndex: 1}, - ), - Entry("transfer and call succeeds with CALL permission policy set to permissioned and signer whitelisted on both", func() evmtypes.Params { - blockedSignerIndex := 1 - // Set params to default values - defaultParams := evmtypes.DefaultParams() - defaultParams.AccessControl.Call = evmtypes.AccessControlType{ - AccessType: evmtypes.AccessTypePermissioned, - AccessControlList: []string{s.keyring.GetAddr(blockedSignerIndex).String()}, - } - return defaultParams - }, - PermissionsTableTest{ExpFail: false, SignerIndex: 1}, - PermissionsTableTest{ExpFail: false, SignerIndex: 1}, - ), - Entry("transfer and call fails with CALL permission policy set to permissioned and signer not whitelisted on both", func() evmtypes.Params { - blockedSignerIndex := 1 - // Set params to default values - defaultParams := evmtypes.DefaultParams() - defaultParams.AccessControl.Call = evmtypes.AccessControlType{ - AccessType: evmtypes.AccessTypePermissioned, - AccessControlList: []string{s.keyring.GetAddr(blockedSignerIndex).String()}, - } - return defaultParams - }, - PermissionsTableTest{ExpFail: true, SignerIndex: 0}, - PermissionsTableTest{ExpFail: true, SignerIndex: 0}, - ), - ) - - DescribeTable("Performs contract deployment and contract call with AccessControl", func(getTestParams func() evmtypes.Params, createParams, callParams PermissionsTableTest) { - params := getTestParams() - err := integrationutils.UpdateEvmParams( - integrationutils.UpdateParamsInput{ - Tf: s.factory, - Network: s.network, - Pk: s.keyring.GetPrivKey(0), - Params: params, - }, - ) - Expect(err).To(BeNil()) - - err = s.network.NextBlock() - Expect(err).To(BeNil()) - - createSigner := s.keyring.GetPrivKey(createParams.SignerIndex) - constructorArgs := []interface{}{"coin", "token", uint8(18)} - compiledContract := contracts.ERC20MinterBurnerDecimalsContract - - contractAddr, err := s.factory.DeployContract( - createSigner, - evmtypes.EvmTxArgs{}, // Default values - factory.ContractDeploymentData{ - Contract: compiledContract, - ConstructorArgs: constructorArgs, - }, - ) - if createParams.ExpFail { - Expect(err).NotTo(BeNil()) - Expect(err.Error()).To(ContainSubstring("does not have permission to deploy contracts")) - // If contract deployment is expected to fail, we can skip the rest of the test - return - } - - Expect(err).To(BeNil()) - Expect(contractAddr).ToNot(Equal(common.Address{})) - - err = s.network.NextBlock() - Expect(err).To(BeNil()) - - callSigner := s.keyring.GetPrivKey(callParams.SignerIndex) - totalSupplyTxArgs := evmtypes.EvmTxArgs{ - To: &contractAddr, - } - totalSupplyArgs := factory.CallArgs{ - ContractABI: compiledContract.ABI, - MethodName: "totalSupply", - Args: []interface{}{}, - } - res, err := s.factory.ExecuteContractCall(callSigner, totalSupplyTxArgs, totalSupplyArgs) - if callParams.ExpFail { - Expect(err).NotTo(BeNil()) - Expect(err.Error()).To(ContainSubstring("does not have permission to perform a call")) - } else { - Expect(err).To(BeNil()) - Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog()) - } - }, - Entry("Create and call is successful with create permission policy set to permissionless and address not blocked ", func() evmtypes.Params { - blockedSignerIndex := 1 - // Set params to default values - defaultParams := evmtypes.DefaultParams() - defaultParams.AccessControl.Create = evmtypes.AccessControlType{ - AccessType: evmtypes.AccessTypePermissionless, - AccessControlList: []string{s.keyring.GetAddr(blockedSignerIndex).String()}, - } - return defaultParams - }, - PermissionsTableTest{ExpFail: false, SignerIndex: 0}, - PermissionsTableTest{ExpFail: false, SignerIndex: 0}, - ), - Entry("Create fails with create permission policy set to permissionless and signer is blocked ", func() evmtypes.Params { - blockedSignerIndex := 1 - // Set params to default values - defaultParams := evmtypes.DefaultParams() - defaultParams.AccessControl.Create = evmtypes.AccessControlType{ - AccessType: evmtypes.AccessTypePermissionless, - AccessControlList: []string{s.keyring.GetAddr(blockedSignerIndex).String()}, - } - return defaultParams - }, - PermissionsTableTest{ExpFail: true, SignerIndex: 1}, - PermissionsTableTest{}, // Call should not be executed - ), - Entry("Create and call is successful with call permission policy set to permissionless and address not blocked ", func() evmtypes.Params { - blockedSignerIndex := 1 - // Set params to default values - defaultParams := evmtypes.DefaultParams() - defaultParams.AccessControl.Call = evmtypes.AccessControlType{ - AccessType: evmtypes.AccessTypePermissionless, - AccessControlList: []string{s.keyring.GetAddr(blockedSignerIndex).String()}, - } - return defaultParams - }, - PermissionsTableTest{ExpFail: false, SignerIndex: 0}, - PermissionsTableTest{ExpFail: false, SignerIndex: 0}, - ), - Entry("Create is successful and call fails with call permission policy set to permissionless and address blocked ", func() evmtypes.Params { - blockedSignerIndex := 1 - // Set params to default values - defaultParams := evmtypes.DefaultParams() - defaultParams.AccessControl.Call = evmtypes.AccessControlType{ - AccessType: evmtypes.AccessTypePermissionless, - AccessControlList: []string{s.keyring.GetAddr(blockedSignerIndex).String()}, - } - return defaultParams - }, - PermissionsTableTest{ExpFail: false, SignerIndex: 0}, - PermissionsTableTest{ExpFail: true, SignerIndex: 1}, - ), - Entry("Create fails create permission policy set to restricted", func() evmtypes.Params { - // Set params to default values - defaultParams := evmtypes.DefaultParams() - defaultParams.AccessControl.Create = evmtypes.AccessControlType{ - AccessType: evmtypes.AccessTypeRestricted, - } - return defaultParams - }, - PermissionsTableTest{ExpFail: true, SignerIndex: 0}, - PermissionsTableTest{}, // Call should not be executed - ), - Entry("Create succeeds and call fails when call permission policy set to restricted", func() evmtypes.Params { - // Set params to default values - defaultParams := evmtypes.DefaultParams() - defaultParams.AccessControl.Call = evmtypes.AccessControlType{ - AccessType: evmtypes.AccessTypeRestricted, - } - return defaultParams - }, - PermissionsTableTest{ExpFail: false, SignerIndex: 0}, - PermissionsTableTest{ExpFail: true, SignerIndex: 0}, - ), - Entry("Create and call are successful with create permission policy set to permissioned and signer whitelisted", func() evmtypes.Params { - whitelistedSignerIndex := 1 - // Set params to default values - defaultParams := evmtypes.DefaultParams() - defaultParams.AccessControl.Create = evmtypes.AccessControlType{ - AccessType: evmtypes.AccessTypePermissioned, - AccessControlList: []string{s.keyring.GetAddr(whitelistedSignerIndex).String()}, - } - return defaultParams - }, - PermissionsTableTest{ExpFail: false, SignerIndex: 1}, - PermissionsTableTest{ExpFail: false, SignerIndex: 0}, - ), - Entry("Create fails with create permission policy set to permissioned and signer NOT whitelisted", func() evmtypes.Params { - whitelistedSignerIndex := 1 - // Set params to default values - defaultParams := evmtypes.DefaultParams() - defaultParams.AccessControl.Create = evmtypes.AccessControlType{ - AccessType: evmtypes.AccessTypePermissioned, - AccessControlList: []string{s.keyring.GetAddr(whitelistedSignerIndex).String()}, - } - return defaultParams - }, - PermissionsTableTest{ExpFail: true, SignerIndex: 0}, - PermissionsTableTest{}, - ), - Entry("Create and call are successful with call permission policy set to permissioned and signer whitelisted", func() evmtypes.Params { - whitelistedSignerIndex := 1 - // Set params to default values - defaultParams := evmtypes.DefaultParams() - defaultParams.AccessControl.Call = evmtypes.AccessControlType{ - AccessType: evmtypes.AccessTypePermissioned, - AccessControlList: []string{s.keyring.GetAddr(whitelistedSignerIndex).String()}, - } - return defaultParams - }, - PermissionsTableTest{ExpFail: false, SignerIndex: 0}, - PermissionsTableTest{ExpFail: false, SignerIndex: 1}, - ), - Entry("Create succeeds and call fails with call permission policy set to permissioned and signer NOT whitelisted", func() evmtypes.Params { - whitelistedSignerIndex := 1 - // Set params to default values - defaultParams := evmtypes.DefaultParams() - defaultParams.AccessControl.Call = evmtypes.AccessControlType{ - AccessType: evmtypes.AccessTypePermissioned, - AccessControlList: []string{s.keyring.GetAddr(whitelistedSignerIndex).String()}, - } - return defaultParams - }, - PermissionsTableTest{ExpFail: false, SignerIndex: 0}, - PermissionsTableTest{ExpFail: true, SignerIndex: 0}, - ), - ) -}) - -type PermissionsTableTest struct { - ExpFail bool - SignerIndex int -} - -func checkMintTopics(res abcitypes.ExecTxResult) error { - // Check contract call response has the expected topics for a mint - // call within an ERC20 contract - expectedTopics := []string{ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x0000000000000000000000000000000000000000000000000000000000000000", - } - return integrationutils.CheckTxTopics(res, expectedTopics) -} diff --git a/x/vm/keeper/state_transition.go b/x/vm/keeper/state_transition.go index cf3ce16ba..041ef2342 100644 --- a/x/vm/keeper/state_transition.go +++ b/x/vm/keeper/state_transition.go @@ -166,7 +166,7 @@ func (k *Keeper) ApplyTransaction(ctx sdk.Context, tx *ethtypes.Transaction) (*t return nil, errorsmod.Wrap(err, "failed to return ethereum transaction as core message") } - // Create a cache context to revert state. The cache context is only committed when both tx and hooks executed successfully. + // create a cache context to revert state. The cache context is only committed when both tx and hooks executed successfully. // Didn't use `Snapshot` because the context stack has exponential complexity on certain operations, // thus restricted to be used only inside `ApplyMessage`. tmpCtx, commit := ctx.CacheContext() @@ -347,7 +347,9 @@ func (k *Keeper) ApplyMessageWithConfig( msg.From, ) defer func() { - vmCfg.Tracer.OnTxEnd(ðtypes.Receipt{GasUsed: msg.GasLimit - leftoverGas}, vmErr) + if vmCfg.Tracer.OnTxEnd != nil { + vmCfg.Tracer.OnTxEnd(ðtypes.Receipt{GasUsed: msg.GasLimit - leftoverGas}, vmErr) + } }() } diff --git a/x/vm/statedb/integration_test.go b/x/vm/statedb/integration_test.go deleted file mode 100644 index d3d2ad8f0..000000000 --- a/x/vm/statedb/integration_test.go +++ /dev/null @@ -1,325 +0,0 @@ -package statedb_test - -import ( - "fmt" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - - //nolint:revive // okay to use dot imports for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // okay to use dot imports for Ginkgo - . "github.com/onsi/gomega" - - "github.com/cosmos/evm/contracts" - testcontracts "github.com/cosmos/evm/precompiles/testutil/contracts" - testfactory "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" - testnetwork "github.com/cosmos/evm/testutil/integration/os/network" - evmtypes "github.com/cosmos/evm/x/vm/types" - - "cosmossdk.io/math" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -func TestNestedEVMExtensionCall(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Nested EVM Extension Call Test Suite") -} - -type testCase struct { - method string - expDelegation bool - expSenderERC20Balance *big.Int - expContractERC20Balance *big.Int -} - -// This test is a demonstration of the flash loan exploit that was reported. -// This happens when interacting with EVM extensions in smart contract methods, -// where a resulting state change has the same value as the original state value. -// -// Before the fix, this would result in state changes not being persisted after the EVM extension call, -// therefore leaving the loaned funds in the contract. -var _ = Describe("testing the flash loan exploit", Ordered, func() { - var ( - keyring testkeyring.Keyring - // NOTE: we need to use the unit test network here because we need it to instantiate the staking precompile correctly - network *testnetwork.UnitTestNetwork - handler grpc.Handler - factory testfactory.TxFactory - - deployer testkeyring.Key - - erc20Addr common.Address - flashLoanAddr common.Address - flashLoanContract evmtypes.CompiledContract - - validatorToDelegateTo string - - delegatedAmountPre math.Int - ) - - mintAmount := big.NewInt(2e18) - delegateAmount := big.NewInt(1e18) - - BeforeAll(func() { - keyring = testkeyring.New(2) - network = testnetwork.NewUnitTestNetwork( - testnetwork.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), - ) - handler = grpc.NewIntegrationHandler(network) - factory = testfactory.New(network, handler) - - deployer = keyring.GetKey(0) - - var err error - - // Load the flash loan contract from the compiled JSON data. - flashLoanContract, err = testcontracts.LoadFlashLoanContract() - Expect(err).ToNot(HaveOccurred(), "failed to load flash loan contract") - }) - - BeforeEach(func() { - valsRes, err := handler.GetBondedValidators() - Expect(err).ToNot(HaveOccurred(), "failed to get bonded validators") - - validatorToDelegateTo = valsRes.Validators[0].OperatorAddress - - // Initial delegation of flash loan contract to the validator is 0. - delegatedAmountPre = math.NewInt(0) - - // Deploy an ERC-20 token contract. - erc20Addr, err = factory.DeployContract( - deployer.Priv, - evmtypes.EvmTxArgs{}, - testfactory.ContractDeploymentData{ - Contract: contracts.ERC20MinterBurnerDecimalsContract, - ConstructorArgs: []interface{}{"TestToken", "TT", uint8(18)}, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to deploy ERC-20 contract") - - Expect(network.NextBlock()).ToNot(HaveOccurred(), "failed to commit block") - - // Mint some tokens to the deployer. - _, err = factory.ExecuteContractCall( - deployer.Priv, - evmtypes.EvmTxArgs{To: &erc20Addr}, - testfactory.CallArgs{ - ContractABI: contracts.ERC20MinterBurnerDecimalsContract.ABI, - MethodName: "mint", - Args: []interface{}{ - deployer.Addr, mintAmount, - }, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to mint tokens") - - Expect(network.NextBlock()).ToNot(HaveOccurred(), "failed to commit block") - - // Check the balance of the deployer on the ERC20 contract. - res, err := factory.ExecuteContractCall( - deployer.Priv, - evmtypes.EvmTxArgs{To: &erc20Addr}, - testfactory.CallArgs{ - ContractABI: contracts.ERC20MinterBurnerDecimalsContract.ABI, - MethodName: "balanceOf", - Args: []interface{}{ - deployer.Addr, - }, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to get balance") - - Expect(network.NextBlock()).ToNot(HaveOccurred(), "failed to commit block") - - ethRes, err := evmtypes.DecodeTxResponse(res.Data) - Expect(err).ToNot(HaveOccurred(), "failed to decode balance of tx response") - - unpacked, err := contracts.ERC20MinterBurnerDecimalsContract.ABI.Unpack( - "balanceOf", - ethRes.Ret, - ) - Expect(err).ToNot(HaveOccurred(), "failed to unpack balance") - - balance, ok := unpacked[0].(*big.Int) - Expect(ok).To(BeTrue(), "failed to convert balance to big.Int") - Expect(balance.String()).To(Equal(mintAmount.String()), "balance is not correct") - - // Deploy the flash loan contract. - flashLoanAddr, err = factory.DeployContract( - deployer.Priv, - evmtypes.EvmTxArgs{}, - testfactory.ContractDeploymentData{ - Contract: flashLoanContract, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to deploy flash loan contract") - - Expect(network.NextBlock()).ToNot(HaveOccurred(), "failed to commit block") - - // Approve the flash loan contract to spend tokens. This is required because - // the contract will get funds from the caller to perform actions. - _, err = factory.ExecuteContractCall( - deployer.Priv, - evmtypes.EvmTxArgs{To: &erc20Addr}, - testfactory.CallArgs{ - ContractABI: contracts.ERC20MinterBurnerDecimalsContract.ABI, - MethodName: "approve", - Args: []interface{}{ - flashLoanAddr, mintAmount, - }, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to approve flash loan contract") - - Expect(network.NextBlock()).ToNot(HaveOccurred(), "failed to commit block") - - // Check the allowance. - res, err = factory.ExecuteContractCall( - deployer.Priv, - evmtypes.EvmTxArgs{To: &erc20Addr}, - testfactory.CallArgs{ - ContractABI: contracts.ERC20MinterBurnerDecimalsContract.ABI, - MethodName: "allowance", - Args: []interface{}{ - deployer.Addr, flashLoanAddr, - }, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to get allowance") - - Expect(network.NextBlock()).ToNot(HaveOccurred(), "failed to commit block") - - ethRes, err = evmtypes.DecodeTxResponse(res.Data) - Expect(err).ToNot(HaveOccurred(), "failed to decode allowance tx response") - - unpacked, err = contracts.ERC20MinterBurnerDecimalsContract.ABI.Unpack( - "allowance", - ethRes.Ret, - ) - Expect(err).ToNot(HaveOccurred(), "failed to unpack allowance") - - var allowance *big.Int - allowance, ok = unpacked[0].(*big.Int) - Expect(ok).To(BeTrue(), "failed to convert allowance to big.Int") - Expect(allowance.String()).To(Equal(mintAmount.String()), "allowance is not correct") - }) - - DescribeTable("call the flashLoan contract", func(tc testCase) { - _, err := factory.ExecuteContractCall( - deployer.Priv, - evmtypes.EvmTxArgs{ - To: &flashLoanAddr, - GasPrice: big.NewInt(900_000_000), - GasLimit: 400_000, - Amount: delegateAmount, - }, - testfactory.CallArgs{ - ContractABI: flashLoanContract.ABI, - MethodName: tc.method, - Args: []interface{}{ - erc20Addr, - validatorToDelegateTo, - }, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to execute flash loan") - - Expect(network.NextBlock()).ToNot(HaveOccurred(), "failed to commit block") - - falshLoanAccAddr := sdk.AccAddress(flashLoanAddr.Bytes()) - - if tc.expDelegation { - delRes, err := handler.GetDelegation(falshLoanAccAddr.String(), validatorToDelegateTo) - Expect(err).ToNot(HaveOccurred(), "failed to get delegation") - delAmtPost := delRes.DelegationResponse.Balance.Amount - Expect(delAmtPost).To(Equal( - delegatedAmountPre.Add(math.NewIntFromBigInt(delegateAmount))), - "delegated amount is not correct", - ) - } else { - _, err := handler.GetDelegation(falshLoanAccAddr.String(), validatorToDelegateTo) - Expect(err).To(HaveOccurred(), "failed to get delegation") - Expect(err.Error()).To(ContainSubstring( - fmt.Sprintf("delegation with delegator %s not found for validator %s", - falshLoanAccAddr.String(), - validatorToDelegateTo), - ), "delegation should not exist") - } - - // Check the ERC20 token balance of the deployer. - res, err := factory.ExecuteContractCall( - deployer.Priv, - evmtypes.EvmTxArgs{To: &erc20Addr}, - testfactory.CallArgs{ - ContractABI: contracts.ERC20MinterBurnerDecimalsContract.ABI, - MethodName: "balanceOf", - Args: []interface{}{ - deployer.Addr, - }, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to get balance") - - Expect(network.NextBlock()).ToNot(HaveOccurred(), "failed to commit block") - - ethRes, err := evmtypes.DecodeTxResponse(res.Data) - Expect(err).ToNot(HaveOccurred(), "failed to decode balance of tx response") - - unpacked, err := contracts.ERC20MinterBurnerDecimalsContract.ABI.Unpack( - "balanceOf", - ethRes.Ret, - ) - Expect(err).ToNot(HaveOccurred(), "failed to unpack balance") - - balance, ok := unpacked[0].(*big.Int) - Expect(ok).To(BeTrue(), "failed to convert balance to big.Int") - Expect(balance.String()).To(Equal(tc.expSenderERC20Balance.String()), "balance is not correct") - - // Check FlashLoan smart contract ERC20 token balance. - res, err = factory.ExecuteContractCall( - deployer.Priv, - evmtypes.EvmTxArgs{To: &erc20Addr}, - testfactory.CallArgs{ - ContractABI: contracts.ERC20MinterBurnerDecimalsContract.ABI, - MethodName: "balanceOf", - Args: []interface{}{ - flashLoanAddr, - }, - }, - ) - Expect(err).ToNot(HaveOccurred(), "failed to get balance") - - Expect(network.NextBlock()).ToNot(HaveOccurred(), "failed to commit block") - - ethRes, err = evmtypes.DecodeTxResponse(res.Data) - Expect(err).ToNot(HaveOccurred(), "failed to decode balance of tx response") - - unpacked, err = contracts.ERC20MinterBurnerDecimalsContract.ABI.Unpack( - "balanceOf", - ethRes.Ret, - ) - Expect(err).ToNot(HaveOccurred(), "failed to unpack balance") - - balance, ok = unpacked[0].(*big.Int) - Expect(ok).To(BeTrue(), "failed to convert balance to big.Int") - Expect(balance.String()).To(Equal(tc.expContractERC20Balance.String()), "balance is not correct") - }, - Entry("flashLoan method & expect delegation", testCase{ - method: "flashLoan", - expDelegation: true, - expSenderERC20Balance: mintAmount, - expContractERC20Balance: big.NewInt(0), - }), - Entry("flashLoanWithRevert method - delegation reverted", testCase{ - method: "flashLoanWithRevert", - expDelegation: false, - expSenderERC20Balance: delegateAmount, - expContractERC20Balance: delegateAmount, - }), - ) -}) diff --git a/x/vm/types/errors.go b/x/vm/types/errors.go index 40942908c..2e26ed4e9 100644 --- a/x/vm/types/errors.go +++ b/x/vm/types/errors.go @@ -43,7 +43,7 @@ var ( ErrZeroAddress = errorsmod.Register(ModuleName, codeErrZeroAddress, "invalid zero address") // ErrCreateDisabled returns an error if the EnableCreate parameter is false. - ErrCreateDisabled = errorsmod.Register(ModuleName, codeErrCreateDisabled, "EVM Create operation is disabled") + ErrCreateDisabled = errorsmod.Register(ModuleName, codeErrCreateDisabled, "EVM create operation is disabled") // ErrCallDisabled returns an error if the EnableCall parameter is false. ErrCallDisabled = errorsmod.Register(ModuleName, codeErrCallDisabled, "EVM Call operation is disabled") diff --git a/x/vm/types/evm.pb.go b/x/vm/types/evm.pb.go index 9f6826192..f3393fef9 100644 --- a/x/vm/types/evm.pb.go +++ b/x/vm/types/evm.pb.go @@ -2538,7 +2538,7 @@ func (m *AccessControl) Unmarshal(dAtA []byte) error { switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Create", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field create", wireType) } var msglen int for shift := uint(0); ; shift += 7 { diff --git a/x/vm/types/msg_test.go b/x/vm/types/msg_test.go index 7157c12a0..6562e80ba 100644 --- a/x/vm/types/msg_test.go +++ b/x/vm/types/msg_test.go @@ -8,6 +8,7 @@ import ( "strings" "testing" + "cosmosevm.io/evmd" "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" @@ -15,7 +16,6 @@ import ( "github.com/cosmos/evm/crypto/ethsecp256k1" "github.com/cosmos/evm/encoding" - exampleapp "github.com/cosmos/evm/evmd" testconstants "github.com/cosmos/evm/testutil/constants" utiltx "github.com/cosmos/evm/testutil/tx" "github.com/cosmos/evm/x/vm/types" @@ -57,7 +57,7 @@ func (suite *MsgsTestSuite) SetupTest() { encodingConfig := encoding.MakeConfig(suite.chainID.Uint64()) suite.clientCtx = client.Context{}.WithTxConfig(encodingConfig.TxConfig) - err := exampleapp.EvmAppOptions(9001) + err := evmd.EvmAppOptions(9001) suite.Require().NoError(err) } diff --git a/x/vm/types/permissions_test.go b/x/vm/types/permissions_test.go index 1674c2b58..be8683e6c 100644 --- a/x/vm/types/permissions_test.go +++ b/x/vm/types/permissions_test.go @@ -6,7 +6,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/suite" - testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" + testkeyring "github.com/cosmos/evm/testutil/keyring" "github.com/cosmos/evm/x/vm/types" ) From f597df946c48a8d7583460f3b47de31b62043121 Mon Sep 17 00:00:00 2001 From: zsystm Date: Wed, 4 Jun 2025 21:48:51 +0900 Subject: [PATCH 02/21] upstream merge and resolve conflicts --- tests/integration/rpc/backend/test_backend_suite.go | 1 - x/erc20/types/params_test.go | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/integration/rpc/backend/test_backend_suite.go b/tests/integration/rpc/backend/test_backend_suite.go index 6aa186bb7..10b92ba36 100644 --- a/tests/integration/rpc/backend/test_backend_suite.go +++ b/tests/integration/rpc/backend/test_backend_suite.go @@ -20,7 +20,6 @@ import ( rpcbackend "github.com/cosmos/evm/rpc/backend" "github.com/cosmos/evm/rpc/backend/mocks" rpctypes "github.com/cosmos/evm/rpc/types" - "github.com/cosmos/evm/server/config" "github.com/cosmos/evm/testutil/constants" "github.com/cosmos/evm/testutil/integration/evm/network" utiltx "github.com/cosmos/evm/testutil/tx" diff --git a/x/erc20/types/params_test.go b/x/erc20/types/params_test.go index 59cd08b03..e6dca0918 100644 --- a/x/erc20/types/params_test.go +++ b/x/erc20/types/params_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" - exampleapp "github.com/cosmos/evm/evmd" + "github.com/cosmos/evm/evmd" testconstants "github.com/cosmos/evm/testutil/constants" "github.com/cosmos/evm/x/erc20/types" ) @@ -162,7 +162,7 @@ func (suite *ParamsTestSuite) TestIsNativePrecompile() { }{ { "default", - func() types.Params { return exampleapp.NewErc20GenesisState().Params }, + func() types.Params { return evmd.NewErc20GenesisState().Params }, common.HexToAddress(testconstants.WEVMOSContractMainnet), true, }, From 1868405622501c900aad777941bb6bfe7f91a986 Mon Sep 17 00:00:00 2001 From: zsystm Date: Thu, 5 Jun 2025 01:04:10 +0900 Subject: [PATCH 03/21] fix lints & ci removed already migrated test also --- ethereum/eip712/eip712_fuzzer_test.go | 194 ------------------ evmd/tests/integration/backend_test.go | 2 +- evmd/tests/integration/eip712_test.go | 4 +- .../integration/iterate_contracts_test.go | 7 + interfaces.go | 2 +- rpc/backend/backend.go | 4 +- rpc/backend/blocks.go | 26 +-- rpc/backend/chain_info.go | 2 +- rpc/backend/filters.go | 2 +- rpc/backend/tx_info.go | 8 +- tests/integration/README.md | 49 ++++- tests/integration/ante/ante_test_suite.go | 2 +- .../ante/benchmark_evm_antehandler.go | 1 + tests/integration/ante/test_bench_evm_ante.go | 1 + tests/integration/ante/test_integration.go | 6 +- .../ante/test_validate_handler_options.go | 1 + tests/integration/eip712/test_eip712.go | 38 ++-- .../integration/eip712/test_eip712_fuzzer.go | 22 +- tests/integration/eips/test_eips.go | 18 +- tests/integration/ledger/evmosd_suite_test.go | 6 +- tests/integration/ledger/ledger_test.go | 3 +- .../precompiles/bank/test_integration.go | 10 +- .../precompiles/bank/test_setup.go | 2 - .../precompiles/bech32/test_setup.go | 2 - .../distribution/test_integration.go | 12 +- .../precompiles/erc20/test_integration.go | 10 +- .../precompiles/erc20/test_setup.go | 2 - .../precompiles/gov/test_integration.go | 10 +- .../precompiles/p256/test_integration.go | 14 +- .../precompiles/p256/test_setup.go | 11 +- .../precompiles/staking/test_integration.go | 14 +- .../precompiles/staking/test_setup.go | 8 +- .../precompiles/werc20/test_integration.go | 9 +- .../rpc/backend/test_account_info.go | 10 +- .../rpc/backend/test_backend_suite.go | 20 +- tests/integration/rpc/backend/test_blocks.go | 32 +-- tests/integration/rpc/backend/test_call_tx.go | 8 +- .../rpc/backend/test_chain_info.go | 12 +- tests/integration/rpc/backend/test_filters.go | 4 +- .../integration/rpc/backend/test_node_info.go | 14 +- tests/integration/rpc/backend/test_sign_tx.go | 8 +- tests/integration/rpc/backend/test_tracing.go | 4 +- tests/integration/rpc/backend/test_tx_info.go | 20 +- tests/integration/rpc/backend/test_utils.go | 2 +- .../integration/wallets/test_ledger_suite.go | 10 +- tests/integration/x/erc20/test_integration.go | 6 +- .../x/feemarket/test_integration.go | 8 +- .../x/precisebank/test_burn_integration.go | 8 +- .../x/precisebank/test_integration.go | 6 +- .../x/precisebank/test_send_integration.go | 14 +- .../x/precisebank/test_view_integration.go | 4 +- tests/integration/x/vm/genesis_test_suite.go | 7 +- tests/integration/x/vm/keeper_test_suite.go | 7 +- .../x/vm/nested_evm_extension_test_suite.go | 7 +- .../x/vm/test_iterate_contracts.go | 71 +++++++ tests/integration/x/vm/test_statedb.go | 61 +----- testutil/integration/evm/utils/genesis.go | 5 +- x/erc20/types/params_test.go | 2 +- x/precisebank/keeper/keeper_test.go | 6 +- 59 files changed, 347 insertions(+), 511 deletions(-) delete mode 100644 ethereum/eip712/eip712_fuzzer_test.go create mode 100644 evmd/tests/integration/iterate_contracts_test.go create mode 100644 tests/integration/x/vm/test_iterate_contracts.go diff --git a/ethereum/eip712/eip712_fuzzer_test.go b/ethereum/eip712/eip712_fuzzer_test.go deleted file mode 100644 index f0a3efd48..000000000 --- a/ethereum/eip712/eip712_fuzzer_test.go +++ /dev/null @@ -1,194 +0,0 @@ -package eip712_test - -import ( - "fmt" - "strings" - - "github.com/tidwall/gjson" - "github.com/tidwall/sjson" - - rand "github.com/cometbft/cometbft/libs/rand" - - "github.com/cosmos/evm/ethereum/eip712" -) - -type EIP712FuzzTestParams struct { - numTestObjects int - maxNumFieldsPerObject int - minStringLength int - maxStringLength int - randomFloatRange float64 - maxArrayLength int - maxObjectDepth int -} - -const ( - numPrimitiveJSONTypes = 3 - numJSONTypes = 5 - asciiRangeStart = 65 - asciiRangeEnd = 127 - fuzzTestName = "Flatten" -) - -const ( - jsonBoolType = iota - jsonStringType = iota - jsonFloatType = iota - jsonArrayType = iota - jsonObjectType = iota -) - -var params = EIP712FuzzTestParams{ - numTestObjects: 16, - maxNumFieldsPerObject: 16, - minStringLength: 16, - maxStringLength: 48, - randomFloatRange: 120000000, - maxArrayLength: 8, - maxObjectDepth: 4, -} - -// TestRandomPayloadFlattening generates many random payloads with different JSON values to ensure -// that Flattening works across all inputs. -// Note that this is a fuzz test, although it doesn't use Go's Fuzz testing suite, since there are -// variable input sizes, types, and fields. While it may be possible to translate a single input into -// a JSON object, it would require difficult parsing, and ultimately approximates our randomized unit -// tests as they are. -func (suite *EIP712TestSuite) TestRandomPayloadFlattening() { - // Re-seed rand generator - rand.Seed(rand.Int64()) - - for i := 0; i < params.numTestObjects; i++ { - suite.Run(fmt.Sprintf("%v%d", fuzzTestName, i), func() { - payload := suite.generateRandomPayload(i) - - flattened, numMessages, err := eip712.FlattenPayloadMessages(payload) - - suite.Require().NoError(err) - suite.Require().Equal(numMessages, i) - - suite.verifyPayloadAgainstFlattened(payload, flattened) - }) - } -} - -// generateRandomPayload creates a random payload of the desired format, with random sub-objects. -func (suite *EIP712TestSuite) generateRandomPayload(numMessages int) gjson.Result { - payload := suite.createRandomJSONObject().Raw - msgs := make([]gjson.Result, numMessages) - - for i := 0; i < numMessages; i++ { - msgs[i] = suite.createRandomJSONObject() - } - - payload, err := sjson.Set(payload, msgsFieldName, msgs) - suite.Require().NoError(err) - - return gjson.Parse(payload) -} - -// createRandomJSONObject creates a JSON object with random fields. -func (suite *EIP712TestSuite) createRandomJSONObject() gjson.Result { - var err error - payloadRaw := "" - - numFields := suite.createRandomIntInRange(0, params.maxNumFieldsPerObject) - for i := 0; i < numFields; i++ { - key := suite.createRandomString() - - randField := suite.createRandomJSONField(i, 0) - payloadRaw, err = sjson.Set(payloadRaw, key, randField) - suite.Require().NoError(err) - } - - return gjson.Parse(payloadRaw) -} - -// createRandomJSONField creates a random field with a random JSON type, with the possibility of -// nested fields up to depth objects. -func (suite *EIP712TestSuite) createRandomJSONField(t int, depth int) interface{} { - switch t % numJSONTypes { - case jsonBoolType: - return suite.createRandomBoolean() - case jsonStringType: - return suite.createRandomString() - case jsonFloatType: - return suite.createRandomFloat() - case jsonArrayType: - return suite.createRandomJSONNestedArray(depth) - case jsonObjectType: - return suite.createRandomJSONNestedObject(depth) - default: - return nil - } -} - -// createRandomJSONNestedArray creates an array of random nested JSON fields. -func (suite *EIP712TestSuite) createRandomJSONNestedArray(depth int) []interface{} { - arr := make([]interface{}, rand.Intn(params.maxArrayLength)) - for i := range arr { - arr[i] = suite.createRandomJSONNestedField(depth) - } - - return arr -} - -// createRandomJSONNestedObject creates a key-value set of objects with random nested JSON fields. -func (suite *EIP712TestSuite) createRandomJSONNestedObject(depth int) interface{} { - numFields := rand.Intn(params.maxNumFieldsPerObject) - obj := make(map[string]interface{}) - - for i := 0; i < numFields; i++ { - subField := suite.createRandomJSONNestedField(depth) - - obj[suite.createRandomString()] = subField - } - - return obj -} - -// createRandomJSONNestedField serves as a helper for createRandomJSONField and returns a random -// subfield to populate an array or object type. -func (suite *EIP712TestSuite) createRandomJSONNestedField(depth int) interface{} { - var newFieldType int - - if depth == params.maxObjectDepth { - newFieldType = rand.Intn(numPrimitiveJSONTypes) - } else { - newFieldType = rand.Intn(numJSONTypes) - } - - return suite.createRandomJSONField(newFieldType, depth+1) -} - -func (suite *EIP712TestSuite) createRandomBoolean() bool { - return rand.Intn(2) == 0 -} - -func (suite *EIP712TestSuite) createRandomFloat() float64 { - return (rand.Float64() - 0.5) * params.randomFloatRange -} - -func (suite *EIP712TestSuite) createRandomString() string { - bzLen := suite.createRandomIntInRange(params.minStringLength, params.maxStringLength) - bz := make([]byte, bzLen) - - for i := 0; i < bzLen; i++ { - bz[i] = byte(suite.createRandomIntInRange(asciiRangeStart, asciiRangeEnd)) - } - - str := string(bz) - - // Remove control characters, since they will make JSON invalid - str = strings.ReplaceAll(str, "{", "") - str = strings.ReplaceAll(str, "}", "") - str = strings.ReplaceAll(str, "]", "") - str = strings.ReplaceAll(str, "[", "") - - return str -} - -// createRandomIntInRange provides a random integer between [min, max) -func (suite *EIP712TestSuite) createRandomIntInRange(minInt int, maxInt int) int { - return rand.Intn(maxInt-minInt) + minInt -} diff --git a/evmd/tests/integration/backend_test.go b/evmd/tests/integration/backend_test.go index 303f0e7c6..541eed416 100644 --- a/evmd/tests/integration/backend_test.go +++ b/evmd/tests/integration/backend_test.go @@ -9,6 +9,6 @@ import ( ) func TestBackend(t *testing.T) { - s := backend.NewBackendTestSuite(CreateEvmd) + s := backend.NewTestSuite(CreateEvmd) suite.Run(t, s) } diff --git a/evmd/tests/integration/eip712_test.go b/evmd/tests/integration/eip712_test.go index 2df778a52..777d8e087 100644 --- a/evmd/tests/integration/eip712_test.go +++ b/evmd/tests/integration/eip712_test.go @@ -9,11 +9,11 @@ import ( ) func TestEIP712TestSuite(t *testing.T) { - s := eip712.NewEIP712TestSuite(CreateEvmd, false) + s := eip712.NewTestSuite(CreateEvmd, false) suite.Run(t, s) // Note that we don't test the Legacy EIP-712 Extension, since that case // is sufficiently covered by the AnteHandler tests. - s = eip712.NewEIP712TestSuite(CreateEvmd, true) + s = eip712.NewTestSuite(CreateEvmd, true) suite.Run(t, s) } diff --git a/evmd/tests/integration/iterate_contracts_test.go b/evmd/tests/integration/iterate_contracts_test.go new file mode 100644 index 000000000..8931986c4 --- /dev/null +++ b/evmd/tests/integration/iterate_contracts_test.go @@ -0,0 +1,7 @@ +package integration + +import "testing" + +func TestIterateContracts(t *testing.T) { + TestIterateContracts(t) +} diff --git a/interfaces.go b/interfaces.go index ce233fc80..e249f24fb 100644 --- a/interfaces.go +++ b/interfaces.go @@ -40,7 +40,7 @@ import ( ) // EvmApp defines the interface for an EVM application. -type EvmApp interface { +type EvmApp interface { //nolint:revive ibctesting.TestingApp runtime.AppI InterfaceRegistry() types.InterfaceRegistry diff --git a/rpc/backend/backend.go b/rpc/backend/backend.go index 98fe07eb0..6bf5a253a 100644 --- a/rpc/backend/backend.go +++ b/rpc/backend/backend.go @@ -128,7 +128,7 @@ var _ BackendI = (*Backend)(nil) type Backend struct { Ctx context.Context ClientCtx client.Context - RpcClient tmrpcclient.SignClient + RPCClient tmrpcclient.SignClient QueryClient *rpctypes.QueryClient // gRPC query client Logger log.Logger EvmChainID *big.Int @@ -158,7 +158,7 @@ func NewBackend( return &Backend{ Ctx: context.Background(), ClientCtx: clientCtx, - RpcClient: rpcClient, + RPCClient: rpcClient, QueryClient: rpctypes.NewQueryClient(clientCtx), Logger: logger.With("module", "backend"), EvmChainID: big.NewInt(int64(appConf.EVM.EVMChainID)), //nolint:gosec // G115 // won't exceed uint64 diff --git a/rpc/backend/blocks.go b/rpc/backend/blocks.go index 3c72681cd..6054932b4 100644 --- a/rpc/backend/blocks.go +++ b/rpc/backend/blocks.go @@ -67,7 +67,7 @@ func (b *Backend) GetBlockByNumber(blockNum rpctypes.BlockNumber, fullTx bool) ( return nil, nil } - blockRes, err := b.RpcClient.BlockResults(b.Ctx, &resBlock.Block.Height) + blockRes, err := b.RPCClient.BlockResults(b.Ctx, &resBlock.Block.Height) if err != nil { b.Logger.Debug("failed to fetch block result from Tendermint", "height", blockNum, "error", err.Error()) return nil, nil @@ -95,7 +95,7 @@ func (b *Backend) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]inte return nil, nil } - blockRes, err := b.RpcClient.BlockResults(b.Ctx, &resBlock.Block.Height) + blockRes, err := b.RPCClient.BlockResults(b.Ctx, &resBlock.Block.Height) if err != nil { b.Logger.Debug("failed to fetch block result from Tendermint", "block-hash", hash.String(), "error", err.Error()) return nil, nil @@ -113,7 +113,7 @@ func (b *Backend) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]inte // GetBlockTransactionCountByHash returns the number of Ethereum transactions in // the block identified by hash. func (b *Backend) GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Uint { - block, err := b.RpcClient.BlockByHash(b.Ctx, hash.Bytes()) + block, err := b.RPCClient.BlockByHash(b.Ctx, hash.Bytes()) if err != nil { b.Logger.Debug("block not found", "hash", hash.Hex(), "error", err.Error()) return nil @@ -147,7 +147,7 @@ func (b *Backend) GetBlockTransactionCountByNumber(blockNum rpctypes.BlockNumber // GetBlockTransactionCount returns the number of Ethereum transactions in a // given block. func (b *Backend) GetBlockTransactionCount(block *tmrpctypes.ResultBlock) *hexutil.Uint { - blockRes, err := b.RpcClient.BlockResults(b.Ctx, &block.Block.Height) + blockRes, err := b.RPCClient.BlockResults(b.Ctx, &block.Block.Height) if err != nil { return nil } @@ -169,7 +169,7 @@ func (b *Backend) TendermintBlockByNumber(blockNum rpctypes.BlockNumber) (*tmrpc } height = int64(n) //#nosec G115 -- checked for int overflow already } - resBlock, err := b.RpcClient.Block(b.Ctx, &height) + resBlock, err := b.RPCClient.Block(b.Ctx, &height) if err != nil { b.Logger.Debug("tendermint client failed to get block", "height", height, "error", err.Error()) return nil, err @@ -186,12 +186,12 @@ func (b *Backend) TendermintBlockByNumber(blockNum rpctypes.BlockNumber) (*tmrpc // TendermintBlockResultByNumber returns a Tendermint-formatted block result // by block number func (b *Backend) TendermintBlockResultByNumber(height *int64) (*tmrpctypes.ResultBlockResults, error) { - return b.RpcClient.BlockResults(b.Ctx, height) + return b.RPCClient.BlockResults(b.Ctx, height) } // TendermintBlockByHash returns a Tendermint-formatted block by block number func (b *Backend) TendermintBlockByHash(blockHash common.Hash) (*tmrpctypes.ResultBlock, error) { - resBlock, err := b.RpcClient.BlockByHash(b.Ctx, blockHash.Bytes()) + resBlock, err := b.RPCClient.BlockByHash(b.Ctx, blockHash.Bytes()) if err != nil { b.Logger.Debug("tendermint client failed to get block", "blockHash", blockHash.Hex(), "error", err.Error()) return nil, err @@ -225,7 +225,7 @@ func (b *Backend) BlockNumberFromTendermint(blockNrOrHash rpctypes.BlockNumberOr // BlockNumberFromTendermintByHash returns the block height of given block hash func (b *Backend) BlockNumberFromTendermintByHash(blockHash common.Hash) (*big.Int, error) { - resBlock, err := b.RpcClient.HeaderByHash(b.Ctx, blockHash.Bytes()) + resBlock, err := b.RPCClient.HeaderByHash(b.Ctx, blockHash.Bytes()) if err != nil { return nil, err } @@ -290,7 +290,7 @@ func (b *Backend) HeaderByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Heade return nil, errors.Errorf("block not found for height %d", blockNum) } - blockRes, err := b.RpcClient.BlockResults(b.Ctx, &resBlock.Block.Height) + blockRes, err := b.RPCClient.BlockResults(b.Ctx, &resBlock.Block.Height) if err != nil { return nil, errors.Errorf("block result not found for height %d", resBlock.Block.Height) } @@ -312,7 +312,7 @@ func (b *Backend) HeaderByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Heade // HeaderByHash returns the block header identified by hash. func (b *Backend) HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) { - resHeader, err := b.RpcClient.HeaderByHash(b.Ctx, blockHash.Bytes()) + resHeader, err := b.RPCClient.HeaderByHash(b.Ctx, blockHash.Bytes()) if err != nil { return nil, err } @@ -323,7 +323,7 @@ func (b *Backend) HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) height := resHeader.Header.Height - blockRes, err := b.RpcClient.BlockResults(b.Ctx, &resHeader.Header.Height) + blockRes, err := b.RPCClient.BlockResults(b.Ctx, &resHeader.Header.Height) if err != nil { return nil, errors.Errorf("block result not found for height %d", height) } @@ -468,7 +468,7 @@ func (b *Backend) EthBlockByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Blo return nil, fmt.Errorf("block not found for height %d", blockNum) } - blockRes, err := b.RpcClient.BlockResults(b.Ctx, &resBlock.Block.Height) + blockRes, err := b.RPCClient.BlockResults(b.Ctx, &resBlock.Block.Height) if err != nil { return nil, fmt.Errorf("block result not found for height %d", resBlock.Block.Height) } @@ -530,7 +530,7 @@ func (b *Backend) GetBlockReceipts( return nil, fmt.Errorf("block not found for height %d", *blockNum.TmHeight()) } - blockRes, err := b.RpcClient.BlockResults(b.Ctx, blockNum.TmHeight()) + blockRes, err := b.RPCClient.BlockResults(b.Ctx, blockNum.TmHeight()) if err != nil { return nil, fmt.Errorf("block result not found for height %d", resBlock.Block.Height) } diff --git a/rpc/backend/chain_info.go b/rpc/backend/chain_info.go index 87d662bbf..cd570ed57 100644 --- a/rpc/backend/chain_info.go +++ b/rpc/backend/chain_info.go @@ -201,7 +201,7 @@ func (b *Backend) FeeHistory( } // tendermint block result - tendermintBlockResult, err := b.RpcClient.BlockResults(b.Ctx, &tendermintblock.Block.Height) + tendermintBlockResult, err := b.RPCClient.BlockResults(b.Ctx, &tendermintblock.Block.Height) if tendermintBlockResult == nil { b.Logger.Debug("block result not found", "height", tendermintblock.Block.Height, "error", err.Error()) return nil, err diff --git a/rpc/backend/filters.go b/rpc/backend/filters.go index d5cdc0b2c..715419ffa 100644 --- a/rpc/backend/filters.go +++ b/rpc/backend/filters.go @@ -21,7 +21,7 @@ func (b *Backend) GetLogs(hash common.Hash) ([][]*ethtypes.Log, error) { // GetLogsByHeight returns all the logs from all the ethereum transactions in a block. func (b *Backend) GetLogsByHeight(height *int64) ([][]*ethtypes.Log, error) { // NOTE: we query the state in case the tx result logs are not persisted after an upgrade. - blockRes, err := b.RpcClient.BlockResults(b.Ctx, height) + blockRes, err := b.RPCClient.BlockResults(b.Ctx, height) if err != nil { return nil, err } diff --git a/rpc/backend/tx_info.go b/rpc/backend/tx_info.go index dfa770802..cded70a40 100644 --- a/rpc/backend/tx_info.go +++ b/rpc/backend/tx_info.go @@ -48,7 +48,7 @@ func (b *Backend) GetTransactionByHash(txHash common.Hash) (*rpctypes.RPCTransac return nil, errors.New("invalid ethereum tx") } - blockRes, err := b.RpcClient.BlockResults(b.Ctx, &block.Block.Height) + blockRes, err := b.RPCClient.BlockResults(b.Ctx, &block.Block.Height) if err != nil { b.Logger.Debug("block result not found", "height", block.Block.Height, "error", err.Error()) return nil, nil @@ -171,7 +171,7 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{ } cumulativeGasUsed := uint64(0) - blockRes, err := b.RpcClient.BlockResults(b.Ctx, &res.Height) + blockRes, err := b.RPCClient.BlockResults(b.Ctx, &res.Height) if err != nil { b.Logger.Debug("failed to retrieve block results", "height", res.Height, "error", err.Error()) return nil, nil @@ -296,7 +296,7 @@ func (b *Backend) GetTransactionLogs(hash common.Hash) ([]*ethtypes.Log, error) return nil, nil } - resBlockResult, err := b.RpcClient.BlockResults(b.Ctx, &res.Height) + resBlockResult, err := b.RPCClient.BlockResults(b.Ctx, &res.Height) if err != nil { b.Logger.Debug("block result not found", "number", res.Height, "error", err.Error()) return nil, nil @@ -415,7 +415,7 @@ func (b *Backend) QueryTendermintTxIndexer(query string, txGetter func(*rpctypes // GetTransactionByBlockAndIndex is the common code shared by `GetTransactionByBlockNumberAndIndex` and `GetTransactionByBlockHashAndIndex`. func (b *Backend) GetTransactionByBlockAndIndex(block *tmrpctypes.ResultBlock, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) { - blockRes, err := b.RpcClient.BlockResults(b.Ctx, &block.Block.Height) + blockRes, err := b.RPCClient.BlockResults(b.Ctx, &block.Block.Height) if err != nil { return nil, nil } diff --git a/tests/integration/README.md b/tests/integration/README.md index 0b1eca323..a1d0bab62 100644 --- a/tests/integration/README.md +++ b/tests/integration/README.md @@ -1,16 +1,49 @@ # Integration Test Suite ## Test File Naming Convention -To support external integration testing, all test-related helper files in this module are named using the `test_*.go` prefix instead of the conventional `*_test.go`. -This change is intentional: -In Go, files ending with `*_test.go` are excluded from regular build contexts and only compiled during go test execution. -As a result, such files are not included when **the package is imported by other modules** — for example, when downstream chains want to reuse our EVM test harness. +To support external integration testing, all test-related helper files in this module are named +using the `test_*.go` prefix instead of the conventional `*_test.go`. + +This change is intentional. In Go, files ending with `*_test.go` are excluded from regular build contexts +and only compiled during `go test` execution. +As a result, such files are not included when the package is imported by other modules. +For example, downstream chains cannot reuse our EVM test harness. To work around this, we rename those files to `test_*.go`, which: -- Keeps them recognizable as test helpers, -- Ensures they are compiled as part of the package during regular builds, -- Allows external chains to import and invoke testing utilities like `NewKeeperTestSuite()` or `NewUnitTestNetwork(...)`. -> Note: These files are still test-focused and should not be used in production builds. +- Keeps them recognizable as test helpers + +- Ensures they are compiled as part of the package during regular builds + +- Allows external chains to import and invoke testing utilities like `NewKeeperTestSuite()` or `NewUnitTestNetwork(...)` + +> **Note:** These files are still test-focused and should not be used in production builds. + +## External Client Usage + +All tests defined here can be used by any client application that implements the `EvmApp` interface. +You can find usage examples under `evmd/tests/integration`. + +For instance, if you want to test your own application with the Bank Precompile Integration Test Suite, +implement your own `CreateApp` function and pass it in as shown below: + +```go +package integration + +import ( + "testing" + + "github.com/stretchr/testify/suite" + "github.com/cosmos/evm/tests/integration/precompiles/bank" +) + +func TestBankPrecompileTestSuite(t *testing.T) { + s := bank.NewPrecompileTestSuite(CreateEvmd) + suite.Run(t, s) +} +func TestBankPrecompileIntegrationTestSuite(t *testing.T) { + bank.TestIntegrationSuite(t, CreateEvmd) +} +``` diff --git a/tests/integration/ante/ante_test_suite.go b/tests/integration/ante/ante_test_suite.go index 911f797ea..807f1452c 100644 --- a/tests/integration/ante/ante_test_suite.go +++ b/tests/integration/ante/ante_test_suite.go @@ -22,7 +22,7 @@ import ( const TestGasLimit uint64 = 100000 -type AnteTestSuite struct { +type AnteTestSuite struct { // nolint:revive suite.Suite create network.CreateEvmApp diff --git a/tests/integration/ante/benchmark_evm_antehandler.go b/tests/integration/ante/benchmark_evm_antehandler.go index e30f8cea8..ea2f2ce31 100644 --- a/tests/integration/ante/benchmark_evm_antehandler.go +++ b/tests/integration/ante/benchmark_evm_antehandler.go @@ -59,6 +59,7 @@ var table = []struct { }, } +//nolint:thelper // RunBenchmarkAnteHandler is not a helper function; it's an externally called benchmark entry point func RunBenchmarkAnteHandler(b *testing.B, create network.CreateEvmApp, options ...network.ConfigOption) { keyring := testkeyring.New(2) diff --git a/tests/integration/ante/test_bench_evm_ante.go b/tests/integration/ante/test_bench_evm_ante.go index 1d19b3e06..5b3e6a089 100644 --- a/tests/integration/ante/test_bench_evm_ante.go +++ b/tests/integration/ante/test_bench_evm_ante.go @@ -20,6 +20,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) +//nolint:thelper // RunBenchmarkEthGasConsumeDecorator is not a helper function; it's an externally called benchmark entry point func RunBenchmarkEthGasConsumeDecorator(b *testing.B, create network.CreateEvmApp, options ...network.ConfigOption) { s := NewEvmAnteTestSuite(create, options...) s.SetT(&testing.T{}) diff --git a/tests/integration/ante/test_integration.go b/tests/integration/ante/test_integration.go index adbe1a979..95005afce 100644 --- a/tests/integration/ante/test_integration.go +++ b/tests/integration/ante/test_integration.go @@ -5,10 +5,8 @@ import ( "github.com/stretchr/testify/suite" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" + . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" //nolint:ST1001 // dot imports are fine for Ginkgo testconstants "github.com/cosmos/evm/testutil/constants" commonfactory "github.com/cosmos/evm/testutil/integration/base/factory" diff --git a/tests/integration/ante/test_validate_handler_options.go b/tests/integration/ante/test_validate_handler_options.go index 57d60231c..794748d5c 100644 --- a/tests/integration/ante/test_validate_handler_options.go +++ b/tests/integration/ante/test_validate_handler_options.go @@ -12,6 +12,7 @@ import ( "github.com/cosmos/evm/types" ) +//nolint:thelper // RunValidateHandlerOptionsTest is not a helper function; it's an externally called benchmark entry point func RunValidateHandlerOptionsTest(t *testing.T, create network.CreateEvmApp, options ...network.ConfigOption) { nw := network.NewUnitTestNetwork(create, options...) cases := []struct { diff --git a/tests/integration/eip712/test_eip712.go b/tests/integration/eip712/test_eip712.go index 38f4ad41b..1ee092b45 100644 --- a/tests/integration/eip712/test_eip712.go +++ b/tests/integration/eip712/test_eip712.go @@ -40,7 +40,7 @@ const ( msgsFieldName = "msgs" ) -type EIP712TestSuite struct { +type TestSuite struct { suite.Suite create network.CreateEvmApp @@ -51,15 +51,15 @@ type EIP712TestSuite struct { denom string } -func NewEIP712TestSuite(create network.CreateEvmApp, useLegacyEIP712TypedData bool, options ...network.ConfigOption) *EIP712TestSuite { - return &EIP712TestSuite{ +func NewTestSuite(create network.CreateEvmApp, useLegacyEIP712TypedData bool, options ...network.ConfigOption) *TestSuite { + return &TestSuite{ create: create, useLegacyEIP712TypedData: useLegacyEIP712TypedData, options: options, } } -type EIP712TestParams struct { +type TestParams struct { fee txtypes.Fee address sdk.AccAddress accountNumber uint64 @@ -67,7 +67,7 @@ type EIP712TestParams struct { memo string } -func (suite *EIP712TestSuite) SetupTest() { +func (suite *TestSuite) SetupTest() { nw := network.New(suite.create, suite.options...) suite.config = nw.GetEncodingConfig() suite.clientCtx = client.Context{}.WithTxConfig(suite.config.TxConfig) @@ -77,7 +77,7 @@ func (suite *EIP712TestSuite) SetupTest() { } // createTestAddress creates random test addresses for messages -func (suite *EIP712TestSuite) createTestAddress() sdk.AccAddress { +func (suite *TestSuite) createTestAddress() sdk.AccAddress { privkey, _ := ethsecp256k1.GenerateKey() key, err := privkey.ToECDSA() suite.Require().NoError(err) @@ -88,7 +88,7 @@ func (suite *EIP712TestSuite) createTestAddress() sdk.AccAddress { } // createTestKeyPair creates a random keypair for signing and verification -func (suite *EIP712TestSuite) createTestKeyPair() (*ethsecp256k1.PrivKey, *ethsecp256k1.PubKey) { +func (suite *TestSuite) createTestKeyPair() (*ethsecp256k1.PrivKey, *ethsecp256k1.PubKey) { privKey, err := ethsecp256k1.GenerateKey() suite.Require().NoError(err) @@ -101,7 +101,7 @@ func (suite *EIP712TestSuite) createTestKeyPair() (*ethsecp256k1.PrivKey, *ethse } // makeCoins helps create an instance of sdk.Coins[] with single coin -func (suite *EIP712TestSuite) makeCoins(denom string, amount math.Int) sdk.Coins { +func (suite *TestSuite) makeCoins(denom string, amount math.Int) sdk.Coins { return sdk.NewCoins( sdk.NewCoin( denom, @@ -110,7 +110,7 @@ func (suite *EIP712TestSuite) makeCoins(denom string, amount math.Int) sdk.Coins ) } -func (suite *EIP712TestSuite) TestEIP712() { +func (suite *TestSuite) TestEIP712() { suite.SetupTest() signModes := []signing.SignMode{ @@ -118,7 +118,7 @@ func (suite *EIP712TestSuite) TestEIP712() { signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, } - params := EIP712TestParams{ + params := TestParams{ fee: txtypes.Fee{ Amount: suite.makeCoins(suite.denom, math.NewInt(2000)), GasLimit: 20000, @@ -375,7 +375,7 @@ func (suite *EIP712TestSuite) TestEIP712() { } // verifyEIP712SignatureVerification verifies that the payload passes signature verification if signed as its EIP-712 representation. -func (suite *EIP712TestSuite) verifyEIP712SignatureVerification(expectedSuccess bool, privKey ethsecp256k1.PrivKey, pubKey ethsecp256k1.PubKey, signBytes []byte) { +func (suite *TestSuite) verifyEIP712SignatureVerification(expectedSuccess bool, privKey ethsecp256k1.PrivKey, pubKey ethsecp256k1.PubKey, signBytes []byte) { eip712Bytes, err := eip712.GetEIP712BytesForMsg(signBytes) if suite.useLegacyEIP712TypedData { @@ -412,7 +412,7 @@ func (suite *EIP712TestSuite) verifyEIP712SignatureVerification(expectedSuccess // verifySignDocFlattening tests the flattening algorithm against the sign doc's JSON payload, // using verifyPayloadAgainstFlattened. -func (suite *EIP712TestSuite) verifySignDocFlattening(signDoc []byte) { +func (suite *TestSuite) verifySignDocFlattening(signDoc []byte) { payload := gjson.ParseBytes(signDoc) suite.Require().True(payload.IsObject()) @@ -424,7 +424,7 @@ func (suite *EIP712TestSuite) verifySignDocFlattening(signDoc []byte) { // verifyPayloadAgainstFlattened compares a payload against its flattened counterpart to ensure that // the flattening algorithm behaved as expected. -func (suite *EIP712TestSuite) verifyPayloadAgainstFlattened(payload gjson.Result, flattened gjson.Result) { +func (suite *TestSuite) verifyPayloadAgainstFlattened(payload gjson.Result, flattened gjson.Result) { payloadMap, ok := payload.Value().(map[string]interface{}) suite.Require().True(ok) flattenedMap, ok := flattened.Value().(map[string]interface{}) @@ -435,7 +435,7 @@ func (suite *EIP712TestSuite) verifyPayloadAgainstFlattened(payload gjson.Result // verifyPayloadMapAgainstFlattenedMap directly compares two JSON maps in Go representations to // test flattening. -func (suite *EIP712TestSuite) verifyPayloadMapAgainstFlattenedMap(original map[string]interface{}, flattened map[string]interface{}) { +func (suite *TestSuite) verifyPayloadMapAgainstFlattenedMap(original map[string]interface{}, flattened map[string]interface{}) { interfaceMessages, ok := original[msgsFieldName] suite.Require().True(ok) @@ -482,7 +482,7 @@ func (suite *EIP712TestSuite) verifyPayloadMapAgainstFlattenedMap(original map[s } // verifyBasicTypedData performs basic verification on the TypedData generation. -func (suite *EIP712TestSuite) verifyBasicTypedData(signDoc []byte) { +func (suite *TestSuite) verifyBasicTypedData(signDoc []byte) { typedData, err := eip712.GetEIP712TypedDataForMsg(signDoc) suite.Require().NoError(err) @@ -502,7 +502,7 @@ func (suite *EIP712TestSuite) verifyBasicTypedData(signDoc []byte) { // TestFlattenPayloadErrorHandling tests error handling in TypedData generation, // specifically regarding the payload. -func (suite *EIP712TestSuite) TestFlattenPayloadErrorHandling() { +func (suite *TestSuite) TestFlattenPayloadErrorHandling() { // No msgs _, _, err := eip712.FlattenPayloadMessages(gjson.Parse("")) suite.Require().ErrorContains(err, "no messages found") @@ -524,7 +524,7 @@ func (suite *EIP712TestSuite) TestFlattenPayloadErrorHandling() { // TestTypedDataErrorHandling tests error handling for TypedData generation // in the main algorithm. -func (suite *EIP712TestSuite) TestTypedDataErrorHandling() { +func (suite *TestSuite) TestTypedDataErrorHandling() { // Empty JSON _, err := eip712.WrapTxToTypedData(0, make([]byte, 0)) suite.Require().ErrorContains(err, "invalid JSON") @@ -555,7 +555,7 @@ func (suite *EIP712TestSuite) TestTypedDataErrorHandling() { // TestTypedDataEdgeCases tests certain interesting edge cases to ensure that they work // (or don't work) as expected. -func (suite *EIP712TestSuite) TestTypedDataEdgeCases() { +func (suite *TestSuite) TestTypedDataEdgeCases() { // Type without '/' separator typedData, err := eip712.WrapTxToTypedData(0, []byte(gjson.Parse(`{"msgs": [{ "type": "MsgSend", "value": { "field": 10 } }] }`).Raw)) suite.Require().NoError(err) @@ -606,7 +606,7 @@ func (suite *EIP712TestSuite) TestTypedDataEdgeCases() { } // TestTypedDataGeneration tests certain qualities about the output Types representation. -func (suite *EIP712TestSuite) TestTypedDataGeneration() { +func (suite *TestSuite) TestTypedDataGeneration() { // Multiple messages with the same schema should share one type payloadRaw := `{ "msgs": [{ "type": "msgType", "value": { "field1": 10 }}, { "type": "msgType", "value": { "field1": 20 }}] }` diff --git a/tests/integration/eip712/test_eip712_fuzzer.go b/tests/integration/eip712/test_eip712_fuzzer.go index fbb99b0e2..4ef187715 100644 --- a/tests/integration/eip712/test_eip712_fuzzer.go +++ b/tests/integration/eip712/test_eip712_fuzzer.go @@ -54,7 +54,7 @@ var params = EIP712FuzzTestParams{ // variable input sizes, types, and fields. While it may be possible to translate a single input into // a JSON object, it would require difficult parsing, and ultimately approximates our randomized unit // tests as they are. -func (suite *EIP712TestSuite) TestRandomPayloadFlattening() { +func (suite *TestSuite) TestRandomPayloadFlattening() { // Re-seed rand generator rand.Seed(rand.Int64()) @@ -73,7 +73,7 @@ func (suite *EIP712TestSuite) TestRandomPayloadFlattening() { } // generateRandomPayload creates a random payload of the desired format, with random sub-objects. -func (suite *EIP712TestSuite) generateRandomPayload(numMessages int) gjson.Result { +func (suite *TestSuite) generateRandomPayload(numMessages int) gjson.Result { payload := suite.createRandomJSONObject().Raw msgs := make([]gjson.Result, numMessages) @@ -88,7 +88,7 @@ func (suite *EIP712TestSuite) generateRandomPayload(numMessages int) gjson.Resul } // createRandomJSONObject creates a JSON object with random fields. -func (suite *EIP712TestSuite) createRandomJSONObject() gjson.Result { +func (suite *TestSuite) createRandomJSONObject() gjson.Result { var err error payloadRaw := "" @@ -106,7 +106,7 @@ func (suite *EIP712TestSuite) createRandomJSONObject() gjson.Result { // createRandomJSONField creates a random field with a random JSON type, with the possibility of // nested fields up to depth objects. -func (suite *EIP712TestSuite) createRandomJSONField(t int, depth int) interface{} { +func (suite *TestSuite) createRandomJSONField(t int, depth int) interface{} { switch t % numJSONTypes { case jsonBoolType: return suite.createRandomBoolean() @@ -124,7 +124,7 @@ func (suite *EIP712TestSuite) createRandomJSONField(t int, depth int) interface{ } // createRandomJSONNestedArray creates an array of random nested JSON fields. -func (suite *EIP712TestSuite) createRandomJSONNestedArray(depth int) []interface{} { +func (suite *TestSuite) createRandomJSONNestedArray(depth int) []interface{} { arr := make([]interface{}, rand.Intn(params.maxArrayLength)) for i := range arr { arr[i] = suite.createRandomJSONNestedField(depth) @@ -134,7 +134,7 @@ func (suite *EIP712TestSuite) createRandomJSONNestedArray(depth int) []interface } // createRandomJSONNestedObject creates a key-value set of objects with random nested JSON fields. -func (suite *EIP712TestSuite) createRandomJSONNestedObject(depth int) interface{} { +func (suite *TestSuite) createRandomJSONNestedObject(depth int) interface{} { numFields := rand.Intn(params.maxNumFieldsPerObject) obj := make(map[string]interface{}) @@ -149,7 +149,7 @@ func (suite *EIP712TestSuite) createRandomJSONNestedObject(depth int) interface{ // createRandomJSONNestedField serves as a helper for createRandomJSONField and returns a random // subfield to populate an array or object type. -func (suite *EIP712TestSuite) createRandomJSONNestedField(depth int) interface{} { +func (suite *TestSuite) createRandomJSONNestedField(depth int) interface{} { var newFieldType int if depth == params.maxObjectDepth { @@ -161,15 +161,15 @@ func (suite *EIP712TestSuite) createRandomJSONNestedField(depth int) interface{} return suite.createRandomJSONField(newFieldType, depth+1) } -func (suite *EIP712TestSuite) createRandomBoolean() bool { +func (suite *TestSuite) createRandomBoolean() bool { return rand.Intn(2) == 0 } -func (suite *EIP712TestSuite) createRandomFloat() float64 { +func (suite *TestSuite) createRandomFloat() float64 { return (rand.Float64() - 0.5) * params.randomFloatRange } -func (suite *EIP712TestSuite) createRandomString() string { +func (suite *TestSuite) createRandomString() string { bzLen := suite.createRandomIntInRange(params.minStringLength, params.maxStringLength) bz := make([]byte, bzLen) @@ -189,6 +189,6 @@ func (suite *EIP712TestSuite) createRandomString() string { } // createRandomIntInRange provides a random integer between [min, max) -func (suite *EIP712TestSuite) createRandomIntInRange(minInt int, maxInt int) int { +func (suite *TestSuite) createRandomIntInRange(minInt int, maxInt int) int { return rand.Intn(maxInt-minInt) + minInt } diff --git a/tests/integration/eips/test_eips.go b/tests/integration/eips/test_eips.go index 0ad39b11c..a51db6dba 100644 --- a/tests/integration/eips/test_eips.go +++ b/tests/integration/eips/test_eips.go @@ -10,10 +10,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/params" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" + . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" //nolint:ST1001 // dot imports are fine for Ginkgo "github.com/cosmos/evm/testutil/integration/evm/factory" "github.com/cosmos/evm/testutil/integration/evm/grpc" @@ -34,7 +32,7 @@ import ( // the EIP. func TestEIPs(t *testing.T, create network.CreateEvmApp, options ...network.ConfigOption) { - var _ = Describe("EIP-0000 - ", Ordered, func() { + _ = Describe("EIP-0000 - ", Ordered, func() { var ( in network.Network tf factory.TxFactory @@ -145,12 +143,12 @@ func TestEIPs(t *testing.T, create network.CreateEvmApp, options ...network.Conf // The difference in gas is the new cost of the opcode, minus the cost of the // opcode before enabling the new eip. gasUsedDiff := eipMultiplier*gasCostPre - gasCostPre - expectedGas := gasUsedPre + int64(gasUsedDiff) + expectedGas := gasUsedPre + int64(gasUsedDiff) //#nosec G115 -- int overflow is not a concern here Expect(gasUsedPost).To(Equal(expectedGas)) }) }) - var _ = Describe("EIP0001 - ", Ordered, func() { + _ = Describe("EIP0001 - ", Ordered, func() { var ( in network.Network tf factory.TxFactory @@ -324,12 +322,12 @@ func TestEIPs(t *testing.T, create network.CreateEvmApp, options ...network.Conf // The difference in gas is the new cost of the opcode, minus the cost of the // opcode before enabling the new eip. gasUsedDiff := eipMultiplier*gasCostPre - gasCostPre - expectedGas := gasUsedPre + int64(gasUsedDiff) + expectedGas := gasUsedPre + int64(gasUsedDiff) //#nosec G115 -- int overflow is not a concern here Expect(gasUsedPost).To(Equal(expectedGas)) }) }) - var _ = Describe("EIP0002 - ", Ordered, func() { + _ = Describe("EIP0002 - ", Ordered, func() { var ( in network.Network tf factory.TxFactory @@ -435,7 +433,7 @@ func TestEIPs(t *testing.T, create network.CreateEvmApp, options ...network.Conf // The expected gas is previous gas plus the constant gas because // previous this eip, SSTORE was using only the dynamic gas. - expectedGas := gasUsedPre + int64(constantGas) + expectedGas := gasUsedPre + int64(constantGas) //#nosec G115 -- int overflow is not a concern here Expect(gasUsedPost).To(Equal(expectedGas)) }) }) diff --git a/tests/integration/ledger/evmosd_suite_test.go b/tests/integration/ledger/evmosd_suite_test.go index a69640d52..f3906534e 100644 --- a/tests/integration/ledger/evmosd_suite_test.go +++ b/tests/integration/ledger/evmosd_suite_test.go @@ -13,10 +13,8 @@ import ( "github.com/spf13/cobra" "github.com/stretchr/testify/suite" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" + . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" //nolint:ST1001 // dot imports are fine for Ginkgo "github.com/cometbft/cometbft/crypto/tmhash" tmproto "github.com/cometbft/cometbft/proto/tendermint/types" diff --git a/tests/integration/ledger/ledger_test.go b/tests/integration/ledger/ledger_test.go index a916fa010..d88ef6b7e 100644 --- a/tests/integration/ledger/ledger_test.go +++ b/tests/integration/ledger/ledger_test.go @@ -6,8 +6,7 @@ import ( "github.com/spf13/cobra" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo "github.com/cosmos/evm/crypto/hd" "github.com/cosmos/evm/encoding" diff --git a/tests/integration/precompiles/bank/test_integration.go b/tests/integration/precompiles/bank/test_integration.go index 84fab9b4c..65cf8001e 100644 --- a/tests/integration/precompiles/bank/test_integration.go +++ b/tests/integration/precompiles/bank/test_integration.go @@ -7,10 +7,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/suite" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" + . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" //nolint:ST1001 // dot imports are fine for Ginkgo bank2 "github.com/cosmos/evm/precompiles/bank" "github.com/cosmos/evm/precompiles/bank/testdata" @@ -30,8 +28,6 @@ import ( minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" ) -var is *IntegrationTestSuite - // IntegrationTestSuite is the implementation of the TestSuite interface for Bank precompile // unit testis. type IntegrationTestSuite struct { @@ -107,7 +103,7 @@ func (is *IntegrationTestSuite) SetupTest() { func TestIntegrationSuite(t *testing.T, create network.CreateEvmApp, options ...network.ConfigOption) { var is *IntegrationTestSuite - var _ = Describe("Bank Extension -", func() { + _ = Describe("Bank Extension -", func() { var ( bankCallerContractAddr common.Address bankCallerContract evmtypes.CompiledContract diff --git a/tests/integration/precompiles/bank/test_setup.go b/tests/integration/precompiles/bank/test_setup.go index ab8fc6b6c..cd7127bac 100644 --- a/tests/integration/precompiles/bank/test_setup.go +++ b/tests/integration/precompiles/bank/test_setup.go @@ -17,8 +17,6 @@ import ( minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" ) -var s *PrecompileTestSuite - // PrecompileTestSuite is the implementation of the TestSuite interface for ERC20 precompile // unit tests. type PrecompileTestSuite struct { diff --git a/tests/integration/precompiles/bech32/test_setup.go b/tests/integration/precompiles/bech32/test_setup.go index 53b47b3b9..8b2cc201e 100644 --- a/tests/integration/precompiles/bech32/test_setup.go +++ b/tests/integration/precompiles/bech32/test_setup.go @@ -8,8 +8,6 @@ import ( testkeyring "github.com/cosmos/evm/testutil/keyring" ) -var s *PrecompileTestSuite - // PrecompileTestSuite is the implementation of the TestSuite interface for ERC20 precompile // unit tests. type PrecompileTestSuite struct { diff --git a/tests/integration/precompiles/distribution/test_integration.go b/tests/integration/precompiles/distribution/test_integration.go index a19e60035..6e21c8317 100644 --- a/tests/integration/precompiles/distribution/test_integration.go +++ b/tests/integration/precompiles/distribution/test_integration.go @@ -7,10 +7,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" + . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" //nolint:ST1001 // dot imports are fine for Ginkgo cmn "github.com/cosmos/evm/precompiles/common" "github.com/cosmos/evm/precompiles/distribution" @@ -55,7 +53,7 @@ var ( ) func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmApp, options ...network.ConfigOption) { - var _ = Describe("Calling distribution precompile from EOA", func() { + _ = Describe("Calling distribution precompile from EOA", func() { s := NewPrecompileTestSuite(create, options...) BeforeEach(func() { @@ -605,7 +603,7 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp valCount := len(s.network.GetValidators()) callArgs.Args = []interface{}{ - s.keyring.GetAddr(0), uint32(valCount), + s.keyring.GetAddr(0), uint32(valCount), //#nosec G115 -- int overflow is not a concern here } txArgs.GasLimit = 250_000 @@ -1293,7 +1291,7 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp }) }) }) - var _ = Describe("Calling distribution precompile from contract", Ordered, func() { + _ = Describe("Calling distribution precompile from contract", Ordered, func() { s := NewPrecompileTestSuite(create, options...) // testCase is a struct used for cases of contracts calls that have some operation // performed before and/or after the precompile call diff --git a/tests/integration/precompiles/erc20/test_integration.go b/tests/integration/precompiles/erc20/test_integration.go index a5c6b8708..09e426eda 100644 --- a/tests/integration/precompiles/erc20/test_integration.go +++ b/tests/integration/precompiles/erc20/test_integration.go @@ -12,10 +12,8 @@ import ( "github.com/ethereum/go-ethereum/core/vm" "github.com/stretchr/testify/suite" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" + . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" //nolint:ST1001 // dot imports are fine for Ginkgo "github.com/cosmos/evm/contracts" "github.com/cosmos/evm/precompiles/erc20" @@ -104,7 +102,7 @@ var ( func TestIntegrationTestSuite(t *testing.T, create network.CreateEvmApp, options ...network.ConfigOption) { is = NewIntegrationTestSuite(create, options...) - var _ = Describe("ERC20 Extension -", func() { + _ = Describe("ERC20 Extension -", func() { var ( // contractsData holds the addresses and ABIs for the different // contract instances that are subject to testing here. @@ -2656,7 +2654,7 @@ func TestIntegrationTestSuite(t *testing.T, create network.CreateEvmApp, options }) }) }) - var _ = Describe("ERC20 Extension migration Flows -", func() { + _ = Describe("ERC20 Extension migration Flows -", func() { When("migrating an existing ERC20 token", func() { var ( contractData ContractsData diff --git a/tests/integration/precompiles/erc20/test_setup.go b/tests/integration/precompiles/erc20/test_setup.go index 6348ce493..40e4fb238 100644 --- a/tests/integration/precompiles/erc20/test_setup.go +++ b/tests/integration/precompiles/erc20/test_setup.go @@ -10,8 +10,6 @@ import ( testkeyring "github.com/cosmos/evm/testutil/keyring" ) -var s *PrecompileTestSuite - // PrecompileTestSuite is the implementation of the TestSuite interface for ERC20 precompile // unit tests. type PrecompileTestSuite struct { diff --git a/tests/integration/precompiles/gov/test_integration.go b/tests/integration/precompiles/gov/test_integration.go index 5393ee9ec..2a0c9aae5 100644 --- a/tests/integration/precompiles/gov/test_integration.go +++ b/tests/integration/precompiles/gov/test_integration.go @@ -8,10 +8,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" + . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" //nolint:ST1001 // dot imports are fine for Ginkgo cmn "github.com/cosmos/evm/precompiles/common" "github.com/cosmos/evm/precompiles/gov" @@ -59,7 +57,7 @@ const ( ) func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmApp, options ...network.ConfigOption) { - var _ = Describe("Calling governance precompile from EOA", func() { + _ = Describe("Calling governance precompile from EOA", func() { var ( s *PrecompileTestSuite proposerKey types.PrivKey @@ -992,7 +990,7 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp }) }) }) - var _ = Describe("Calling governance precompile from contract", Ordered, func() { + _ = Describe("Calling governance precompile from contract", Ordered, func() { s := NewPrecompileTestSuite(create, options...) // testCase is a struct used for cases of contracts calls that have some operation // performed before and/or after the precompile call diff --git a/tests/integration/precompiles/p256/test_integration.go b/tests/integration/precompiles/p256/test_integration.go index 8c4302d76..e05b4c90c 100644 --- a/tests/integration/precompiles/p256/test_integration.go +++ b/tests/integration/precompiles/p256/test_integration.go @@ -8,10 +8,8 @@ import ( "github.com/ethereum/go-ethereum/common" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" + . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" //nolint:ST1001 // dot imports are fine for Ginkgo "github.com/cometbft/cometbft/crypto" @@ -33,7 +31,7 @@ type IntegrationTestSuite struct { } func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmApp, options ...network.ConfigOption) { - var _ = Describe("Calling p256 precompile directly", Label("P256 Precompile"), Ordered, func() { + _ = Describe("Calling p256 precompile directly", Label("P256 Precompile"), Ordered, func() { var s *IntegrationTestSuite BeforeAll(func() { @@ -89,7 +87,8 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp Entry( "valid signature", func() (input, expOutput []byte, expErr string) { - input = signMsg(t, []byte("hello world"), s.p256Priv) + input, err := signMsg([]byte("hello world"), s.p256Priv) + Expect(err).To(BeNil()) return input, trueValue, "" }, ), @@ -148,7 +147,8 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp Entry( "valid signature", func() (input []byte) { - input = signMsg(t, []byte("hello world"), s.p256Priv) + input, err := signMsg([]byte("hello world"), s.p256Priv) + Expect(err).To(BeNil()) return input }, ), diff --git a/tests/integration/precompiles/p256/test_setup.go b/tests/integration/precompiles/p256/test_setup.go index 683cfb71d..f2cd20426 100644 --- a/tests/integration/precompiles/p256/test_setup.go +++ b/tests/integration/precompiles/p256/test_setup.go @@ -5,8 +5,6 @@ import ( "crypto/elliptic" "crypto/rand" "errors" - "testing" - "github.com/stretchr/testify/suite" "golang.org/x/crypto/cryptobyte" "golang.org/x/crypto/cryptobyte/asn1" @@ -17,8 +15,6 @@ import ( "github.com/cosmos/evm/testutil/integration/evm/network" ) -var s *PrecompileTestSuite - type PrecompileTestSuite struct { suite.Suite @@ -41,12 +37,13 @@ func (s *PrecompileTestSuite) SetupTest() { s.precompile = &p256.Precompile{} } -func signMsg(t *testing.T, msg []byte, priv *ecdsa.PrivateKey) []byte { +// nolint:thelper +func signMsg(msg []byte, priv *ecdsa.PrivateKey) ([]byte, error) { hash := crypto.Sha256(msg) rInt, sInt, err := ecdsa.Sign(rand.Reader, priv, hash) if err != nil { - t.Fatalf("failed to sign message: %v", err) + return nil, err } input := make([]byte, p256.VerifyInputLength) @@ -56,7 +53,7 @@ func signMsg(t *testing.T, msg []byte, priv *ecdsa.PrivateKey) []byte { copy(input[96:128], priv.PublicKey.X.Bytes()) copy(input[128:160], priv.PublicKey.Y.Bytes()) - return input + return input, nil } func parseSignature(sig []byte) (r, s []byte, err error) { diff --git a/tests/integration/precompiles/staking/test_integration.go b/tests/integration/precompiles/staking/test_integration.go index cccdc4542..b1696d4ec 100644 --- a/tests/integration/precompiles/staking/test_integration.go +++ b/tests/integration/precompiles/staking/test_integration.go @@ -8,10 +8,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" + . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" //nolint:ST1001 // dot imports are fine for Ginkgo compiledcontracts "github.com/cosmos/evm/contracts" "github.com/cosmos/evm/crypto/ethsecp256k1" @@ -54,7 +52,7 @@ var ( ) func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmApp, options ...network.ConfigOption) { - var _ = Describe("Calling staking precompile directly", func() { + _ = Describe("Calling staking precompile directly", func() { // s is the precompile test suite to use for the tests var s *PrecompileTestSuite @@ -1194,7 +1192,7 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp Expect(redelOut.PageResponse.NextKey).To(BeEmpty()) Expect(redelOut.PageResponse.Total).To(Equal(redelTotalCount)) - Expect(redelOut.Response).To(HaveLen(int(redelTotalCount)), "expected two redelegations to be returned") + Expect(redelOut.Response).To(HaveLen(int(redelTotalCount)), "expected two redelegations to be returned") //#nosec G115 -- int overflow is not a concern here // return order can change redOrder := []int{0, 1} if len(redelOut.Response[0].Entries) == 2 { @@ -1339,7 +1337,7 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp Expect(difference.Amount.Int64()).To(Equal(expDifference), "expected different total transaction cost") }) }) - var _ = Describe("Calling staking precompile via Solidity", Ordered, func() { + _ = Describe("Calling staking precompile via Solidity", Ordered, func() { var ( // s is the precompile test suite to use for the tests s *PrecompileTestSuite @@ -3085,7 +3083,7 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp // // There are ERC20 tokens minted to the address of the deployed StakingCaller contract, // which will transfer these to the message sender when successfully executed. - var _ = Describe("Batching cosmos and eth interactions", func() { + _ = Describe("Batching cosmos and eth interactions", func() { const ( erc20Name = "Test" erc20Token = "TTT" diff --git a/tests/integration/precompiles/staking/test_setup.go b/tests/integration/precompiles/staking/test_setup.go index 522a7a71f..6c0e8da7a 100644 --- a/tests/integration/precompiles/staking/test_setup.go +++ b/tests/integration/precompiles/staking/test_setup.go @@ -53,14 +53,14 @@ func (s *PrecompileTestSuite) SetupTest() { bankGenesis := banktypes.DefaultGenesisState() bankGenesis.Balances = balances customGenesis[banktypes.ModuleName] = bankGenesis - cfgOpts := []network.ConfigOption{ + opts := []network.ConfigOption{ network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), } if s.customGenesis { - cfgOpts = append(cfgOpts, network.WithCustomGenesis(customGenesis)) + opts = append(opts, network.WithCustomGenesis(customGenesis)) } - options := append(s.options, cfgOpts...) - nw := network.NewUnitTestNetwork(s.create, options...) + opts = append(opts, s.options...) + nw := network.NewUnitTestNetwork(s.create, opts...) grpcHandler := grpc.NewIntegrationHandler(nw) txFactory := factory.New(nw, grpcHandler) diff --git a/tests/integration/precompiles/werc20/test_integration.go b/tests/integration/precompiles/werc20/test_integration.go index bf0285cc9..c44240f76 100644 --- a/tests/integration/precompiles/werc20/test_integration.go +++ b/tests/integration/precompiles/werc20/test_integration.go @@ -6,10 +6,8 @@ import ( "github.com/ethereum/go-ethereum/common" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" + . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" //nolint:ST1001 // dot imports are fine for Ginkgo "github.com/cosmos/evm/precompiles/erc20" "github.com/cosmos/evm/precompiles/testutil" @@ -36,7 +34,6 @@ import ( // ------------------------------------------------------------------------------------------------- type PrecompileIntegrationTestSuite struct { - create network.CreateEvmApp network *network.UnitTestNetwork factory factory.TxFactory grpcHandler grpc.Handler @@ -50,7 +47,7 @@ type PrecompileIntegrationTestSuite struct { } func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmApp, options ...network.ConfigOption) { - var _ = When("a user interact with the WEVMOS precompiled contract", func() { + _ = When("a user interact with the WEVMOS precompiled contract", func() { var ( is *PrecompileIntegrationTestSuite passCheck, failCheck testutil.LogCheckArgs diff --git a/tests/integration/rpc/backend/test_account_info.go b/tests/integration/rpc/backend/test_account_info.go index 52d948829..220472807 100644 --- a/tests/integration/rpc/backend/test_account_info.go +++ b/tests/integration/rpc/backend/test_account_info.go @@ -19,7 +19,7 @@ import ( authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) -func (s *BackendTestSuite) TestGetCode() { +func (s *TestSuite) TestGetCode() { blockNr := rpctypes.NewBlockNumber(big.NewInt(1)) contractCode := []byte("0xef616c92f3cfc9e92dc270d6acff9cea213cecc7020a76ee4395af09bdceb4837a1ebdb5735e11e7d3adb6104e0c3ac55180b4ddf5e54d022cc5e8837f6a4f971b") @@ -78,7 +78,7 @@ func (s *BackendTestSuite) TestGetCode() { } } -func (s *BackendTestSuite) TestGetProof() { +func (s *TestSuite) TestGetProof() { blockNrInvalid := rpctypes.NewBlockNumber(big.NewInt(1)) blockNr := rpctypes.NewBlockNumber(big.NewInt(4)) address1 := utiltx.GenerateAddress() @@ -185,7 +185,7 @@ func (s *BackendTestSuite) TestGetProof() { } } -func (s *BackendTestSuite) TestGetStorageAt() { +func (s *TestSuite) TestGetStorageAt() { blockNr := rpctypes.NewBlockNumber(big.NewInt(1)) testCases := []struct { @@ -247,7 +247,7 @@ func (s *BackendTestSuite) TestGetStorageAt() { } } -func (s *BackendTestSuite) TestGetBalance() { +func (s *TestSuite) TestGetBalance() { blockNr := rpctypes.NewBlockNumber(big.NewInt(1)) testCases := []struct { @@ -355,7 +355,7 @@ func (s *BackendTestSuite) TestGetBalance() { } } -func (s *BackendTestSuite) TestGetTransactionCount() { +func (s *TestSuite) TestGetTransactionCount() { testCases := []struct { name string accExists bool diff --git a/tests/integration/rpc/backend/test_backend_suite.go b/tests/integration/rpc/backend/test_backend_suite.go index 10b92ba36..ab4fdb2e9 100644 --- a/tests/integration/rpc/backend/test_backend_suite.go +++ b/tests/integration/rpc/backend/test_backend_suite.go @@ -31,7 +31,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -type BackendTestSuite struct { +type TestSuite struct { suite.Suite create network.CreateEvmApp @@ -42,8 +42,8 @@ type BackendTestSuite struct { signer keyring.Signer } -func NewBackendTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *BackendTestSuite { - return &BackendTestSuite{ +func NewTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *TestSuite { + return &TestSuite{ create: create, options: options, } @@ -51,8 +51,8 @@ func NewBackendTestSuite(create network.CreateEvmApp, options ...network.ConfigO var ChainID = constants.ExampleChainID -// SetupTest is executed before every BackendTestSuite test -func (s *BackendTestSuite) SetupTest() { +// SetupTest is executed before every TestSuite test +func (s *TestSuite) SetupTest() { ctx := server.NewDefaultContext() ctx.Viper.Set("telemetry.global-labels", []interface{}{}) ctx.Viper.Set("evm.evm-chain-id", evmdconfig.EVMChainID) @@ -106,7 +106,7 @@ func (s *BackendTestSuite) SetupTest() { } // buildEthereumTx returns an example legacy Ethereum transaction -func (s *BackendTestSuite) buildEthereumTx() (*evmtypes.MsgEthereumTx, []byte) { +func (s *TestSuite) buildEthereumTx() (*evmtypes.MsgEthereumTx, []byte) { ethTxParams := evmtypes.EvmTxArgs{ ChainID: s.backend.EvmChainID, Nonce: uint64(0), @@ -130,7 +130,7 @@ func (s *BackendTestSuite) buildEthereumTx() (*evmtypes.MsgEthereumTx, []byte) { } // buildEthereumTx returns an example legacy Ethereum transaction -func (s *BackendTestSuite) buildEthereumTxWithChainID(eip155ChainID *big.Int) *evmtypes.MsgEthereumTx { +func (s *TestSuite) buildEthereumTxWithChainID(eip155ChainID *big.Int) *evmtypes.MsgEthereumTx { ethTxParams := evmtypes.EvmTxArgs{ ChainID: eip155ChainID, Nonce: uint64(0), @@ -152,7 +152,7 @@ func (s *BackendTestSuite) buildEthereumTxWithChainID(eip155ChainID *big.Int) *e } // buildFormattedBlock returns a formatted block for testing -func (s *BackendTestSuite) buildFormattedBlock( +func (s *TestSuite) buildFormattedBlock( blockRes *cmtrpctypes.ResultBlockResults, resBlock *cmtrpctypes.ResultBlock, fullTx bool, @@ -198,13 +198,13 @@ func (s *BackendTestSuite) buildFormattedBlock( ) } -func (s *BackendTestSuite) generateTestKeyring(clientDir string) (keyring.Keyring, error) { +func (s *TestSuite) generateTestKeyring(clientDir string) (keyring.Keyring, error) { buf := bufio.NewReader(os.Stdin) encCfg := encoding.MakeConfig(evmdconfig.EVMChainID) return keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, clientDir, buf, encCfg.Codec, []keyring.Option{hd.EthSecp256k1Option()}...) } -func (s *BackendTestSuite) signAndEncodeEthTx(msgEthereumTx *evmtypes.MsgEthereumTx) []byte { +func (s *TestSuite) signAndEncodeEthTx(msgEthereumTx *evmtypes.MsgEthereumTx) []byte { from, priv := utiltx.NewAddrKey() signer := utiltx.NewSigner(priv) diff --git a/tests/integration/rpc/backend/test_blocks.go b/tests/integration/rpc/backend/test_blocks.go index ef6603bb7..095dd5a32 100644 --- a/tests/integration/rpc/backend/test_blocks.go +++ b/tests/integration/rpc/backend/test_blocks.go @@ -24,7 +24,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -func (s *BackendTestSuite) TestBlockNumber() { +func (s *TestSuite) TestBlockNumber() { testCases := []struct { name string registerMock func() @@ -82,7 +82,7 @@ func (s *BackendTestSuite) TestBlockNumber() { } } -func (s *BackendTestSuite) TestGetBlockByNumber() { +func (s *TestSuite) TestGetBlockByNumber() { var ( blockRes *cmtrpctypes.ResultBlockResults resBlock *cmtrpctypes.ResultBlock @@ -225,7 +225,7 @@ func (s *BackendTestSuite) TestGetBlockByNumber() { } } -func (s *BackendTestSuite) TestGetBlockByHash() { +func (s *TestSuite) TestGetBlockByHash() { var ( blockRes *cmtrpctypes.ResultBlockResults resBlock *cmtrpctypes.ResultBlock @@ -371,7 +371,7 @@ func (s *BackendTestSuite) TestGetBlockByHash() { } } -func (s *BackendTestSuite) TestGetBlockTransactionCountByHash() { +func (s *TestSuite) TestGetBlockTransactionCountByHash() { _, bz := s.buildEthereumTx() block := cmttypes.MakeBlock(1, []cmttypes.Tx{bz}, nil, nil) emptyBlock := cmttypes.MakeBlock(1, []cmttypes.Tx{}, nil, nil) @@ -450,7 +450,7 @@ func (s *BackendTestSuite) TestGetBlockTransactionCountByHash() { } } -func (s *BackendTestSuite) TestGetBlockTransactionCountByNumber() { +func (s *TestSuite) TestGetBlockTransactionCountByNumber() { _, bz := s.buildEthereumTx() block := cmttypes.MakeBlock(1, []cmttypes.Tx{bz}, nil, nil) emptyBlock := cmttypes.MakeBlock(1, []cmttypes.Tx{}, nil, nil) @@ -530,7 +530,7 @@ func (s *BackendTestSuite) TestGetBlockTransactionCountByNumber() { } } -func (s *BackendTestSuite) TestTendermintBlockByNumber() { +func (s *TestSuite) TestTendermintBlockByNumber() { var expResultBlock *cmtrpctypes.ResultBlock testCases := []struct { @@ -637,7 +637,7 @@ func (s *BackendTestSuite) TestTendermintBlockByNumber() { } } -func (s *BackendTestSuite) TestTendermintBlockResultByNumber() { +func (s *TestSuite) TestTendermintBlockResultByNumber() { var expBlockRes *cmtrpctypes.ResultBlockResults testCases := []struct { @@ -688,7 +688,7 @@ func (s *BackendTestSuite) TestTendermintBlockResultByNumber() { } } -func (s *BackendTestSuite) TestBlockNumberFromTendermint() { +func (s *TestSuite) TestBlockNumberFromTendermint() { var resHeader *cmtrpctypes.ResultHeader _, bz := s.buildEthereumTx() @@ -765,7 +765,7 @@ func (s *BackendTestSuite) TestBlockNumberFromTendermint() { } } -func (s *BackendTestSuite) TestBlockNumberFromTendermintByHash() { +func (s *TestSuite) TestBlockNumberFromTendermintByHash() { var resHeader *cmtrpctypes.ResultHeader _, bz := s.buildEthereumTx() @@ -823,7 +823,7 @@ func (s *BackendTestSuite) TestBlockNumberFromTendermintByHash() { } } -func (s *BackendTestSuite) TestBlockBloom() { +func (s *TestSuite) TestBlockBloom() { testCases := []struct { name string blockRes *cmtrpctypes.ResultBlockResults @@ -889,7 +889,7 @@ func (s *BackendTestSuite) TestBlockBloom() { } } -func (s *BackendTestSuite) TestGetEthBlockFromTendermint() { +func (s *TestSuite) TestGetEthBlockFromTendermint() { msgEthereumTx, bz := s.buildEthereumTx() emptyBlock := cmttypes.MakeBlock(1, []cmttypes.Tx{}, nil, nil) @@ -1134,7 +1134,7 @@ func (s *BackendTestSuite) TestGetEthBlockFromTendermint() { } } -func (s *BackendTestSuite) TestEthMsgsFromTendermintBlock() { +func (s *TestSuite) TestEthMsgsFromTendermintBlock() { msgEthereumTx, bz := s.buildEthereumTx() testCases := []struct { @@ -1198,7 +1198,7 @@ func (s *BackendTestSuite) TestEthMsgsFromTendermintBlock() { } } -func (s *BackendTestSuite) TestHeaderByNumber() { +func (s *TestSuite) TestHeaderByNumber() { var expResultBlock *cmtrpctypes.ResultBlock _, bz := s.buildEthereumTx() @@ -1310,7 +1310,7 @@ func (s *BackendTestSuite) TestHeaderByNumber() { } } -func (s *BackendTestSuite) TestHeaderByHash() { +func (s *TestSuite) TestHeaderByHash() { var expResultHeader *cmtrpctypes.ResultHeader _, bz := s.buildEthereumTx() @@ -1421,7 +1421,7 @@ func (s *BackendTestSuite) TestHeaderByHash() { } } -func (s *BackendTestSuite) TestEthBlockByNumber() { +func (s *TestSuite) TestEthBlockByNumber() { msgEthereumTx, bz := s.buildEthereumTx() emptyBlock := cmttypes.MakeBlock(1, []cmttypes.Tx{}, nil, nil) @@ -1534,7 +1534,7 @@ func (s *BackendTestSuite) TestEthBlockByNumber() { } } -func (s *BackendTestSuite) TestEthBlockFromTendermintBlock() { +func (s *TestSuite) TestEthBlockFromTendermintBlock() { msgEthereumTx, bz := s.buildEthereumTx() emptyBlock := cmttypes.MakeBlock(1, []cmttypes.Tx{}, nil, nil) diff --git a/tests/integration/rpc/backend/test_call_tx.go b/tests/integration/rpc/backend/test_call_tx.go index e329d5c85..06cdad25c 100644 --- a/tests/integration/rpc/backend/test_call_tx.go +++ b/tests/integration/rpc/backend/test_call_tx.go @@ -22,7 +22,7 @@ import ( errortypes "github.com/cosmos/cosmos-sdk/types/errors" ) -func (s *BackendTestSuite) TestResend() { +func (s *TestSuite) TestResend() { txNonce := (hexutil.Uint64)(1) baseFee := math.NewInt(1) gasPrice := new(hexutil.Big) @@ -288,7 +288,7 @@ func (s *BackendTestSuite) TestResend() { } } -func (s *BackendTestSuite) TestSendRawTransaction() { +func (s *TestSuite) TestSendRawTransaction() { ethTx, bz := s.buildEthereumTx() emptyEvmChainIDTx := s.buildEthereumTxWithChainID(nil) @@ -408,7 +408,7 @@ func (s *BackendTestSuite) TestSendRawTransaction() { } } -func (s *BackendTestSuite) TestDoCall() { +func (s *TestSuite) TestDoCall() { _, bz := s.buildEthereumTx() gasPrice := (*hexutil.Big)(big.NewInt(1)) toAddr := utiltx.GenerateAddress() @@ -483,7 +483,7 @@ func (s *BackendTestSuite) TestDoCall() { } } -func (s *BackendTestSuite) TestGasPrice() { +func (s *TestSuite) TestGasPrice() { defaultGasPrice := (*hexutil.Big)(big.NewInt(1)) testCases := []struct { diff --git a/tests/integration/rpc/backend/test_chain_info.go b/tests/integration/rpc/backend/test_chain_info.go index b604865d2..ee0bf2d11 100644 --- a/tests/integration/rpc/backend/test_chain_info.go +++ b/tests/integration/rpc/backend/test_chain_info.go @@ -22,7 +22,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -func (s *BackendTestSuite) TestBaseFee() { +func (s *TestSuite) TestBaseFee() { baseFee := math.NewInt(1) testCases := []struct { @@ -154,7 +154,7 @@ func (s *BackendTestSuite) TestBaseFee() { } } -func (s *BackendTestSuite) TestChainId() { +func (s *TestSuite) TestChainID() { expChainID := (*hexutil.Big)(big.NewInt(evmdconfig.EVMChainID)) testCases := []struct { name string @@ -190,7 +190,7 @@ func (s *BackendTestSuite) TestChainId() { } } -func (s *BackendTestSuite) TestGetCoinbase() { +func (s *TestSuite) TestGetCoinbase() { validatorAcc := sdk.AccAddress(utiltx.GenerateAddress().Bytes()) testCases := []struct { name string @@ -247,7 +247,7 @@ func (s *BackendTestSuite) TestGetCoinbase() { } } -func (s *BackendTestSuite) TestSuggestGasTipCap() { +func (s *TestSuite) TestSuggestGasTipCap() { testCases := []struct { name string registerMock func() @@ -287,7 +287,7 @@ func (s *BackendTestSuite) TestSuggestGasTipCap() { } } -func (s *BackendTestSuite) TestGlobalMinGasPrice() { +func (s *TestSuite) TestGlobalMinGasPrice() { testCases := []struct { name string registerMock func() @@ -321,7 +321,7 @@ func (s *BackendTestSuite) TestGlobalMinGasPrice() { } } -func (s *BackendTestSuite) TestFeeHistory() { +func (s *TestSuite) TestFeeHistory() { testCases := []struct { name string registerMock func(validator sdk.AccAddress) diff --git a/tests/integration/rpc/backend/test_filters.go b/tests/integration/rpc/backend/test_filters.go index d6df8cd88..844334333 100644 --- a/tests/integration/rpc/backend/test_filters.go +++ b/tests/integration/rpc/backend/test_filters.go @@ -13,7 +13,7 @@ import ( evmtypes "github.com/cosmos/evm/x/vm/types" ) -func (s *BackendTestSuite) TestGetLogs() { +func (s *TestSuite) TestGetLogs() { _, bz := s.buildEthereumTx() block := cmttypes.MakeBlock(1, []cmttypes.Tx{bz}, nil, nil) logs := make([]*evmtypes.Log, 0, 1) @@ -94,7 +94,7 @@ func (s *BackendTestSuite) TestGetLogs() { } } -func (s *BackendTestSuite) TestBloomStatus() { +func (s *TestSuite) TestBloomStatus() { testCases := []struct { name string registerMock func() diff --git a/tests/integration/rpc/backend/test_node_info.go b/tests/integration/rpc/backend/test_node_info.go index faee2eed0..479c766ca 100644 --- a/tests/integration/rpc/backend/test_node_info.go +++ b/tests/integration/rpc/backend/test_node_info.go @@ -23,7 +23,7 @@ import ( authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) -func (s *BackendTestSuite) TestRPCMinGasPrice() { +func (s *TestSuite) TestRPCMinGasPrice() { testCases := []struct { name string registerMock func() @@ -59,7 +59,7 @@ func (s *BackendTestSuite) TestRPCMinGasPrice() { } } -func (s *BackendTestSuite) TestGenerateMinGasCoin() { +func (s *TestSuite) TestGenerateMinGasCoin() { defaultGasPrice := (*hexutil.Big)(big.NewInt(1)) testCases := []struct { name string @@ -102,7 +102,7 @@ func (s *BackendTestSuite) TestGenerateMinGasCoin() { } // TODO: Combine these 2 into one test since the code is identical -func (s *BackendTestSuite) TestListAccounts() { +func (s *TestSuite) TestListAccounts() { testCases := []struct { name string registerMock func() @@ -134,7 +134,7 @@ func (s *BackendTestSuite) TestListAccounts() { } } -func (s *BackendTestSuite) TestAccounts() { +func (s *TestSuite) TestAccounts() { testCases := []struct { name string registerMock func() @@ -166,7 +166,7 @@ func (s *BackendTestSuite) TestAccounts() { } } -func (s *BackendTestSuite) TestSyncing() { +func (s *TestSuite) TestSyncing() { testCases := []struct { name string registerMock func() @@ -224,7 +224,7 @@ func (s *BackendTestSuite) TestSyncing() { } } -func (s *BackendTestSuite) TestSetEtherbase() { +func (s *TestSuite) TestSetEtherbase() { testCases := []struct { name string registerMock func() @@ -316,7 +316,7 @@ func (s *BackendTestSuite) TestSetEtherbase() { } } -func (s *BackendTestSuite) TestImportRawKey() { +func (s *TestSuite) TestImportRawKey() { priv, _ := ethsecp256k1.GenerateKey() privHex := common.Bytes2Hex(priv.Bytes()) pubAddr := common.BytesToAddress(priv.PubKey().Address().Bytes()) diff --git a/tests/integration/rpc/backend/test_sign_tx.go b/tests/integration/rpc/backend/test_sign_tx.go index 59eb30239..aa261ec29 100644 --- a/tests/integration/rpc/backend/test_sign_tx.go +++ b/tests/integration/rpc/backend/test_sign_tx.go @@ -22,7 +22,7 @@ import ( signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" ) -func (s *BackendTestSuite) TestSendTransaction() { +func (s *TestSuite) TestSendTransaction() { gasPrice := new(hexutil.Big) gas := hexutil.Uint64(1) zeroGas := hexutil.Uint64(0) @@ -144,7 +144,7 @@ func (s *BackendTestSuite) TestSendTransaction() { } } -func (s *BackendTestSuite) TestSign() { +func (s *TestSuite) TestSign() { from, priv := utiltx.NewAddrKey() testCases := []struct { name string @@ -191,7 +191,7 @@ func (s *BackendTestSuite) TestSign() { } } -func (s *BackendTestSuite) TestSignTypedData() { +func (s *TestSuite) TestSignTypedData() { from, priv := utiltx.NewAddrKey() testCases := []struct { name string @@ -241,7 +241,7 @@ func (s *BackendTestSuite) TestSignTypedData() { } } -func broadcastTx(suite *BackendTestSuite, priv *ethsecp256k1.PrivKey, baseFee math.Int, callArgsDefault evmtypes.TransactionArgs) (client *mocks.Client, txBytes []byte) { +func broadcastTx(suite *TestSuite, priv *ethsecp256k1.PrivKey, baseFee math.Int, callArgsDefault evmtypes.TransactionArgs) (client *mocks.Client, txBytes []byte) { var header metadata.MD QueryClient := suite.backend.QueryClient.QueryClient.(*mocks.EVMQueryClient) client = suite.backend.ClientCtx.Client.(*mocks.Client) diff --git a/tests/integration/rpc/backend/test_tracing.go b/tests/integration/rpc/backend/test_tracing.go index 58c1e56f7..172b98340 100644 --- a/tests/integration/rpc/backend/test_tracing.go +++ b/tests/integration/rpc/backend/test_tracing.go @@ -21,7 +21,7 @@ import ( "github.com/cosmos/cosmos-sdk/crypto" ) -func (s *BackendTestSuite) TestTraceTransaction() { +func (s *TestSuite) TestTraceTransaction() { msgEthereumTx, _ := s.buildEthereumTx() msgEthereumTx2, _ := s.buildEthereumTx() @@ -208,7 +208,7 @@ func (s *BackendTestSuite) TestTraceTransaction() { } } -func (s *BackendTestSuite) TestTraceBlock() { +func (s *TestSuite) TestTraceBlock() { msgEthTx, bz := s.buildEthereumTx() emptyBlock := types.MakeBlock(1, []types.Tx{}, nil, nil) emptyBlock.ChainID = ChainID.ChainID diff --git a/tests/integration/rpc/backend/test_tx_info.go b/tests/integration/rpc/backend/test_tx_info.go index 57db91d9d..91c6befaf 100644 --- a/tests/integration/rpc/backend/test_tx_info.go +++ b/tests/integration/rpc/backend/test_tx_info.go @@ -23,7 +23,7 @@ import ( "cosmossdk.io/math" ) -func (s *BackendTestSuite) TestGetTransactionByHash() { +func (s *TestSuite) TestGetTransactionByHash() { msgEthereumTx, _ := s.buildEthereumTx() txHash := msgEthereumTx.AsTransaction().Hash() @@ -130,7 +130,7 @@ func (s *BackendTestSuite) TestGetTransactionByHash() { } } -func (s *BackendTestSuite) TestGetTransactionsByHashPending() { +func (s *TestSuite) TestGetTransactionsByHashPending() { msgEthereumTx, bz := s.buildEthereumTx() rpcTransaction, _ := rpctypes.NewRPCTransaction(msgEthereumTx.AsTransaction(), common.Hash{}, 0, 0, big.NewInt(1), s.backend.EvmChainID) @@ -190,7 +190,7 @@ func (s *BackendTestSuite) TestGetTransactionsByHashPending() { } } -func (s *BackendTestSuite) TestGetTxByEthHash() { +func (s *TestSuite) TestGetTxByEthHash() { msgEthereumTx, bz := s.buildEthereumTx() rpcTransaction, _ := rpctypes.NewRPCTransaction(msgEthereumTx.AsTransaction(), common.Hash{}, 0, 0, big.NewInt(1), s.backend.EvmChainID) @@ -232,7 +232,7 @@ func (s *BackendTestSuite) TestGetTxByEthHash() { } } -func (s *BackendTestSuite) TestGetTransactionByBlockHashAndIndex() { +func (s *TestSuite) TestGetTransactionByBlockHashAndIndex() { _, bz := s.buildEthereumTx() testCases := []struct { @@ -283,7 +283,7 @@ func (s *BackendTestSuite) TestGetTransactionByBlockHashAndIndex() { } } -func (s *BackendTestSuite) TestGetTransactionByBlockAndIndex() { +func (s *TestSuite) TestGetTransactionByBlockAndIndex() { msgEthTx, bz := s.buildEthereumTx() defaultBlock := types.MakeBlock(1, []types.Tx{bz}, nil, nil) @@ -398,7 +398,7 @@ func (s *BackendTestSuite) TestGetTransactionByBlockAndIndex() { } } -func (s *BackendTestSuite) TestGetTransactionByBlockNumberAndIndex() { +func (s *TestSuite) TestGetTransactionByBlockNumberAndIndex() { msgEthTx, bz := s.buildEthereumTx() defaultBlock := types.MakeBlock(1, []types.Tx{bz}, nil, nil) txFromMsg, _ := rpctypes.NewTransactionFromMsg( @@ -462,7 +462,7 @@ func (s *BackendTestSuite) TestGetTransactionByBlockNumberAndIndex() { } } -func (s *BackendTestSuite) TestGetTransactionByTxIndex() { +func (s *TestSuite) TestGetTransactionByTxIndex() { _, bz := s.buildEthereumTx() testCases := []struct { @@ -504,7 +504,7 @@ func (s *BackendTestSuite) TestGetTransactionByTxIndex() { } } -func (s *BackendTestSuite) TestQueryTendermintTxIndexer() { +func (s *TestSuite) TestQueryTendermintTxIndexer() { testCases := []struct { name string registerMock func() @@ -545,7 +545,7 @@ func (s *BackendTestSuite) TestQueryTendermintTxIndexer() { } } -func (s *BackendTestSuite) TestGetTransactionReceipt() { +func (s *TestSuite) TestGetTransactionReceipt() { msgEthereumTx, _ := s.buildEthereumTx() txHash := msgEthereumTx.AsTransaction().Hash() @@ -615,7 +615,7 @@ func (s *BackendTestSuite) TestGetTransactionReceipt() { } } -func (s *BackendTestSuite) TestGetGasUsed() { +func (s *TestSuite) TestGetGasUsed() { origin := s.backend.Cfg.JSONRPC.FixRevertGasRefundHeight testCases := []struct { name string diff --git a/tests/integration/rpc/backend/test_utils.go b/tests/integration/rpc/backend/test_utils.go index 418633534..8b3aae1d2 100644 --- a/tests/integration/rpc/backend/test_utils.go +++ b/tests/integration/rpc/backend/test_utils.go @@ -23,7 +23,7 @@ func mookProofs(num int, withData bool) *crypto.ProofOps { return proofOps } -func (s *BackendTestSuite) TestGetHexProofs() { +func (s *TestSuite) TestGetHexProofs() { defaultRes := []string{""} testCases := []struct { name string diff --git a/tests/integration/wallets/test_ledger_suite.go b/tests/integration/wallets/test_ledger_suite.go index 2f16fc395..a9f166c19 100644 --- a/tests/integration/wallets/test_ledger_suite.go +++ b/tests/integration/wallets/test_ledger_suite.go @@ -45,14 +45,10 @@ func NewLedgerTestSuite(create network.CreateEvmApp, options ...network.ConfigOp } } -// Load encoding config for sign doc encoding/decoding -// This is done on app instantiation. -// We use the testutil network to load the encoding config -//func init() { -// network.New() -//} - func (suite *LedgerTestSuite) SetupTest() { + // Load encoding config for sign doc encoding/decoding + // This is done on app instantiation. + // We use the testutil network to load the encoding config network.New(suite.create, suite.options...) suite.hrp = "cosmos" diff --git a/tests/integration/x/erc20/test_integration.go b/tests/integration/x/erc20/test_integration.go index fcbef69b5..f85950045 100644 --- a/tests/integration/x/erc20/test_integration.go +++ b/tests/integration/x/erc20/test_integration.go @@ -6,10 +6,8 @@ import ( "github.com/ethereum/go-ethereum/common" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" + . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" //nolint:ST1001 // dot imports are fine for Ginkgo "github.com/cosmos/evm/testutil/integration/base/factory" "github.com/cosmos/evm/testutil/integration/evm/network" diff --git a/tests/integration/x/feemarket/test_integration.go b/tests/integration/x/feemarket/test_integration.go index 8902eb2ec..81873df5c 100644 --- a/tests/integration/x/feemarket/test_integration.go +++ b/tests/integration/x/feemarket/test_integration.go @@ -6,10 +6,8 @@ import ( ethtypes "github.com/ethereum/go-ethereum/core/types" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/ginkgo/v2" - //nolint:revive // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" + . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" //nolint:ST1001 // dot imports are fine for Ginkgo "github.com/cosmos/evm/testutil/integration/base/factory" "github.com/cosmos/evm/testutil/integration/evm/network" @@ -39,7 +37,7 @@ func TestKeeperIntegrationTestSuite(t *testing.T) { panic("CreateApp must be set before running the tests") } - var _ = Describe("Feemarket", func() { + _ = Describe("Feemarket", func() { var ( s *KeeperTestSuite privKey cryptotypes.PrivKey diff --git a/tests/integration/x/precisebank/test_burn_integration.go b/tests/integration/x/precisebank/test_burn_integration.go index 800fdf136..c0f35ea2f 100644 --- a/tests/integration/x/precisebank/test_burn_integration.go +++ b/tests/integration/x/precisebank/test_burn_integration.go @@ -19,7 +19,7 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) -func (s *KeeperIntegrationTestSuite) TestBurnCoins_MatchingErrors() { +func (s *KeeperIntegrationTestSuite) TestBurnCoinsMatchingErrors() { // x/precisebank BurnCoins should be identical to x/bank BurnCoins to // consumers. This test ensures that the panics & errors returned by // x/precisebank are identical to x/bank. @@ -226,7 +226,7 @@ func (s *KeeperIntegrationTestSuite) TestBurnCoins() { } } -func (s *KeeperIntegrationTestSuite) TestBurnCoins_Remainder() { +func (s *KeeperIntegrationTestSuite) TestBurnCoinsRemainder() { // This tests a series of small burns to ensure the remainder is both // updated correctly and reserve is correctly updated. This only burns from // 1 single account. @@ -315,7 +315,7 @@ func (s *KeeperIntegrationTestSuite) TestBurnCoins_Remainder() { } } -func (s *KeeperIntegrationTestSuite) TestBurnCoins_Spread_Remainder() { +func (s *KeeperIntegrationTestSuite) TestBurnCoinsSpreadRemainder() { // This tests a series of small burns to ensure the remainder is both // updated correctly and reserve is correctly updated. This burns from // a series of multiple accounts, to test when the remainder is modified @@ -426,7 +426,7 @@ func (s *KeeperIntegrationTestSuite) TestBurnCoins_Spread_Remainder() { } } -func (s *KeeperIntegrationTestSuite) TestBurnCoins_RandomValueMultiDecimals() { +func (s *KeeperIntegrationTestSuite) TestBurnCoinsRandomValueMultiDecimals() { tests := []struct { name string chainID testconstants.ChainID diff --git a/tests/integration/x/precisebank/test_integration.go b/tests/integration/x/precisebank/test_integration.go index 42071575e..1ee116391 100644 --- a/tests/integration/x/precisebank/test_integration.go +++ b/tests/integration/x/precisebank/test_integration.go @@ -18,7 +18,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -func (s *KeeperIntegrationTestSuite) TestMintBurnSendCoins_RandomValueMultiDecimals() { +func (s *KeeperIntegrationTestSuite) TestMintBurnSendCoinsRandomValueMultiDecimals() { tests := []struct { name string chainID testconstants.ChainID @@ -131,7 +131,7 @@ func (s *KeeperIntegrationTestSuite) TestMintBurnSendCoins_RandomValueMultiDecim } } -func (s *KeeperIntegrationTestSuite) TestSendEvmTx_RandomValueMultiDecimals() { +func (s *KeeperIntegrationTestSuite) TestSendEvmTxRandomValueMultiDecimals() { maxGasLimit := int64(500000) defaultEVMCoinTransferGasLimit := int64(21000) @@ -247,7 +247,7 @@ func (s *KeeperIntegrationTestSuite) TestSendEvmTx_RandomValueMultiDecimals() { } } -func (s *KeeperIntegrationTestSuite) TestWATOMWrapUnwrap_MultiDecimal() { +func (s *KeeperIntegrationTestSuite) TestWATOMWrapUnwrapMultiDecimal() { tests := []struct { name string chainID testconstants.ChainID diff --git a/tests/integration/x/precisebank/test_send_integration.go b/tests/integration/x/precisebank/test_send_integration.go index ac0e4fdfa..22aa0bfda 100644 --- a/tests/integration/x/precisebank/test_send_integration.go +++ b/tests/integration/x/precisebank/test_send_integration.go @@ -22,7 +22,7 @@ import ( stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) -func (s *KeeperIntegrationTestSuite) TestSendCoinsFromAccountToModule_MatchingErrors() { +func (s *KeeperIntegrationTestSuite) TestSendCoinsFromAccountToModuleMatchingErrors() { // No specific errors for SendCoinsFromAccountToModule, only 1 panic if // the module account does not exist @@ -70,7 +70,7 @@ func (s *KeeperIntegrationTestSuite) TestSendCoinsFromAccountToModule_MatchingEr } } -func (s *KeeperIntegrationTestSuite) TestSendCoinsFromModuleToAccount_MatchingErrors() { +func (s *KeeperIntegrationTestSuite) TestSendCoinsFromModuleToAccountMatchingErrors() { // Ensure errors match x/bank errors AND panics. This needs to be well // tested before SendCoins as all send tests rely on this to initialize // account balances. @@ -222,7 +222,7 @@ func (s *KeeperIntegrationTestSuite) TestSendCoinsFromModuleToAccount_MatchingEr } } -func (s *KeeperIntegrationTestSuite) TestSendCoins_MatchingErrors() { +func (s *KeeperIntegrationTestSuite) TestSendCoinsMatchingErrors() { // Ensure errors match x/bank errors tests := []struct { @@ -470,7 +470,7 @@ func (s *KeeperIntegrationTestSuite) TestSendCoins() { } } -func (s *KeeperIntegrationTestSuite) TestSendCoins_Matrix() { +func (s *KeeperIntegrationTestSuite) TestSendCoinsMatrix() { // SendCoins is tested mostly in this integration test, as a unit test with // mocked BankKeeper overcomplicates expected keepers and makes initializing // balances very complex. @@ -619,7 +619,7 @@ func (s *KeeperIntegrationTestSuite) TestSendCoinsFromAccountToModule() { ) } -func (s *KeeperIntegrationTestSuite) TestSendCoinsFromAccountToModule_BlockedRecipientCarry() { +func (s *KeeperIntegrationTestSuite) TestSendCoinsFromAccountToModuleBlockedRecipientCarry() { // Carrying to module account balance. This tests that SendCoinsFromAccountToModule // does not fail when sending to a blocked module account. @@ -648,7 +648,7 @@ func (s *KeeperIntegrationTestSuite) TestSendCoinsFromAccountToModule_BlockedRec s.Require().NoError(err) } -func (s *KeeperIntegrationTestSuite) TestSendCoins_BlockedRecipientCarry() { +func (s *KeeperIntegrationTestSuite) TestSendCoinsBlockedRecipientCarry() { // Same test as TestSendCoinsFromModuleToAccount_Blocked, but with SendCoins // which also should not fail when sending to a blocked module account. sender := sdk.AccAddress([]byte{1}) @@ -715,7 +715,7 @@ func (s *KeeperIntegrationTestSuite) TestSendCoinsFromModuleToAccount() { ) } -func (s *KeeperIntegrationTestSuite) TestSendCoins_RandomValueMultiDecimals() { +func (s *KeeperIntegrationTestSuite) TestSendCoinsRandomValueMultiDecimals() { tests := []struct { name string chainID testconstants.ChainID diff --git a/tests/integration/x/precisebank/test_view_integration.go b/tests/integration/x/precisebank/test_view_integration.go index ab4ab954c..4e0cfc892 100644 --- a/tests/integration/x/precisebank/test_view_integration.go +++ b/tests/integration/x/precisebank/test_view_integration.go @@ -10,7 +10,7 @@ import ( vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" ) -func (s *KeeperIntegrationTestSuite) TestKeeper_SpendableCoin() { +func (s *KeeperIntegrationTestSuite) TestKeeperSpendableCoin() { tests := []struct { name string giveDenom string // queried denom for balance @@ -116,7 +116,7 @@ func (s *KeeperIntegrationTestSuite) TestKeeper_SpendableCoin() { } } -func (s *KeeperIntegrationTestSuite) TestKeeper_HiddenReserve() { +func (s *KeeperIntegrationTestSuite) TestKeeperHiddenReserve() { // Reserve balances should not be shown to consumers of x/precisebank, as it // represents the fractional balances of accounts. diff --git a/tests/integration/x/vm/genesis_test_suite.go b/tests/integration/x/vm/genesis_test_suite.go index 31bb774be..74b8f4fce 100644 --- a/tests/integration/x/vm/genesis_test_suite.go +++ b/tests/integration/x/vm/genesis_test_suite.go @@ -35,10 +35,11 @@ func (s *GenesisTestSuite) SetupTest() { if s.options == nil { s.options = []network.ConfigOption{} } - options := append(s.options, + opts := []network.ConfigOption{ network.WithPreFundedAccounts(s.keyring.GetAllAccAddrs()...), - ) - s.network = network.NewUnitTestNetwork(s.create, options...) + } + opts = append(opts, s.options...) + s.network = network.NewUnitTestNetwork(s.create, opts...) s.handler = grpc.NewIntegrationHandler(s.network) s.factory = factory.New(s.network, s.handler) } diff --git a/tests/integration/x/vm/keeper_test_suite.go b/tests/integration/x/vm/keeper_test_suite.go index ade6f3112..8b76b4718 100644 --- a/tests/integration/x/vm/keeper_test_suite.go +++ b/tests/integration/x/vm/keeper_test_suite.go @@ -74,11 +74,12 @@ func (s *KeeperTestSuite) SetupTest() { if s.Options == nil { s.Options = []network.ConfigOption{} } - options := append(s.Options, + opts := []network.ConfigOption{ network.WithPreFundedAccounts(keys.GetAllAccAddrs()...), network.WithCustomGenesis(customGenesis), - ) - nw := network.NewUnitTestNetwork(s.Create, options...) + } + opts = append(opts, s.Options...) + nw := network.NewUnitTestNetwork(s.Create, opts...) gh := grpc.NewIntegrationHandler(nw) tf := factory.New(nw, gh) diff --git a/tests/integration/x/vm/nested_evm_extension_test_suite.go b/tests/integration/x/vm/nested_evm_extension_test_suite.go index 771dbcc1d..fbfbe34a8 100644 --- a/tests/integration/x/vm/nested_evm_extension_test_suite.go +++ b/tests/integration/x/vm/nested_evm_extension_test_suite.go @@ -67,11 +67,12 @@ func (s *NestedEVMExtensionCallSuite) SetupTest() { if s.options == nil { s.options = []network.ConfigOption{} } - options := append(s.options, + opts := []network.ConfigOption{ network.WithPreFundedAccounts(s.keyring.GetAllAccAddrs()...), - ) + } + opts = append(opts, s.options...) // fresh network, handler, factory - s.network = network.NewUnitTestNetwork(s.create, options...) + s.network = network.NewUnitTestNetwork(s.create, opts...) s.handler = grpc.NewIntegrationHandler(s.network) s.factory = factory.New(s.network, s.handler) diff --git a/tests/integration/x/vm/test_iterate_contracts.go b/tests/integration/x/vm/test_iterate_contracts.go new file mode 100644 index 000000000..7e4556052 --- /dev/null +++ b/tests/integration/x/vm/test_iterate_contracts.go @@ -0,0 +1,71 @@ +package vm + +import ( + "bytes" + "github.com/cosmos/evm/contracts" + testconstants "github.com/cosmos/evm/testutil/constants" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + testKeyring "github.com/cosmos/evm/testutil/keyring" + testutiltypes "github.com/cosmos/evm/testutil/types" + "github.com/cosmos/evm/x/vm/types" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + "testing" +) + +func TestIterateContracts(t *testing.T, create network.CreateEvmApp, options ...network.ConfigOption) { + keyring := testKeyring.New(1) + opts := []network.ConfigOption{ + network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), + } + opts = append(opts, options...) + network := network.NewUnitTestNetwork(create, opts...) + handler := grpc.NewIntegrationHandler(network) + factory := factory.New(network, handler) + + contractAddr, err := factory.DeployContract( + keyring.GetPrivKey(0), + types.EvmTxArgs{}, + testutiltypes.ContractDeploymentData{ + Contract: contracts.ERC20MinterBurnerDecimalsContract, + ConstructorArgs: []interface{}{"TestToken", "TTK", uint8(18)}, + }, + ) + require.NoError(t, err, "failed to deploy contract") + require.NoError(t, network.NextBlock(), "failed to advance block") + + contractAddr2, err := factory.DeployContract( + keyring.GetPrivKey(0), + types.EvmTxArgs{}, + testutiltypes.ContractDeploymentData{ + Contract: contracts.ERC20MinterBurnerDecimalsContract, + ConstructorArgs: []interface{}{"AnotherToken", "ATK", uint8(18)}, + }, + ) + require.NoError(t, err, "failed to deploy contract") + require.NoError(t, network.NextBlock(), "failed to advance block") + + var ( + foundAddrs []common.Address + foundHashes []common.Hash + ) + + network.App.GetEVMKeeper().IterateContracts(network.GetContext(), func(addr common.Address, codeHash common.Hash) bool { + // NOTE: we only care about the 2 contracts deployed above, not the ERC20 native precompile for the aatom denomination + if bytes.Equal(addr.Bytes(), common.HexToAddress(testconstants.WEVMOSContractMainnet).Bytes()) { + return false + } + + foundAddrs = append(foundAddrs, addr) + foundHashes = append(foundHashes, codeHash) + return false + }) + + require.Len(t, foundAddrs, 2, "expected 2 contracts to be found when iterating") + require.Contains(t, foundAddrs, contractAddr, "expected contract 1 to be found when iterating") + require.Contains(t, foundAddrs, contractAddr2, "expected contract 2 to be found when iterating") + require.Equal(t, foundHashes[0], foundHashes[1], "expected both contracts to have the same code hash") + require.NotEqual(t, types.EmptyCodeHash, foundHashes[0], "expected store code hash not to be the keccak256 of empty code") +} diff --git a/tests/integration/x/vm/test_statedb.go b/tests/integration/x/vm/test_statedb.go index 963143a4f..09a563282 100644 --- a/tests/integration/x/vm/test_statedb.go +++ b/tests/integration/x/vm/test_statedb.go @@ -1,8 +1,15 @@ package vm import ( + "bytes" "fmt" + "github.com/cosmos/evm/contracts" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + testutiltypes "github.com/cosmos/evm/testutil/types" + "github.com/stretchr/testify/require" "math/big" + "testing" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/tracing" @@ -356,60 +363,6 @@ func (s *KeeperTestSuite) TestKeeperSetOrDeleteCode() { } } -// TODO: Move to evmd -//func TestIterateContracts(t *testing.T) { -// Keyring := testKeyring.New(1) -// Network := network.NewUnitTestNetwork( -// network.WithPreFundedAccounts(Keyring.GetAllAccAddrs()...), -// ) -// handler := grpc.NewIntegrationHandler(Network) -// factory := factory2.New(Network, handler) -// -// contractAddr, err := factory.DeployContract( -// Keyring.GetPrivKey(0), -// types.EvmTxArgs{}, -// factory2.ContractDeploymentData{ -// Contract: contracts.ERC20MinterBurnerDecimalsContract, -// ConstructorArgs: []interface{}{"TestToken", "TTK", uint8(18)}, -// }, -// ) -// require.NoError(t, err, "failed to deploy contract") -// require.NoError(t, Network.NextBlock(), "failed to advance block") -// -// contractAddr2, err := factory.DeployContract( -// Keyring.GetPrivKey(0), -// types.EvmTxArgs{}, -// factory2.ContractDeploymentData{ -// Contract: contracts.ERC20MinterBurnerDecimalsContract, -// ConstructorArgs: []interface{}{"AnotherToken", "ATK", uint8(18)}, -// }, -// ) -// require.NoError(t, err, "failed to deploy contract") -// require.NoError(t, Network.NextBlock(), "failed to advance block") -// -// var ( -// foundAddrs []common.Address -// foundHashes []common.Hash -// ) -// -// Network.App.GetEVMKeeper().IterateContracts(Network.GetContext(), func(addr common.Address, codeHash common.Hash) bool { -// // NOTE: we only care about the 2 contracts deployed above, not the ERC20 native precompile for the aatom denomination -// if bytes.Equal(addr.Bytes(), common.HexToAddress(testconstants.WEVMOSContractMainnet).Bytes()) { -// return false -// } -// -// foundAddrs = append(foundAddrs, addr) -// foundHashes = append(foundHashes, codeHash) -// return false -// }) -// -// require.Len(t, foundAddrs, 2, "expected 2 contracts to be found when iterating") -// require.Contains(t, foundAddrs, contractAddr, "expected contract 1 to be found when iterating") -// require.Contains(t, foundAddrs, contractAddr2, "expected contract 2 to be found when iterating") -// require.Equal(t, foundHashes[0], foundHashes[1], "expected both contracts to have the same code hash") -// require.NotEqual(t, types.EmptyCodeHash, foundHashes[0], "expected store code hash not to be the keccak256 of empty code") -//} - func (s *KeeperTestSuite) TestRefund() { testCases := []struct { name string diff --git a/testutil/integration/evm/utils/genesis.go b/testutil/integration/evm/utils/genesis.go index e2493a0ff..9fd9604c4 100644 --- a/testutil/integration/evm/utils/genesis.go +++ b/testutil/integration/evm/utils/genesis.go @@ -2,7 +2,6 @@ package utils import ( "github.com/cosmos/evm/testutil/constants" - testconstants "github.com/cosmos/evm/testutil/constants" "github.com/cosmos/evm/testutil/integration/evm/network" testkeyring "github.com/cosmos/evm/testutil/keyring" utiltx "github.com/cosmos/evm/testutil/tx" @@ -87,8 +86,8 @@ func CreateGenesisWithTokenPairs(keyring testkeyring.Keyring, denoms ...string) // which is the base denomination of the chain (i.e. the WEVMOS contract). func NewErc20GenesisState() *erc20types.GenesisState { erc20GenState := erc20types.DefaultGenesisState() - erc20GenState.TokenPairs = testconstants.ExampleTokenPairs - erc20GenState.Params.NativePrecompiles = append(erc20GenState.Params.NativePrecompiles, testconstants.WEVMOSContractMainnet) + erc20GenState.TokenPairs = constants.ExampleTokenPairs + erc20GenState.Params.NativePrecompiles = append(erc20GenState.Params.NativePrecompiles, constants.WEVMOSContractMainnet) return erc20GenState } diff --git a/x/erc20/types/params_test.go b/x/erc20/types/params_test.go index e6dca0918..e0be3ef50 100644 --- a/x/erc20/types/params_test.go +++ b/x/erc20/types/params_test.go @@ -4,11 +4,11 @@ import ( "slices" "testing" + "cosmosevm.io/evmd" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" - "github.com/cosmos/evm/evmd" testconstants "github.com/cosmos/evm/testutil/constants" "github.com/cosmos/evm/x/erc20/types" ) diff --git a/x/precisebank/keeper/keeper_test.go b/x/precisebank/keeper/keeper_test.go index 1ae52d647..8bb7af34f 100644 --- a/x/precisebank/keeper/keeper_test.go +++ b/x/precisebank/keeper/keeper_test.go @@ -41,11 +41,11 @@ func newMockedTestData(t *testing.T) testData { bk := mocks.NewMockBankKeeper(t) ak := mocks.NewMockAccountKeeper(t) - chainId := testconstants.SixDecimalsChainID.EVMChainID - cfg := evmosencoding.MakeConfig(chainId) + chainID := testconstants.SixDecimalsChainID.EVMChainID + cfg := evmosencoding.MakeConfig(chainID) cdc := cfg.Codec k := keeper.NewKeeper(cdc, storeKey, bk, ak) - err := evmd.EvmAppOptions(chainId) + err := evmd.EvmAppOptions(chainID) if err != nil { return testData{} } From d37f1a21b225630eb561a330a7e3cc35ea52ce1e Mon Sep 17 00:00:00 2001 From: zsystm Date: Thu, 5 Jun 2025 08:55:44 +0900 Subject: [PATCH 04/21] fix ci --- tests/integration/ante/ante_test_suite.go | 2 +- tests/integration/ante/test_integration.go | 8 +++++--- tests/integration/eips/test_eips.go | 6 ++++-- tests/integration/ledger/evmosd_suite_test.go | 6 ++++-- tests/integration/ledger/ledger_test.go | 3 ++- tests/integration/precompiles/bank/test_integration.go | 6 ++++-- .../precompiles/distribution/test_integration.go | 6 ++++-- .../integration/precompiles/erc20/test_integration.go | 6 ++++-- tests/integration/precompiles/gov/test_integration.go | 6 ++++-- tests/integration/precompiles/p256/test_integration.go | 6 ++++-- tests/integration/precompiles/p256/test_setup.go | 4 ++-- .../precompiles/staking/test_integration.go | 6 ++++-- .../integration/precompiles/werc20/test_integration.go | 6 ++++-- tests/integration/x/erc20/test_integration.go | 10 ++++++---- tests/integration/x/feemarket/test_integration.go | 6 ++++-- .../integration/x/precisebank/test_mint_integration.go | 4 ++-- tests/integration/x/vm/test_iterate_contracts.go | 8 +++++--- tests/integration/x/vm/test_statedb.go | 7 ------- 18 files changed, 63 insertions(+), 43 deletions(-) diff --git a/tests/integration/ante/ante_test_suite.go b/tests/integration/ante/ante_test_suite.go index 807f1452c..61c49eb66 100644 --- a/tests/integration/ante/ante_test_suite.go +++ b/tests/integration/ante/ante_test_suite.go @@ -22,7 +22,7 @@ import ( const TestGasLimit uint64 = 100000 -type AnteTestSuite struct { // nolint:revive +type AnteTestSuite struct { //nolint:revive suite.Suite create network.CreateEvmApp diff --git a/tests/integration/ante/test_integration.go b/tests/integration/ante/test_integration.go index 95005afce..0a8d8bfb1 100644 --- a/tests/integration/ante/test_integration.go +++ b/tests/integration/ante/test_integration.go @@ -5,8 +5,10 @@ import ( "github.com/stretchr/testify/suite" - . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" //nolint:ST1001 // dot imports are fine for Ginkgo + //nolint:revive,ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/ginkgo/v2" + //nolint:revive,ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" testconstants "github.com/cosmos/evm/testutil/constants" commonfactory "github.com/cosmos/evm/testutil/integration/base/factory" @@ -84,7 +86,7 @@ func TestIntegrationAnteHandler(t *testing.T, create network.CreateEvmApp, optio panic("create function cannot be nil") } - var _ = Describe("when sending a Cosmos transaction", Label("AnteHandler"), Ordered, func() { + _ = Describe("when sending a Cosmos transaction", Label("AnteHandler"), Ordered, func() { var s *IntegrationTestSuite BeforeAll(func() { diff --git a/tests/integration/eips/test_eips.go b/tests/integration/eips/test_eips.go index a51db6dba..e983c22f1 100644 --- a/tests/integration/eips/test_eips.go +++ b/tests/integration/eips/test_eips.go @@ -10,8 +10,10 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/params" - . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" //nolint:ST1001 // dot imports are fine for Ginkgo + //nolint:revive,ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/ginkgo/v2" + //nolint:revive,ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" "github.com/cosmos/evm/testutil/integration/evm/factory" "github.com/cosmos/evm/testutil/integration/evm/grpc" diff --git a/tests/integration/ledger/evmosd_suite_test.go b/tests/integration/ledger/evmosd_suite_test.go index f3906534e..1fd68b1db 100644 --- a/tests/integration/ledger/evmosd_suite_test.go +++ b/tests/integration/ledger/evmosd_suite_test.go @@ -13,8 +13,10 @@ import ( "github.com/spf13/cobra" "github.com/stretchr/testify/suite" - . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" //nolint:ST1001 // dot imports are fine for Ginkgo + //nolint:revive,ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/ginkgo/v2" + //nolint:revive,ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" "github.com/cometbft/cometbft/crypto/tmhash" tmproto "github.com/cometbft/cometbft/proto/tendermint/types" diff --git a/tests/integration/ledger/ledger_test.go b/tests/integration/ledger/ledger_test.go index d88ef6b7e..81da2d2da 100644 --- a/tests/integration/ledger/ledger_test.go +++ b/tests/integration/ledger/ledger_test.go @@ -6,7 +6,8 @@ import ( "github.com/spf13/cobra" - . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo + //nolint:revive,ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/ginkgo/v2" "github.com/cosmos/evm/crypto/hd" "github.com/cosmos/evm/encoding" diff --git a/tests/integration/precompiles/bank/test_integration.go b/tests/integration/precompiles/bank/test_integration.go index 65cf8001e..195b651ba 100644 --- a/tests/integration/precompiles/bank/test_integration.go +++ b/tests/integration/precompiles/bank/test_integration.go @@ -7,8 +7,10 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/suite" - . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" //nolint:ST1001 // dot imports are fine for Ginkgo + //nolint:revive,ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/ginkgo/v2" + //nolint:revive,ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" bank2 "github.com/cosmos/evm/precompiles/bank" "github.com/cosmos/evm/precompiles/bank/testdata" diff --git a/tests/integration/precompiles/distribution/test_integration.go b/tests/integration/precompiles/distribution/test_integration.go index 6e21c8317..732840875 100644 --- a/tests/integration/precompiles/distribution/test_integration.go +++ b/tests/integration/precompiles/distribution/test_integration.go @@ -7,8 +7,10 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" - . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" //nolint:ST1001 // dot imports are fine for Ginkgo + //nolint:revive,ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/ginkgo/v2" + //nolint:revive,ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" cmn "github.com/cosmos/evm/precompiles/common" "github.com/cosmos/evm/precompiles/distribution" diff --git a/tests/integration/precompiles/erc20/test_integration.go b/tests/integration/precompiles/erc20/test_integration.go index 09e426eda..c7926185c 100644 --- a/tests/integration/precompiles/erc20/test_integration.go +++ b/tests/integration/precompiles/erc20/test_integration.go @@ -12,8 +12,10 @@ import ( "github.com/ethereum/go-ethereum/core/vm" "github.com/stretchr/testify/suite" - . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" //nolint:ST1001 // dot imports are fine for Ginkgo + //nolint:revive,ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/ginkgo/v2" + //nolint:revive,ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" "github.com/cosmos/evm/contracts" "github.com/cosmos/evm/precompiles/erc20" diff --git a/tests/integration/precompiles/gov/test_integration.go b/tests/integration/precompiles/gov/test_integration.go index 2a0c9aae5..8d3c288d8 100644 --- a/tests/integration/precompiles/gov/test_integration.go +++ b/tests/integration/precompiles/gov/test_integration.go @@ -8,8 +8,10 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" - . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" //nolint:ST1001 // dot imports are fine for Ginkgo + //nolint:revive,ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/ginkgo/v2" + //nolint:revive,ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" cmn "github.com/cosmos/evm/precompiles/common" "github.com/cosmos/evm/precompiles/gov" diff --git a/tests/integration/precompiles/p256/test_integration.go b/tests/integration/precompiles/p256/test_integration.go index e05b4c90c..185beaef8 100644 --- a/tests/integration/precompiles/p256/test_integration.go +++ b/tests/integration/precompiles/p256/test_integration.go @@ -8,8 +8,10 @@ import ( "github.com/ethereum/go-ethereum/common" - . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" //nolint:ST1001 // dot imports are fine for Ginkgo + //nolint:revive,ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/ginkgo/v2" + //nolint:revive,ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" "github.com/cometbft/cometbft/crypto" diff --git a/tests/integration/precompiles/p256/test_setup.go b/tests/integration/precompiles/p256/test_setup.go index f2cd20426..86a6818d5 100644 --- a/tests/integration/precompiles/p256/test_setup.go +++ b/tests/integration/precompiles/p256/test_setup.go @@ -5,6 +5,7 @@ import ( "crypto/elliptic" "crypto/rand" "errors" + "github.com/stretchr/testify/suite" "golang.org/x/crypto/cryptobyte" "golang.org/x/crypto/cryptobyte/asn1" @@ -37,8 +38,7 @@ func (s *PrecompileTestSuite) SetupTest() { s.precompile = &p256.Precompile{} } -// nolint:thelper -func signMsg(msg []byte, priv *ecdsa.PrivateKey) ([]byte, error) { +func signMsg(msg []byte, priv *ecdsa.PrivateKey) ([]byte, error) { //nolint:thelper hash := crypto.Sha256(msg) rInt, sInt, err := ecdsa.Sign(rand.Reader, priv, hash) diff --git a/tests/integration/precompiles/staking/test_integration.go b/tests/integration/precompiles/staking/test_integration.go index b1696d4ec..22ba50e04 100644 --- a/tests/integration/precompiles/staking/test_integration.go +++ b/tests/integration/precompiles/staking/test_integration.go @@ -8,8 +8,10 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" - . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" //nolint:ST1001 // dot imports are fine for Ginkgo + //nolint:revive,ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/ginkgo/v2" + //nolint:revive,ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" compiledcontracts "github.com/cosmos/evm/contracts" "github.com/cosmos/evm/crypto/ethsecp256k1" diff --git a/tests/integration/precompiles/werc20/test_integration.go b/tests/integration/precompiles/werc20/test_integration.go index c44240f76..46c8980d8 100644 --- a/tests/integration/precompiles/werc20/test_integration.go +++ b/tests/integration/precompiles/werc20/test_integration.go @@ -6,8 +6,10 @@ import ( "github.com/ethereum/go-ethereum/common" - . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" //nolint:ST1001 // dot imports are fine for Ginkgo + //nolint:revive,ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/ginkgo/v2" + //nolint:revive,ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" "github.com/cosmos/evm/precompiles/erc20" "github.com/cosmos/evm/precompiles/testutil" diff --git a/tests/integration/x/erc20/test_integration.go b/tests/integration/x/erc20/test_integration.go index f85950045..a5b04c3f5 100644 --- a/tests/integration/x/erc20/test_integration.go +++ b/tests/integration/x/erc20/test_integration.go @@ -6,8 +6,10 @@ import ( "github.com/ethereum/go-ethereum/common" - . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" //nolint:ST1001 // dot imports are fine for Ginkgo + //nolint:revive,ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/ginkgo/v2" + //nolint:revive,ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" "github.com/cosmos/evm/testutil/integration/base/factory" "github.com/cosmos/evm/testutil/integration/evm/network" @@ -21,7 +23,7 @@ import ( ) func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmApp, options ...network.ConfigOption) { - var _ = Describe("Performing EVM transactions", Ordered, func() { + _ = Describe("Performing EVM transactions", Ordered, func() { var s *KeeperTestSuite BeforeEach(func() { s = NewKeeperTestSuite(create, options...) @@ -54,7 +56,7 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp }) }) - var _ = Describe("ERC20:", Ordered, func() { + _ = Describe("ERC20:", Ordered, func() { var ( s *KeeperTestSuite contract common.Address diff --git a/tests/integration/x/feemarket/test_integration.go b/tests/integration/x/feemarket/test_integration.go index 81873df5c..b7c28b592 100644 --- a/tests/integration/x/feemarket/test_integration.go +++ b/tests/integration/x/feemarket/test_integration.go @@ -6,8 +6,10 @@ import ( ethtypes "github.com/ethereum/go-ethereum/core/types" - . "github.com/onsi/ginkgo/v2" //nolint:ST1001 // dot imports are fine for Ginkgo - . "github.com/onsi/gomega" //nolint:ST1001 // dot imports are fine for Ginkgo + //nolint:revive,ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/ginkgo/v2" + //nolint:revive,ST1001 // dot imports are fine for Ginkgo + . "github.com/onsi/gomega" "github.com/cosmos/evm/testutil/integration/base/factory" "github.com/cosmos/evm/testutil/integration/evm/network" diff --git a/tests/integration/x/precisebank/test_mint_integration.go b/tests/integration/x/precisebank/test_mint_integration.go index bd92a00e4..d9d00f665 100644 --- a/tests/integration/x/precisebank/test_mint_integration.go +++ b/tests/integration/x/precisebank/test_mint_integration.go @@ -43,7 +43,7 @@ func (s *KeeperIntegrationTestSuite) TestBlockedRecipient() { ) } -func (s *KeeperIntegrationTestSuite) TestMintCoins_MatchingErrors() { +func (s *KeeperIntegrationTestSuite) TestMintCoinsMatchingErrors() { // x/precisebank MintCoins should be identical to x/bank MintCoins to // consumers. This test ensures that the panics & errors returned by // x/precisebank are identical to x/bank. @@ -355,7 +355,7 @@ func (s *KeeperIntegrationTestSuite) TestMintCoins() { } } -func (s *KeeperIntegrationTestSuite) TestMintCoins_RandomValueMultiDecimals() { +func (s *KeeperIntegrationTestSuite) TestMintCoinsRandomValueMultiDecimals() { tests := []struct { name string chainID testconstants.ChainID diff --git a/tests/integration/x/vm/test_iterate_contracts.go b/tests/integration/x/vm/test_iterate_contracts.go index 7e4556052..5fa1ebae3 100644 --- a/tests/integration/x/vm/test_iterate_contracts.go +++ b/tests/integration/x/vm/test_iterate_contracts.go @@ -2,6 +2,11 @@ package vm import ( "bytes" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + "github.com/cosmos/evm/contracts" testconstants "github.com/cosmos/evm/testutil/constants" "github.com/cosmos/evm/testutil/integration/evm/factory" @@ -10,9 +15,6 @@ import ( testKeyring "github.com/cosmos/evm/testutil/keyring" testutiltypes "github.com/cosmos/evm/testutil/types" "github.com/cosmos/evm/x/vm/types" - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" - "testing" ) func TestIterateContracts(t *testing.T, create network.CreateEvmApp, options ...network.ConfigOption) { diff --git a/tests/integration/x/vm/test_statedb.go b/tests/integration/x/vm/test_statedb.go index 09a563282..2acb9d5f5 100644 --- a/tests/integration/x/vm/test_statedb.go +++ b/tests/integration/x/vm/test_statedb.go @@ -1,15 +1,8 @@ package vm import ( - "bytes" "fmt" - "github.com/cosmos/evm/contracts" - "github.com/cosmos/evm/testutil/integration/evm/factory" - "github.com/cosmos/evm/testutil/integration/evm/grpc" - testutiltypes "github.com/cosmos/evm/testutil/types" - "github.com/stretchr/testify/require" "math/big" - "testing" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/tracing" From cce11c92b6e865b94531c0908b2d7867516dc7ed Mon Sep 17 00:00:00 2001 From: zsystm Date: Thu, 5 Jun 2025 09:53:50 +0900 Subject: [PATCH 05/21] fix lint issues --- .golangci.yml | 4 ++++ ante/evm/fee_checker_test.go | 6 +++--- tests/integration/eip712/test_eip712_fuzzer.go | 4 ++-- tests/integration/precompiles/bank/test_utils.go | 2 +- tests/integration/precompiles/p256/test_setup.go | 2 +- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index d4a987bb9..20ac7dbdb 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -52,6 +52,10 @@ issues: text: 'SA1019:' linters: - staticcheck + - path: ^tests/integration/ + linters: + - stylecheck + text: 'ST1001:' exclude-dirs: - x/vm/core diff --git a/ante/evm/fee_checker_test.go b/ante/evm/fee_checker_test.go index e47db6ab5..e97acf66d 100644 --- a/ante/evm/fee_checker_test.go +++ b/ante/evm/fee_checker_test.go @@ -58,9 +58,9 @@ func TestSDKTxFeeChecker(t *testing.T) { // with extension option // without extension option // london hardfork enableness - chainId := uint64(evmdconfig.EighteenDecimalsChainID) - encodingConfig := encoding.MakeConfig(chainId) - err := evmd.EvmAppOptions(chainId) + chainID := uint64(evmdconfig.EighteenDecimalsChainID) + encodingConfig := encoding.MakeConfig(chainID) + err := evmd.EvmAppOptions(chainID) require.NoError(t, err) evmDenom := evmtypes.GetEVMCoinDenom() diff --git a/tests/integration/eip712/test_eip712_fuzzer.go b/tests/integration/eip712/test_eip712_fuzzer.go index 4ef187715..7d58ab619 100644 --- a/tests/integration/eip712/test_eip712_fuzzer.go +++ b/tests/integration/eip712/test_eip712_fuzzer.go @@ -12,7 +12,7 @@ import ( "github.com/cosmos/evm/ethereum/eip712" ) -type EIP712FuzzTestParams struct { +type FuzzTestParams struct { numTestObjects int maxNumFieldsPerObject int minStringLength int @@ -38,7 +38,7 @@ const ( jsonObjectType = iota ) -var params = EIP712FuzzTestParams{ +var params = FuzzTestParams{ numTestObjects: 16, maxNumFieldsPerObject: 16, minStringLength: 16, diff --git a/tests/integration/precompiles/bank/test_utils.go b/tests/integration/precompiles/bank/test_utils.go index 5856fd70f..7fdfa5a6d 100644 --- a/tests/integration/precompiles/bank/test_utils.go +++ b/tests/integration/precompiles/bank/test_utils.go @@ -4,7 +4,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" - //nolint:revive // dot imports are fine for Ginkgo + //nolint:revive,ST1001 // dot imports are fine for Ginkgo . "github.com/onsi/gomega" "github.com/cosmos/evm/precompiles/bank" diff --git a/tests/integration/precompiles/p256/test_setup.go b/tests/integration/precompiles/p256/test_setup.go index 86a6818d5..5fbec5fc0 100644 --- a/tests/integration/precompiles/p256/test_setup.go +++ b/tests/integration/precompiles/p256/test_setup.go @@ -38,7 +38,7 @@ func (s *PrecompileTestSuite) SetupTest() { s.precompile = &p256.Precompile{} } -func signMsg(msg []byte, priv *ecdsa.PrivateKey) ([]byte, error) { //nolint:thelper +func signMsg(msg []byte, priv *ecdsa.PrivateKey) ([]byte, error) { hash := crypto.Sha256(msg) rInt, sInt, err := ecdsa.Sign(rand.Reader, priv, hash) From bde9b525429a45bc7a80ee843dfc2ffdedcc410d Mon Sep 17 00:00:00 2001 From: zsystm Date: Thu, 5 Jun 2025 13:15:48 +0900 Subject: [PATCH 06/21] fix ginkgo issues and update testing ci, makefile --- .github/workflows/test.yml | 3 ++ Makefile | 43 ++++++++++++++----- ethereum/eip712/preprocess_test.go | 4 ++ .../tests/integration/{ => ante}/ante_test.go | 5 ++- .../tests/integration/{ => eips}/eips_test.go | 5 ++- .../integration/iterate_contracts_test.go | 7 --- .../bank}/precompile_bank_test.go | 7 +-- .../bech32}/precompile_bech32_test.go | 5 ++- .../precompile_distribution_test.go | 7 +-- .../erc20}/precompile_erc20_test.go | 7 +-- .../evidence}/precompile_evidence_test.go | 5 ++- .../gov}/precompile_gov_test.go | 7 +-- .../p256}/precompile_p256_test.go | 7 +-- .../slashing}/precompile_slashing_test.go | 5 ++- .../staking}/precompile_staking_test.go | 7 +-- .../werc20}/precompile_werc20_test.go | 7 +-- evmd/tests/integration/x_vm_test.go | 4 ++ tests/integration/x/vm/test_ctx.go | 8 ++-- 18 files changed, 90 insertions(+), 53 deletions(-) rename evmd/tests/integration/{ => ante}/ante_test.go (51%) rename evmd/tests/integration/{ => eips}/eips_test.go (53%) delete mode 100644 evmd/tests/integration/iterate_contracts_test.go rename evmd/tests/integration/{ => precompiles/bank}/precompile_bank_test.go (60%) rename evmd/tests/integration/{ => precompiles/bech32}/precompile_bech32_test.go (63%) rename evmd/tests/integration/{ => precompiles/distribution}/precompile_distribution_test.go (57%) rename evmd/tests/integration/{ => precompiles/erc20}/precompile_erc20_test.go (59%) rename evmd/tests/integration/{ => precompiles/evidence}/precompile_evidence_test.go (62%) rename evmd/tests/integration/{ => precompiles/gov}/precompile_gov_test.go (58%) rename evmd/tests/integration/{ => precompiles/p256}/precompile_p256_test.go (58%) rename evmd/tests/integration/{ => precompiles/slashing}/precompile_slashing_test.go (62%) rename evmd/tests/integration/{ => precompiles/staking}/precompile_staking_test.go (58%) rename evmd/tests/integration/{ => precompiles/werc20}/precompile_werc20_test.go (58%) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3e8fc3e67..ca3540444 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,6 +32,9 @@ jobs: **/**.go go.mod go.sum + evmd/go.mod + evmd/go.sum + evmd/**/**.go *.toml - name: Test and Create Coverage Report run: | diff --git a/Makefile b/Makefile index b6a460918..d8849a171 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,5 @@ #!/usr/bin/make -f -PACKAGES_NOSIMULATION=$(shell go list ./... | grep -v '/simulation') VERSION ?= $(shell echo $(shell git describe --tags --always) | sed 's/^v//') TMVERSION := $(shell go list -m github.com/cometbft/cometbft | sed 's:.* ::') COMMIT := $(shell git log -1 --format='%H') @@ -102,38 +101,60 @@ vulncheck: ############################################################################### test: test-unit -test-all: test-unit test-race +test-all: + @echo "🔍 Running evm module tests..." + @go test -tags=test -mod=readonly -timeout=15m $(PACKAGES_NOSIMULATION) + @echo "🔍 Running evmd module tests..." + @cd evmd && go test -tags=test -mod=readonly -timeout=15m $(PACKAGES_EVMD) + # For unit tests we don't want to execute the upgrade tests in tests/e2e but # we want to include all unit tests in the subfolders (tests/e2e/*) -PACKAGES_UNIT=$(shell go list ./... | grep -v '/tests/e2e$$') +PACKAGES_UNIT := $(shell go list ./... | grep -v '/tests/e2e$$' | grep -v '/simulation') +PACKAGES_EVMD := $(shell cd evmd && go list ./... | grep -v '/simulation') +COVERPKG_EVM := $(shell go list ./... | grep -v '/tests/e2e$$' | grep -v '/simulation' | paste -sd, -) +COVERPKG_ALL := $(COVERPKG_EVM) +COMMON_COVER_ARGS := -timeout=15m -covermode=atomic + TEST_PACKAGES=./... -TEST_TARGETS := test-unit test-unit-cover test-race +TEST_TARGETS := test-unit test-evmd test-unit-cover test-race # Test runs-specific rules. To add a new test target, just add # a new rule, customise ARGS or TEST_PACKAGES ad libitum, and # append the new rule to the TEST_TARGETS list. test-unit: ARGS=-timeout=15m test-unit: TEST_PACKAGES=$(PACKAGES_UNIT) +test-unit: run-tests test-race: ARGS=-race -test-race: TEST_PACKAGES=$(PACKAGES_NOSIMULATION) -$(TEST_TARGETS): run-tests +test-race: TEST_PACKAGES=$(PACKAGES_UNIT) +test-race: run-tests + +test-evmd: ARGS=-timeout=15m +test-evmd: TEST_PACKAGES=$(PACKAGES_EVMD) +test-evmd: + @cd evmd && go test -tags=test -mod=readonly $(ARGS) $(EXTRA_ARGS) $(PACKAGES_EVMD) test-unit-cover: ARGS=-timeout=15m -coverprofile=coverage.txt -covermode=atomic test-unit-cover: TEST_PACKAGES=$(PACKAGES_UNIT) -test-unit-cover: - @echo "Filtering ignored files from coverage.txt..." +test-unit-cover: run-tests + @echo "🔍 Running evm (root) coverage..." + @go test -tags=test $(COMMON_COVER_ARGS) -coverpkg=$(COVERPKG_ALL) -coverprofile=coverage.txt ./... + @echo "🔍 Running evmd coverage (evm 코어 로직만)..." + @cd evmd && go test -tags=test $(COMMON_COVER_ARGS) -coverpkg=$(COVERPKG_ALL) -coverprofile=coverage_evmd.txt ./... + @echo "🔀 Merging evmd coverage into root coverage..." + @tail -n +2 evmd/coverage_evmd.txt >> coverage.txt + @rm evmd/coverage_evmd.txt + @echo "🚫 Filtering ignored paths from coverage.txt..." @grep -v -E '/cmd/|/client/|/proto/|/testutil/|/mocks/|/test_.*\.go:|\.pb\.go:|\.pb\.gw\.go:|/x/[^/]+/module\.go:|/scripts/|/ibc/testing/|/version/|\.md:|\.pulsar\.go:' coverage.txt > tmp_coverage.txt && mv tmp_coverage.txt coverage.txt - @echo "Function-level coverage summary:" + @echo "📊 Function-level coverage summary:" @go tool cover -func=coverage.txt - run-tests: ifneq (,$(shell which tparse 2>/dev/null)) go test -tags=test -mod=readonly -json $(ARGS) $(EXTRA_ARGS) $(TEST_PACKAGES) | tparse else - go test -tags=test -mod=readonly $(ARGS) $(EXTRA_ARGS) $(TEST_PACKAGES) + go test -tags=test -mod=readonly $(ARGS) $(EXTRA_ARGS) $(TEST_PACKAGES) endif # Use the old Apple linker to workaround broken xcode - https://github.com/golang/go/issues/65169 diff --git a/ethereum/eip712/preprocess_test.go b/ethereum/eip712/preprocess_test.go index d8e405b52..c0376fda0 100644 --- a/ethereum/eip712/preprocess_test.go +++ b/ethereum/eip712/preprocess_test.go @@ -56,6 +56,10 @@ type TestCaseStruct struct { func TestLedgerPreprocessing(t *testing.T) { // Update bech32 prefix sdk.GetConfig().SetBech32PrefixForAccount(constants.ExampleBech32Prefix, "") + evmConfigurator := evmtypes.NewEVMConfigurator(). + WithEVMCoinInfo(constants.ExampleChainCoinInfo[constants.ExampleChainID]) + err := evmConfigurator.Configure() + require.NoError(t, err) testCases := []TestCaseStruct{ createBasicTestCase(t), diff --git a/evmd/tests/integration/ante_test.go b/evmd/tests/integration/ante/ante_test.go similarity index 51% rename from evmd/tests/integration/ante_test.go rename to evmd/tests/integration/ante/ante_test.go index 03294b1f4..f17fa8fe8 100644 --- a/evmd/tests/integration/ante_test.go +++ b/evmd/tests/integration/ante/ante_test.go @@ -1,11 +1,12 @@ -package integration +package ante import ( + "cosmosevm.io/evmd/tests/integration" "testing" "github.com/cosmos/evm/tests/integration/ante" ) func TestAnte_Integration(t *testing.T) { - ante.TestIntegrationAnteHandler(t, CreateEvmd) + ante.TestIntegrationAnteHandler(t, integration.CreateEvmd) } diff --git a/evmd/tests/integration/eips_test.go b/evmd/tests/integration/eips/eips_test.go similarity index 53% rename from evmd/tests/integration/eips_test.go rename to evmd/tests/integration/eips/eips_test.go index fffbefc79..a0bd4458b 100644 --- a/evmd/tests/integration/eips_test.go +++ b/evmd/tests/integration/eips/eips_test.go @@ -1,11 +1,12 @@ -package integration +package eips import ( + "cosmosevm.io/evmd/tests/integration" "testing" "github.com/cosmos/evm/tests/integration/eips" ) func Test_EIPs(t *testing.T) { - eips.TestEIPs(t, CreateEvmd) + eips.TestEIPs(t, integration.CreateEvmd) } diff --git a/evmd/tests/integration/iterate_contracts_test.go b/evmd/tests/integration/iterate_contracts_test.go deleted file mode 100644 index 8931986c4..000000000 --- a/evmd/tests/integration/iterate_contracts_test.go +++ /dev/null @@ -1,7 +0,0 @@ -package integration - -import "testing" - -func TestIterateContracts(t *testing.T) { - TestIterateContracts(t) -} diff --git a/evmd/tests/integration/precompile_bank_test.go b/evmd/tests/integration/precompiles/bank/precompile_bank_test.go similarity index 60% rename from evmd/tests/integration/precompile_bank_test.go rename to evmd/tests/integration/precompiles/bank/precompile_bank_test.go index 1009201c1..c7a35a5f1 100644 --- a/evmd/tests/integration/precompile_bank_test.go +++ b/evmd/tests/integration/precompiles/bank/precompile_bank_test.go @@ -1,6 +1,7 @@ -package integration +package bank import ( + "cosmosevm.io/evmd/tests/integration" "testing" "github.com/stretchr/testify/suite" @@ -9,10 +10,10 @@ import ( ) func TestBankPrecompileTestSuite(t *testing.T) { - s := bank.NewPrecompileTestSuite(CreateEvmd) + s := bank.NewPrecompileTestSuite(integration.CreateEvmd) suite.Run(t, s) } func TestBankPrecompileIntegrationTestSuite(t *testing.T) { - bank.TestIntegrationSuite(t, CreateEvmd) + bank.TestIntegrationSuite(t, integration.CreateEvmd) } diff --git a/evmd/tests/integration/precompile_bech32_test.go b/evmd/tests/integration/precompiles/bech32/precompile_bech32_test.go similarity index 63% rename from evmd/tests/integration/precompile_bech32_test.go rename to evmd/tests/integration/precompiles/bech32/precompile_bech32_test.go index 52052b86c..a712354ad 100644 --- a/evmd/tests/integration/precompile_bech32_test.go +++ b/evmd/tests/integration/precompiles/bech32/precompile_bech32_test.go @@ -1,6 +1,7 @@ -package integration +package bech32 import ( + "cosmosevm.io/evmd/tests/integration" "testing" "github.com/stretchr/testify/suite" @@ -9,6 +10,6 @@ import ( ) func TestBech32PrecompileTestSuite(t *testing.T) { - s := bech32.NewPrecompileTestSuite(CreateEvmd) + s := bech32.NewPrecompileTestSuite(integration.CreateEvmd) suite.Run(t, s) } diff --git a/evmd/tests/integration/precompile_distribution_test.go b/evmd/tests/integration/precompiles/distribution/precompile_distribution_test.go similarity index 57% rename from evmd/tests/integration/precompile_distribution_test.go rename to evmd/tests/integration/precompiles/distribution/precompile_distribution_test.go index 3d0c7d60d..d7d432a59 100644 --- a/evmd/tests/integration/precompile_distribution_test.go +++ b/evmd/tests/integration/precompiles/distribution/precompile_distribution_test.go @@ -1,6 +1,7 @@ -package integration +package distribution import ( + "cosmosevm.io/evmd/tests/integration" "testing" "github.com/stretchr/testify/suite" @@ -9,10 +10,10 @@ import ( ) func TestDistributionPrecompileTestSuite(t *testing.T) { - s := distribution.NewPrecompileTestSuite(CreateEvmd) + s := distribution.NewPrecompileTestSuite(integration.CreateEvmd) suite.Run(t, s) } func TestDistributionPrecompileIntegrationTestSuite(t *testing.T) { - distribution.TestPrecompileIntegrationTestSuite(t, CreateEvmd) + distribution.TestPrecompileIntegrationTestSuite(t, integration.CreateEvmd) } diff --git a/evmd/tests/integration/precompile_erc20_test.go b/evmd/tests/integration/precompiles/erc20/precompile_erc20_test.go similarity index 59% rename from evmd/tests/integration/precompile_erc20_test.go rename to evmd/tests/integration/precompiles/erc20/precompile_erc20_test.go index 81313367e..ee199a92d 100644 --- a/evmd/tests/integration/precompile_erc20_test.go +++ b/evmd/tests/integration/precompiles/erc20/precompile_erc20_test.go @@ -1,6 +1,7 @@ -package integration +package erc20 import ( + "cosmosevm.io/evmd/tests/integration" "testing" "github.com/stretchr/testify/suite" @@ -9,10 +10,10 @@ import ( ) func TestErc20PrecompileTestSuite(t *testing.T) { - s := erc21.NewPrecompileTestSuite(CreateEvmd) + s := erc21.NewPrecompileTestSuite(integration.CreateEvmd) suite.Run(t, s) } func TestErc20IntegrationTestSuite(t *testing.T) { - erc21.TestIntegrationTestSuite(t, CreateEvmd) + erc21.TestIntegrationTestSuite(t, integration.CreateEvmd) } diff --git a/evmd/tests/integration/precompile_evidence_test.go b/evmd/tests/integration/precompiles/evidence/precompile_evidence_test.go similarity index 62% rename from evmd/tests/integration/precompile_evidence_test.go rename to evmd/tests/integration/precompiles/evidence/precompile_evidence_test.go index 649d48c76..b1310bf74 100644 --- a/evmd/tests/integration/precompile_evidence_test.go +++ b/evmd/tests/integration/precompiles/evidence/precompile_evidence_test.go @@ -1,6 +1,7 @@ -package integration +package evidence import ( + "cosmosevm.io/evmd/tests/integration" "testing" "github.com/stretchr/testify/suite" @@ -9,6 +10,6 @@ import ( ) func TestEvidencePrecompileTestSuite(t *testing.T) { - s := evidence.NewPrecompileTestSuite(CreateEvmd) + s := evidence.NewPrecompileTestSuite(integration.CreateEvmd) suite.Run(t, s) } diff --git a/evmd/tests/integration/precompile_gov_test.go b/evmd/tests/integration/precompiles/gov/precompile_gov_test.go similarity index 58% rename from evmd/tests/integration/precompile_gov_test.go rename to evmd/tests/integration/precompiles/gov/precompile_gov_test.go index 3b474b89a..a35e8475f 100644 --- a/evmd/tests/integration/precompile_gov_test.go +++ b/evmd/tests/integration/precompiles/gov/precompile_gov_test.go @@ -1,6 +1,7 @@ -package integration +package gov import ( + "cosmosevm.io/evmd/tests/integration" "testing" "github.com/stretchr/testify/suite" @@ -9,10 +10,10 @@ import ( ) func TestGovPrecompileTestSuite(t *testing.T) { - s := gov.NewPrecompileTestSuite(CreateEvmd) + s := gov.NewPrecompileTestSuite(integration.CreateEvmd) suite.Run(t, s) } func TestGovPrecompileIntegrationTestSuite(t *testing.T) { - gov.TestPrecompileIntegrationTestSuite(t, CreateEvmd) + gov.TestPrecompileIntegrationTestSuite(t, integration.CreateEvmd) } diff --git a/evmd/tests/integration/precompile_p256_test.go b/evmd/tests/integration/precompiles/p256/precompile_p256_test.go similarity index 58% rename from evmd/tests/integration/precompile_p256_test.go rename to evmd/tests/integration/precompiles/p256/precompile_p256_test.go index 75600909c..1aa06984e 100644 --- a/evmd/tests/integration/precompile_p256_test.go +++ b/evmd/tests/integration/precompiles/p256/precompile_p256_test.go @@ -1,6 +1,7 @@ -package integration +package p256 import ( + "cosmosevm.io/evmd/tests/integration" "testing" "github.com/stretchr/testify/suite" @@ -9,10 +10,10 @@ import ( ) func TestP256PrecompileTestSuite(t *testing.T) { - s := p256.NewPrecompileTestSuite(CreateEvmd) + s := p256.NewPrecompileTestSuite(integration.CreateEvmd) suite.Run(t, s) } func TestP256PrecompileIntegrationTestSuite(t *testing.T) { - p256.TestPrecompileIntegrationTestSuite(t, CreateEvmd) + p256.TestPrecompileIntegrationTestSuite(t, integration.CreateEvmd) } diff --git a/evmd/tests/integration/precompile_slashing_test.go b/evmd/tests/integration/precompiles/slashing/precompile_slashing_test.go similarity index 62% rename from evmd/tests/integration/precompile_slashing_test.go rename to evmd/tests/integration/precompiles/slashing/precompile_slashing_test.go index ad0990a80..530eb1607 100644 --- a/evmd/tests/integration/precompile_slashing_test.go +++ b/evmd/tests/integration/precompiles/slashing/precompile_slashing_test.go @@ -1,6 +1,7 @@ -package integration +package slashing import ( + "cosmosevm.io/evmd/tests/integration" "testing" "github.com/stretchr/testify/suite" @@ -9,6 +10,6 @@ import ( ) func TestSlashingPrecompileTestSuite(t *testing.T) { - s := slashing.NewPrecompileTestSuite(CreateEvmd) + s := slashing.NewPrecompileTestSuite(integration.CreateEvmd) suite.Run(t, s) } diff --git a/evmd/tests/integration/precompile_staking_test.go b/evmd/tests/integration/precompiles/staking/precompile_staking_test.go similarity index 58% rename from evmd/tests/integration/precompile_staking_test.go rename to evmd/tests/integration/precompiles/staking/precompile_staking_test.go index 0c906bf6c..0a69a1062 100644 --- a/evmd/tests/integration/precompile_staking_test.go +++ b/evmd/tests/integration/precompiles/staking/precompile_staking_test.go @@ -1,6 +1,7 @@ -package integration +package staking import ( + "cosmosevm.io/evmd/tests/integration" "testing" "github.com/stretchr/testify/suite" @@ -9,10 +10,10 @@ import ( ) func TestStakingPrecompileTestSuite(t *testing.T) { - s := staking.NewPrecompileTestSuite(CreateEvmd) + s := staking.NewPrecompileTestSuite(integration.CreateEvmd) suite.Run(t, s) } func TestStakingPrecompileIntegrationTestSuite(t *testing.T) { - staking.TestPrecompileIntegrationTestSuite(t, CreateEvmd) + staking.TestPrecompileIntegrationTestSuite(t, integration.CreateEvmd) } diff --git a/evmd/tests/integration/precompile_werc20_test.go b/evmd/tests/integration/precompiles/werc20/precompile_werc20_test.go similarity index 58% rename from evmd/tests/integration/precompile_werc20_test.go rename to evmd/tests/integration/precompiles/werc20/precompile_werc20_test.go index 3a63d5c04..2e71f8aaa 100644 --- a/evmd/tests/integration/precompile_werc20_test.go +++ b/evmd/tests/integration/precompiles/werc20/precompile_werc20_test.go @@ -1,6 +1,7 @@ -package integration +package werc20 import ( + "cosmosevm.io/evmd/tests/integration" "testing" "github.com/stretchr/testify/suite" @@ -9,10 +10,10 @@ import ( ) func TestWERC20PrecompileUnitTestSuite(t *testing.T) { - s := werc20.NewPrecompileUnitTestSuite(CreateEvmd) + s := werc20.NewPrecompileUnitTestSuite(integration.CreateEvmd) suite.Run(t, s) } func TestWERC20PrecompileIntegrationTestSuite(t *testing.T) { - werc20.TestPrecompileIntegrationTestSuite(t, CreateEvmd) + werc20.TestPrecompileIntegrationTestSuite(t, integration.CreateEvmd) } diff --git a/evmd/tests/integration/x_vm_test.go b/evmd/tests/integration/x_vm_test.go index 92ddbe214..37c439a17 100644 --- a/evmd/tests/integration/x_vm_test.go +++ b/evmd/tests/integration/x_vm_test.go @@ -29,3 +29,7 @@ func TestVmAnteTestSuite(t *testing.T) { s := vm.NewEvmAnteTestSuite(CreateEvmd) suite.Run(t, s) } + +func TestIterateContracts(t *testing.T) { + vm.TestIterateContracts(t, CreateEvmd) +} diff --git a/tests/integration/x/vm/test_ctx.go b/tests/integration/x/vm/test_ctx.go index e84b029b6..6603fb9ca 100644 --- a/tests/integration/x/vm/test_ctx.go +++ b/tests/integration/x/vm/test_ctx.go @@ -7,11 +7,11 @@ import ( storetypes "cosmossdk.io/store/types" ) -func (suite *EvmAnteTestSuite) TestBuildEvmExecutionCtx() { - network := network.New(suite.create, nil) +func (s *EvmAnteTestSuite) TestBuildEvmExecutionCtx() { + network := network.New(s.create, s.options...) ctx := evmante.BuildEvmExecutionCtx(network.GetContext()) - suite.Equal(storetypes.GasConfig{}, ctx.KVGasConfig()) - suite.Equal(storetypes.GasConfig{}, ctx.TransientKVGasConfig()) + s.Equal(storetypes.GasConfig{}, ctx.KVGasConfig()) + s.Equal(storetypes.GasConfig{}, ctx.TransientKVGasConfig()) } From a8bd138bbf4a6fa743e5035e8eec68c1eb6a37e0 Mon Sep 17 00:00:00 2001 From: zsystm Date: Thu, 5 Jun 2025 13:26:21 +0900 Subject: [PATCH 07/21] gci formatted and re-organize authz test --- {evmd/tests/ante => ante/cosmos}/authz_test.go | 18 +++++++++++------- evmd/tests/integration/ante/ante_test.go | 3 ++- evmd/tests/integration/eips/eips_test.go | 3 ++- .../precompiles/bank/precompile_bank_test.go | 2 +- .../bech32/precompile_bech32_test.go | 2 +- .../precompile_distribution_test.go | 2 +- .../precompiles/erc20/precompile_erc20_test.go | 2 +- .../evidence/precompile_evidence_test.go | 2 +- .../precompiles/gov/precompile_gov_test.go | 2 +- .../precompiles/p256/precompile_p256_test.go | 2 +- .../slashing/precompile_slashing_test.go | 2 +- .../staking/precompile_staking_test.go | 2 +- .../werc20/precompile_werc20_test.go | 2 +- 13 files changed, 25 insertions(+), 19 deletions(-) rename {evmd/tests/ante => ante/cosmos}/authz_test.go (93%) diff --git a/evmd/tests/ante/authz_test.go b/ante/cosmos/authz_test.go similarity index 93% rename from evmd/tests/ante/authz_test.go rename to ante/cosmos/authz_test.go index f52ce2584..0fe7a3eef 100644 --- a/evmd/tests/ante/authz_test.go +++ b/ante/cosmos/authz_test.go @@ -1,16 +1,16 @@ -package ante_test +package cosmos_test import ( "fmt" "testing" "time" - "cosmosevm.io/evmd/tests/integration" "github.com/stretchr/testify/require" - cosmosante "github.com/cosmos/evm/ante/cosmos" + "github.com/cosmos/evm/ante/cosmos" + "github.com/cosmos/evm/encoding" "github.com/cosmos/evm/testutil" - "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/constants" evmtypes "github.com/cosmos/evm/x/vm/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -21,8 +21,12 @@ import ( ) func TestAuthzLimiterDecorator(t *testing.T) { - nw := network.New(integration.CreateEvmd) - txCfg := nw.GetEncodingConfig().TxConfig + evmConfigurator := evmtypes.NewEVMConfigurator(). + WithEVMCoinInfo(constants.ExampleChainCoinInfo[constants.ExampleChainID]) + err := evmConfigurator.Configure() + + encodingCfg := encoding.MakeConfig(constants.ExampleChainID.EVMChainID) + txCfg := encodingCfg.TxConfig testPrivKeys, testAddresses, err := testutil.GeneratePrivKeyAddressPairs(5) require.NoError(t, err) @@ -36,7 +40,7 @@ func TestAuthzLimiterDecorator(t *testing.T) { stakingAuthUndelegate, err := stakingtypes.NewStakeAuthorization([]sdk.ValAddress{validator}, nil, stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_UNDELEGATE, nil) require.NoError(t, err) - decorator := cosmosante.NewAuthzLimiterDecorator( + decorator := cosmos.NewAuthzLimiterDecorator( sdk.MsgTypeURL(&evmtypes.MsgEthereumTx{}), sdk.MsgTypeURL(&stakingtypes.MsgUndelegate{}), ) diff --git a/evmd/tests/integration/ante/ante_test.go b/evmd/tests/integration/ante/ante_test.go index f17fa8fe8..fb6651b64 100644 --- a/evmd/tests/integration/ante/ante_test.go +++ b/evmd/tests/integration/ante/ante_test.go @@ -1,9 +1,10 @@ package ante import ( - "cosmosevm.io/evmd/tests/integration" "testing" + "cosmosevm.io/evmd/tests/integration" + "github.com/cosmos/evm/tests/integration/ante" ) diff --git a/evmd/tests/integration/eips/eips_test.go b/evmd/tests/integration/eips/eips_test.go index a0bd4458b..34ecab0ce 100644 --- a/evmd/tests/integration/eips/eips_test.go +++ b/evmd/tests/integration/eips/eips_test.go @@ -1,9 +1,10 @@ package eips import ( - "cosmosevm.io/evmd/tests/integration" "testing" + "cosmosevm.io/evmd/tests/integration" + "github.com/cosmos/evm/tests/integration/eips" ) diff --git a/evmd/tests/integration/precompiles/bank/precompile_bank_test.go b/evmd/tests/integration/precompiles/bank/precompile_bank_test.go index c7a35a5f1..6f504cc54 100644 --- a/evmd/tests/integration/precompiles/bank/precompile_bank_test.go +++ b/evmd/tests/integration/precompiles/bank/precompile_bank_test.go @@ -1,9 +1,9 @@ package bank import ( - "cosmosevm.io/evmd/tests/integration" "testing" + "cosmosevm.io/evmd/tests/integration" "github.com/stretchr/testify/suite" "github.com/cosmos/evm/tests/integration/precompiles/bank" diff --git a/evmd/tests/integration/precompiles/bech32/precompile_bech32_test.go b/evmd/tests/integration/precompiles/bech32/precompile_bech32_test.go index a712354ad..73a64d3aa 100644 --- a/evmd/tests/integration/precompiles/bech32/precompile_bech32_test.go +++ b/evmd/tests/integration/precompiles/bech32/precompile_bech32_test.go @@ -1,9 +1,9 @@ package bech32 import ( - "cosmosevm.io/evmd/tests/integration" "testing" + "cosmosevm.io/evmd/tests/integration" "github.com/stretchr/testify/suite" "github.com/cosmos/evm/tests/integration/precompiles/bech32" diff --git a/evmd/tests/integration/precompiles/distribution/precompile_distribution_test.go b/evmd/tests/integration/precompiles/distribution/precompile_distribution_test.go index d7d432a59..37317a84a 100644 --- a/evmd/tests/integration/precompiles/distribution/precompile_distribution_test.go +++ b/evmd/tests/integration/precompiles/distribution/precompile_distribution_test.go @@ -1,9 +1,9 @@ package distribution import ( - "cosmosevm.io/evmd/tests/integration" "testing" + "cosmosevm.io/evmd/tests/integration" "github.com/stretchr/testify/suite" "github.com/cosmos/evm/tests/integration/precompiles/distribution" diff --git a/evmd/tests/integration/precompiles/erc20/precompile_erc20_test.go b/evmd/tests/integration/precompiles/erc20/precompile_erc20_test.go index ee199a92d..18547f268 100644 --- a/evmd/tests/integration/precompiles/erc20/precompile_erc20_test.go +++ b/evmd/tests/integration/precompiles/erc20/precompile_erc20_test.go @@ -1,9 +1,9 @@ package erc20 import ( - "cosmosevm.io/evmd/tests/integration" "testing" + "cosmosevm.io/evmd/tests/integration" "github.com/stretchr/testify/suite" erc21 "github.com/cosmos/evm/tests/integration/precompiles/erc20" diff --git a/evmd/tests/integration/precompiles/evidence/precompile_evidence_test.go b/evmd/tests/integration/precompiles/evidence/precompile_evidence_test.go index b1310bf74..ac72e94cb 100644 --- a/evmd/tests/integration/precompiles/evidence/precompile_evidence_test.go +++ b/evmd/tests/integration/precompiles/evidence/precompile_evidence_test.go @@ -1,9 +1,9 @@ package evidence import ( - "cosmosevm.io/evmd/tests/integration" "testing" + "cosmosevm.io/evmd/tests/integration" "github.com/stretchr/testify/suite" "github.com/cosmos/evm/tests/integration/precompiles/evidence" diff --git a/evmd/tests/integration/precompiles/gov/precompile_gov_test.go b/evmd/tests/integration/precompiles/gov/precompile_gov_test.go index a35e8475f..b33005841 100644 --- a/evmd/tests/integration/precompiles/gov/precompile_gov_test.go +++ b/evmd/tests/integration/precompiles/gov/precompile_gov_test.go @@ -1,9 +1,9 @@ package gov import ( - "cosmosevm.io/evmd/tests/integration" "testing" + "cosmosevm.io/evmd/tests/integration" "github.com/stretchr/testify/suite" "github.com/cosmos/evm/tests/integration/precompiles/gov" diff --git a/evmd/tests/integration/precompiles/p256/precompile_p256_test.go b/evmd/tests/integration/precompiles/p256/precompile_p256_test.go index 1aa06984e..1a8da1297 100644 --- a/evmd/tests/integration/precompiles/p256/precompile_p256_test.go +++ b/evmd/tests/integration/precompiles/p256/precompile_p256_test.go @@ -1,9 +1,9 @@ package p256 import ( - "cosmosevm.io/evmd/tests/integration" "testing" + "cosmosevm.io/evmd/tests/integration" "github.com/stretchr/testify/suite" "github.com/cosmos/evm/tests/integration/precompiles/p256" diff --git a/evmd/tests/integration/precompiles/slashing/precompile_slashing_test.go b/evmd/tests/integration/precompiles/slashing/precompile_slashing_test.go index 530eb1607..80f2f7eb8 100644 --- a/evmd/tests/integration/precompiles/slashing/precompile_slashing_test.go +++ b/evmd/tests/integration/precompiles/slashing/precompile_slashing_test.go @@ -1,9 +1,9 @@ package slashing import ( - "cosmosevm.io/evmd/tests/integration" "testing" + "cosmosevm.io/evmd/tests/integration" "github.com/stretchr/testify/suite" "github.com/cosmos/evm/tests/integration/precompiles/slashing" diff --git a/evmd/tests/integration/precompiles/staking/precompile_staking_test.go b/evmd/tests/integration/precompiles/staking/precompile_staking_test.go index 0a69a1062..f73015886 100644 --- a/evmd/tests/integration/precompiles/staking/precompile_staking_test.go +++ b/evmd/tests/integration/precompiles/staking/precompile_staking_test.go @@ -1,9 +1,9 @@ package staking import ( - "cosmosevm.io/evmd/tests/integration" "testing" + "cosmosevm.io/evmd/tests/integration" "github.com/stretchr/testify/suite" "github.com/cosmos/evm/tests/integration/precompiles/staking" diff --git a/evmd/tests/integration/precompiles/werc20/precompile_werc20_test.go b/evmd/tests/integration/precompiles/werc20/precompile_werc20_test.go index 2e71f8aaa..1a08f0047 100644 --- a/evmd/tests/integration/precompiles/werc20/precompile_werc20_test.go +++ b/evmd/tests/integration/precompiles/werc20/precompile_werc20_test.go @@ -1,9 +1,9 @@ package werc20 import ( - "cosmosevm.io/evmd/tests/integration" "testing" + "cosmosevm.io/evmd/tests/integration" "github.com/stretchr/testify/suite" "github.com/cosmos/evm/tests/integration/precompiles/werc20" From 1111de9adfdea9416d7bd555b60acbe082916621 Mon Sep 17 00:00:00 2001 From: zsystm Date: Thu, 5 Jun 2025 13:32:52 +0900 Subject: [PATCH 08/21] add missed test case --- tests/integration/ante/test_authz.go | 235 +++++++++++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 tests/integration/ante/test_authz.go diff --git a/tests/integration/ante/test_authz.go b/tests/integration/ante/test_authz.go new file mode 100644 index 000000000..2bb2097d5 --- /dev/null +++ b/tests/integration/ante/test_authz.go @@ -0,0 +1,235 @@ +package ante + +import ( + "fmt" + "math/big" + "time" + + ethtypes "github.com/ethereum/go-ethereum/core/types" + + abci "github.com/cometbft/cometbft/abci/types" + + "github.com/cosmos/evm/testutil" + "github.com/cosmos/evm/testutil/integration/base/factory" + utiltx "github.com/cosmos/evm/testutil/tx" + evmtypes "github.com/cosmos/evm/x/vm/types" + + "cosmossdk.io/math" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + sdkvesting "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" + "github.com/cosmos/cosmos-sdk/x/authz" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +func (suite *AnteTestSuite) TestRejectMsgsInAuthz() { + _, testAddresses, err := testutil.GeneratePrivKeyAddressPairs(10) + suite.Require().NoError(err) + + var gasLimit uint64 = 1000000 + distantFuture := time.Date(9000, 1, 1, 0, 0, 0, 0, time.UTC) + + nw := suite.GetNetwork() + evmDenom := evmtypes.GetEVMCoinDenom() + + baseFeeRes, err := nw.GetEvmClient().BaseFee(nw.GetContext(), &evmtypes.QueryBaseFeeRequest{}) + suite.Require().NoError(err, "failed to get base fee") + + // create a dummy MsgEthereumTx for the test + // otherwise throws error that cannot unpack tx data + msgEthereumTx := evmtypes.NewTx(&evmtypes.EvmTxArgs{ + ChainID: nw.GetEIP155ChainID(), + Nonce: 0, + GasLimit: gasLimit, + GasFeeCap: baseFeeRes.BaseFee.BigInt(), + GasTipCap: big.NewInt(1), + Input: nil, + Accesses: ðtypes.AccessList{}, + }) + + newMsgGrant := func(msgTypeUrl string) *authz.MsgGrant { + msg, err := authz.NewMsgGrant( + testAddresses[0], + testAddresses[1], + authz.NewGenericAuthorization(msgTypeUrl), + &distantFuture, + ) + if err != nil { + panic(err) + } + return msg + } + + testcases := []struct { + name string + msgs []sdk.Msg + expectedCode uint32 + isEIP712 bool + }{ + { + name: "a MsgGrant with MsgEthereumTx typeURL on the authorization field is blocked", + msgs: []sdk.Msg{newMsgGrant(sdk.MsgTypeURL(&evmtypes.MsgEthereumTx{}))}, + expectedCode: sdkerrors.ErrUnauthorized.ABCICode(), + }, + { + name: "a MsgGrant with MsgCreateVestingAccount typeURL on the authorization field is blocked", + msgs: []sdk.Msg{newMsgGrant(sdk.MsgTypeURL(&sdkvesting.MsgCreateVestingAccount{}))}, + expectedCode: sdkerrors.ErrUnauthorized.ABCICode(), + }, + { + name: "a MsgGrant with MsgEthereumTx typeURL on the authorization field included on EIP712 tx is blocked", + msgs: []sdk.Msg{newMsgGrant(sdk.MsgTypeURL(&evmtypes.MsgEthereumTx{}))}, + expectedCode: sdkerrors.ErrUnauthorized.ABCICode(), + isEIP712: true, + }, + { + name: "a MsgExec with nested messages (valid: MsgSend and invalid: MsgEthereumTx) is blocked", + msgs: []sdk.Msg{ + testutil.NewMsgExec( + testAddresses[1], + []sdk.Msg{ + banktypes.NewMsgSend( + testAddresses[0], + testAddresses[3], + sdk.NewCoins(sdk.NewInt64Coin(evmDenom, 100e6)), + ), + msgEthereumTx, + }, + ), + }, + expectedCode: sdkerrors.ErrUnauthorized.ABCICode(), + }, + { + name: "a MsgExec with nested MsgExec messages that has invalid messages is blocked", + msgs: []sdk.Msg{ + testutil.CreateNestedMsgExec( + testAddresses[1], + 2, + []sdk.Msg{ + msgEthereumTx, + }, + ), + }, + expectedCode: sdkerrors.ErrUnauthorized.ABCICode(), + }, + { + name: "a MsgExec with more nested MsgExec messages than allowed and with valid messages is blocked", + msgs: []sdk.Msg{ + testutil.CreateNestedMsgExec( + testAddresses[1], + 6, + []sdk.Msg{ + banktypes.NewMsgSend( + testAddresses[0], + testAddresses[3], + sdk.NewCoins(sdk.NewInt64Coin(evmDenom, 100e6)), + ), + }, + ), + }, + expectedCode: sdkerrors.ErrUnauthorized.ABCICode(), + }, + { + name: "two MsgExec messages NOT containing a blocked msg but between the two have more nesting than the allowed. Then, is blocked", + msgs: []sdk.Msg{ + testutil.CreateNestedMsgExec( + testAddresses[1], + 5, + []sdk.Msg{ + banktypes.NewMsgSend( + testAddresses[0], + testAddresses[3], + sdk.NewCoins(sdk.NewInt64Coin(evmDenom, 100e6)), + ), + }, + ), + testutil.CreateNestedMsgExec( + testAddresses[1], + 5, + []sdk.Msg{ + banktypes.NewMsgSend( + testAddresses[0], + testAddresses[3], + sdk.NewCoins(sdk.NewInt64Coin(evmDenom, 100e6)), + ), + }, + ), + }, + expectedCode: sdkerrors.ErrUnauthorized.ABCICode(), + }, + } + + for _, tc := range testcases { + suite.Run(fmt.Sprintf("Case %s", tc.name), func() { + suite.SetupTest() + nw = suite.GetNetwork() + var ( + tx sdk.Tx + err error + ) + ctx := nw.GetContext() + priv := suite.GetKeyring().GetPrivKey(0) + + if tc.isEIP712 { + coinAmount := sdk.NewCoin(evmDenom, math.NewInt(20)) + fees := sdk.NewCoins(coinAmount) + cosmosTxArgs := utiltx.CosmosTxArgs{ + TxCfg: suite.GetClientCtx().TxConfig, + Priv: priv, + ChainID: ctx.ChainID(), + Gas: 200000, + Fees: fees, + Msgs: tc.msgs, + } + + tx, err = utiltx.CreateEIP712CosmosTx( + ctx, + nw.App, + utiltx.EIP712TxArgs{ + CosmosTxArgs: cosmosTxArgs, + UseLegacyTypedData: true, + }, + ) + } else { + tx, err = suite.GetTxFactory().BuildCosmosTx( + priv, + factory.CosmosTxArgs{ + Gas: &gasLimit, + Msgs: tc.msgs, + }, + ) + } + suite.Require().NoError(err) + + txEncoder := suite.GetClientCtx().TxConfig.TxEncoder() + bz, err := txEncoder(tx) + suite.Require().NoError(err) + + resCheckTx, err := nw.App.CheckTx( + &abci.RequestCheckTx{ + Tx: bz, + Type: abci.CheckTxType_New, + }, + ) + suite.Require().NoError(err) + suite.Require().Equal(resCheckTx.Code, tc.expectedCode, resCheckTx.Log) + + header := ctx.BlockHeader() + blockRes, err := nw.App.FinalizeBlock( + &abci.RequestFinalizeBlock{ + Height: ctx.BlockHeight() + 1, + Txs: [][]byte{bz}, + Hash: header.AppHash, + NextValidatorsHash: header.NextValidatorsHash, + ProposerAddress: header.ProposerAddress, + Time: header.Time.Add(time.Second), + }, + ) + suite.Require().NoError(err) + suite.Require().Len(blockRes.TxResults, 1) + txRes := blockRes.TxResults[0] + suite.Require().Equal(txRes.Code, tc.expectedCode, txRes.Log) + }) + } +} From a8ab4a1abf429478ab3ef77d8f8f2ab446bc71de Mon Sep 17 00:00:00 2001 From: zsystm Date: Thu, 5 Jun 2025 13:34:42 +0900 Subject: [PATCH 09/21] fix ci issue --- ante/cosmos/authz_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/ante/cosmos/authz_test.go b/ante/cosmos/authz_test.go index 0fe7a3eef..aee72f910 100644 --- a/ante/cosmos/authz_test.go +++ b/ante/cosmos/authz_test.go @@ -24,6 +24,7 @@ func TestAuthzLimiterDecorator(t *testing.T) { evmConfigurator := evmtypes.NewEVMConfigurator(). WithEVMCoinInfo(constants.ExampleChainCoinInfo[constants.ExampleChainID]) err := evmConfigurator.Configure() + require.NoError(t, err) encodingCfg := encoding.MakeConfig(constants.ExampleChainID.EVMChainID) txCfg := encodingCfg.TxConfig From 361336a2bcbcee70477efdc1446b3503d2bd8e8b Mon Sep 17 00:00:00 2001 From: zsystm Date: Thu, 5 Jun 2025 13:55:30 +0900 Subject: [PATCH 10/21] erc20 cyclic dependencies resolved --- evmd/app.go | 7 +- evmd/precompiles.go | 2 +- interfaces.go | 91 +------------------ precompiles/bank/bank.go | 6 +- .../precompiles/bank/test_utils.go | 4 +- tests/integration/x/erc20/test_evm.go | 4 +- tests/integration/x/erc20/test_genesis.go | 7 +- .../integration/x/erc20/test_ibc_callback.go | 2 +- tests/integration/x/erc20/test_msg_server.go | 26 +++--- tests/integration/x/erc20/test_proposals.go | 2 +- 10 files changed, 31 insertions(+), 120 deletions(-) diff --git a/evmd/app.go b/evmd/app.go index 6c1d8446c..8814148ef 100644 --- a/evmd/app.go +++ b/evmd/app.go @@ -19,7 +19,6 @@ import ( abci "github.com/cometbft/cometbft/abci/types" dbm "github.com/cosmos/cosmos-db" - "github.com/cosmos/evm" evmante "github.com/cosmos/evm/ante" cosmosevmante "github.com/cosmos/evm/ante/evm" evmosencoding "github.com/cosmos/evm/encoding" @@ -1039,12 +1038,12 @@ func (app *EVMD) GetEVMKeeper() *evmkeeper.Keeper { return app.EVMKeeper } -func (app *EVMD) GetErc20Keeper() evm.Erc20Keeper { +func (app *EVMD) GetErc20Keeper() *erc20keeper.Keeper { return &app.Erc20Keeper } -func (app *EVMD) SetErc20Keeper(erc20Keeper evm.Erc20Keeper) { - app.Erc20Keeper = *erc20Keeper.(*erc20keeper.Keeper) +func (app *EVMD) SetErc20Keeper(erc20Keeper erc20keeper.Keeper) { + app.Erc20Keeper = erc20Keeper } func (app *EVMD) GetGovKeeper() govkeeper.Keeper { diff --git a/evmd/precompiles.go b/evmd/precompiles.go index 01aa23418..49fcdab1a 100644 --- a/evmd/precompiles.go +++ b/evmd/precompiles.go @@ -84,7 +84,7 @@ func NewAvailableStaticPrecompiles( panic(fmt.Errorf("failed to instantiate ICS20 precompile: %w", err)) } - bankPrecompile, err := bankprecompile.NewPrecompile(bankKeeper, &erc20Keeper) + bankPrecompile, err := bankprecompile.NewPrecompile(bankKeeper, erc20Keeper) if err != nil { panic(fmt.Errorf("failed to instantiate bank precompile: %w", err)) } diff --git a/interfaces.go b/interfaces.go index e249f24fb..46462c26e 100644 --- a/interfaces.go +++ b/interfaces.go @@ -1,22 +1,13 @@ package evm import ( - "context" "encoding/json" - "math/big" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/vm" - - erc20types "github.com/cosmos/evm/x/erc20/types" + erc20keeper "github.com/cosmos/evm/x/erc20/keeper" feemarketkeeper "github.com/cosmos/evm/x/feemarket/keeper" transferkeeper "github.com/cosmos/evm/x/ibc/transfer/keeper" precisebankkeeper "github.com/cosmos/evm/x/precisebank/keeper" evmkeeper "github.com/cosmos/evm/x/vm/keeper" - transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" - channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" - "github.com/cosmos/ibc-go/v10/modules/core/exported" ibctesting "github.com/cosmos/ibc-go/v10/testing" storetypes "cosmossdk.io/store/types" @@ -30,7 +21,6 @@ import ( authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper" @@ -46,8 +36,8 @@ type EvmApp interface { //nolint:revive InterfaceRegistry() types.InterfaceRegistry ChainID() string GetEVMKeeper() *evmkeeper.Keeper - GetErc20Keeper() Erc20Keeper - SetErc20Keeper(Erc20Keeper) + GetErc20Keeper() *erc20keeper.Keeper + SetErc20Keeper(erc20keeper.Keeper) GetGovKeeper() govkeeper.Keeper GetSlashingKeeper() slashingkeeper.Keeper GetEvidenceKeeper() *evidencekeeper.Keeper @@ -68,78 +58,3 @@ type EvmApp interface { //nolint:revive GetSubspace(moduleName string) paramstypes.Subspace MsgServiceRouter() *baseapp.MsgServiceRouter } - -type Erc20Keeper interface { - SetToken(ctx sdk.Context, pair erc20types.TokenPair) - GetTokenPairID(ctx sdk.Context, token string) []byte - GetTokenPair(ctx sdk.Context, id []byte) (erc20types.TokenPair, bool) - GetParams(ctx sdk.Context) erc20types.Params - SetAllowance(ctx sdk.Context, erc20 common.Address, owner common.Address, spender common.Address, value *big.Int) error - GetAllowance(ctx sdk.Context, erc20 common.Address, owner common.Address, spender common.Address) (*big.Int, error) - DeleteAllowance(ctx sdk.Context, erc20 common.Address, owner common.Address, spender common.Address) error - EnableDynamicPrecompiles(ctx sdk.Context, addresses ...common.Address) error - TokenPairs(context.Context, *erc20types.QueryTokenPairsRequest) (*erc20types.QueryTokenPairsResponse, error) - TokenPair(context.Context, *erc20types.QueryTokenPairRequest) (*erc20types.QueryTokenPairResponse, error) - Params(context.Context, *erc20types.QueryParamsRequest) (*erc20types.QueryParamsResponse, error) - RegisterERC20Extension(ctx sdk.Context, denom string) (*erc20types.TokenPair, error) - GetDenomMap(ctx sdk.Context, denom string) []byte - GetERC20Map(ctx sdk.Context, erc20 common.Address) []byte - BalanceOf(ctx sdk.Context, abi abi.ABI, contract, account common.Address) *big.Int - GetCoinAddress(ctx sdk.Context, denom string) (common.Address, error) - GetTokenDenom(ctx sdk.Context, tokenAddress common.Address) (string, error) - ConvertERC20(ctx context.Context, msg *erc20types.MsgConvertERC20) (*erc20types.MsgConvertERC20Response, error) - IsERC20Enabled(ctx sdk.Context) bool - GetTokenPairs(ctx sdk.Context) []erc20types.TokenPair - GetAllowances(ctx sdk.Context) []erc20types.Allowance - SetERC20Map(ctx sdk.Context, erc20 common.Address, id []byte) - SetDenomMap(ctx sdk.Context, denom string, id []byte) - CreateCoinMetadata(ctx sdk.Context, contract common.Address) (*banktypes.Metadata, error) - SetPermissionlessRegistration(ctx sdk.Context, permissionlessRegistration bool) - RegisterERC20(goCtx context.Context, req *erc20types.MsgRegisterERC20) (*erc20types.MsgRegisterERC20Response, error) - ToggleConversion(goCtx context.Context, req *erc20types.MsgToggleConversion) (*erc20types.MsgToggleConversionResponse, error) - UnsafeSetAllowance( - ctx sdk.Context, - erc20 common.Address, - owner common.Address, - spender common.Address, - value *big.Int, - ) error - DeleteTokenPair(ctx sdk.Context, tokenPair erc20types.TokenPair) - RegisterERC20CodeHash(ctx sdk.Context, erc20Addr common.Address) error - UnRegisterERC20CodeHash(ctx sdk.Context, erc20Addr common.Address) error - QueryERC20( - ctx sdk.Context, - contract common.Address, - ) (erc20types.ERC20Data, error) - SetTokenPair(ctx sdk.Context, tokenPair erc20types.TokenPair) - SetParams(ctx sdk.Context, newParams erc20types.Params) error - ConvertCoinToERC20FromPacket(ctx sdk.Context, data transfertypes.FungibleTokenPacketData) error - OnRecvPacket( - ctx sdk.Context, - packet channeltypes.Packet, - ack exported.Acknowledgement, - ) exported.Acknowledgement - OnAcknowledgementPacket( - ctx sdk.Context, _ channeltypes.Packet, - data transfertypes.FungibleTokenPacketData, - ack channeltypes.Acknowledgement, - ) error - OnTimeoutPacket(ctx sdk.Context, _ channeltypes.Packet, data transfertypes.FungibleTokenPacketData) error - MintingEnabled( - ctx sdk.Context, - sender, receiver sdk.AccAddress, - token string, - ) (erc20types.TokenPair, error) - ConvertCoin( - goCtx context.Context, - msg *erc20types.MsgConvertCoin, - ) (*erc20types.MsgConvertCoinResponse, error) - UpdateParams(goCtx context.Context, req *erc20types.MsgUpdateParams) (*erc20types.MsgUpdateParamsResponse, error) - GetERC20PrecompileInstance( - ctx sdk.Context, - address common.Address, - ) (contract vm.PrecompiledContract, found bool, err error) - IsTokenPairRegistered(ctx sdk.Context, id []byte) bool - IsERC20Registered(ctx sdk.Context, erc20 common.Address) bool - IsDenomRegistered(ctx sdk.Context, denom string) bool -} diff --git a/precompiles/bank/bank.go b/precompiles/bank/bank.go index 6cb201b90..dde996ba2 100644 --- a/precompiles/bank/bank.go +++ b/precompiles/bank/bank.go @@ -14,8 +14,8 @@ import ( "github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/vm" - "github.com/cosmos/evm" cmn "github.com/cosmos/evm/precompiles/common" + erc20Keeper "github.com/cosmos/evm/x/erc20/keeper" evmtypes "github.com/cosmos/evm/x/vm/types" storetypes "cosmossdk.io/store/types" @@ -43,14 +43,14 @@ var f embed.FS type Precompile struct { cmn.Precompile bankKeeper cmn.BankKeeper - erc20Keeper evm.Erc20Keeper + erc20Keeper erc20Keeper.Keeper } // NewPrecompile creates a new bank Precompile instance implementing the // PrecompiledContract interface. func NewPrecompile( bankKeeper cmn.BankKeeper, - erc20Keeper evm.Erc20Keeper, + erc20Keeper erc20Keeper.Keeper, ) (*Precompile, error) { newABI, err := cmn.LoadABI(f, "abi.json") if err != nil { diff --git a/tests/integration/precompiles/bank/test_utils.go b/tests/integration/precompiles/bank/test_utils.go index 7fdfa5a6d..83c943341 100644 --- a/tests/integration/precompiles/bank/test_utils.go +++ b/tests/integration/precompiles/bank/test_utils.go @@ -23,7 +23,7 @@ import ( func (s *PrecompileTestSuite) setupBankPrecompile() *bank.Precompile { precompile, err := bank.NewPrecompile( s.network.App.GetBankKeeper(), - s.network.App.GetErc20Keeper(), + *s.network.App.GetErc20Keeper(), ) s.Require().NoError(err, "failed to create bank precompile") @@ -36,7 +36,7 @@ func (s *PrecompileTestSuite) setupBankPrecompile() *bank.Precompile { func (is *IntegrationTestSuite) setupBankPrecompile() *bank.Precompile { precompile, err := bank.NewPrecompile( is.network.App.GetBankKeeper(), - is.network.App.GetErc20Keeper(), + *is.network.App.GetErc20Keeper(), ) Expect(err).ToNot(HaveOccurred(), "failed to create bank precompile") return precompile diff --git a/tests/integration/x/erc20/test_evm.go b/tests/integration/x/erc20/test_evm.go index 1ece254d1..cdf401b3a 100644 --- a/tests/integration/x/erc20/test_evm.go +++ b/tests/integration/x/erc20/test_evm.go @@ -121,7 +121,7 @@ func (s *KeeperTestSuite) TestBalanceOf() { s.network.App.GetAccountKeeper(), s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), &transferKeeper) - s.network.App.SetErc20Keeper(&erc20Keeper) + s.network.App.SetErc20Keeper(erc20Keeper) tc.malleate() @@ -221,7 +221,7 @@ func (s *KeeperTestSuite) TestQueryERC20ForceFail() { s.network.App.GetAccountKeeper(), s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), &transferKeeper) - s.network.App.SetErc20Keeper(&erc20Keeper) + s.network.App.SetErc20Keeper(erc20Keeper) tc.malleate() diff --git a/tests/integration/x/erc20/test_genesis.go b/tests/integration/x/erc20/test_genesis.go index 4b419da0f..3c5b5e02e 100644 --- a/tests/integration/x/erc20/test_genesis.go +++ b/tests/integration/x/erc20/test_genesis.go @@ -6,7 +6,6 @@ import ( "github.com/cosmos/evm/testutil/integration/evm/network" utiltx "github.com/cosmos/evm/testutil/tx" "github.com/cosmos/evm/x/erc20" - "github.com/cosmos/evm/x/erc20/keeper" "github.com/cosmos/evm/x/erc20/types" transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" @@ -200,11 +199,9 @@ func (s *GenesisTestSuite) TestErc20ExportGenesis() { for _, tc := range testGenCases { erc20Keeper := s.network.App.GetErc20Keeper() - impl, ok := erc20Keeper.(*keeper.Keeper) - s.Require().True(ok, "Erc20Keeper should implement Keeper interface") - erc20.InitGenesis(s.network.GetContext(), *impl, s.network.App.GetAccountKeeper(), tc.genesisState) + erc20.InitGenesis(s.network.GetContext(), *erc20Keeper, s.network.App.GetAccountKeeper(), tc.genesisState) s.Require().NotPanics(func() { - genesisExported := erc20.ExportGenesis(s.network.GetContext(), *impl) + genesisExported := erc20.ExportGenesis(s.network.GetContext(), *erc20Keeper) params := s.network.App.GetErc20Keeper().GetParams(s.network.GetContext()) s.Require().Equal(genesisExported.Params, params) diff --git a/tests/integration/x/erc20/test_ibc_callback.go b/tests/integration/x/erc20/test_ibc_callback.go index e49490bf2..e1ed9cd81 100644 --- a/tests/integration/x/erc20/test_ibc_callback.go +++ b/tests/integration/x/erc20/test_ibc_callback.go @@ -260,7 +260,7 @@ func (s *KeeperTestSuite) TestOnRecvPacket() { s.network.App.GetStakingKeeper(), &tranasferKeeper, ) - s.network.App.SetErc20Keeper(&erc20Keeper) + s.network.App.SetErc20Keeper(erc20Keeper) // Fund receiver account with ATOM, ERC20 coins and IBC vouchers // We do this since we are interested in the conversion portion w/ OnRecvPacket diff --git a/tests/integration/x/erc20/test_msg_server.go b/tests/integration/x/erc20/test_msg_server.go index f98b9c4ae..2eb4f0005 100644 --- a/tests/integration/x/erc20/test_msg_server.go +++ b/tests/integration/x/erc20/test_msg_server.go @@ -135,7 +135,7 @@ func (s *KeeperTestSuite) TestConvertERC20NativeERC20() { s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), &transferKeeper, ) - s.network.App.SetErc20Keeper(&erc20Keeper) + s.network.App.SetErc20Keeper(erc20Keeper) existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} balance := make([]uint8, 32) @@ -164,7 +164,7 @@ func (s *KeeperTestSuite) TestConvertERC20NativeERC20() { s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), &transferKeeper, ) - s.network.App.SetErc20Keeper(&erc20Keeper) + s.network.App.SetErc20Keeper(erc20Keeper) existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} balance := make([]uint8, 32) @@ -192,7 +192,7 @@ func (s *KeeperTestSuite) TestConvertERC20NativeERC20() { s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), &transferKeeper, ) - s.network.App.SetErc20Keeper(&erc20Keeper) + s.network.App.SetErc20Keeper(erc20Keeper) existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} balance := make([]uint8, 32) @@ -221,7 +221,7 @@ func (s *KeeperTestSuite) TestConvertERC20NativeERC20() { s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), &transferKeeper, ) - s.network.App.SetErc20Keeper(&erc20Keeper) + s.network.App.SetErc20Keeper(erc20Keeper) existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} balance := make([]uint8, 32) @@ -250,7 +250,7 @@ func (s *KeeperTestSuite) TestConvertERC20NativeERC20() { authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), mockBankKeeper, s.network.App.GetEVMKeeper(), s.network.App.GetStakingKeeper(), &transferKeeper) - s.network.App.SetErc20Keeper(&erc20Keeper) + s.network.App.SetErc20Keeper(erc20Keeper) mockBankKeeper.EXPECT().MintCoins(gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("failed to mint")).AnyTimes() mockBankKeeper.EXPECT().SendCoinsFromModuleToAccount(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("failed to unescrow")).AnyTimes() @@ -275,7 +275,7 @@ func (s *KeeperTestSuite) TestConvertERC20NativeERC20() { authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), mockBankKeeper, s.network.App.GetEVMKeeper(), s.network.App.GetStakingKeeper(), &transferKeeper) - s.network.App.SetErc20Keeper(&erc20Keeper) + s.network.App.SetErc20Keeper(erc20Keeper) mockBankKeeper.EXPECT().MintCoins(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) mockBankKeeper.EXPECT().SendCoinsFromModuleToAccount(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("failed to unescrow")) @@ -300,7 +300,7 @@ func (s *KeeperTestSuite) TestConvertERC20NativeERC20() { authtypes.NewModuleAddress(govtypes.ModuleName), s.network.App.GetAccountKeeper(), mockBankKeeper, s.network.App.GetEVMKeeper(), s.network.App.GetStakingKeeper(), &transferKeeper) - s.network.App.SetErc20Keeper(&erc20Keeper) + s.network.App.SetErc20Keeper(erc20Keeper) mockBankKeeper.EXPECT().MintCoins(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) mockBankKeeper.EXPECT().SendCoinsFromModuleToAccount(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) @@ -434,7 +434,7 @@ func (s *KeeperTestSuite) TestConvertNativeERC20ToEVMERC20() { s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), &transferKeeper, ) - s.network.App.SetErc20Keeper(&erc20Keeper) + s.network.App.SetErc20Keeper(erc20Keeper) existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} balance := make([]uint8, 32) @@ -463,7 +463,7 @@ func (s *KeeperTestSuite) TestConvertNativeERC20ToEVMERC20() { s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), &transferKeeper, ) - s.network.App.SetErc20Keeper(&erc20Keeper) + s.network.App.SetErc20Keeper(erc20Keeper) existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} balance := make([]uint8, 32) @@ -491,7 +491,7 @@ func (s *KeeperTestSuite) TestConvertNativeERC20ToEVMERC20() { s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), &transferKeeper, ) - s.network.App.SetErc20Keeper(&erc20Keeper) + s.network.App.SetErc20Keeper(erc20Keeper) existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} balance := make([]uint8, 32) @@ -520,7 +520,7 @@ func (s *KeeperTestSuite) TestConvertNativeERC20ToEVMERC20() { s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), &transferKeeper, ) - s.network.App.SetErc20Keeper(&erc20Keeper) + s.network.App.SetErc20Keeper(erc20Keeper) existingAcc := &statedb.Account{Nonce: uint64(1), Balance: uint256.NewInt(1)} balance := make([]uint8, 32) @@ -550,7 +550,7 @@ func (s *KeeperTestSuite) TestConvertNativeERC20ToEVMERC20() { mockBankKeeper, s.network.App.GetEVMKeeper(), s.network.App.GetStakingKeeper(), &transferKeeper, ) - s.network.App.SetErc20Keeper(&erc20Keeper) + s.network.App.SetErc20Keeper(erc20Keeper) mockBankKeeper.EXPECT().MintCoins(gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("failed to mint")).AnyTimes() mockBankKeeper.EXPECT().SendCoinsFromAccountToModule(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("failed to unescrow")).AnyTimes() @@ -576,7 +576,7 @@ func (s *KeeperTestSuite) TestConvertNativeERC20ToEVMERC20() { mockBankKeeper, s.network.App.GetEVMKeeper(), s.network.App.GetStakingKeeper(), &transferKeeper, ) - s.network.App.SetErc20Keeper(&erc20Keeper) + s.network.App.SetErc20Keeper(erc20Keeper) mockBankKeeper.EXPECT().SendCoinsFromAccountToModule(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) mockBankKeeper.EXPECT().BurnCoins(gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("failed to burn")).AnyTimes() diff --git a/tests/integration/x/erc20/test_proposals.go b/tests/integration/x/erc20/test_proposals.go index 5e3a6de5c..c2f0e3196 100644 --- a/tests/integration/x/erc20/test_proposals.go +++ b/tests/integration/x/erc20/test_proposals.go @@ -162,7 +162,7 @@ func (s *KeeperTestSuite) TestRegisterERC20() { s.network.App.GetBankKeeper(), mockEVMKeeper, s.network.App.GetStakingKeeper(), &transferKeeper, ) - s.network.App.SetErc20Keeper(&erc20Keeper) + s.network.App.SetErc20Keeper(erc20Keeper) mockEVMKeeper.On("EstimateGasInternal", mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.EstimateGasResponse{Gas: uint64(200)}, nil) mockEVMKeeper.On("CallEVM", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("forced CallEVM error")) From 9c0777dacb997b23409537086816167ec3ee9646 Mon Sep 17 00:00:00 2001 From: zsystm Date: Thu, 5 Jun 2025 13:58:23 +0900 Subject: [PATCH 11/21] chore: typo --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d8849a171..5c7556396 100644 --- a/Makefile +++ b/Makefile @@ -140,7 +140,7 @@ test-unit-cover: TEST_PACKAGES=$(PACKAGES_UNIT) test-unit-cover: run-tests @echo "🔍 Running evm (root) coverage..." @go test -tags=test $(COMMON_COVER_ARGS) -coverpkg=$(COVERPKG_ALL) -coverprofile=coverage.txt ./... - @echo "🔍 Running evmd coverage (evm 코어 로직만)..." + @echo "🔍 Running evmd coverage..." @cd evmd && go test -tags=test $(COMMON_COVER_ARGS) -coverpkg=$(COVERPKG_ALL) -coverprofile=coverage_evmd.txt ./... @echo "🔀 Merging evmd coverage into root coverage..." @tail -n +2 evmd/coverage_evmd.txt >> coverage.txt From d4955e3d01cc13a92023a07768de09f841e3eb78 Mon Sep 17 00:00:00 2001 From: zsystm Date: Thu, 5 Jun 2025 14:00:44 +0900 Subject: [PATCH 12/21] chore: package name --- precompiles/bank/bank.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/precompiles/bank/bank.go b/precompiles/bank/bank.go index dde996ba2..f81b725e6 100644 --- a/precompiles/bank/bank.go +++ b/precompiles/bank/bank.go @@ -15,7 +15,7 @@ import ( "github.com/ethereum/go-ethereum/core/vm" cmn "github.com/cosmos/evm/precompiles/common" - erc20Keeper "github.com/cosmos/evm/x/erc20/keeper" + erc20keeper "github.com/cosmos/evm/x/erc20/keeper" evmtypes "github.com/cosmos/evm/x/vm/types" storetypes "cosmossdk.io/store/types" @@ -43,14 +43,14 @@ var f embed.FS type Precompile struct { cmn.Precompile bankKeeper cmn.BankKeeper - erc20Keeper erc20Keeper.Keeper + erc20Keeper erc20keeper.Keeper } // NewPrecompile creates a new bank Precompile instance implementing the // PrecompiledContract interface. func NewPrecompile( bankKeeper cmn.BankKeeper, - erc20Keeper erc20Keeper.Keeper, + erc20Keeper erc20keeper.Keeper, ) (*Precompile, error) { newABI, err := cmn.LoadABI(f, "abi.json") if err != nil { From 6ef544ea2291588572c397d930d4797ea8ab6445 Mon Sep 17 00:00:00 2001 From: zsystm Date: Thu, 5 Jun 2025 14:18:30 +0900 Subject: [PATCH 13/21] chore: test convention --- tests/integration/ante/test_evm_fee_market.go | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/integration/ante/test_evm_fee_market.go b/tests/integration/ante/test_evm_fee_market.go index e610893d7..5008f0c9d 100644 --- a/tests/integration/ante/test_evm_fee_market.go +++ b/tests/integration/ante/test_evm_fee_market.go @@ -19,11 +19,11 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) -func (suite *EvmAnteTestSuite) TestGasWantedDecorator() { - suite.WithFeemarketEnabled(true) - suite.SetupTest() - ctx := suite.GetNetwork().GetContext() - dec := evm.NewGasWantedDecorator(suite.GetNetwork().App.GetEVMKeeper(), suite.GetNetwork().App.GetFeeMarketKeeper()) +func (s *EvmAnteTestSuite) TestGasWantedDecorator() { + s.WithFeemarketEnabled(true) + s.SetupTest() + ctx := s.GetNetwork().GetContext() + dec := evm.NewGasWantedDecorator(s.GetNetwork().App.GetEVMKeeper(), s.GetNetwork().App.GetFeeMarketKeeper()) from, fromPrivKey := utiltx.NewAddrKey() to := utiltx.GenerateAddress() denom := evmtypes.GetEVMCoinDenom() @@ -43,7 +43,7 @@ func (suite *EvmAnteTestSuite) TestGasWantedDecorator() { ToAddress: "cosmos1dx67l23hz9l0k9hcher8xz04uj7wf3yu26l2yn", Amount: sdk.Coins{sdk.Coin{Amount: sdkmath.NewInt(10), Denom: denom}}, } - txBuilder := suite.CreateTestCosmosTxBuilder(sdkmath.NewInt(10), denom, &testMsg) + txBuilder := s.CreateTestCosmosTxBuilder(sdkmath.NewInt(10), denom, &testMsg) return txBuilder.GetTx() }, true, @@ -57,7 +57,7 @@ func (suite *EvmAnteTestSuite) TestGasWantedDecorator() { GasPrice: big.NewInt(0), GasLimit: TestGasLimit, } - return suite.CreateTxBuilder(fromPrivKey, txArgs).GetTx() + return s.CreateTxBuilder(fromPrivKey, txArgs).GetTx() }, true, }, @@ -72,7 +72,7 @@ func (suite *EvmAnteTestSuite) TestGasWantedDecorator() { GasLimit: TestGasLimit, Accesses: &emptyAccessList, } - return suite.CreateTxBuilder(fromPrivKey, txArgs).GetTx() + return s.CreateTxBuilder(fromPrivKey, txArgs).GetTx() }, true, }, @@ -89,7 +89,7 @@ func (suite *EvmAnteTestSuite) TestGasWantedDecorator() { GasTipCap: big.NewInt(50), Accesses: &emptyAccessList, } - return suite.CreateTxBuilder(fromPrivKey, txArgs).GetTx() + return s.CreateTxBuilder(fromPrivKey, txArgs).GetTx() }, true, }, @@ -99,11 +99,11 @@ func (suite *EvmAnteTestSuite) TestGasWantedDecorator() { func() sdk.Tx { amount := sdk.NewCoins(sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(20))) gas := uint64(200000) - acc := suite.GetNetwork().App.GetAccountKeeper().NewAccountWithAddress(ctx, from.Bytes()) - suite.Require().NoError(acc.SetSequence(1)) - suite.GetNetwork().App.GetAccountKeeper().SetAccount(ctx, acc) - builder, err := suite.CreateTestEIP712TxBuilderMsgSend(acc.GetAddress(), fromPrivKey, ctx.ChainID(), config.DefaultEVMChainID, gas, amount) - suite.Require().NoError(err) + acc := s.GetNetwork().App.GetAccountKeeper().NewAccountWithAddress(ctx, from.Bytes()) + s.Require().NoError(acc.SetSequence(1)) + s.GetNetwork().App.GetAccountKeeper().SetAccount(ctx, acc) + builder, err := s.CreateTestEIP712TxBuilderMsgSend(acc.GetAddress(), fromPrivKey, ctx.ChainID(), config.DefaultEVMChainID, gas, amount) + s.Require().NoError(err) return builder.GetTx() }, true, @@ -118,7 +118,7 @@ func (suite *EvmAnteTestSuite) TestGasWantedDecorator() { ToAddress: "cosmos1dx67l23hz9l0k9hcher8xz04uj7wf3yu26l2yn", Amount: sdk.Coins{sdk.Coin{Amount: sdkmath.NewInt(10), Denom: denom}}, } - txBuilder := suite.CreateTestCosmosTxBuilder(sdkmath.NewInt(10), testconstants.ExampleAttoDenom, &testMsg) + txBuilder := s.CreateTestCosmosTxBuilder(sdkmath.NewInt(10), testconstants.ExampleAttoDenom, &testMsg) limit := types.BlockGasLimit(ctx) txBuilder.SetGasLimit(limit + 5) return txBuilder.GetTx() @@ -131,17 +131,17 @@ func (suite *EvmAnteTestSuite) TestGasWantedDecorator() { var expectedGasWanted uint64 for _, tc := range testCases { - suite.Run(tc.name, func() { + s.Run(tc.name, func() { _, err := dec.AnteHandle(ctx, tc.malleate(), false, testutil.NoOpNextFn) if tc.expPass { - suite.Require().NoError(err) + s.Require().NoError(err) - gasWanted := suite.GetNetwork().App.GetFeeMarketKeeper().GetTransientGasWanted(ctx) + gasWanted := s.GetNetwork().App.GetFeeMarketKeeper().GetTransientGasWanted(ctx) expectedGasWanted += tc.expectedGasWanted - suite.Require().Equal(expectedGasWanted, gasWanted) + s.Require().Equal(expectedGasWanted, gasWanted) } else { // TODO: check for specific error message - suite.Require().Error(err) + s.Require().Error(err) } }) } From d9ac8d2225b2f258e5bd72419a9ed9fd7e798529 Mon Sep 17 00:00:00 2001 From: zsystm Date: Thu, 5 Jun 2025 14:19:03 +0900 Subject: [PATCH 14/21] chore: test convention --- .../ante/test_evm_unit_02_mempool_fee.go | 10 ++-- .../ante/test_evm_unit_03_global_fee.go | 10 ++-- .../ante/test_evm_unit_04_validate.go | 38 +++++++------- .../test_evm_unit_06_account_verification.go | 50 +++++++++---------- .../ante/test_evm_unit_07_can_transfer.go | 32 ++++++------ .../ante/test_evm_unit_08_gas_consume.go | 50 +++++++++---------- .../test_evm_unit_09_increment_sequence.go | 24 ++++----- .../ante/test_evm_unit_10_gas_wanted.go | 30 +++++------ 8 files changed, 122 insertions(+), 122 deletions(-) diff --git a/tests/integration/ante/test_evm_unit_02_mempool_fee.go b/tests/integration/ante/test_evm_unit_02_mempool_fee.go index b033eecca..1855a3060 100644 --- a/tests/integration/ante/test_evm_unit_02_mempool_fee.go +++ b/tests/integration/ante/test_evm_unit_02_mempool_fee.go @@ -8,7 +8,7 @@ import ( errortypes "github.com/cosmos/cosmos-sdk/types/errors" ) -func (suite *EvmUnitAnteTestSuite) TestMempoolFee() { +func (s *EvmUnitAnteTestSuite) TestMempoolFee() { testCases := []struct { name string expectedError error @@ -45,7 +45,7 @@ func (suite *EvmUnitAnteTestSuite) TestMempoolFee() { } for _, tc := range testCases { - suite.Run(tc.name, func() { + s.Run(tc.name, func() { // Function under test err := evm.CheckMempoolFee( tc.txFee, @@ -55,10 +55,10 @@ func (suite *EvmUnitAnteTestSuite) TestMempoolFee() { ) if tc.expectedError != nil { - suite.Require().Error(err) - suite.Contains(err.Error(), tc.expectedError.Error()) + s.Require().Error(err) + s.Contains(err.Error(), tc.expectedError.Error()) } else { - suite.Require().NoError(err) + s.Require().NoError(err) } }) } diff --git a/tests/integration/ante/test_evm_unit_03_global_fee.go b/tests/integration/ante/test_evm_unit_03_global_fee.go index c7276df4c..33ebeb6d2 100644 --- a/tests/integration/ante/test_evm_unit_03_global_fee.go +++ b/tests/integration/ante/test_evm_unit_03_global_fee.go @@ -8,7 +8,7 @@ import ( errortypes "github.com/cosmos/cosmos-sdk/types/errors" ) -func (suite *EvmUnitAnteTestSuite) TestGlobalFee() { +func (s *EvmUnitAnteTestSuite) TestGlobalFee() { testCases := []struct { name string expectedError error @@ -41,7 +41,7 @@ func (suite *EvmUnitAnteTestSuite) TestGlobalFee() { } for _, tc := range testCases { - suite.Run(tc.name, func() { + s.Run(tc.name, func() { // Function under test err := evm.CheckGlobalFee( tc.txFee, @@ -50,10 +50,10 @@ func (suite *EvmUnitAnteTestSuite) TestGlobalFee() { ) if tc.expectedError != nil { - suite.Require().Error(err) - suite.Contains(err.Error(), tc.expectedError.Error()) + s.Require().Error(err) + s.Contains(err.Error(), tc.expectedError.Error()) } else { - suite.Require().NoError(err) + s.Require().NoError(err) } }) } diff --git a/tests/integration/ante/test_evm_unit_04_validate.go b/tests/integration/ante/test_evm_unit_04_validate.go index b65a35895..7ef1a69ac 100644 --- a/tests/integration/ante/test_evm_unit_04_validate.go +++ b/tests/integration/ante/test_evm_unit_04_validate.go @@ -24,7 +24,7 @@ type validateMsgParams struct { txData evmtypes.TxData } -func (suite *EvmUnitAnteTestSuite) TestValidateMsg() { +func (s *EvmUnitAnteTestSuite) TestValidateMsg() { keyring := testkeyring.New(2) testCases := []struct { @@ -49,7 +49,7 @@ func (suite *EvmUnitAnteTestSuite) TestValidateMsg() { getFunctionParams: func() validateMsgParams { txArgs := getTxByType("transfer", keyring.GetAddr(1)) txData, err := txArgs.ToTxData() - suite.Require().NoError(err) + s.Require().NoError(err) return validateMsgParams{ evmParams: evmtypes.DefaultParams(), txData: txData, @@ -63,7 +63,7 @@ func (suite *EvmUnitAnteTestSuite) TestValidateMsg() { getFunctionParams: func() validateMsgParams { txArgs := getTxByType("transfer", keyring.GetAddr(1)) txData, err := txArgs.ToTxData() - suite.Require().NoError(err) + s.Require().NoError(err) params := evmtypes.DefaultParams() params.AccessControl.Call.AccessType = evmtypes.AccessTypeRestricted @@ -82,7 +82,7 @@ func (suite *EvmUnitAnteTestSuite) TestValidateMsg() { getFunctionParams: func() validateMsgParams { txArgs := getTxByType("call", keyring.GetAddr(1)) txData, err := txArgs.ToTxData() - suite.Require().NoError(err) + s.Require().NoError(err) return validateMsgParams{ evmParams: evmtypes.DefaultParams(), txData: txData, @@ -96,7 +96,7 @@ func (suite *EvmUnitAnteTestSuite) TestValidateMsg() { getFunctionParams: func() validateMsgParams { txArgs := getTxByType("call", keyring.GetAddr(1)) txData, err := txArgs.ToTxData() - suite.Require().NoError(err) + s.Require().NoError(err) params := evmtypes.DefaultParams() params.AccessControl.Create.AccessType = evmtypes.AccessTypeRestricted @@ -114,7 +114,7 @@ func (suite *EvmUnitAnteTestSuite) TestValidateMsg() { getFunctionParams: func() validateMsgParams { txArgs := getTxByType("call", keyring.GetAddr(1)) txData, err := txArgs.ToTxData() - suite.Require().NoError(err) + s.Require().NoError(err) params := evmtypes.DefaultParams() params.AccessControl.Call.AccessType = evmtypes.AccessTypeRestricted @@ -132,7 +132,7 @@ func (suite *EvmUnitAnteTestSuite) TestValidateMsg() { getFunctionParams: func() validateMsgParams { txArgs := getTxByType("create", keyring.GetAddr(1)) txData, err := txArgs.ToTxData() - suite.Require().NoError(err) + s.Require().NoError(err) return validateMsgParams{ evmParams: evmtypes.DefaultParams(), txData: txData, @@ -146,7 +146,7 @@ func (suite *EvmUnitAnteTestSuite) TestValidateMsg() { getFunctionParams: func() validateMsgParams { txArgs := getTxByType("create", keyring.GetAddr(1)) txData, err := txArgs.ToTxData() - suite.Require().NoError(err) + s.Require().NoError(err) params := evmtypes.DefaultParams() params.AccessControl.Call.AccessType = evmtypes.AccessTypeRestricted @@ -164,7 +164,7 @@ func (suite *EvmUnitAnteTestSuite) TestValidateMsg() { getFunctionParams: func() validateMsgParams { txArgs := getTxByType("create", keyring.GetAddr(1)) txData, err := txArgs.ToTxData() - suite.Require().NoError(err) + s.Require().NoError(err) params := evmtypes.DefaultParams() params.AccessControl.Create.AccessType = evmtypes.AccessTypeRestricted @@ -179,7 +179,7 @@ func (suite *EvmUnitAnteTestSuite) TestValidateMsg() { } for _, tc := range testCases { - suite.Run(tc.name, func() { + s.Run(tc.name, func() { params := tc.getFunctionParams() // Function under test @@ -190,10 +190,10 @@ func (suite *EvmUnitAnteTestSuite) TestValidateMsg() { ) if tc.expectedError != nil { - suite.Require().Error(err) - suite.Contains(err.Error(), tc.expectedError.Error()) + s.Require().Error(err) + s.Contains(err.Error(), tc.expectedError.Error()) } else { - suite.Require().NoError(err) + s.Require().NoError(err) } }) } @@ -220,7 +220,7 @@ func getTxByType(typeTx string, recipient common.Address) evmtypes.EvmTxArgs { } } -func (suite *EvmUnitAnteTestSuite) TestCheckTxFee() { +func (s *EvmUnitAnteTestSuite) TestCheckTxFee() { // amount represents 1 token in the 18 decimals representation. amount := math.NewInt(1e18) gasLimit := uint64(1e6) @@ -250,12 +250,12 @@ func (suite *EvmUnitAnteTestSuite) TestCheckTxFee() { testconstants.SixDecimalsChainID, } { for _, tc := range testCases { - suite.Run(fmt.Sprintf("%s, %s", chainID.ChainID, tc.name), func() { + s.Run(fmt.Sprintf("%s, %s", chainID.ChainID, tc.name), func() { // Call the configurator to set the EVM coin required for the // function to be tested. configurator := evmtypes.NewEVMConfigurator() configurator.ResetTestConfig() - suite.Require().NoError(configurator.WithEVMCoinInfo(testconstants.ExampleChainCoinInfo[chainID]).Configure()) + s.Require().NoError(configurator.WithEVMCoinInfo(testconstants.ExampleChainCoinInfo[chainID]).Configure()) // If decimals is not 18 decimals, we have to convert txFeeInfo to original // decimals representation. @@ -273,10 +273,10 @@ func (suite *EvmUnitAnteTestSuite) TestCheckTxFee() { err := evm.CheckTxFee(txFeeInfo, tc.txFee, tc.txGasLimit) if tc.expError != nil { - suite.Require().Error(err) - suite.Contains(err.Error(), tc.expError.Error()) + s.Require().Error(err) + s.Contains(err.Error(), tc.expError.Error()) } else { - suite.Require().NoError(err) + s.Require().NoError(err) } }) } diff --git a/tests/integration/ante/test_evm_unit_06_account_verification.go b/tests/integration/ante/test_evm_unit_06_account_verification.go index 3c784ec99..91b643e42 100644 --- a/tests/integration/ante/test_evm_unit_06_account_verification.go +++ b/tests/integration/ante/test_evm_unit_06_account_verification.go @@ -20,15 +20,15 @@ import ( errortypes "github.com/cosmos/cosmos-sdk/types/errors" ) -func (suite *EvmUnitAnteTestSuite) TestVerifyAccountBalance() { +func (s *EvmUnitAnteTestSuite) TestVerifyAccountBalance() { // Setup keyring := testkeyring.New(2) unitNetwork := network.NewUnitTestNetwork( - suite.create, + s.create, network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), network.WithChainID(testconstants.ChainID{ - ChainID: suite.ChainID, - EVMChainID: suite.EvmChainID, + ChainID: s.ChainID, + EVMChainID: s.EvmChainID, }), ) grpcHandler := grpc.NewIntegrationHandler(unitNetwork) @@ -45,11 +45,11 @@ func (suite *EvmUnitAnteTestSuite) TestVerifyAccountBalance() { expectedError: errortypes.ErrInvalidType, generateAccountAndArgs: func() (*statedb.Account, evmtypes.EvmTxArgs) { statedbAccount := getDefaultStateDBAccount(unitNetwork, senderKey.Addr) - txArgs, err := txFactory.GenerateDefaultTxTypeArgs(senderKey.Addr, suite.EthTxType) - suite.Require().NoError(err) + txArgs, err := txFactory.GenerateDefaultTxTypeArgs(senderKey.Addr, s.EthTxType) + s.Require().NoError(err) statedbAccount.CodeHash = []byte("test") - suite.Require().NoError(err) + s.Require().NoError(err) return statedbAccount, txArgs }, }, @@ -58,15 +58,15 @@ func (suite *EvmUnitAnteTestSuite) TestVerifyAccountBalance() { expectedError: errortypes.ErrInsufficientFunds, generateAccountAndArgs: func() (*statedb.Account, evmtypes.EvmTxArgs) { statedbAccount := getDefaultStateDBAccount(unitNetwork, senderKey.Addr) - txArgs, err := txFactory.GenerateDefaultTxTypeArgs(senderKey.Addr, suite.EthTxType) - suite.Require().NoError(err) + txArgs, err := txFactory.GenerateDefaultTxTypeArgs(senderKey.Addr, s.EthTxType) + s.Require().NoError(err) // Make tx cost greater than balance balanceResp, err := grpcHandler.GetBalanceFromEVM(senderKey.AccAddr) - suite.Require().NoError(err) + s.Require().NoError(err) balance, ok := math.NewIntFromString(balanceResp.Balance) - suite.Require().True(ok) + s.Require().True(ok) invalidAmount := balance.Add(math.NewInt(100)) txArgs.Amount = invalidAmount.BigInt() return statedbAccount, txArgs @@ -77,8 +77,8 @@ func (suite *EvmUnitAnteTestSuite) TestVerifyAccountBalance() { expectedError: errortypes.ErrInvalidCoins, generateAccountAndArgs: func() (*statedb.Account, evmtypes.EvmTxArgs) { statedbAccount := getDefaultStateDBAccount(unitNetwork, senderKey.Addr) - txArgs, err := txFactory.GenerateDefaultTxTypeArgs(senderKey.Addr, suite.EthTxType) - suite.Require().NoError(err) + txArgs, err := txFactory.GenerateDefaultTxTypeArgs(senderKey.Addr, s.EthTxType) + s.Require().NoError(err) // Make tx cost negative. This has to be a big value because // it has to be bigger than the fee for the full cost to be negative @@ -91,8 +91,8 @@ func (suite *EvmUnitAnteTestSuite) TestVerifyAccountBalance() { name: "success: tx is successful and account is created if its nil", expectedError: errortypes.ErrInsufficientFunds, generateAccountAndArgs: func() (*statedb.Account, evmtypes.EvmTxArgs) { - txArgs, err := txFactory.GenerateDefaultTxTypeArgs(senderKey.Addr, suite.EthTxType) - suite.Require().NoError(err) + txArgs, err := txFactory.GenerateDefaultTxTypeArgs(senderKey.Addr, s.EthTxType) + s.Require().NoError(err) return nil, txArgs }, }, @@ -101,19 +101,19 @@ func (suite *EvmUnitAnteTestSuite) TestVerifyAccountBalance() { expectedError: nil, generateAccountAndArgs: func() (*statedb.Account, evmtypes.EvmTxArgs) { statedbAccount := getDefaultStateDBAccount(unitNetwork, senderKey.Addr) - txArgs, err := txFactory.GenerateDefaultTxTypeArgs(senderKey.Addr, suite.EthTxType) - suite.Require().NoError(err) + txArgs, err := txFactory.GenerateDefaultTxTypeArgs(senderKey.Addr, s.EthTxType) + s.Require().NoError(err) return statedbAccount, txArgs }, }, } for _, tc := range testCases { - suite.Run(fmt.Sprintf("%v_%v_%v", evmtypes.GetTxTypeName(suite.EthTxType), suite.ChainID, tc.name), func() { + s.Run(fmt.Sprintf("%v_%v_%v", evmtypes.GetTxTypeName(s.EthTxType), s.ChainID, tc.name), func() { // Perform test logic statedbAccount, txArgs := tc.generateAccountAndArgs() txData, err := txArgs.ToTxData() - suite.Require().NoError(err) + s.Require().NoError(err) // Function to be tested err = evm.VerifyAccountBalance( @@ -125,19 +125,19 @@ func (suite *EvmUnitAnteTestSuite) TestVerifyAccountBalance() { ) if tc.expectedError != nil { - suite.Require().Error(err) - suite.Contains(err.Error(), tc.expectedError.Error()) + s.Require().Error(err) + s.Contains(err.Error(), tc.expectedError.Error()) } else { - suite.Require().NoError(err) + s.Require().NoError(err) } // Make sure the account is created either wa acc, err := grpcHandler.GetAccount(senderKey.AccAddr.String()) - suite.Require().NoError(err) - suite.Require().NotEmpty(acc) + s.Require().NoError(err) + s.Require().NotEmpty(acc) // Clean block for next test err = unitNetwork.NextBlock() - suite.Require().NoError(err) + s.Require().NoError(err) }) } } diff --git a/tests/integration/ante/test_evm_unit_07_can_transfer.go b/tests/integration/ante/test_evm_unit_07_can_transfer.go index 5bf3d0fc9..95537d617 100644 --- a/tests/integration/ante/test_evm_unit_07_can_transfer.go +++ b/tests/integration/ante/test_evm_unit_07_can_transfer.go @@ -19,13 +19,13 @@ import ( errortypes "github.com/cosmos/cosmos-sdk/types/errors" ) -func (suite *EvmUnitAnteTestSuite) TestCanTransfer() { +func (s *EvmUnitAnteTestSuite) TestCanTransfer() { keyring := testkeyring.New(1) unitNetwork := network.NewUnitTestNetwork( - suite.create, + s.create, network.WithChainID(testconstants.ChainID{ - ChainID: suite.ChainID, - EVMChainID: suite.EvmChainID, + ChainID: s.ChainID, + EVMChainID: s.EvmChainID, }), network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), ) @@ -53,10 +53,10 @@ func (suite *EvmUnitAnteTestSuite) TestCanTransfer() { isLondon: true, malleate: func(txArgs *evmtypes.EvmTxArgs) { balanceResp, err := grpcHandler.GetBalanceFromEVM(senderKey.AccAddr) - suite.Require().NoError(err) + s.Require().NoError(err) balance, ok := math.NewIntFromString(balanceResp.Balance) - suite.Require().True(ok) + s.Require().True(ok) invalidAmount := balance.Add(math.NewInt(1)).BigInt() txArgs.Amount = invalidAmount }, @@ -71,16 +71,16 @@ func (suite *EvmUnitAnteTestSuite) TestCanTransfer() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("%v_%v_%v", evmtypes.GetTxTypeName(suite.EthTxType), suite.ChainID, tc.name), func() { + s.Run(fmt.Sprintf("%v_%v_%v", evmtypes.GetTxTypeName(s.EthTxType), s.ChainID, tc.name), func() { baseFeeResp, err := grpcHandler.GetEvmBaseFee() - suite.Require().NoError(err) + s.Require().NoError(err) ethCfg := unitNetwork.GetEVMChainConfig() evmParams, err := grpcHandler.GetEvmParams() - suite.Require().NoError(err) + s.Require().NoError(err) ctx := unitNetwork.GetContext() signer := gethtypes.MakeSigner(ethCfg, big.NewInt(ctx.BlockHeight()), uint64(ctx.BlockTime().Unix())) //#nosec G115 -- int overflow is not a concern here - txArgs, err := txFactory.GenerateDefaultTxTypeArgs(senderKey.Addr, suite.EthTxType) - suite.Require().NoError(err) + txArgs, err := txFactory.GenerateDefaultTxTypeArgs(senderKey.Addr, s.EthTxType) + s.Require().NoError(err) txArgs.Amount = big.NewInt(100) tc.malleate(&txArgs) @@ -88,9 +88,9 @@ func (suite *EvmUnitAnteTestSuite) TestCanTransfer() { msg := evmtypes.NewTx(&txArgs) msg.From = senderKey.Addr.String() signMsg, err := txFactory.SignMsgEthereumTx(senderKey.Priv, *msg) - suite.Require().NoError(err) + s.Require().NoError(err) coreMsg, err := signMsg.AsMessage(signer, baseFeeResp.BaseFee.BigInt()) - suite.Require().NoError(err) + s.Require().NoError(err) // Function under test err = evm.CanTransfer( @@ -103,11 +103,11 @@ func (suite *EvmUnitAnteTestSuite) TestCanTransfer() { ) if tc.expectedError != nil { - suite.Require().Error(err) - suite.Contains(err.Error(), tc.expectedError.Error()) + s.Require().Error(err) + s.Contains(err.Error(), tc.expectedError.Error()) } else { - suite.Require().NoError(err) + s.Require().NoError(err) } }) } diff --git a/tests/integration/ante/test_evm_unit_08_gas_consume.go b/tests/integration/ante/test_evm_unit_08_gas_consume.go index 03f6e2bc2..605221891 100644 --- a/tests/integration/ante/test_evm_unit_08_gas_consume.go +++ b/tests/integration/ante/test_evm_unit_08_gas_consume.go @@ -18,13 +18,13 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) -func (suite *EvmUnitAnteTestSuite) TestUpdateCumulativeGasWanted() { +func (s *EvmUnitAnteTestSuite) TestUpdateCumulativeGasWanted() { keyring := testkeyring.New(1) unitNetwork := network.NewUnitTestNetwork( - suite.create, + s.create, network.WithChainID(testconstants.ChainID{ - ChainID: suite.ChainID, - EVMChainID: suite.EvmChainID, + ChainID: s.ChainID, + EVMChainID: s.EvmChainID, }), network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), ) @@ -80,7 +80,7 @@ func (suite *EvmUnitAnteTestSuite) TestUpdateCumulativeGasWanted() { } for _, tc := range testCases { - suite.Run(tc.name, func() { + s.Run(tc.name, func() { // Function under test gasWanted := evmante.UpdateCumulativeGasWanted( tc.getCtx(), @@ -89,19 +89,19 @@ func (suite *EvmUnitAnteTestSuite) TestUpdateCumulativeGasWanted() { tc.cumulativeGasWanted, ) - suite.Require().Equal(tc.expectedResponse, gasWanted) + s.Require().Equal(tc.expectedResponse, gasWanted) }) } } // NOTE: claim rewards are not tested since there is an independent suite to test just that -func (suite *EvmUnitAnteTestSuite) TestConsumeGasAndEmitEvent() { +func (s *EvmUnitAnteTestSuite) TestConsumeGasAndEmitEvent() { keyring := testkeyring.New(1) unitNetwork := network.NewUnitTestNetwork( - suite.create, + s.create, network.WithChainID(testconstants.ChainID{ - ChainID: suite.ChainID, - EVMChainID: suite.EvmChainID, + ChainID: s.ChainID, + EVMChainID: s.EvmChainID, }), network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), ) @@ -147,7 +147,7 @@ func (suite *EvmUnitAnteTestSuite) TestConsumeGasAndEmitEvent() { Amount: sdktypes.Coins{sdktypes.NewCoin(unitNetwork.GetBaseDenom(), sdkmath.NewInt(500))}, }}, }) - suite.Require().NoError(err, "failed to send funds to new key") + s.Require().NoError(err, "failed to send funds to new key") return acc.AccAddr }, @@ -155,13 +155,13 @@ func (suite *EvmUnitAnteTestSuite) TestConsumeGasAndEmitEvent() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("%v_%v_%v", evmtypes.GetTxTypeName(suite.EthTxType), suite.ChainID, tc.name), func() { + s.Run(fmt.Sprintf("%v_%v_%v", evmtypes.GetTxTypeName(s.EthTxType), s.ChainID, tc.name), func() { sender := tc.getSender() resp, err := grpcHandler.GetBalanceFromEVM(sender) - suite.Require().NoError(err) + s.Require().NoError(err) prevBalance, ok := sdkmath.NewIntFromString(resp.Balance) - suite.Require().True(ok) + s.Require().True(ok) evmDecimals := evmtypes.GetEVMCoinDecimals() feesAmt := tc.feesAmt.Mul(evmDecimals.ConversionFactor()) @@ -176,24 +176,24 @@ func (suite *EvmUnitAnteTestSuite) TestConsumeGasAndEmitEvent() { ) if tc.expectedError != "" { - suite.Require().Error(err) - suite.Contains(err.Error(), tc.expectedError) + s.Require().Error(err) + s.Contains(err.Error(), tc.expectedError) // Check events are not present events := unitNetwork.GetContext().EventManager().Events() - suite.Require().Zero(len(events), "required no events to be emitted") + s.Require().Zero(len(events), "required no events to be emitted") } else { - suite.Require().NoError(err) + s.Require().NoError(err) // Check fees are deducted resp, err := grpcHandler.GetBalanceFromEVM(sender) - suite.Require().NoError(err) + s.Require().NoError(err) afterBalance, ok := sdkmath.NewIntFromString(resp.Balance) - suite.Require().True(ok) + s.Require().True(ok) - suite.Require().NoError(err) + s.Require().NoError(err) expectedBalance := prevBalance.Sub(feesAmt) - suite.Require().True(expectedBalance.Equal(afterBalance), "expected different balance after fees deduction") + s.Require().True(expectedBalance.Equal(afterBalance), "expected different balance after fees deduction") // Event to be emitted expectedEvent := sdktypes.NewEvent( @@ -202,8 +202,8 @@ func (suite *EvmUnitAnteTestSuite) TestConsumeGasAndEmitEvent() { ) // Check events are present events := unitNetwork.GetContext().EventManager().Events() - suite.Require().NotZero(len(events)) - suite.Require().Contains( + s.Require().NotZero(len(events)) + s.Require().Contains( events, expectedEvent, "expected different events after fees deduction", @@ -212,7 +212,7 @@ func (suite *EvmUnitAnteTestSuite) TestConsumeGasAndEmitEvent() { // Reset the context err = unitNetwork.NextBlock() - suite.Require().NoError(err) + s.Require().NoError(err) }) } } diff --git a/tests/integration/ante/test_evm_unit_09_increment_sequence.go b/tests/integration/ante/test_evm_unit_09_increment_sequence.go index 84909fbc6..d90e07026 100644 --- a/tests/integration/ante/test_evm_unit_09_increment_sequence.go +++ b/tests/integration/ante/test_evm_unit_09_increment_sequence.go @@ -11,13 +11,13 @@ import ( errortypes "github.com/cosmos/cosmos-sdk/types/errors" ) -func (suite *EvmUnitAnteTestSuite) TestIncrementSequence() { +func (s *EvmUnitAnteTestSuite) TestIncrementSequence() { keyring := testkeyring.New(1) unitNetwork := network.NewUnitTestNetwork( - suite.create, + s.create, network.WithChainID(testconstants.ChainID{ - ChainID: suite.ChainID, - EVMChainID: suite.EvmChainID, + ChainID: s.ChainID, + EVMChainID: s.EvmChainID, }), network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), ) @@ -46,9 +46,9 @@ func (suite *EvmUnitAnteTestSuite) TestIncrementSequence() { } for _, tc := range testCases { - suite.Run(tc.name, func() { + s.Run(tc.name, func() { account, err := grpcHandler.GetAccount(accAddr.String()) - suite.Require().NoError(err) + s.Require().NoError(err) preSequence := account.GetSequence() nonce := tc.malleate(account) @@ -62,15 +62,15 @@ func (suite *EvmUnitAnteTestSuite) TestIncrementSequence() { ) if tc.expectedError != nil { - suite.Require().Error(err) - suite.Contains(err.Error(), tc.expectedError.Error()) + s.Require().Error(err) + s.Contains(err.Error(), tc.expectedError.Error()) } else { - suite.Require().NoError(err) + s.Require().NoError(err) - suite.Require().Equal(preSequence+1, account.GetSequence()) + s.Require().Equal(preSequence+1, account.GetSequence()) updatedAccount, err := grpcHandler.GetAccount(accAddr.String()) - suite.Require().NoError(err) - suite.Require().Equal(preSequence+1, updatedAccount.GetSequence()) + s.Require().NoError(err) + s.Require().Equal(preSequence+1, updatedAccount.GetSequence()) } }) } diff --git a/tests/integration/ante/test_evm_unit_10_gas_wanted.go b/tests/integration/ante/test_evm_unit_10_gas_wanted.go index 04e5e6350..5c30816bc 100644 --- a/tests/integration/ante/test_evm_unit_10_gas_wanted.go +++ b/tests/integration/ante/test_evm_unit_10_gas_wanted.go @@ -18,13 +18,13 @@ import ( errortypes "github.com/cosmos/cosmos-sdk/types/errors" ) -func (suite *EvmUnitAnteTestSuite) TestCheckGasWanted() { +func (s *EvmUnitAnteTestSuite) TestCheckGasWanted() { keyring := testkeyring.New(1) unitNetwork := network.NewUnitTestNetwork( - suite.create, + s.create, network.WithChainID(testconstants.ChainID{ - ChainID: suite.ChainID, - EVMChainID: suite.EvmChainID, + ChainID: s.ChainID, + EVMChainID: s.EvmChainID, }), network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), ) @@ -76,7 +76,7 @@ func (suite *EvmUnitAnteTestSuite) TestCheckGasWanted() { getCtx: func() sdktypes.Context { // Set basefee param to false feeMarketParams, err := grpcHandler.GetFeeMarketParams() - suite.Require().NoError(err) + s.Require().NoError(err) feeMarketParams.Params.NoBaseFee = true err = utils.UpdateFeeMarketParams(utils.UpdateParamsInput{ @@ -85,7 +85,7 @@ func (suite *EvmUnitAnteTestSuite) TestCheckGasWanted() { Pk: keyring.GetPrivKey(0), Params: feeMarketParams.Params, }) - suite.Require().NoError(err, "expected no error when updating fee market params") + s.Require().NoError(err, "expected no error when updating fee market params") blockMeter := storetypes.NewGasMeter(commonGasLimit + 10_000) return unitNetwork.GetContext().WithBlockGasMeter(blockMeter) @@ -96,16 +96,16 @@ func (suite *EvmUnitAnteTestSuite) TestCheckGasWanted() { } for _, tc := range testCases { - suite.Run(fmt.Sprintf("%v_%v_%v", evmtypes.GetTxTypeName(suite.EthTxType), suite.ChainID, tc.name), func() { + s.Run(fmt.Sprintf("%v_%v_%v", evmtypes.GetTxTypeName(s.EthTxType), s.ChainID, tc.name), func() { sender := keyring.GetKey(0) txArgs, err := txFactory.GenerateDefaultTxTypeArgs( sender.Addr, - suite.EthTxType, + s.EthTxType, ) - suite.Require().NoError(err) + s.Require().NoError(err) txArgs.GasLimit = commonGasLimit tx, err := txFactory.GenerateSignedEthTx(sender.Priv, txArgs) - suite.Require().NoError(err) + s.Require().NoError(err) ctx := tc.getCtx() @@ -118,19 +118,19 @@ func (suite *EvmUnitAnteTestSuite) TestCheckGasWanted() { ) if tc.expectedError != nil { - suite.Require().Error(err) - suite.Contains(err.Error(), tc.expectedError.Error()) + s.Require().Error(err) + s.Contains(err.Error(), tc.expectedError.Error()) } else { - suite.Require().NoError(err) + s.Require().NoError(err) transientGasWanted := unitNetwork.App.GetFeeMarketKeeper().GetTransientGasWanted( unitNetwork.GetContext(), ) - suite.Require().Equal(tc.expectedTransientGasWanted, transientGasWanted) + s.Require().Equal(tc.expectedTransientGasWanted, transientGasWanted) } // Start from a fresh block and ctx err = unitNetwork.NextBlock() - suite.Require().NoError(err) + s.Require().NoError(err) }) } } From 4eee98d6dc725261323b95d896a58a31c3e94d0c Mon Sep 17 00:00:00 2001 From: zsystm Date: Thu, 5 Jun 2025 14:28:03 +0900 Subject: [PATCH 15/21] chore: align convention --- tests/integration/eip712/test_eip712.go | 236 +++++++++--------- .../integration/eip712/test_eip712_fuzzer.go | 68 ++--- .../precompiles/erc20/test_errors.go | 4 +- 3 files changed, 154 insertions(+), 154 deletions(-) diff --git a/tests/integration/eip712/test_eip712.go b/tests/integration/eip712/test_eip712.go index 1ee092b45..32aade1e0 100644 --- a/tests/integration/eip712/test_eip712.go +++ b/tests/integration/eip712/test_eip712.go @@ -67,20 +67,20 @@ type TestParams struct { memo string } -func (suite *TestSuite) SetupTest() { - nw := network.New(suite.create, suite.options...) - suite.config = nw.GetEncodingConfig() - suite.clientCtx = client.Context{}.WithTxConfig(suite.config.TxConfig) - suite.denom = evmtypes.GetEVMCoinDenom() +func (s *TestSuite) SetupTest() { + nw := network.New(s.create, s.options...) + s.config = nw.GetEncodingConfig() + s.clientCtx = client.Context{}.WithTxConfig(s.config.TxConfig) + s.denom = evmtypes.GetEVMCoinDenom() sdk.GetConfig().SetBech32PrefixForAccount(chainconfig.Bech32Prefix, "") } // createTestAddress creates random test addresses for messages -func (suite *TestSuite) createTestAddress() sdk.AccAddress { +func (s *TestSuite) createTestAddress() sdk.AccAddress { privkey, _ := ethsecp256k1.GenerateKey() key, err := privkey.ToECDSA() - suite.Require().NoError(err) + s.Require().NoError(err) addr := crypto.PubkeyToAddress(key.PublicKey) @@ -88,20 +88,20 @@ func (suite *TestSuite) createTestAddress() sdk.AccAddress { } // createTestKeyPair creates a random keypair for signing and verification -func (suite *TestSuite) createTestKeyPair() (*ethsecp256k1.PrivKey, *ethsecp256k1.PubKey) { +func (s *TestSuite) createTestKeyPair() (*ethsecp256k1.PrivKey, *ethsecp256k1.PubKey) { privKey, err := ethsecp256k1.GenerateKey() - suite.Require().NoError(err) + s.Require().NoError(err) pubKey := ðsecp256k1.PubKey{ Key: privKey.PubKey().Bytes(), } - suite.Require().Implements((*cryptotypes.PubKey)(nil), pubKey) + s.Require().Implements((*cryptotypes.PubKey)(nil), pubKey) return privKey, pubKey } // makeCoins helps create an instance of sdk.Coins[] with single coin -func (suite *TestSuite) makeCoins(denom string, amount math.Int) sdk.Coins { +func (s *TestSuite) makeCoins(denom string, amount math.Int) sdk.Coins { return sdk.NewCoins( sdk.NewCoin( denom, @@ -110,8 +110,8 @@ func (suite *TestSuite) makeCoins(denom string, amount math.Int) sdk.Coins { ) } -func (suite *TestSuite) TestEIP712() { - suite.SetupTest() +func (s *TestSuite) TestEIP712() { + s.SetupTest() signModes := []signing.SignMode{ signing.SignMode_SIGN_MODE_DIRECT, @@ -120,10 +120,10 @@ func (suite *TestSuite) TestEIP712() { params := TestParams{ fee: txtypes.Fee{ - Amount: suite.makeCoins(suite.denom, math.NewInt(2000)), + Amount: s.makeCoins(s.denom, math.NewInt(2000)), GasLimit: 20000, }, - address: suite.createTestAddress(), + address: s.createTestAddress(), accountNumber: 25, sequence: 78, memo: "", @@ -140,9 +140,9 @@ func (suite *TestSuite) TestEIP712() { title: "Succeeds - Standard MsgSend", msgs: []sdk.Msg{ banktypes.NewMsgSend( - suite.createTestAddress(), - suite.createTestAddress(), - suite.makeCoins(suite.denom, math.NewInt(1)), + s.createTestAddress(), + s.createTestAddress(), + s.makeCoins(s.denom, math.NewInt(1)), ), }, expectSuccess: true, @@ -151,7 +151,7 @@ func (suite *TestSuite) TestEIP712() { title: "Succeeds - Standard MsgVote", msgs: []sdk.Msg{ govtypes.NewMsgVote( - suite.createTestAddress(), + s.createTestAddress(), 5, govtypes.OptionNo, ), @@ -162,9 +162,9 @@ func (suite *TestSuite) TestEIP712() { title: "Succeeds - Standard MsgDelegate", msgs: []sdk.Msg{ stakingtypes.NewMsgDelegate( - suite.createTestAddress().String(), - sdk.ValAddress(suite.createTestAddress()).String(), - suite.makeCoins(suite.denom, math.NewInt(1))[0], + s.createTestAddress().String(), + sdk.ValAddress(s.createTestAddress()).String(), + s.makeCoins(s.denom, math.NewInt(1))[0], ), }, expectSuccess: true, @@ -173,8 +173,8 @@ func (suite *TestSuite) TestEIP712() { title: "Succeeds - Standard MsgWithdrawDelegationReward", msgs: []sdk.Msg{ distributiontypes.NewMsgWithdrawDelegatorReward( - suite.createTestAddress().String(), - sdk.ValAddress(suite.createTestAddress()).String(), + s.createTestAddress().String(), + sdk.ValAddress(s.createTestAddress()).String(), ), }, expectSuccess: true, @@ -184,13 +184,13 @@ func (suite *TestSuite) TestEIP712() { msgs: []sdk.Msg{ stakingtypes.NewMsgDelegate( params.address.String(), - sdk.ValAddress(suite.createTestAddress()).String(), - suite.makeCoins(suite.denom, math.NewInt(1))[0], + sdk.ValAddress(s.createTestAddress()).String(), + s.makeCoins(s.denom, math.NewInt(1))[0], ), stakingtypes.NewMsgDelegate( params.address.String(), - sdk.ValAddress(suite.createTestAddress()).String(), - suite.makeCoins(suite.denom, math.NewInt(5))[0], + sdk.ValAddress(s.createTestAddress()).String(), + s.makeCoins(s.denom, math.NewInt(5))[0], ), }, expectSuccess: true, @@ -217,11 +217,11 @@ func (suite *TestSuite) TestEIP712() { ), banktypes.NewMsgSend( params.address, - suite.createTestAddress(), - suite.makeCoins(suite.denom, math.NewInt(50)), + s.createTestAddress(), + s.makeCoins(s.denom, math.NewInt(50)), ), }, - expectSuccess: !suite.useLegacyEIP712TypedData, + expectSuccess: !s.useLegacyEIP712TypedData, }, { title: "Succeeds - Single-Signer 2x MsgVoteV1 with Different Schemas", @@ -239,18 +239,18 @@ func (suite *TestSuite) TestEIP712() { "Has Metadata", ), }, - expectSuccess: !suite.useLegacyEIP712TypedData, + expectSuccess: !s.useLegacyEIP712TypedData, }, { title: "Fails - Two MsgVotes with Different Signers", msgs: []sdk.Msg{ govtypes.NewMsgVote( - suite.createTestAddress(), + s.createTestAddress(), 5, govtypes.OptionNo, ), govtypes.NewMsgVote( - suite.createTestAddress(), + s.createTestAddress(), 25, govtypes.OptionAbstain, ), @@ -266,7 +266,7 @@ func (suite *TestSuite) TestEIP712() { title: "Fails - Includes TimeoutHeight", msgs: []sdk.Msg{ govtypes.NewMsgVote( - suite.createTestAddress(), + s.createTestAddress(), 5, govtypes.OptionNo, ), @@ -280,22 +280,22 @@ func (suite *TestSuite) TestEIP712() { &banktypes.MsgMultiSend{ Inputs: []banktypes.Input{ banktypes.NewInput( - suite.createTestAddress(), - suite.makeCoins(suite.denom, math.NewInt(50)), + s.createTestAddress(), + s.makeCoins(s.denom, math.NewInt(50)), ), banktypes.NewInput( - suite.createTestAddress(), - suite.makeCoins(suite.denom, math.NewInt(50)), + s.createTestAddress(), + s.makeCoins(s.denom, math.NewInt(50)), ), }, Outputs: []banktypes.Output{ banktypes.NewOutput( - suite.createTestAddress(), - suite.makeCoins(suite.denom, math.NewInt(50)), + s.createTestAddress(), + s.makeCoins(s.denom, math.NewInt(50)), ), banktypes.NewOutput( - suite.createTestAddress(), - suite.makeCoins(suite.denom, math.NewInt(50)), + s.createTestAddress(), + s.makeCoins(s.denom, math.NewInt(50)), ), }, }, @@ -306,16 +306,16 @@ func (suite *TestSuite) TestEIP712() { for _, tc := range testCases { for _, signMode := range signModes { - suite.Run(tc.title, func() { - privKey, pubKey := suite.createTestKeyPair() + s.Run(tc.title, func() { + privKey, pubKey := s.createTestKeyPair() - txBuilder := suite.clientCtx.TxConfig.NewTxBuilder() + txBuilder := s.clientCtx.TxConfig.NewTxBuilder() txBuilder.SetGasLimit(params.fee.GasLimit) txBuilder.SetFeeAmount(params.fee.Amount) err := txBuilder.SetMsgs(tc.msgs...) - suite.Require().NoError(err) + s.Require().NoError(err) txBuilder.SetMemo(params.memo) @@ -331,7 +331,7 @@ func (suite *TestSuite) TestEIP712() { } err = txBuilder.SetSignatures([]signing.SignatureV2{txSig}...) - suite.Require().NoError(err) + s.Require().NoError(err) chainID := constants.ExampleChainID.ChainID if tc.chainID != "" { @@ -351,22 +351,22 @@ func (suite *TestSuite) TestEIP712() { } bz, err := authsigning.GetSignBytesAdapter( - suite.clientCtx.CmdContext, - suite.clientCtx.TxConfig.SignModeHandler(), + s.clientCtx.CmdContext, + s.clientCtx.TxConfig.SignModeHandler(), signMode, signerData, txBuilder.GetTx(), ) - suite.Require().NoError(err) + s.Require().NoError(err) - suite.verifyEIP712SignatureVerification(tc.expectSuccess, *privKey, *pubKey, bz) + s.verifyEIP712SignatureVerification(tc.expectSuccess, *privKey, *pubKey, bz) // Verify payload flattening only if the payload is in valid JSON format if signMode == signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON { - suite.verifySignDocFlattening(bz) + s.verifySignDocFlattening(bz) if tc.expectSuccess { - suite.verifyBasicTypedData(bz) + s.verifyBasicTypedData(bz) } } }) @@ -375,31 +375,31 @@ func (suite *TestSuite) TestEIP712() { } // verifyEIP712SignatureVerification verifies that the payload passes signature verification if signed as its EIP-712 representation. -func (suite *TestSuite) verifyEIP712SignatureVerification(expectedSuccess bool, privKey ethsecp256k1.PrivKey, pubKey ethsecp256k1.PubKey, signBytes []byte) { +func (s *TestSuite) verifyEIP712SignatureVerification(expectedSuccess bool, privKey ethsecp256k1.PrivKey, pubKey ethsecp256k1.PubKey, signBytes []byte) { eip712Bytes, err := eip712.GetEIP712BytesForMsg(signBytes) - if suite.useLegacyEIP712TypedData { + if s.useLegacyEIP712TypedData { eip712Bytes, err = eip712.LegacyGetEIP712BytesForMsg(signBytes) } if !expectedSuccess { - suite.Require().Error(err) + s.Require().Error(err) return } - suite.Require().NoError(err) + s.Require().NoError(err) sig, err := privKey.Sign(eip712Bytes) - suite.Require().NoError(err) + s.Require().NoError(err) // Verify against original payload bytes. This should pass, even though it is not // the original message that was signed. res := pubKey.VerifySignature(signBytes, sig) - suite.Require().True(res) + s.Require().True(res) // Verify against the signed EIP-712 bytes. This should pass, since it is the message signed. res = pubKey.VerifySignature(eip712Bytes, sig) - suite.Require().True(res) + s.Require().True(res) // Verify against random bytes to ensure it does not pass unexpectedly (sanity check). randBytes := make([]byte, len(signBytes)) @@ -407,37 +407,37 @@ func (suite *TestSuite) verifyEIP712SignatureVerification(expectedSuccess bool, // Change the first element of signBytes to a different value randBytes[0] = (signBytes[0] + 10) % 255 res = pubKey.VerifySignature(randBytes, sig) - suite.Require().False(res) + s.Require().False(res) } // verifySignDocFlattening tests the flattening algorithm against the sign doc's JSON payload, // using verifyPayloadAgainstFlattened. -func (suite *TestSuite) verifySignDocFlattening(signDoc []byte) { +func (s *TestSuite) verifySignDocFlattening(signDoc []byte) { payload := gjson.ParseBytes(signDoc) - suite.Require().True(payload.IsObject()) + s.Require().True(payload.IsObject()) flattened, _, err := eip712.FlattenPayloadMessages(payload) - suite.Require().NoError(err) + s.Require().NoError(err) - suite.verifyPayloadAgainstFlattened(payload, flattened) + s.verifyPayloadAgainstFlattened(payload, flattened) } // verifyPayloadAgainstFlattened compares a payload against its flattened counterpart to ensure that // the flattening algorithm behaved as expected. -func (suite *TestSuite) verifyPayloadAgainstFlattened(payload gjson.Result, flattened gjson.Result) { +func (s *TestSuite) verifyPayloadAgainstFlattened(payload gjson.Result, flattened gjson.Result) { payloadMap, ok := payload.Value().(map[string]interface{}) - suite.Require().True(ok) + s.Require().True(ok) flattenedMap, ok := flattened.Value().(map[string]interface{}) - suite.Require().True(ok) + s.Require().True(ok) - suite.verifyPayloadMapAgainstFlattenedMap(payloadMap, flattenedMap) + s.verifyPayloadMapAgainstFlattenedMap(payloadMap, flattenedMap) } // verifyPayloadMapAgainstFlattenedMap directly compares two JSON maps in Go representations to // test flattening. -func (suite *TestSuite) verifyPayloadMapAgainstFlattenedMap(original map[string]interface{}, flattened map[string]interface{}) { +func (s *TestSuite) verifyPayloadMapAgainstFlattenedMap(original map[string]interface{}, flattened map[string]interface{}) { interfaceMessages, ok := original[msgsFieldName] - suite.Require().True(ok) + s.Require().True(ok) messages, ok := interfaceMessages.([]interface{}) // If passing an empty msgs array @@ -447,18 +447,18 @@ func (suite *TestSuite) verifyPayloadMapAgainstFlattenedMap(original map[string] // Verify message contents for i, msg := range messages { flattenedMsg, ok := flattened[fmt.Sprintf("msg%d", i)] - suite.Require().True(ok) + s.Require().True(ok) flattenedMsgJSON, ok := flattenedMsg.(map[string]interface{}) - suite.Require().True(ok) + s.Require().True(ok) - suite.Require().Equal(flattenedMsgJSON, msg) + s.Require().Equal(flattenedMsgJSON, msg) } } // Verify new payload does not have msgs field _, ok = flattened[msgsFieldName] - suite.Require().False(ok) + s.Require().False(ok) // Verify number of total keys numKeysOriginal := len(original) @@ -466,7 +466,7 @@ func (suite *TestSuite) verifyPayloadMapAgainstFlattenedMap(original map[string] numMessages := len(messages) // + N keys, then -1 for msgs - suite.Require().Equal(numKeysFlattened, numKeysOriginal+numMessages-1) + s.Require().Equal(numKeysFlattened, numKeysOriginal+numMessages-1) // Verify contents of remaining keys for k, obj := range original { @@ -475,66 +475,66 @@ func (suite *TestSuite) verifyPayloadMapAgainstFlattenedMap(original map[string] } flattenedObj, ok := flattened[k] - suite.Require().True(ok) + s.Require().True(ok) - suite.Require().Equal(obj, flattenedObj) + s.Require().Equal(obj, flattenedObj) } } // verifyBasicTypedData performs basic verification on the TypedData generation. -func (suite *TestSuite) verifyBasicTypedData(signDoc []byte) { +func (s *TestSuite) verifyBasicTypedData(signDoc []byte) { typedData, err := eip712.GetEIP712TypedDataForMsg(signDoc) - suite.Require().NoError(err) + s.Require().NoError(err) jsonPayload := gjson.ParseBytes(signDoc) - suite.Require().True(jsonPayload.IsObject()) + s.Require().True(jsonPayload.IsObject()) flattened, _, err := eip712.FlattenPayloadMessages(jsonPayload) - suite.Require().NoError(err) - suite.Require().True(flattened.IsObject()) + s.Require().NoError(err) + s.Require().True(flattened.IsObject()) flattenedMsgMap, ok := flattened.Value().(map[string]interface{}) - suite.Require().True(ok) + s.Require().True(ok) - suite.Require().Equal(typedData.Message, flattenedMsgMap) + s.Require().Equal(typedData.Message, flattenedMsgMap) } // TestFlattenPayloadErrorHandling tests error handling in TypedData generation, // specifically regarding the payload. -func (suite *TestSuite) TestFlattenPayloadErrorHandling() { +func (s *TestSuite) TestFlattenPayloadErrorHandling() { // No msgs _, _, err := eip712.FlattenPayloadMessages(gjson.Parse("")) - suite.Require().ErrorContains(err, "no messages found") + s.Require().ErrorContains(err, "no messages found") // Non-array Msgs _, _, err = eip712.FlattenPayloadMessages(gjson.Parse(`{"msgs": 10}`)) - suite.Require().ErrorContains(err, "array of messages") + s.Require().ErrorContains(err, "array of messages") // Array with non-object items _, _, err = eip712.FlattenPayloadMessages(gjson.Parse(`{"msgs": [10, 20]}`)) - suite.Require().ErrorContains(err, "not valid JSON") + s.Require().ErrorContains(err, "not valid JSON") // Malformed payload - malformed, err := sjson.Set(suite.generateRandomPayload(2).Raw, "msg0", 20) - suite.Require().NoError(err) + malformed, err := sjson.Set(s.generateRandomPayload(2).Raw, "msg0", 20) + s.Require().NoError(err) _, _, err = eip712.FlattenPayloadMessages(gjson.Parse(malformed)) - suite.Require().ErrorContains(err, "malformed payload") + s.Require().ErrorContains(err, "malformed payload") } // TestTypedDataErrorHandling tests error handling for TypedData generation // in the main algorithm. -func (suite *TestSuite) TestTypedDataErrorHandling() { +func (s *TestSuite) TestTypedDataErrorHandling() { // Empty JSON _, err := eip712.WrapTxToTypedData(0, make([]byte, 0)) - suite.Require().ErrorContains(err, "invalid JSON") + s.Require().ErrorContains(err, "invalid JSON") _, err = eip712.WrapTxToTypedData(0, []byte(gjson.Parse(`{"msgs": 10}`).Raw)) - suite.Require().ErrorContains(err, "array of messages") + s.Require().ErrorContains(err, "array of messages") // Invalid message 'type' _, err = eip712.WrapTxToTypedData(0, []byte(gjson.Parse(`{"msgs": [{ "type": 10 }] }`).Raw)) - suite.Require().ErrorContains(err, "message type value") + s.Require().ErrorContains(err, "message type value") // Max duplicate type recursion depth messagesArr := new(bytes.Buffer) @@ -550,74 +550,74 @@ func (suite *TestSuite) TestTypedDataErrorHandling() { messagesArr.WriteString("]") _, err = eip712.WrapTxToTypedData(0, []byte(fmt.Sprintf(`{ "msgs": %v }`, messagesArr))) - suite.Require().ErrorContains(err, "maximum number of duplicates") + s.Require().ErrorContains(err, "maximum number of duplicates") } // TestTypedDataEdgeCases tests certain interesting edge cases to ensure that they work // (or don't work) as expected. -func (suite *TestSuite) TestTypedDataEdgeCases() { +func (s *TestSuite) TestTypedDataEdgeCases() { // Type without '/' separator typedData, err := eip712.WrapTxToTypedData(0, []byte(gjson.Parse(`{"msgs": [{ "type": "MsgSend", "value": { "field": 10 } }] }`).Raw)) - suite.Require().NoError(err) + s.Require().NoError(err) types := typedData.Types["TypeMsgSend0"] - suite.Require().Greater(len(types), 0) + s.Require().Greater(len(types), 0) // Null value typedData, err = eip712.WrapTxToTypedData(0, []byte(gjson.Parse(`{"msgs": [{ "type": "MsgSend", "value": { "field": null } }] }`).Raw)) - suite.Require().NoError(err) + s.Require().NoError(err) types = typedData.Types["TypeValue0"] // Skip null type, since we don't expect any in the payload - suite.Require().Equal(len(types), 0) + s.Require().Equal(len(types), 0) // Boolean value typedData, err = eip712.WrapTxToTypedData(0, []byte(gjson.Parse(`{"msgs": [{ "type": "MsgSend", "value": { "field": true } }] }`).Raw)) - suite.Require().NoError(err) + s.Require().NoError(err) types = typedData.Types["TypeValue0"] - suite.Require().Equal(len(types), 1) - suite.Require().Equal(types[0], apitypes.Type{ + s.Require().Equal(len(types), 1) + s.Require().Equal(types[0], apitypes.Type{ Name: "field", Type: "bool", }) // Empty array typedData, err = eip712.WrapTxToTypedData(0, []byte(gjson.Parse(`{"msgs": [{ "type": "MsgSend", "value": { "field": [] } }] }`).Raw)) - suite.Require().NoError(err) + s.Require().NoError(err) types = typedData.Types["TypeValue0"] - suite.Require().Equal(types[0], apitypes.Type{ + s.Require().Equal(types[0], apitypes.Type{ Name: "field", Type: "string[]", }) // Simple arrays typedData, err = eip712.WrapTxToTypedData(0, []byte(gjson.Parse(`{"msgs": [{ "type": "MsgSend", "value": { "array": [1, 2, 3] } }] }`).Raw)) - suite.Require().NoError(err) + s.Require().NoError(err) types = typedData.Types["TypeValue0"] - suite.Require().Equal(len(types), 1) - suite.Require().Equal(types[0], apitypes.Type{ + s.Require().Equal(len(types), 1) + s.Require().Equal(types[0], apitypes.Type{ Name: "array", Type: "int64[]", }) // Nested arrays (EIP-712 does not support nested arrays) typedData, err = eip712.WrapTxToTypedData(0, []byte(gjson.Parse(`{"msgs": [{ "type": "MsgSend", "value": { "array": [[1, 2, 3], [1, 2]] } }] }`).Raw)) - suite.Require().NoError(err) + s.Require().NoError(err) types = typedData.Types["TypeValue0"] - suite.Require().Equal(len(types), 0) + s.Require().Equal(len(types), 0) } // TestTypedDataGeneration tests certain qualities about the output Types representation. -func (suite *TestSuite) TestTypedDataGeneration() { +func (s *TestSuite) TestTypedDataGeneration() { // Multiple messages with the same schema should share one type payloadRaw := `{ "msgs": [{ "type": "msgType", "value": { "field1": 10 }}, { "type": "msgType", "value": { "field1": 20 }}] }` typedData, err := eip712.WrapTxToTypedData(0, []byte(payloadRaw)) - suite.Require().NoError(err) - suite.Require().True(typedData.Types["TypemsgType1"] == nil) + s.Require().NoError(err) + s.Require().True(typedData.Types["TypemsgType1"] == nil) // Multiple messages with different schemas should have different types payloadRaw = `{ "msgs": [{ "type": "msgType", "value": { "field1": 10 }}, { "type": "msgType", "value": { "field2": 20 }}] }` typedData, err = eip712.WrapTxToTypedData(0, []byte(payloadRaw)) - suite.Require().NoError(err) - suite.Require().False(typedData.Types["TypemsgType1"] == nil) + s.Require().NoError(err) + s.Require().False(typedData.Types["TypemsgType1"] == nil) } diff --git a/tests/integration/eip712/test_eip712_fuzzer.go b/tests/integration/eip712/test_eip712_fuzzer.go index 7d58ab619..36d3e4e70 100644 --- a/tests/integration/eip712/test_eip712_fuzzer.go +++ b/tests/integration/eip712/test_eip712_fuzzer.go @@ -54,51 +54,51 @@ var params = FuzzTestParams{ // variable input sizes, types, and fields. While it may be possible to translate a single input into // a JSON object, it would require difficult parsing, and ultimately approximates our randomized unit // tests as they are. -func (suite *TestSuite) TestRandomPayloadFlattening() { +func (s *TestSuite) TestRandomPayloadFlattening() { // Re-seed rand generator rand.Seed(rand.Int64()) for i := 0; i < params.numTestObjects; i++ { - suite.Run(fmt.Sprintf("%v%d", fuzzTestName, i), func() { - payload := suite.generateRandomPayload(i) + s.Run(fmt.Sprintf("%v%d", fuzzTestName, i), func() { + payload := s.generateRandomPayload(i) flattened, numMessages, err := eip712.FlattenPayloadMessages(payload) - suite.Require().NoError(err) - suite.Require().Equal(numMessages, i) + s.Require().NoError(err) + s.Require().Equal(numMessages, i) - suite.verifyPayloadAgainstFlattened(payload, flattened) + s.verifyPayloadAgainstFlattened(payload, flattened) }) } } // generateRandomPayload creates a random payload of the desired format, with random sub-objects. -func (suite *TestSuite) generateRandomPayload(numMessages int) gjson.Result { - payload := suite.createRandomJSONObject().Raw +func (s *TestSuite) generateRandomPayload(numMessages int) gjson.Result { + payload := s.createRandomJSONObject().Raw msgs := make([]gjson.Result, numMessages) for i := 0; i < numMessages; i++ { - msgs[i] = suite.createRandomJSONObject() + msgs[i] = s.createRandomJSONObject() } payload, err := sjson.Set(payload, msgsFieldName, msgs) - suite.Require().NoError(err) + s.Require().NoError(err) return gjson.Parse(payload) } // createRandomJSONObject creates a JSON object with random fields. -func (suite *TestSuite) createRandomJSONObject() gjson.Result { +func (s *TestSuite) createRandomJSONObject() gjson.Result { var err error payloadRaw := "" - numFields := suite.createRandomIntInRange(0, params.maxNumFieldsPerObject) + numFields := s.createRandomIntInRange(0, params.maxNumFieldsPerObject) for i := 0; i < numFields; i++ { - key := suite.createRandomString() + key := s.createRandomString() - randField := suite.createRandomJSONField(i, 0) + randField := s.createRandomJSONField(i, 0) payloadRaw, err = sjson.Set(payloadRaw, key, randField) - suite.Require().NoError(err) + s.Require().NoError(err) } return gjson.Parse(payloadRaw) @@ -106,42 +106,42 @@ func (suite *TestSuite) createRandomJSONObject() gjson.Result { // createRandomJSONField creates a random field with a random JSON type, with the possibility of // nested fields up to depth objects. -func (suite *TestSuite) createRandomJSONField(t int, depth int) interface{} { +func (s *TestSuite) createRandomJSONField(t int, depth int) interface{} { switch t % numJSONTypes { case jsonBoolType: - return suite.createRandomBoolean() + return s.createRandomBoolean() case jsonStringType: - return suite.createRandomString() + return s.createRandomString() case jsonFloatType: - return suite.createRandomFloat() + return s.createRandomFloat() case jsonArrayType: - return suite.createRandomJSONNestedArray(depth) + return s.createRandomJSONNestedArray(depth) case jsonObjectType: - return suite.createRandomJSONNestedObject(depth) + return s.createRandomJSONNestedObject(depth) default: return nil } } // createRandomJSONNestedArray creates an array of random nested JSON fields. -func (suite *TestSuite) createRandomJSONNestedArray(depth int) []interface{} { +func (s *TestSuite) createRandomJSONNestedArray(depth int) []interface{} { arr := make([]interface{}, rand.Intn(params.maxArrayLength)) for i := range arr { - arr[i] = suite.createRandomJSONNestedField(depth) + arr[i] = s.createRandomJSONNestedField(depth) } return arr } // createRandomJSONNestedObject creates a key-value set of objects with random nested JSON fields. -func (suite *TestSuite) createRandomJSONNestedObject(depth int) interface{} { +func (s *TestSuite) createRandomJSONNestedObject(depth int) interface{} { numFields := rand.Intn(params.maxNumFieldsPerObject) obj := make(map[string]interface{}) for i := 0; i < numFields; i++ { - subField := suite.createRandomJSONNestedField(depth) + subField := s.createRandomJSONNestedField(depth) - obj[suite.createRandomString()] = subField + obj[s.createRandomString()] = subField } return obj @@ -149,7 +149,7 @@ func (suite *TestSuite) createRandomJSONNestedObject(depth int) interface{} { // createRandomJSONNestedField serves as a helper for createRandomJSONField and returns a random // subfield to populate an array or object type. -func (suite *TestSuite) createRandomJSONNestedField(depth int) interface{} { +func (s *TestSuite) createRandomJSONNestedField(depth int) interface{} { var newFieldType int if depth == params.maxObjectDepth { @@ -158,23 +158,23 @@ func (suite *TestSuite) createRandomJSONNestedField(depth int) interface{} { newFieldType = rand.Intn(numJSONTypes) } - return suite.createRandomJSONField(newFieldType, depth+1) + return s.createRandomJSONField(newFieldType, depth+1) } -func (suite *TestSuite) createRandomBoolean() bool { +func (s *TestSuite) createRandomBoolean() bool { return rand.Intn(2) == 0 } -func (suite *TestSuite) createRandomFloat() float64 { +func (s *TestSuite) createRandomFloat() float64 { return (rand.Float64() - 0.5) * params.randomFloatRange } -func (suite *TestSuite) createRandomString() string { - bzLen := suite.createRandomIntInRange(params.minStringLength, params.maxStringLength) +func (s *TestSuite) createRandomString() string { + bzLen := s.createRandomIntInRange(params.minStringLength, params.maxStringLength) bz := make([]byte, bzLen) for i := 0; i < bzLen; i++ { - bz[i] = byte(suite.createRandomIntInRange(asciiRangeStart, asciiRangeEnd)) + bz[i] = byte(s.createRandomIntInRange(asciiRangeStart, asciiRangeEnd)) } str := string(bz) @@ -189,6 +189,6 @@ func (suite *TestSuite) createRandomString() string { } // createRandomIntInRange provides a random integer between [min, max) -func (suite *TestSuite) createRandomIntInRange(minInt int, maxInt int) int { +func (s *TestSuite) createRandomIntInRange(minInt int, maxInt int) int { return rand.Intn(maxInt-minInt) + minInt } diff --git a/tests/integration/precompiles/erc20/test_errors.go b/tests/integration/precompiles/erc20/test_errors.go index 4614c09c9..66a6d3d36 100644 --- a/tests/integration/precompiles/erc20/test_errors.go +++ b/tests/integration/precompiles/erc20/test_errors.go @@ -1,7 +1,7 @@ package erc20 import ( - erc21 "github.com/cosmos/evm/precompiles/erc20" + "github.com/cosmos/evm/precompiles/erc20" evmtypes "github.com/cosmos/evm/x/vm/types" ) @@ -11,7 +11,7 @@ func (s *PrecompileTestSuite) TestBuildExecRevertedError() { s.T().Skip("skipping until correctly implemented") reason := "ERC20: transfer amount exceeds balance" - revErr, err := erc21.BuildExecRevertedErr(reason) + revErr, err := erc20.BuildExecRevertedErr(reason) s.Require().NoError(err, "should not error when building revert error") revertErr, ok := revErr.(*evmtypes.RevertError) From 08eb803da3b0e132ad35f97f43ba08e21fb4eef4 Mon Sep 17 00:00:00 2001 From: zsystm Date: Thu, 5 Jun 2025 14:43:00 +0900 Subject: [PATCH 16/21] un-do un-necessary change pb files should not be touched --- x/vm/types/evm.pb.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/vm/types/evm.pb.go b/x/vm/types/evm.pb.go index f3393fef9..9f6826192 100644 --- a/x/vm/types/evm.pb.go +++ b/x/vm/types/evm.pb.go @@ -2538,7 +2538,7 @@ func (m *AccessControl) Unmarshal(dAtA []byte) error { switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field create", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Create", wireType) } var msglen int for shift := uint(0); ; shift += 7 { From c928080f7308c665ae8a43eae78a85b981cd15a7 Mon Sep 17 00:00:00 2001 From: zsystm Date: Tue, 10 Jun 2025 14:36:00 +0900 Subject: [PATCH 17/21] re-organize ibc testing dir and make ibc testsing using EvmApp, not evmd --- evmd/tests/ibc/helper.go | 2 +- evmd/tests/ibc/ibc_middleware_test.go | 2 +- evmd/tests/ibc/ics20_precompile_transfer_test.go | 2 +- evmd/tests/ibc/transfer_test.go | 2 +- evmd/tests/ibc/v2_ibc_middleware_test.go | 2 +- evmd/tests/ibc/v2_ics20_precompile_transfer_test.go | 2 +- evmd/tests/ibc/v2_transfer_test.go | 2 +- {ibc/testing => testutil/ibc}/README.md | 0 {ibc/testing => testutil/ibc}/chain.go | 4 ++-- {ibc/testing => testutil/ibc}/config.go | 0 {ibc/testing => testutil/ibc}/coordinator.go | 0 {ibc/testing => testutil/ibc}/endpoint.go | 0 {ibc/testing => testutil/ibc}/endpoint_v2.go | 0 {ibc/testing => testutil/ibc}/events.go | 0 {ibc/testing => testutil/ibc}/helpers.go | 0 {ibc/testing => testutil/ibc}/path.go | 0 {ibc/testing => testutil/ibc}/testing_app.go | 0 {ibc/testing => testutil/ibc}/values.go | 0 18 files changed, 9 insertions(+), 9 deletions(-) rename {ibc/testing => testutil/ibc}/README.md (100%) rename {ibc/testing => testutil/ibc}/chain.go (99%) rename {ibc/testing => testutil/ibc}/config.go (100%) rename {ibc/testing => testutil/ibc}/coordinator.go (100%) rename {ibc/testing => testutil/ibc}/endpoint.go (100%) rename {ibc/testing => testutil/ibc}/endpoint_v2.go (100%) rename {ibc/testing => testutil/ibc}/events.go (100%) rename {ibc/testing => testutil/ibc}/helpers.go (100%) rename {ibc/testing => testutil/ibc}/path.go (100%) rename {ibc/testing => testutil/ibc}/testing_app.go (100%) rename {ibc/testing => testutil/ibc}/values.go (100%) diff --git a/evmd/tests/ibc/helper.go b/evmd/tests/ibc/helper.go index fd56cf5e9..262ab88c6 100644 --- a/evmd/tests/ibc/helper.go +++ b/evmd/tests/ibc/helper.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/cosmos/evm/contracts" - evmibctesting "github.com/cosmos/evm/ibc/testing" + evmibctesting "github.com/cosmos/evm/testutil/ibc" erc20types "github.com/cosmos/evm/x/erc20/types" ibctesting "github.com/cosmos/ibc-go/v10/testing" diff --git a/evmd/tests/ibc/ibc_middleware_test.go b/evmd/tests/ibc/ibc_middleware_test.go index 478e29e03..cb6e23687 100644 --- a/evmd/tests/ibc/ibc_middleware_test.go +++ b/evmd/tests/ibc/ibc_middleware_test.go @@ -9,8 +9,8 @@ import ( testifysuite "github.com/stretchr/testify/suite" "github.com/cosmos/evm/ibc" - evmibctesting "github.com/cosmos/evm/ibc/testing" "github.com/cosmos/evm/testutil" + evmibctesting "github.com/cosmos/evm/testutil/ibc" "github.com/cosmos/evm/x/erc20" erc20Keeper "github.com/cosmos/evm/x/erc20/keeper" "github.com/cosmos/evm/x/erc20/types" diff --git a/evmd/tests/ibc/ics20_precompile_transfer_test.go b/evmd/tests/ibc/ics20_precompile_transfer_test.go index bf3f92d95..7a6113082 100644 --- a/evmd/tests/ibc/ics20_precompile_transfer_test.go +++ b/evmd/tests/ibc/ics20_precompile_transfer_test.go @@ -13,8 +13,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/suite" - evmibctesting "github.com/cosmos/evm/ibc/testing" "github.com/cosmos/evm/precompiles/ics20" + evmibctesting "github.com/cosmos/evm/testutil/ibc" evmante "github.com/cosmos/evm/x/vm/ante" transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" diff --git a/evmd/tests/ibc/transfer_test.go b/evmd/tests/ibc/transfer_test.go index 4f740c9f1..306889c7c 100644 --- a/evmd/tests/ibc/transfer_test.go +++ b/evmd/tests/ibc/transfer_test.go @@ -11,7 +11,7 @@ import ( "cosmosevm.io/evmd" "github.com/stretchr/testify/suite" - evmibctesting "github.com/cosmos/evm/ibc/testing" + evmibctesting "github.com/cosmos/evm/testutil/ibc" "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" diff --git a/evmd/tests/ibc/v2_ibc_middleware_test.go b/evmd/tests/ibc/v2_ibc_middleware_test.go index d10249ce6..d2997c2e9 100644 --- a/evmd/tests/ibc/v2_ibc_middleware_test.go +++ b/evmd/tests/ibc/v2_ibc_middleware_test.go @@ -10,8 +10,8 @@ import ( "cosmosevm.io/evmd" testifysuite "github.com/stretchr/testify/suite" - evmibctesting "github.com/cosmos/evm/ibc/testing" "github.com/cosmos/evm/testutil" + evmibctesting "github.com/cosmos/evm/testutil/ibc" erc20Keeper "github.com/cosmos/evm/x/erc20/keeper" "github.com/cosmos/evm/x/erc20/types" "github.com/cosmos/evm/x/erc20/v2" diff --git a/evmd/tests/ibc/v2_ics20_precompile_transfer_test.go b/evmd/tests/ibc/v2_ics20_precompile_transfer_test.go index 08a23fcda..b5f0e83dd 100644 --- a/evmd/tests/ibc/v2_ics20_precompile_transfer_test.go +++ b/evmd/tests/ibc/v2_ics20_precompile_transfer_test.go @@ -14,8 +14,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/suite" - evmibctesting "github.com/cosmos/evm/ibc/testing" "github.com/cosmos/evm/precompiles/ics20" + evmibctesting "github.com/cosmos/evm/testutil/ibc" evmante "github.com/cosmos/evm/x/vm/ante" transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" diff --git a/evmd/tests/ibc/v2_transfer_test.go b/evmd/tests/ibc/v2_transfer_test.go index 570627580..d6fe70df6 100644 --- a/evmd/tests/ibc/v2_transfer_test.go +++ b/evmd/tests/ibc/v2_transfer_test.go @@ -20,7 +20,7 @@ import ( "cosmosevm.io/evmd" testifysuite "github.com/stretchr/testify/suite" - evmibctesting "github.com/cosmos/evm/ibc/testing" + evmibctesting "github.com/cosmos/evm/testutil/ibc" "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" diff --git a/ibc/testing/README.md b/testutil/ibc/README.md similarity index 100% rename from ibc/testing/README.md rename to testutil/ibc/README.md diff --git a/ibc/testing/chain.go b/testutil/ibc/chain.go similarity index 99% rename from ibc/testing/chain.go rename to testutil/ibc/chain.go index fd9f0a300..fca598979 100644 --- a/ibc/testing/chain.go +++ b/testutil/ibc/chain.go @@ -7,7 +7,6 @@ import ( "testing" "time" - "cosmosevm.io/evmd" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" @@ -18,6 +17,7 @@ import ( cmttypes "github.com/cometbft/cometbft/types" cmtversion "github.com/cometbft/cometbft/version" + "github.com/cosmos/evm" "github.com/cosmos/evm/cmd/evmd/config" "github.com/cosmos/evm/crypto/ethsecp256k1" "github.com/cosmos/evm/testutil/tx" @@ -367,7 +367,7 @@ func (chain *TestChain) SendEvmTx( amount *big.Int, data []byte, ) (*abci.ExecTxResult, error) { - app, ok := chain.App.(*evmd.EVMD) + app, ok := chain.App.(evm.EvmApp) require.True(chain.TB, ok) ctx := chain.GetContext() diff --git a/ibc/testing/config.go b/testutil/ibc/config.go similarity index 100% rename from ibc/testing/config.go rename to testutil/ibc/config.go diff --git a/ibc/testing/coordinator.go b/testutil/ibc/coordinator.go similarity index 100% rename from ibc/testing/coordinator.go rename to testutil/ibc/coordinator.go diff --git a/ibc/testing/endpoint.go b/testutil/ibc/endpoint.go similarity index 100% rename from ibc/testing/endpoint.go rename to testutil/ibc/endpoint.go diff --git a/ibc/testing/endpoint_v2.go b/testutil/ibc/endpoint_v2.go similarity index 100% rename from ibc/testing/endpoint_v2.go rename to testutil/ibc/endpoint_v2.go diff --git a/ibc/testing/events.go b/testutil/ibc/events.go similarity index 100% rename from ibc/testing/events.go rename to testutil/ibc/events.go diff --git a/ibc/testing/helpers.go b/testutil/ibc/helpers.go similarity index 100% rename from ibc/testing/helpers.go rename to testutil/ibc/helpers.go diff --git a/ibc/testing/path.go b/testutil/ibc/path.go similarity index 100% rename from ibc/testing/path.go rename to testutil/ibc/path.go diff --git a/ibc/testing/testing_app.go b/testutil/ibc/testing_app.go similarity index 100% rename from ibc/testing/testing_app.go rename to testutil/ibc/testing_app.go diff --git a/ibc/testing/values.go b/testutil/ibc/values.go similarity index 100% rename from ibc/testing/values.go rename to testutil/ibc/values.go From 2e8c2b697ff3840b4ccae57168b5f0cc5b512fe4 Mon Sep 17 00:00:00 2001 From: zsystm Date: Tue, 10 Jun 2025 14:36:15 +0900 Subject: [PATCH 18/21] fix Makefile --- Makefile | 42 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/Makefile b/Makefile index 5c7556396..90f1362c9 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ #!/usr/bin/make -f +PACKAGES_NOSIMULATION=$(shell go list ./... | grep -v '/simulation') VERSION ?= $(shell echo $(shell git describe --tags --always) | sed 's/^v//') TMVERSION := $(shell go list -m github.com/cometbft/cometbft | sed 's:.* ::') COMMIT := $(shell git log -1 --format='%H') @@ -100,28 +101,15 @@ vulncheck: ### Tests & Simulation ### ############################################################################### -test: test-unit -test-all: - @echo "🔍 Running evm module tests..." - @go test -tags=test -mod=readonly -timeout=15m $(PACKAGES_NOSIMULATION) - @echo "🔍 Running evmd module tests..." - @cd evmd && go test -tags=test -mod=readonly -timeout=15m $(PACKAGES_EVMD) - - -# For unit tests we don't want to execute the upgrade tests in tests/e2e but -# we want to include all unit tests in the subfolders (tests/e2e/*) -PACKAGES_UNIT := $(shell go list ./... | grep -v '/tests/e2e$$' | grep -v '/simulation') -PACKAGES_EVMD := $(shell cd evmd && go list ./... | grep -v '/simulation') -COVERPKG_EVM := $(shell go list ./... | grep -v '/tests/e2e$$' | grep -v '/simulation' | paste -sd, -) -COVERPKG_ALL := $(COVERPKG_EVM) -COMMON_COVER_ARGS := -timeout=15m -covermode=atomic +PACKAGES_UNIT := $(shell go list ./... | grep -v '/tests/e2e$$' | grep -v '/simulation') +PACKAGES_EVMD := $(shell cd evmd && go list ./... | grep -v '/simulation') +COVERPKG_EVM := $(shell go list ./... | grep -v '/tests/e2e$$' | grep -v '/simulation' | paste -sd, -) +COVERPKG_ALL := $(COVERPKG_EVM) +COMMON_COVER_ARGS := -timeout=15m -covermode=atomic -TEST_PACKAGES=./... +TEST_PACKAGES := ./... TEST_TARGETS := test-unit test-evmd test-unit-cover test-race -# Test runs-specific rules. To add a new test target, just add -# a new rule, customise ARGS or TEST_PACKAGES ad libitum, and -# append the new rule to the TEST_TARGETS list. test-unit: ARGS=-timeout=15m test-unit: TEST_PACKAGES=$(PACKAGES_UNIT) test-unit: run-tests @@ -131,7 +119,6 @@ test-race: TEST_PACKAGES=$(PACKAGES_UNIT) test-race: run-tests test-evmd: ARGS=-timeout=15m -test-evmd: TEST_PACKAGES=$(PACKAGES_EVMD) test-evmd: @cd evmd && go test -tags=test -mod=readonly $(ARGS) $(EXTRA_ARGS) $(PACKAGES_EVMD) @@ -143,13 +130,18 @@ test-unit-cover: run-tests @echo "🔍 Running evmd coverage..." @cd evmd && go test -tags=test $(COMMON_COVER_ARGS) -coverpkg=$(COVERPKG_ALL) -coverprofile=coverage_evmd.txt ./... @echo "🔀 Merging evmd coverage into root coverage..." - @tail -n +2 evmd/coverage_evmd.txt >> coverage.txt - @rm evmd/coverage_evmd.txt - @echo "🚫 Filtering ignored paths from coverage.txt..." - @grep -v -E '/cmd/|/client/|/proto/|/testutil/|/mocks/|/test_.*\.go:|\.pb\.go:|\.pb\.gw\.go:|/x/[^/]+/module\.go:|/scripts/|/ibc/testing/|/version/|\.md:|\.pulsar\.go:' coverage.txt > tmp_coverage.txt && mv tmp_coverage.txt coverage.txt - @echo "📊 Function-level coverage summary:" + @tail -n +2 evmd/coverage_evmd.txt >> coverage.txt && rm evmd/coverage_evmd.txt + @echo "📊 Coverage summary:" @go tool cover -func=coverage.txt +test: test-unit + +test-all: + @echo "🔍 Running evm module tests..." + @go test -tags=test -mod=readonly -timeout=15m $(PACKAGES_NOSIMULATION) + @echo "🔍 Running evmd module tests..." + @cd evmd && go test -tags=test -mod=readonly -timeout=15m $(PACKAGES_EVMD) + run-tests: ifneq (,$(shell which tparse 2>/dev/null)) go test -tags=test -mod=readonly -json $(ARGS) $(EXTRA_ARGS) $(TEST_PACKAGES) | tparse From e7377b4b6ffb1182b907b3d02e8713a450e4bb58 Mon Sep 17 00:00:00 2001 From: zsystm Date: Thu, 12 Jun 2025 00:19:21 +0900 Subject: [PATCH 19/21] change go mod name to github.com/cosmos/evm/evmd --- ante/evm/fee_checker_test.go | 2 +- cmd/evmd/cmd/root.go | 2 +- cmd/evmd/main.go | 2 +- evmd/activators.go | 2 +- evmd/app.go | 2 +- evmd/go.mod | 4 ++-- evmd/tests/ibc/helper.go | 2 +- evmd/tests/ibc/ibc_middleware_test.go | 2 +- evmd/tests/ibc/ics20_precompile_transfer_test.go | 2 +- evmd/tests/ibc/transfer_test.go | 2 +- evmd/tests/ibc/v2_ibc_middleware_test.go | 2 +- evmd/tests/ibc/v2_ics20_precompile_transfer_test.go | 2 +- evmd/tests/ibc/v2_transfer_test.go | 2 +- evmd/tests/integration/ante/ante_test.go | 2 +- evmd/tests/integration/create_app.go | 2 +- evmd/tests/integration/eips/eips_test.go | 2 +- .../integration/precompiles/bank/precompile_bank_test.go | 2 +- .../integration/precompiles/bech32/precompile_bech32_test.go | 2 +- .../precompiles/distribution/precompile_distribution_test.go | 2 +- .../integration/precompiles/erc20/precompile_erc20_test.go | 2 +- .../precompiles/evidence/precompile_evidence_test.go | 2 +- evmd/tests/integration/precompiles/gov/precompile_gov_test.go | 2 +- .../integration/precompiles/p256/precompile_p256_test.go | 2 +- .../precompiles/slashing/precompile_slashing_test.go | 2 +- .../precompiles/staking/precompile_staking_test.go | 2 +- .../integration/precompiles/werc20/precompile_werc20_test.go | 2 +- go.mod | 4 ++-- tests/integration/ante/benchmark_evm_antehandler.go | 2 +- tests/integration/ante/test_validate_handler_options.go | 2 +- tests/integration/eips/test_eips.go | 4 ++-- tests/integration/ledger/evmosd_suite_test.go | 2 +- tests/integration/x/erc20/test_grpc_query.go | 2 +- tests/integration/x/precisebank/test_send_integration.go | 2 +- tests/integration/x/vm/test_params.go | 2 +- tests/integration/x/vm/test_state_transition.go | 2 +- testutil/ibc/coordinator.go | 2 +- testutil/ibc/testing_app.go | 2 +- testutil/network/network.go | 2 +- x/erc20/types/params_test.go | 2 +- x/precisebank/keeper/keeper_test.go | 2 +- x/vm/types/msg_test.go | 2 +- 41 files changed, 44 insertions(+), 44 deletions(-) diff --git a/ante/evm/fee_checker_test.go b/ante/evm/fee_checker_test.go index e97acf66d..bc18ec24a 100644 --- a/ante/evm/fee_checker_test.go +++ b/ante/evm/fee_checker_test.go @@ -4,7 +4,7 @@ import ( "math/big" "testing" - "cosmosevm.io/evmd" + "github.com/cosmos/evm/evmd" "github.com/stretchr/testify/require" tmproto "github.com/cometbft/cometbft/proto/tendermint/types" diff --git a/cmd/evmd/cmd/root.go b/cmd/evmd/cmd/root.go index 2ac01ca02..791792ac3 100644 --- a/cmd/evmd/cmd/root.go +++ b/cmd/evmd/cmd/root.go @@ -5,7 +5,7 @@ import ( "io" "os" - "cosmosevm.io/evmd" + "github.com/cosmos/evm/evmd" "github.com/spf13/cast" "github.com/spf13/cobra" "github.com/spf13/viper" diff --git a/cmd/evmd/main.go b/cmd/evmd/main.go index c65e5cb62..ba0c40566 100644 --- a/cmd/evmd/main.go +++ b/cmd/evmd/main.go @@ -4,7 +4,7 @@ import ( "fmt" "os" - "cosmosevm.io/evmd" + "github.com/cosmos/evm/evmd" "github.com/cosmos/evm/cmd/evmd/cmd" evmdconfig "github.com/cosmos/evm/cmd/evmd/config" diff --git a/evmd/activators.go b/evmd/activators.go index 1416dc6ad..1638e60f0 100644 --- a/evmd/activators.go +++ b/evmd/activators.go @@ -1,7 +1,7 @@ package evmd import ( - "cosmosevm.io/evmd/eips" + "github.com/cosmos/evm/evmd/eips" "github.com/ethereum/go-ethereum/core/vm" ) diff --git a/evmd/app.go b/evmd/app.go index 8814148ef..d421e8a6e 100644 --- a/evmd/app.go +++ b/evmd/app.go @@ -8,7 +8,7 @@ import ( "os" "sort" - chainante "cosmosevm.io/evmd/ante" + chainante "github.com/cosmos/evm/evmd/ante" corevm "github.com/ethereum/go-ethereum/core/vm" "github.com/spf13/cast" diff --git a/evmd/go.mod b/evmd/go.mod index 4d872a18a..4c12eb4e7 100644 --- a/evmd/go.mod +++ b/evmd/go.mod @@ -1,4 +1,4 @@ -module cosmosevm.io/evmd +module github.com/cosmos/evm/evmd go 1.23.8 @@ -265,7 +265,7 @@ require ( ) replace ( - cosmosevm.io/evmd => ./evmd + github.com/cosmos/evm/evmd => ./evmd // use cosmos fork of keyring github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 // Pin this pebble version to avoid breaking compilation of geth diff --git a/evmd/tests/ibc/helper.go b/evmd/tests/ibc/helper.go index 262ab88c6..31ac2e6b0 100644 --- a/evmd/tests/ibc/helper.go +++ b/evmd/tests/ibc/helper.go @@ -4,7 +4,7 @@ import ( "math/big" "testing" - "cosmosevm.io/evmd" + "github.com/cosmos/evm/evmd" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" diff --git a/evmd/tests/ibc/ibc_middleware_test.go b/evmd/tests/ibc/ibc_middleware_test.go index cb6e23687..f0043d7f6 100644 --- a/evmd/tests/ibc/ibc_middleware_test.go +++ b/evmd/tests/ibc/ibc_middleware_test.go @@ -5,7 +5,7 @@ import ( "math/big" "testing" - "cosmosevm.io/evmd" + "github.com/cosmos/evm/evmd" testifysuite "github.com/stretchr/testify/suite" "github.com/cosmos/evm/ibc" diff --git a/evmd/tests/ibc/ics20_precompile_transfer_test.go b/evmd/tests/ibc/ics20_precompile_transfer_test.go index 7a6113082..3a3ebf565 100644 --- a/evmd/tests/ibc/ics20_precompile_transfer_test.go +++ b/evmd/tests/ibc/ics20_precompile_transfer_test.go @@ -9,7 +9,7 @@ import ( "math/big" "testing" - "cosmosevm.io/evmd" + "github.com/cosmos/evm/evmd" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/suite" diff --git a/evmd/tests/ibc/transfer_test.go b/evmd/tests/ibc/transfer_test.go index 306889c7c..6e0f5444b 100644 --- a/evmd/tests/ibc/transfer_test.go +++ b/evmd/tests/ibc/transfer_test.go @@ -8,7 +8,7 @@ package ibc import ( "testing" - "cosmosevm.io/evmd" + "github.com/cosmos/evm/evmd" "github.com/stretchr/testify/suite" evmibctesting "github.com/cosmos/evm/testutil/ibc" diff --git a/evmd/tests/ibc/v2_ibc_middleware_test.go b/evmd/tests/ibc/v2_ibc_middleware_test.go index d2997c2e9..ffd103961 100644 --- a/evmd/tests/ibc/v2_ibc_middleware_test.go +++ b/evmd/tests/ibc/v2_ibc_middleware_test.go @@ -7,7 +7,7 @@ import ( "testing" "time" - "cosmosevm.io/evmd" + "github.com/cosmos/evm/evmd" testifysuite "github.com/stretchr/testify/suite" "github.com/cosmos/evm/testutil" diff --git a/evmd/tests/ibc/v2_ics20_precompile_transfer_test.go b/evmd/tests/ibc/v2_ics20_precompile_transfer_test.go index b5f0e83dd..104e9b77a 100644 --- a/evmd/tests/ibc/v2_ics20_precompile_transfer_test.go +++ b/evmd/tests/ibc/v2_ics20_precompile_transfer_test.go @@ -10,7 +10,7 @@ import ( "testing" "time" - "cosmosevm.io/evmd" + "github.com/cosmos/evm/evmd" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/suite" diff --git a/evmd/tests/ibc/v2_transfer_test.go b/evmd/tests/ibc/v2_transfer_test.go index d6fe70df6..d967534bc 100644 --- a/evmd/tests/ibc/v2_transfer_test.go +++ b/evmd/tests/ibc/v2_transfer_test.go @@ -17,7 +17,7 @@ import ( "testing" "time" - "cosmosevm.io/evmd" + "github.com/cosmos/evm/evmd" testifysuite "github.com/stretchr/testify/suite" evmibctesting "github.com/cosmos/evm/testutil/ibc" diff --git a/evmd/tests/integration/ante/ante_test.go b/evmd/tests/integration/ante/ante_test.go index fb6651b64..28ec4f8ce 100644 --- a/evmd/tests/integration/ante/ante_test.go +++ b/evmd/tests/integration/ante/ante_test.go @@ -3,7 +3,7 @@ package ante import ( "testing" - "cosmosevm.io/evmd/tests/integration" + "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/tests/integration/ante" ) diff --git a/evmd/tests/integration/create_app.go b/evmd/tests/integration/create_app.go index 7f6c0d151..7f49ebe36 100644 --- a/evmd/tests/integration/create_app.go +++ b/evmd/tests/integration/create_app.go @@ -1,7 +1,7 @@ package integration import ( - "cosmosevm.io/evmd" + "github.com/cosmos/evm/evmd" dbm "github.com/cosmos/cosmos-db" "github.com/cosmos/evm" diff --git a/evmd/tests/integration/eips/eips_test.go b/evmd/tests/integration/eips/eips_test.go index 34ecab0ce..6d793836d 100644 --- a/evmd/tests/integration/eips/eips_test.go +++ b/evmd/tests/integration/eips/eips_test.go @@ -3,7 +3,7 @@ package eips import ( "testing" - "cosmosevm.io/evmd/tests/integration" + "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/tests/integration/eips" ) diff --git a/evmd/tests/integration/precompiles/bank/precompile_bank_test.go b/evmd/tests/integration/precompiles/bank/precompile_bank_test.go index 6f504cc54..32fc43ec3 100644 --- a/evmd/tests/integration/precompiles/bank/precompile_bank_test.go +++ b/evmd/tests/integration/precompiles/bank/precompile_bank_test.go @@ -3,7 +3,7 @@ package bank import ( "testing" - "cosmosevm.io/evmd/tests/integration" + "github.com/cosmos/evm/evmd/tests/integration" "github.com/stretchr/testify/suite" "github.com/cosmos/evm/tests/integration/precompiles/bank" diff --git a/evmd/tests/integration/precompiles/bech32/precompile_bech32_test.go b/evmd/tests/integration/precompiles/bech32/precompile_bech32_test.go index 73a64d3aa..5f0f5bb47 100644 --- a/evmd/tests/integration/precompiles/bech32/precompile_bech32_test.go +++ b/evmd/tests/integration/precompiles/bech32/precompile_bech32_test.go @@ -3,7 +3,7 @@ package bech32 import ( "testing" - "cosmosevm.io/evmd/tests/integration" + "github.com/cosmos/evm/evmd/tests/integration" "github.com/stretchr/testify/suite" "github.com/cosmos/evm/tests/integration/precompiles/bech32" diff --git a/evmd/tests/integration/precompiles/distribution/precompile_distribution_test.go b/evmd/tests/integration/precompiles/distribution/precompile_distribution_test.go index 37317a84a..8f24d4894 100644 --- a/evmd/tests/integration/precompiles/distribution/precompile_distribution_test.go +++ b/evmd/tests/integration/precompiles/distribution/precompile_distribution_test.go @@ -3,7 +3,7 @@ package distribution import ( "testing" - "cosmosevm.io/evmd/tests/integration" + "github.com/cosmos/evm/evmd/tests/integration" "github.com/stretchr/testify/suite" "github.com/cosmos/evm/tests/integration/precompiles/distribution" diff --git a/evmd/tests/integration/precompiles/erc20/precompile_erc20_test.go b/evmd/tests/integration/precompiles/erc20/precompile_erc20_test.go index 18547f268..b7c6377ed 100644 --- a/evmd/tests/integration/precompiles/erc20/precompile_erc20_test.go +++ b/evmd/tests/integration/precompiles/erc20/precompile_erc20_test.go @@ -3,7 +3,7 @@ package erc20 import ( "testing" - "cosmosevm.io/evmd/tests/integration" + "github.com/cosmos/evm/evmd/tests/integration" "github.com/stretchr/testify/suite" erc21 "github.com/cosmos/evm/tests/integration/precompiles/erc20" diff --git a/evmd/tests/integration/precompiles/evidence/precompile_evidence_test.go b/evmd/tests/integration/precompiles/evidence/precompile_evidence_test.go index ac72e94cb..7e39ad760 100644 --- a/evmd/tests/integration/precompiles/evidence/precompile_evidence_test.go +++ b/evmd/tests/integration/precompiles/evidence/precompile_evidence_test.go @@ -3,7 +3,7 @@ package evidence import ( "testing" - "cosmosevm.io/evmd/tests/integration" + "github.com/cosmos/evm/evmd/tests/integration" "github.com/stretchr/testify/suite" "github.com/cosmos/evm/tests/integration/precompiles/evidence" diff --git a/evmd/tests/integration/precompiles/gov/precompile_gov_test.go b/evmd/tests/integration/precompiles/gov/precompile_gov_test.go index b33005841..87251abdc 100644 --- a/evmd/tests/integration/precompiles/gov/precompile_gov_test.go +++ b/evmd/tests/integration/precompiles/gov/precompile_gov_test.go @@ -3,7 +3,7 @@ package gov import ( "testing" - "cosmosevm.io/evmd/tests/integration" + "github.com/cosmos/evm/evmd/tests/integration" "github.com/stretchr/testify/suite" "github.com/cosmos/evm/tests/integration/precompiles/gov" diff --git a/evmd/tests/integration/precompiles/p256/precompile_p256_test.go b/evmd/tests/integration/precompiles/p256/precompile_p256_test.go index 1a8da1297..d8f4d0b06 100644 --- a/evmd/tests/integration/precompiles/p256/precompile_p256_test.go +++ b/evmd/tests/integration/precompiles/p256/precompile_p256_test.go @@ -3,7 +3,7 @@ package p256 import ( "testing" - "cosmosevm.io/evmd/tests/integration" + "github.com/cosmos/evm/evmd/tests/integration" "github.com/stretchr/testify/suite" "github.com/cosmos/evm/tests/integration/precompiles/p256" diff --git a/evmd/tests/integration/precompiles/slashing/precompile_slashing_test.go b/evmd/tests/integration/precompiles/slashing/precompile_slashing_test.go index 80f2f7eb8..614b8dc15 100644 --- a/evmd/tests/integration/precompiles/slashing/precompile_slashing_test.go +++ b/evmd/tests/integration/precompiles/slashing/precompile_slashing_test.go @@ -3,7 +3,7 @@ package slashing import ( "testing" - "cosmosevm.io/evmd/tests/integration" + "github.com/cosmos/evm/evmd/tests/integration" "github.com/stretchr/testify/suite" "github.com/cosmos/evm/tests/integration/precompiles/slashing" diff --git a/evmd/tests/integration/precompiles/staking/precompile_staking_test.go b/evmd/tests/integration/precompiles/staking/precompile_staking_test.go index f73015886..f803e5f8d 100644 --- a/evmd/tests/integration/precompiles/staking/precompile_staking_test.go +++ b/evmd/tests/integration/precompiles/staking/precompile_staking_test.go @@ -3,7 +3,7 @@ package staking import ( "testing" - "cosmosevm.io/evmd/tests/integration" + "github.com/cosmos/evm/evmd/tests/integration" "github.com/stretchr/testify/suite" "github.com/cosmos/evm/tests/integration/precompiles/staking" diff --git a/evmd/tests/integration/precompiles/werc20/precompile_werc20_test.go b/evmd/tests/integration/precompiles/werc20/precompile_werc20_test.go index 1a08f0047..9c679a7d1 100644 --- a/evmd/tests/integration/precompiles/werc20/precompile_werc20_test.go +++ b/evmd/tests/integration/precompiles/werc20/precompile_werc20_test.go @@ -3,7 +3,7 @@ package werc20 import ( "testing" - "cosmosevm.io/evmd/tests/integration" + "github.com/cosmos/evm/evmd/tests/integration" "github.com/stretchr/testify/suite" "github.com/cosmos/evm/tests/integration/precompiles/werc20" diff --git a/go.mod b/go.mod index e8b1a23da..a9f27e89c 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module github.com/cosmos/evm go 1.23.8 require ( - cosmosevm.io/evmd v0.0.0 cosmossdk.io/api v0.9.2 cosmossdk.io/core v0.11.3 cosmossdk.io/errors v1.0.2 @@ -20,6 +19,7 @@ require ( github.com/cosmos/cosmos-db v1.1.1 github.com/cosmos/cosmos-proto v1.0.0-beta.5 github.com/cosmos/cosmos-sdk v0.53.0 + github.com/cosmos/evm/evmd v0.0.0 github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/gogoproto v1.7.0 github.com/cosmos/ibc-go/modules/capability v1.0.1 @@ -271,11 +271,11 @@ require ( ) replace ( - cosmosevm.io/evmd => ./evmd // use cosmos fork of keyring github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 // Pin this pebble version to avoid breaking compilation of geth github.com/cockroachdb/pebble => github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 + github.com/cosmos/evm/evmd => ./evmd // use Cosmos geth fork github.com/ethereum/go-ethereum => github.com/cosmos/go-ethereum v1.15.11-cosmos-0 // Security Advisory https://github.com/advisories/GHSA-h395-qcrw-5vmq diff --git a/tests/integration/ante/benchmark_evm_antehandler.go b/tests/integration/ante/benchmark_evm_antehandler.go index ea2f2ce31..7210d8566 100644 --- a/tests/integration/ante/benchmark_evm_antehandler.go +++ b/tests/integration/ante/benchmark_evm_antehandler.go @@ -5,7 +5,7 @@ import ( "math/big" "testing" - chainante "cosmosevm.io/evmd/ante" + chainante "github.com/cosmos/evm/evmd/ante" "github.com/cosmos/evm/ante" ethante "github.com/cosmos/evm/ante/evm" diff --git a/tests/integration/ante/test_validate_handler_options.go b/tests/integration/ante/test_validate_handler_options.go index 794748d5c..2cc3be1e5 100644 --- a/tests/integration/ante/test_validate_handler_options.go +++ b/tests/integration/ante/test_validate_handler_options.go @@ -3,7 +3,7 @@ package ante import ( "testing" - chainante "cosmosevm.io/evmd/ante" + chainante "github.com/cosmos/evm/evmd/ante" "github.com/stretchr/testify/require" "github.com/cosmos/evm/ante" diff --git a/tests/integration/eips/test_eips.go b/tests/integration/eips/test_eips.go index e983c22f1..5b9705a42 100644 --- a/tests/integration/eips/test_eips.go +++ b/tests/integration/eips/test_eips.go @@ -5,8 +5,8 @@ import ( "math/big" "testing" - "cosmosevm.io/evmd/eips" - "cosmosevm.io/evmd/eips/testdata" + "github.com/cosmos/evm/evmd/eips" + "github.com/cosmos/evm/evmd/eips/testdata" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/params" diff --git a/tests/integration/ledger/evmosd_suite_test.go b/tests/integration/ledger/evmosd_suite_test.go index 1fd68b1db..ca111482c 100644 --- a/tests/integration/ledger/evmosd_suite_test.go +++ b/tests/integration/ledger/evmosd_suite_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - exampleapp "cosmosevm.io/evmd" + exampleapp "github.com/cosmos/evm/evmd" "github.com/ethereum/go-ethereum/common" "github.com/spf13/cobra" "github.com/stretchr/testify/suite" diff --git a/tests/integration/x/erc20/test_grpc_query.go b/tests/integration/x/erc20/test_grpc_query.go index a78348c31..2d868e977 100644 --- a/tests/integration/x/erc20/test_grpc_query.go +++ b/tests/integration/x/erc20/test_grpc_query.go @@ -3,7 +3,7 @@ package erc20 import ( "fmt" - exampleapp "cosmosevm.io/evmd" + exampleapp "github.com/cosmos/evm/evmd" testconstants "github.com/cosmos/evm/testutil/constants" utiltx "github.com/cosmos/evm/testutil/tx" diff --git a/tests/integration/x/precisebank/test_send_integration.go b/tests/integration/x/precisebank/test_send_integration.go index 22aa0bfda..d7e5fc69c 100644 --- a/tests/integration/x/precisebank/test_send_integration.go +++ b/tests/integration/x/precisebank/test_send_integration.go @@ -6,7 +6,7 @@ import ( "math/rand" "testing" - "cosmosevm.io/evmd" + "github.com/cosmos/evm/evmd" "github.com/stretchr/testify/require" testconstants "github.com/cosmos/evm/testutil/constants" diff --git a/tests/integration/x/vm/test_params.go b/tests/integration/x/vm/test_params.go index 067cb40f2..487894692 100644 --- a/tests/integration/x/vm/test_params.go +++ b/tests/integration/x/vm/test_params.go @@ -1,7 +1,7 @@ package vm import ( - exampleapp "cosmosevm.io/evmd" + exampleapp "github.com/cosmos/evm/evmd" "github.com/cosmos/evm/x/vm/types" ) diff --git a/tests/integration/x/vm/test_state_transition.go b/tests/integration/x/vm/test_state_transition.go index 3b94e5d38..164bed363 100644 --- a/tests/integration/x/vm/test_state_transition.go +++ b/tests/integration/x/vm/test_state_transition.go @@ -5,7 +5,7 @@ import ( "math" "math/big" - exampleapp "cosmosevm.io/evmd" + exampleapp "github.com/cosmos/evm/evmd" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" gethtypes "github.com/ethereum/go-ethereum/core/types" diff --git a/testutil/ibc/coordinator.go b/testutil/ibc/coordinator.go index 33cf655cb..9484202fe 100644 --- a/testutil/ibc/coordinator.go +++ b/testutil/ibc/coordinator.go @@ -6,7 +6,7 @@ import ( "testing" "time" - "cosmosevm.io/evmd" + "github.com/cosmos/evm/evmd" "github.com/stretchr/testify/require" ibctesting "github.com/cosmos/ibc-go/v10/testing" diff --git a/testutil/ibc/testing_app.go b/testutil/ibc/testing_app.go index b5813bb17..3ec921953 100644 --- a/testutil/ibc/testing_app.go +++ b/testutil/ibc/testing_app.go @@ -3,7 +3,7 @@ package ibctesting import ( "encoding/json" - "cosmosevm.io/evmd" + "github.com/cosmos/evm/evmd" dbm "github.com/cosmos/cosmos-db" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" diff --git a/testutil/network/network.go b/testutil/network/network.go index d226c009b..6c366ddc3 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -17,7 +17,7 @@ import ( "testing" "time" - exampleapp "cosmosevm.io/evmd" + exampleapp "github.com/cosmos/evm/evmd" "github.com/ethereum/go-ethereum/ethclient" "github.com/spf13/cobra" "golang.org/x/sync/errgroup" diff --git a/x/erc20/types/params_test.go b/x/erc20/types/params_test.go index e0be3ef50..60884705a 100644 --- a/x/erc20/types/params_test.go +++ b/x/erc20/types/params_test.go @@ -4,7 +4,7 @@ import ( "slices" "testing" - "cosmosevm.io/evmd" + "github.com/cosmos/evm/evmd" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" diff --git a/x/precisebank/keeper/keeper_test.go b/x/precisebank/keeper/keeper_test.go index 8bb7af34f..4fe0298b9 100644 --- a/x/precisebank/keeper/keeper_test.go +++ b/x/precisebank/keeper/keeper_test.go @@ -3,7 +3,7 @@ package keeper_test import ( "testing" - "cosmosevm.io/evmd" + "github.com/cosmos/evm/evmd" evmosencoding "github.com/cosmos/evm/encoding" testconstants "github.com/cosmos/evm/testutil/constants" diff --git a/x/vm/types/msg_test.go b/x/vm/types/msg_test.go index 6562e80ba..1e46baca2 100644 --- a/x/vm/types/msg_test.go +++ b/x/vm/types/msg_test.go @@ -8,7 +8,7 @@ import ( "strings" "testing" - "cosmosevm.io/evmd" + "github.com/cosmos/evm/evmd" "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" From f6d4a46331e1ef7bf43bd64023339557ae370974 Mon Sep 17 00:00:00 2001 From: zsystm Date: Thu, 12 Jun 2025 03:36:01 +0900 Subject: [PATCH 20/21] merge main & resolve conflicts --- ante/evm/fee_checker_test.go | 2 +- cmd/evmd/cmd/root.go | 2 +- cmd/evmd/main.go | 3 +- evmd/activators.go | 3 +- evmd/app.go | 6 +- evmd/go.mod | 29 ++--- evmd/go.sum | 104 ++++++++++++------ evmd/tests/ibc/helper.go | 6 +- evmd/tests/ibc/ibc_middleware_test.go | 12 +- .../ibc/ics20_precompile_transfer_test.go | 2 +- evmd/tests/ibc/transfer_test.go | 2 +- evmd/tests/ibc/v2_ibc_middleware_test.go | 2 +- .../ibc/v2_ics20_precompile_transfer_test.go | 2 +- evmd/tests/ibc/v2_transfer_test.go | 2 +- evmd/tests/integration/ante/ante_test.go | 1 - evmd/tests/integration/create_app.go | 3 +- evmd/tests/integration/eips/eips_test.go | 1 - evmd/tests/integration/ibc_callbacks_test.go | 13 +++ .../precompiles/bank/precompile_bank_test.go | 2 +- .../bech32/precompile_bech32_test.go | 2 +- .../precompile_distribution_test.go | 2 +- .../erc20/precompile_erc20_test.go | 2 +- .../evidence/precompile_evidence_test.go | 2 +- .../precompiles/gov/precompile_gov_test.go | 2 +- .../precompiles/p256/precompile_p256_test.go | 2 +- .../slashing/precompile_slashing_test.go | 2 +- .../staking/precompile_staking_test.go | 2 +- .../werc20/precompile_werc20_test.go | 2 +- go.mod | 10 +- go.sum | 11 +- interfaces.go | 2 + .../ante/benchmark_evm_antehandler.go | 3 +- .../ante/test_validate_handler_options.go | 2 +- tests/integration/eips/test_eips.go | 4 +- tests/integration/ledger/evmosd_suite_test.go | 2 +- .../precompiles/erc20/test_integration.go | 2 +- tests/integration/x/erc20/test_grpc_query.go | 1 - .../integration/x/erc20/test_ibc_callback.go | 2 +- .../x/ibc/callbacks/test_keeper.go | 46 ++++---- .../integration/x/ibc/callbacks/test_setup.go | 48 ++++++++ .../x/precisebank/test_send_integration.go | 2 +- tests/integration/x/vm/test_call_evm.go | 6 +- tests/integration/x/vm/test_params.go | 1 - .../integration/x/vm/test_state_transition.go | 2 +- testutil/ibc/coordinator.go | 2 +- testutil/ibc/testing_app.go | 3 +- testutil/network/network.go | 2 +- x/erc20/types/params_test.go | 2 +- x/ibc/callbacks/keeper/setup_test.go | 43 -------- x/precisebank/keeper/keeper_test.go | 3 +- x/vm/types/msg_test.go | 2 +- 51 files changed, 236 insertions(+), 180 deletions(-) create mode 100644 evmd/tests/integration/ibc_callbacks_test.go rename x/ibc/callbacks/keeper/keeper_test.go => tests/integration/x/ibc/callbacks/test_keeper.go (83%) create mode 100644 tests/integration/x/ibc/callbacks/test_setup.go delete mode 100644 x/ibc/callbacks/keeper/setup_test.go diff --git a/ante/evm/fee_checker_test.go b/ante/evm/fee_checker_test.go index bc18ec24a..87038f78e 100644 --- a/ante/evm/fee_checker_test.go +++ b/ante/evm/fee_checker_test.go @@ -4,7 +4,6 @@ import ( "math/big" "testing" - "github.com/cosmos/evm/evmd" "github.com/stretchr/testify/require" tmproto "github.com/cometbft/cometbft/proto/tendermint/types" @@ -13,6 +12,7 @@ import ( anteinterfaces "github.com/cosmos/evm/ante/interfaces" evmdconfig "github.com/cosmos/evm/cmd/evmd/config" "github.com/cosmos/evm/encoding" + "github.com/cosmos/evm/evmd" testconstants "github.com/cosmos/evm/testutil/constants" "github.com/cosmos/evm/types" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" diff --git a/cmd/evmd/cmd/root.go b/cmd/evmd/cmd/root.go index 791792ac3..e8b99d7d0 100644 --- a/cmd/evmd/cmd/root.go +++ b/cmd/evmd/cmd/root.go @@ -5,7 +5,6 @@ import ( "io" "os" - "github.com/cosmos/evm/evmd" "github.com/spf13/cast" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -17,6 +16,7 @@ import ( cosmosevmcmd "github.com/cosmos/evm/client" evmdconfig "github.com/cosmos/evm/cmd/evmd/config" cosmosevmkeyring "github.com/cosmos/evm/crypto/keyring" + "github.com/cosmos/evm/evmd" cosmosevmserver "github.com/cosmos/evm/server" cosmosevmserverconfig "github.com/cosmos/evm/server/config" srvflags "github.com/cosmos/evm/server/flags" diff --git a/cmd/evmd/main.go b/cmd/evmd/main.go index ba0c40566..85dc94e20 100644 --- a/cmd/evmd/main.go +++ b/cmd/evmd/main.go @@ -4,10 +4,9 @@ import ( "fmt" "os" - "github.com/cosmos/evm/evmd" - "github.com/cosmos/evm/cmd/evmd/cmd" evmdconfig "github.com/cosmos/evm/cmd/evmd/config" + "github.com/cosmos/evm/evmd" svrcmd "github.com/cosmos/cosmos-sdk/server/cmd" sdk "github.com/cosmos/cosmos-sdk/types" diff --git a/evmd/activators.go b/evmd/activators.go index 1638e60f0..05bccbef6 100644 --- a/evmd/activators.go +++ b/evmd/activators.go @@ -1,8 +1,9 @@ package evmd import ( - "github.com/cosmos/evm/evmd/eips" "github.com/ethereum/go-ethereum/core/vm" + + "github.com/cosmos/evm/evmd/eips" ) // cosmosEVMActivators defines a map of opcode modifiers associated diff --git a/evmd/app.go b/evmd/app.go index eb686c645..b1b2fead4 100644 --- a/evmd/app.go +++ b/evmd/app.go @@ -8,7 +8,6 @@ import ( "os" "sort" - chainante "github.com/cosmos/evm/evmd/ante" corevm "github.com/ethereum/go-ethereum/core/vm" "github.com/spf13/cast" @@ -22,6 +21,7 @@ import ( evmante "github.com/cosmos/evm/ante" cosmosevmante "github.com/cosmos/evm/ante/evm" evmosencoding "github.com/cosmos/evm/encoding" + chainante "github.com/cosmos/evm/evmd/ante" srvflags "github.com/cosmos/evm/server/flags" cosmosevmtypes "github.com/cosmos/evm/types" cosmosevmutils "github.com/cosmos/evm/utils" @@ -1106,6 +1106,10 @@ func (app *EVMD) GetPreciseBankKeeper() *precisebankkeeper.Keeper { return &app.PreciseBankKeeper } +func (app *EVMD) GetCallbackKeeper() ibccallbackskeeper.ContractKeeper { + return app.CallbackKeeper +} + func (app *EVMD) GetTransferKeeper() transferkeeper.Keeper { return app.TransferKeeper } diff --git a/evmd/go.mod b/evmd/go.mod index 4c12eb4e7..b355bdc8b 100644 --- a/evmd/go.mod +++ b/evmd/go.mod @@ -7,7 +7,7 @@ require ( cosmossdk.io/client/v2 v2.0.0-beta.7 cosmossdk.io/core v0.11.3 cosmossdk.io/errors v1.0.2 - cosmossdk.io/log v1.5.1 + cosmossdk.io/log v1.6.0 cosmossdk.io/math v1.5.3 cosmossdk.io/store v1.1.2 cosmossdk.io/x/evidence v0.1.1 @@ -19,8 +19,8 @@ require ( github.com/cosmos/cosmos-sdk v0.53.0 github.com/cosmos/evm v0.2.0 github.com/cosmos/gogoproto v1.7.0 - github.com/cosmos/ibc-go/v10 v10.2.0 - github.com/ethereum/go-ethereum v1.15.10 + github.com/cosmos/ibc-go/v10 v10.0.0-beta.0.0.20250528142215-7d579b91ac6b + github.com/ethereum/go-ethereum v1.15.11 github.com/spf13/cast v1.8.0 github.com/stretchr/testify v1.10.0 ) @@ -34,7 +34,7 @@ require ( cloud.google.com/go/iam v1.2.2 // indirect cloud.google.com/go/monitoring v1.21.2 // indirect cloud.google.com/go/storage v1.49.0 // indirect - cosmossdk.io/collections v1.2.0 // indirect + cosmossdk.io/collections v1.2.1 // indirect cosmossdk.io/depinject v1.2.0 // indirect cosmossdk.io/schema v1.1.0 // indirect filippo.io/edwards25519 v1.1.0 // indirect @@ -48,7 +48,7 @@ require ( github.com/Microsoft/go-winio v0.6.2 // indirect github.com/StackExchange/wmi v1.2.1 // indirect github.com/VictoriaMetrics/fastcache v1.12.2 // indirect - github.com/aws/aws-sdk-go v1.44.224 // indirect + github.com/aws/aws-sdk-go v1.49.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/bgentry/speakeasy v0.2.0 // indirect @@ -65,8 +65,8 @@ require ( github.com/cloudwego/base64x v0.1.5 // indirect github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42 // indirect github.com/cockroachdb/apd/v2 v2.0.2 // indirect - github.com/cockroachdb/errors v1.11.3 // indirect - github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect + github.com/cockroachdb/errors v1.12.0 // indirect + github.com/cockroachdb/logtags v0.0.0-20241215232642-bb51bb14a506 // indirect github.com/cockroachdb/pebble v1.1.5 // indirect github.com/cockroachdb/redact v1.1.6 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect @@ -91,7 +91,7 @@ require ( github.com/dgraph-io/badger/v4 v4.2.0 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dlclark/regexp2 v1.7.0 // indirect - github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 // indirect + github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.7.0 // indirect github.com/emicklei/dot v1.6.2 // indirect @@ -102,7 +102,7 @@ require ( github.com/fatih/color v1.17.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect - github.com/getsentry/sentry-go v0.28.1 // indirect + github.com/getsentry/sentry-go v0.32.0 // indirect github.com/go-jose/go-jose/v4 v4.0.5 // indirect github.com/go-kit/kit v0.13.0 // indirect github.com/go-kit/log v0.2.1 // indirect @@ -120,7 +120,7 @@ require ( github.com/golang/glog v1.2.4 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect - github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect + github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e // indirect github.com/google/btree v1.1.3 // indirect github.com/google/flatbuffers v24.3.25+incompatible // indirect github.com/google/go-cmp v0.7.0 // indirect @@ -143,7 +143,7 @@ require ( github.com/hashicorp/go-metrics v0.5.4 // indirect github.com/hashicorp/go-plugin v1.6.3 // indirect github.com/hashicorp/go-safetemp v1.0.0 // indirect - github.com/hashicorp/go-version v1.7.0 // indirect + github.com/hashicorp/go-version v1.6.0 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hashicorp/yamux v0.1.2 // indirect @@ -152,6 +152,7 @@ require ( github.com/holiman/uint256 v1.3.2 // indirect github.com/huandu/skiplist v1.2.1 // indirect github.com/huin/goupnp v1.3.0 // indirect + github.com/iancoleman/orderedmap v0.3.0 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/improbable-eng/grpc-web v0.15.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -163,7 +164,7 @@ require ( github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/lib/pq v1.10.9 // indirect - github.com/linxGnu/grocksdb v1.9.8 // indirect + github.com/linxGnu/grocksdb v1.9.2 // indirect github.com/manifoldco/promptui v0.9.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect @@ -230,7 +231,7 @@ require ( go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.34.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect go.opentelemetry.io/otel v1.34.0 // indirect go.opentelemetry.io/otel/metric v1.34.0 // indirect go.opentelemetry.io/otel/sdk v1.34.0 // indirect @@ -265,12 +266,12 @@ require ( ) replace ( - github.com/cosmos/evm/evmd => ./evmd // use cosmos fork of keyring github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 // Pin this pebble version to avoid breaking compilation of geth github.com/cockroachdb/pebble => github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 github.com/cosmos/evm => ../ + github.com/cosmos/evm/evmd => ./evmd // use Cosmos geth fork github.com/ethereum/go-ethereum => github.com/cosmos/go-ethereum v1.15.11-cosmos-0 // Security Advisory https://github.com/advisories/GHSA-h395-qcrw-5vmq diff --git a/evmd/go.sum b/evmd/go.sum index ffd48c9d9..9f10ac5b2 100644 --- a/evmd/go.sum +++ b/evmd/go.sum @@ -618,16 +618,16 @@ cosmossdk.io/api v0.9.2 h1:9i9ptOBdmoIEVEVWLtYYHjxZonlF/aOVODLFaxpmNtg= cosmossdk.io/api v0.9.2/go.mod h1:CWt31nVohvoPMTlPv+mMNCtC0a7BqRdESjCsstHcTkU= cosmossdk.io/client/v2 v2.0.0-beta.7 h1:O0PfZL5kC3Sp54wZASLNihQ612Gd6duMp11aM9wawNg= cosmossdk.io/client/v2 v2.0.0-beta.7/go.mod h1:TzwwrzeK+AfSVSESVEIOYO/9xuCh1fPv0HgeocmfVnM= -cosmossdk.io/collections v1.2.0 h1:IesfVG8G/+FYCMVMP01frS/Cw99Omk5vBh3cHbO01Gg= -cosmossdk.io/collections v1.2.0/go.mod h1:4NkMoYw6qRA8fnSH/yn1D/MOutr8qyQnwsO50Mz9ItU= +cosmossdk.io/collections v1.2.1 h1:mAlNMs5vJwkda4TA+k5q/43p24RVAQ/qyDrjANu3BXE= +cosmossdk.io/collections v1.2.1/go.mod h1:PSsEJ/fqny0VPsHLFT6gXDj/2C1tBOTS9eByK0+PBFU= cosmossdk.io/core v0.11.3 h1:mei+MVDJOwIjIniaKelE3jPDqShCc/F4LkNNHh+4yfo= cosmossdk.io/core v0.11.3/go.mod h1:9rL4RE1uDt5AJ4Tg55sYyHWXA16VmpHgbe0PbJc6N2Y= cosmossdk.io/depinject v1.2.0 h1:6NW/FSK1IkWTrX7XxUpBmX1QMBozpEI9SsWkKTBc5zw= cosmossdk.io/depinject v1.2.0/go.mod h1:pvitjtUxZZZTQESKNS9KhGjWVslJZxtO9VooRJYyPjk= cosmossdk.io/errors v1.0.2 h1:wcYiJz08HThbWxd/L4jObeLaLySopyyuUFB5w4AGpCo= cosmossdk.io/errors v1.0.2/go.mod h1:0rjgiHkftRYPj//3DrD6y8hcm40HcPv/dR4R/4efr0k= -cosmossdk.io/log v1.5.1 h1:wLwiYXmfrort/O+j6EkjF+HvbdrRQd+4cYCPKFSm+zM= -cosmossdk.io/log v1.5.1/go.mod h1:5cXXBvfBkR2/BcXmosdCSLXllvgSjphrrDVdfVRmBGM= +cosmossdk.io/log v1.6.0 h1:SJIOmJ059wi1piyRgNRXKXhlDXGqnB5eQwhcZKv2tOk= +cosmossdk.io/log v1.6.0/go.mod h1:5cXXBvfBkR2/BcXmosdCSLXllvgSjphrrDVdfVRmBGM= cosmossdk.io/math v1.5.3 h1:WH6tu6Z3AUCeHbeOSHg2mt9rnoiUWVWaQ2t6Gkll96U= cosmossdk.io/math v1.5.3/go.mod h1:uqcZv7vexnhMFJF+6zh9EWdm/+Ylyln34IvPnBauPCQ= cosmossdk.io/schema v1.1.0 h1:mmpuz3dzouCoyjjcMcA/xHBEmMChN+EHh8EHxHRHhzE= @@ -711,8 +711,8 @@ github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6l github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -github.com/aws/aws-sdk-go v1.44.224 h1:09CiaaF35nRmxrzWZ2uRq5v6Ghg/d2RiPjZnSgtt+RQ= -github.com/aws/aws-sdk-go v1.44.224/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.49.0 h1:g9BkW1fo9GqKfwg2+zCD+TW/D36Ux+vtfJ8guF4AYmY= +github.com/aws/aws-sdk-go v1.49.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -822,10 +822,10 @@ github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOG github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= -github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= -github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= -github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= -github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/errors v1.12.0 h1:d7oCs6vuIMUQRVbi6jWWWEJZahLCfJpnJSVobd1/sUo= +github.com/cockroachdb/errors v1.12.0/go.mod h1:SvzfYNNBshAVbZ8wzNc/UPK3w1vf0dKDUP41ucAIf7g= +github.com/cockroachdb/logtags v0.0.0-20241215232642-bb51bb14a506 h1:ASDL+UJcILMqgNeV5jiqR4j+sTuvQNHdf2chuKj1M5k= +github.com/cockroachdb/logtags v0.0.0-20241215232642-bb51bb14a506/go.mod h1:Mw7HqKr2kdtu6aYGn3tPmAftiP3QPX63LdK/zcariIo= github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= github.com/cockroachdb/redact v1.1.6 h1:zXJBwDZ84xJNlHl1rMyCojqyIxv+7YUpQiJLQ7n4314= @@ -868,8 +868,8 @@ github.com/cosmos/iavl v1.2.2 h1:qHhKW3I70w+04g5KdsdVSHRbFLgt3yY3qTMd4Xa4rC8= github.com/cosmos/iavl v1.2.2/go.mod h1:GiM43q0pB+uG53mLxLDzimxM9l/5N9UuSY3/D0huuVw= github.com/cosmos/ibc-go/modules/capability v1.0.1 h1:ibwhrpJ3SftEEZRxCRkH0fQZ9svjthrX2+oXdZvzgGI= github.com/cosmos/ibc-go/modules/capability v1.0.1/go.mod h1:rquyOV262nGJplkumH+/LeYs04P3eV8oB7ZM4Ygqk4E= -github.com/cosmos/ibc-go/v10 v10.2.0 h1:wlk/zqz2O0WRyE6UConoR1ci2HSW02P9ywamZCh5/N4= -github.com/cosmos/ibc-go/v10 v10.2.0/go.mod h1:ijeyJ1FDvXoc5w+rlhpMntjhZ558EF02SBFjroW1hPo= +github.com/cosmos/ibc-go/v10 v10.0.0-beta.0.0.20250528142215-7d579b91ac6b h1:+TaXFL0WksE7yBs6DqHrRIDtkKZfu3+Lirbs6rK4N20= +github.com/cosmos/ibc-go/v10 v10.0.0-beta.0.0.20250528142215-7d579b91ac6b/go.mod h1:AQ76dzfU5i3UB5UiktWe6q7hpbPyBXuZcnjMQekBkHs= github.com/cosmos/ics23/go v0.11.0 h1:jk5skjT0TqX5e5QJbEnwXIS2yI2vnmLOgpQPeM5RtnU= github.com/cosmos/ics23/go v0.11.0/go.mod h1:A8OjxPE67hHST4Icw94hOxxFEJMBG031xIGF/JHNIY0= github.com/cosmos/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo= @@ -877,6 +877,7 @@ github.com/cosmos/keyring v1.2.0/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStK github.com/cosmos/ledger-cosmos-go v0.14.0 h1:WfCHricT3rPbkPSVKRH+L4fQGKYHuGOK9Edpel8TYpE= github.com/cosmos/ledger-cosmos-go v0.14.0/go.mod h1:E07xCWSBl3mTGofZ2QnL4cIUzMbbGVyik84QYKbX3RA= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/crate-crypto/go-eth-kzg v1.3.0 h1:05GrhASN9kDAidaFJOda6A4BEvgvuXbazXg/0E3OOdI= github.com/crate-crypto/go-eth-kzg v1.3.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI= @@ -902,6 +903,8 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeC github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/deepmap/oapi-codegen v1.6.0 h1:w/d1ntwh91XI0b/8ja7+u5SvA4IFfM0UNNLmiDR1gg0= +github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= github.com/desertbit/timer v1.0.1 h1:yRpYNn5Vaaj6QXecdLMPMJsW81JLiI1eokUft5nBmeo= github.com/desertbit/timer v1.0.1/go.mod h1:htRrYeY5V/t4iu1xCJ5XsQvp4xve8QulXXctAzxqcwE= @@ -916,14 +919,14 @@ github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUn github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 h1:qwcF+vdFrvPSEUDSX5RVoRccG8a5DhOdWdQ4zN62zzo= -github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -972,6 +975,8 @@ github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/ferranbt/fastssz v0.1.2 h1:Dky6dXlngF6Qjc+EfDipAkE83N5I5DE68bY6O0VLNPk= +github.com/ferranbt/fastssz v0.1.2/go.mod h1:X5UPrE2u1UJjxHA8X54u04SBwdAQjG2sFtWs39YxyWs= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= @@ -985,8 +990,10 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4 github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= -github.com/getsentry/sentry-go v0.28.1 h1:zzaSm/vHmGllRM6Tpx1492r0YDzauArdBfkJRtY6P5k= -github.com/getsentry/sentry-go v0.28.1/go.mod h1:1fQZ+7l7eeJ3wYi82q5Hg8GqAPgefRq+FP/QhafYVgg= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/getsentry/sentry-go v0.32.0 h1:YKs+//QmwE3DcYtfKRH8/KyOOF/I6Qnx7qYGNHCGmCY= +github.com/getsentry/sentry-go v0.32.0/go.mod h1:CYNcMMz73YigoHljQRG+qPF+eMq8gG72XcGN/p71BAY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= @@ -1059,6 +1066,8 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= +github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= @@ -1105,8 +1114,8 @@ github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6 github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= -github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e h1:4bw4WeyTYPp0smaXiJZCNnLrvVBqirQVreixayXezGc= +github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= @@ -1208,6 +1217,8 @@ github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= +github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= @@ -1223,6 +1234,8 @@ github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NM github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= @@ -1251,9 +1264,8 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= -github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -1269,6 +1281,8 @@ github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8 github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= github.com/hdevalence/ed25519consensus v0.2.0 h1:37ICyZqdyj0lAZ8P4D1d1id3HqbbG1N3iBb1Tb4rdcU= github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA= @@ -1281,6 +1295,8 @@ github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXM github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc= +github.com/iancoleman/orderedmap v0.3.0/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJDkXXS7VoV7XGE= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= @@ -1292,7 +1308,13 @@ github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPt github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/influxdata/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl/jhnFtxpKFAv9Tu5k= +github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c h1:qSHzRbhzK8RdXOsAdfDgO49TtqC1oZ+acxPrkfTxcCs= +github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 h1:W9WBk7wlPfJLvMCdtV4zPulc4uCPrlywQOmbFOhgQNU= +github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -1363,8 +1385,8 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/linxGnu/grocksdb v1.9.8 h1:vOIKv9/+HKiqJAElJIEYv3ZLcihRxyP7Suu/Mu8Dxjs= -github.com/linxGnu/grocksdb v1.9.8/go.mod h1:C3CNe9UYc9hlEM2pC82AqiGS3LRW537u9LFV4wIZuHk= +github.com/linxGnu/grocksdb v1.9.2 h1:O3mzvO0wuzQ9mtlHbDrShixyVjVbmuqTjFrzlf43wZ8= +github.com/linxGnu/grocksdb v1.9.2/go.mod h1:QYiYypR2d4v63Wj1adOOfzglnoII0gLj3PNh4fZkcFA= github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= @@ -1399,6 +1421,8 @@ github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcs github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q= github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= +github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= +github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -1410,6 +1434,10 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4 github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= @@ -1450,8 +1478,8 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU= github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= @@ -1463,14 +1491,16 @@ github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlR github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= -github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= +github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= +github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss= github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= @@ -1486,6 +1516,8 @@ github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNc github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM= +github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw= github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= @@ -1576,6 +1608,7 @@ github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= @@ -1678,8 +1711,13 @@ github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0o github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= +github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1716,8 +1754,8 @@ go.opentelemetry.io/contrib/detectors/gcp v1.34.0 h1:JRxssobiPg23otYU5SbWtQC//sn go.opentelemetry.io/contrib/detectors/gcp v1.34.0/go.mod h1:cV4BMFcscUR/ckqLkbfQmF0PRsq8w/lMGzdbCSveBHo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 h1:PS8wXpbyaDJQ2VDHHncMe9Vct0Zn1fEjpsjrLxGJoSc= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0/go.mod h1:HDBUsEjOuRC0EzKZ1bSaRGZWUBAzo+MhAcUUORSr4D0= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0 h1:WDdP9acbMYjbKIyJUhTvtzj601sVJOqgWdUxSdR/Ysc= @@ -1738,6 +1776,8 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko= go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= @@ -1903,7 +1943,6 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= @@ -2093,7 +2132,6 @@ golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= @@ -2524,6 +2562,8 @@ gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qS gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= diff --git a/evmd/tests/ibc/helper.go b/evmd/tests/ibc/helper.go index c6a5d2fda..64219ae5e 100644 --- a/evmd/tests/ibc/helper.go +++ b/evmd/tests/ibc/helper.go @@ -11,8 +11,8 @@ import ( "github.com/cosmos/evm/contracts" "github.com/cosmos/evm/evmd" - evmibctesting "github.com/cosmos/evm/ibc/testing" - "github.com/cosmos/evm/testutil/integration/os/factory" + evmibctesting "github.com/cosmos/evm/testutil/ibc" + testutiltypes "github.com/cosmos/evm/testutil/types" erc20types "github.com/cosmos/evm/x/erc20/types" ibctesting "github.com/cosmos/ibc-go/v10/testing" @@ -98,7 +98,7 @@ func SetupNativeErc20(t *testing.T, chain *evmibctesting.TestChain) *NativeErc20 } // SetupNativeErc20 deploys, registers, and mints a native ERC20 token on an EVM-based chain. -func DeployContract(t *testing.T, chain *evmibctesting.TestChain, deploymentData factory.ContractDeploymentData) (common.Address, error) { +func DeployContract(t *testing.T, chain *evmibctesting.TestChain, deploymentData testutiltypes.ContractDeploymentData) (common.Address, error) { t.Helper() // Get account's nonce to create contract hash diff --git a/evmd/tests/ibc/ibc_middleware_test.go b/evmd/tests/ibc/ibc_middleware_test.go index 11106b1dc..d61616397 100644 --- a/evmd/tests/ibc/ibc_middleware_test.go +++ b/evmd/tests/ibc/ibc_middleware_test.go @@ -13,9 +13,9 @@ import ( "github.com/cosmos/evm/contracts" "github.com/cosmos/evm/evmd" "github.com/cosmos/evm/ibc" - evmibctesting "github.com/cosmos/evm/ibc/testing" "github.com/cosmos/evm/testutil" - "github.com/cosmos/evm/testutil/integration/os/factory" + evmibctesting "github.com/cosmos/evm/testutil/ibc" + testutiltypes "github.com/cosmos/evm/testutil/types" "github.com/cosmos/evm/x/erc20" erc20Keeper "github.com/cosmos/evm/x/erc20/keeper" "github.com/cosmos/evm/x/erc20/types" @@ -319,7 +319,7 @@ func (suite *MiddlewareTestSuite) TestOnRecvPacketWithCallback() { contractData, err = testutil2.LoadCounterWithCallbacksContract() suite.Require().NoError(err) - deploymentData := factory.ContractDeploymentData{ + deploymentData := testutiltypes.ContractDeploymentData{ Contract: contractData, ConstructorArgs: nil, } @@ -627,7 +627,7 @@ func (suite *MiddlewareTestSuite) TestOnRecvPacketNativeErc20() { contractData, err := testutil2.LoadCounterWithCallbacksContract() suite.Require().NoError(err) - deploymentData := factory.ContractDeploymentData{ + deploymentData := testutiltypes.ContractDeploymentData{ Contract: contractData, ConstructorArgs: nil, } @@ -950,7 +950,7 @@ func (suite *MiddlewareTestSuite) TestOnAcknowledgementPacketWithCallback() { contractData, err = testutil2.LoadCounterWithCallbacksContract() suite.Require().NoError(err) - deploymentData := factory.ContractDeploymentData{ + deploymentData := testutiltypes.ContractDeploymentData{ Contract: contractData, ConstructorArgs: nil, } @@ -1731,7 +1731,7 @@ func (suite *MiddlewareTestSuite) TestOnTimeoutPacketWithCallback() { contractData, err = testutil2.LoadCounterWithCallbacksContract() suite.Require().NoError(err) - deploymentData := factory.ContractDeploymentData{ + deploymentData := testutiltypes.ContractDeploymentData{ Contract: contractData, ConstructorArgs: nil, } diff --git a/evmd/tests/ibc/ics20_precompile_transfer_test.go b/evmd/tests/ibc/ics20_precompile_transfer_test.go index 86affeac7..e8a4c19a5 100644 --- a/evmd/tests/ibc/ics20_precompile_transfer_test.go +++ b/evmd/tests/ibc/ics20_precompile_transfer_test.go @@ -9,10 +9,10 @@ import ( "math/big" "testing" - "github.com/cosmos/evm/evmd" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/suite" + "github.com/cosmos/evm/evmd" "github.com/cosmos/evm/precompiles/ics20" evmibctesting "github.com/cosmos/evm/testutil/ibc" evmante "github.com/cosmos/evm/x/vm/ante" diff --git a/evmd/tests/ibc/transfer_test.go b/evmd/tests/ibc/transfer_test.go index 6e0f5444b..1eca7c23d 100644 --- a/evmd/tests/ibc/transfer_test.go +++ b/evmd/tests/ibc/transfer_test.go @@ -8,9 +8,9 @@ package ibc import ( "testing" - "github.com/cosmos/evm/evmd" "github.com/stretchr/testify/suite" + "github.com/cosmos/evm/evmd" evmibctesting "github.com/cosmos/evm/testutil/ibc" "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" diff --git a/evmd/tests/ibc/v2_ibc_middleware_test.go b/evmd/tests/ibc/v2_ibc_middleware_test.go index 5f4b349d8..06c2188f8 100644 --- a/evmd/tests/ibc/v2_ibc_middleware_test.go +++ b/evmd/tests/ibc/v2_ibc_middleware_test.go @@ -7,9 +7,9 @@ import ( "testing" "time" - "github.com/cosmos/evm/evmd" testifysuite "github.com/stretchr/testify/suite" + "github.com/cosmos/evm/evmd" "github.com/cosmos/evm/testutil" evmibctesting "github.com/cosmos/evm/testutil/ibc" erc20Keeper "github.com/cosmos/evm/x/erc20/keeper" diff --git a/evmd/tests/ibc/v2_ics20_precompile_transfer_test.go b/evmd/tests/ibc/v2_ics20_precompile_transfer_test.go index 2203f15a9..09c59b928 100644 --- a/evmd/tests/ibc/v2_ics20_precompile_transfer_test.go +++ b/evmd/tests/ibc/v2_ics20_precompile_transfer_test.go @@ -10,10 +10,10 @@ import ( "testing" "time" - "github.com/cosmos/evm/evmd" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/suite" + "github.com/cosmos/evm/evmd" "github.com/cosmos/evm/precompiles/ics20" evmibctesting "github.com/cosmos/evm/testutil/ibc" evmante "github.com/cosmos/evm/x/vm/ante" diff --git a/evmd/tests/ibc/v2_transfer_test.go b/evmd/tests/ibc/v2_transfer_test.go index bba6a921f..2882c83a9 100644 --- a/evmd/tests/ibc/v2_transfer_test.go +++ b/evmd/tests/ibc/v2_transfer_test.go @@ -17,9 +17,9 @@ import ( "testing" "time" - "github.com/cosmos/evm/evmd" testifysuite "github.com/stretchr/testify/suite" + "github.com/cosmos/evm/evmd" evmibctesting "github.com/cosmos/evm/testutil/ibc" "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" diff --git a/evmd/tests/integration/ante/ante_test.go b/evmd/tests/integration/ante/ante_test.go index 28ec4f8ce..1744da4d8 100644 --- a/evmd/tests/integration/ante/ante_test.go +++ b/evmd/tests/integration/ante/ante_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/cosmos/evm/evmd/tests/integration" - "github.com/cosmos/evm/tests/integration/ante" ) diff --git a/evmd/tests/integration/create_app.go b/evmd/tests/integration/create_app.go index 7f49ebe36..79db8ac38 100644 --- a/evmd/tests/integration/create_app.go +++ b/evmd/tests/integration/create_app.go @@ -1,10 +1,9 @@ package integration import ( - "github.com/cosmos/evm/evmd" - dbm "github.com/cosmos/cosmos-db" "github.com/cosmos/evm" + "github.com/cosmos/evm/evmd" "cosmossdk.io/log" diff --git a/evmd/tests/integration/eips/eips_test.go b/evmd/tests/integration/eips/eips_test.go index 6d793836d..a959d02af 100644 --- a/evmd/tests/integration/eips/eips_test.go +++ b/evmd/tests/integration/eips/eips_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/cosmos/evm/evmd/tests/integration" - "github.com/cosmos/evm/tests/integration/eips" ) diff --git a/evmd/tests/integration/ibc_callbacks_test.go b/evmd/tests/integration/ibc_callbacks_test.go new file mode 100644 index 000000000..725e883d5 --- /dev/null +++ b/evmd/tests/integration/ibc_callbacks_test.go @@ -0,0 +1,13 @@ +package integration + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/tests/integration/x/ibc/callbacks" +) + +func TestIBCCallback(t *testing.T) { + suite.Run(t, callbacks.NewKeeperTestSuite(CreateEvmd)) +} diff --git a/evmd/tests/integration/precompiles/bank/precompile_bank_test.go b/evmd/tests/integration/precompiles/bank/precompile_bank_test.go index 32fc43ec3..6f3c8acb2 100644 --- a/evmd/tests/integration/precompiles/bank/precompile_bank_test.go +++ b/evmd/tests/integration/precompiles/bank/precompile_bank_test.go @@ -3,9 +3,9 @@ package bank import ( "testing" - "github.com/cosmos/evm/evmd/tests/integration" "github.com/stretchr/testify/suite" + "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/tests/integration/precompiles/bank" ) diff --git a/evmd/tests/integration/precompiles/bech32/precompile_bech32_test.go b/evmd/tests/integration/precompiles/bech32/precompile_bech32_test.go index 5f0f5bb47..8bbdcd7f5 100644 --- a/evmd/tests/integration/precompiles/bech32/precompile_bech32_test.go +++ b/evmd/tests/integration/precompiles/bech32/precompile_bech32_test.go @@ -3,9 +3,9 @@ package bech32 import ( "testing" - "github.com/cosmos/evm/evmd/tests/integration" "github.com/stretchr/testify/suite" + "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/tests/integration/precompiles/bech32" ) diff --git a/evmd/tests/integration/precompiles/distribution/precompile_distribution_test.go b/evmd/tests/integration/precompiles/distribution/precompile_distribution_test.go index 8f24d4894..0b81df7d6 100644 --- a/evmd/tests/integration/precompiles/distribution/precompile_distribution_test.go +++ b/evmd/tests/integration/precompiles/distribution/precompile_distribution_test.go @@ -3,9 +3,9 @@ package distribution import ( "testing" - "github.com/cosmos/evm/evmd/tests/integration" "github.com/stretchr/testify/suite" + "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/tests/integration/precompiles/distribution" ) diff --git a/evmd/tests/integration/precompiles/erc20/precompile_erc20_test.go b/evmd/tests/integration/precompiles/erc20/precompile_erc20_test.go index b7c6377ed..ba27ed043 100644 --- a/evmd/tests/integration/precompiles/erc20/precompile_erc20_test.go +++ b/evmd/tests/integration/precompiles/erc20/precompile_erc20_test.go @@ -3,9 +3,9 @@ package erc20 import ( "testing" - "github.com/cosmos/evm/evmd/tests/integration" "github.com/stretchr/testify/suite" + "github.com/cosmos/evm/evmd/tests/integration" erc21 "github.com/cosmos/evm/tests/integration/precompiles/erc20" ) diff --git a/evmd/tests/integration/precompiles/evidence/precompile_evidence_test.go b/evmd/tests/integration/precompiles/evidence/precompile_evidence_test.go index 7e39ad760..fcbfe4f6d 100644 --- a/evmd/tests/integration/precompiles/evidence/precompile_evidence_test.go +++ b/evmd/tests/integration/precompiles/evidence/precompile_evidence_test.go @@ -3,9 +3,9 @@ package evidence import ( "testing" - "github.com/cosmos/evm/evmd/tests/integration" "github.com/stretchr/testify/suite" + "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/tests/integration/precompiles/evidence" ) diff --git a/evmd/tests/integration/precompiles/gov/precompile_gov_test.go b/evmd/tests/integration/precompiles/gov/precompile_gov_test.go index 87251abdc..7b06fc343 100644 --- a/evmd/tests/integration/precompiles/gov/precompile_gov_test.go +++ b/evmd/tests/integration/precompiles/gov/precompile_gov_test.go @@ -3,9 +3,9 @@ package gov import ( "testing" - "github.com/cosmos/evm/evmd/tests/integration" "github.com/stretchr/testify/suite" + "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/tests/integration/precompiles/gov" ) diff --git a/evmd/tests/integration/precompiles/p256/precompile_p256_test.go b/evmd/tests/integration/precompiles/p256/precompile_p256_test.go index d8f4d0b06..31a4e3d0f 100644 --- a/evmd/tests/integration/precompiles/p256/precompile_p256_test.go +++ b/evmd/tests/integration/precompiles/p256/precompile_p256_test.go @@ -3,9 +3,9 @@ package p256 import ( "testing" - "github.com/cosmos/evm/evmd/tests/integration" "github.com/stretchr/testify/suite" + "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/tests/integration/precompiles/p256" ) diff --git a/evmd/tests/integration/precompiles/slashing/precompile_slashing_test.go b/evmd/tests/integration/precompiles/slashing/precompile_slashing_test.go index 614b8dc15..6d5cfea69 100644 --- a/evmd/tests/integration/precompiles/slashing/precompile_slashing_test.go +++ b/evmd/tests/integration/precompiles/slashing/precompile_slashing_test.go @@ -3,9 +3,9 @@ package slashing import ( "testing" - "github.com/cosmos/evm/evmd/tests/integration" "github.com/stretchr/testify/suite" + "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/tests/integration/precompiles/slashing" ) diff --git a/evmd/tests/integration/precompiles/staking/precompile_staking_test.go b/evmd/tests/integration/precompiles/staking/precompile_staking_test.go index f803e5f8d..9b44eb220 100644 --- a/evmd/tests/integration/precompiles/staking/precompile_staking_test.go +++ b/evmd/tests/integration/precompiles/staking/precompile_staking_test.go @@ -3,9 +3,9 @@ package staking import ( "testing" - "github.com/cosmos/evm/evmd/tests/integration" "github.com/stretchr/testify/suite" + "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/tests/integration/precompiles/staking" ) diff --git a/evmd/tests/integration/precompiles/werc20/precompile_werc20_test.go b/evmd/tests/integration/precompiles/werc20/precompile_werc20_test.go index 9c679a7d1..011e605fb 100644 --- a/evmd/tests/integration/precompiles/werc20/precompile_werc20_test.go +++ b/evmd/tests/integration/precompiles/werc20/precompile_werc20_test.go @@ -3,9 +3,9 @@ package werc20 import ( "testing" - "github.com/cosmos/evm/evmd/tests/integration" "github.com/stretchr/testify/suite" + "github.com/cosmos/evm/evmd/tests/integration" "github.com/cosmos/evm/tests/integration/precompiles/werc20" ) diff --git a/go.mod b/go.mod index ee7c3f907..9f0525949 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,6 @@ go 1.23.8 require ( cosmossdk.io/api v0.9.2 - cosmossdk.io/client/v2 v2.0.0-beta.7 cosmossdk.io/core v0.11.3 cosmossdk.io/errors v1.0.2 cosmossdk.io/log v1.6.0 @@ -14,7 +13,6 @@ require ( cosmossdk.io/x/evidence v0.1.1 cosmossdk.io/x/feegrant v0.1.1 cosmossdk.io/x/tx v0.14.0 - cosmossdk.io/x/upgrade v0.2.0 github.com/btcsuite/btcd v0.24.2 github.com/btcsuite/btcd/btcutil v1.1.6 github.com/cometbft/cometbft v0.38.17 @@ -69,9 +67,11 @@ require ( cloud.google.com/go/iam v1.2.2 // indirect cloud.google.com/go/monitoring v1.21.2 // indirect cloud.google.com/go/storage v1.49.0 // indirect + cosmossdk.io/client/v2 v2.0.0-beta.7 // indirect cosmossdk.io/collections v1.2.1 // indirect cosmossdk.io/depinject v1.2.0 // indirect cosmossdk.io/schema v1.1.0 // indirect + cosmossdk.io/x/upgrade v0.2.0 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.2 // indirect @@ -121,7 +121,7 @@ require ( github.com/dgraph-io/badger/v4 v4.2.0 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dlclark/regexp2 v1.7.0 // indirect - github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 // indirect + github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.7.0 // indirect github.com/emicklei/dot v1.6.2 // indirect @@ -168,7 +168,7 @@ require ( github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-plugin v1.6.3 // indirect github.com/hashicorp/go-safetemp v1.0.0 // indirect - github.com/hashicorp/go-version v1.7.0 // indirect + github.com/hashicorp/go-version v1.6.0 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hashicorp/yamux v0.1.2 // indirect @@ -187,7 +187,7 @@ require ( github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/lib/pq v1.10.9 // indirect - github.com/linxGnu/grocksdb v1.9.8 // indirect + github.com/linxGnu/grocksdb v1.9.2 // indirect github.com/manifoldco/promptui v0.9.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect diff --git a/go.sum b/go.sum index ecb9b3076..75df5e3c8 100644 --- a/go.sum +++ b/go.sum @@ -931,8 +931,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 h1:qwcF+vdFrvPSEUDSX5RVoRccG8a5DhOdWdQ4zN62zzo= -github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -1270,9 +1270,8 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= -github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -1392,8 +1391,8 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/linxGnu/grocksdb v1.9.8 h1:vOIKv9/+HKiqJAElJIEYv3ZLcihRxyP7Suu/Mu8Dxjs= -github.com/linxGnu/grocksdb v1.9.8/go.mod h1:C3CNe9UYc9hlEM2pC82AqiGS3LRW537u9LFV4wIZuHk= +github.com/linxGnu/grocksdb v1.9.2 h1:O3mzvO0wuzQ9mtlHbDrShixyVjVbmuqTjFrzlf43wZ8= +github.com/linxGnu/grocksdb v1.9.2/go.mod h1:QYiYypR2d4v63Wj1adOOfzglnoII0gLj3PNh4fZkcFA= github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= diff --git a/interfaces.go b/interfaces.go index 46462c26e..3aceac589 100644 --- a/interfaces.go +++ b/interfaces.go @@ -5,6 +5,7 @@ import ( erc20keeper "github.com/cosmos/evm/x/erc20/keeper" feemarketkeeper "github.com/cosmos/evm/x/feemarket/keeper" + "github.com/cosmos/evm/x/ibc/callbacks/keeper" transferkeeper "github.com/cosmos/evm/x/ibc/transfer/keeper" precisebankkeeper "github.com/cosmos/evm/x/precisebank/keeper" evmkeeper "github.com/cosmos/evm/x/vm/keeper" @@ -50,6 +51,7 @@ type EvmApp interface { //nolint:revive GetMintKeeper() mintkeeper.Keeper GetPreciseBankKeeper() *precisebankkeeper.Keeper GetFeeGrantKeeper() feegrantkeeper.Keeper + GetCallbackKeeper() keeper.ContractKeeper GetTransferKeeper() transferkeeper.Keeper SetTransferKeeper(transferKeeper transferkeeper.Keeper) DefaultGenesis() map[string]json.RawMessage diff --git a/tests/integration/ante/benchmark_evm_antehandler.go b/tests/integration/ante/benchmark_evm_antehandler.go index 7210d8566..30d1c22ba 100644 --- a/tests/integration/ante/benchmark_evm_antehandler.go +++ b/tests/integration/ante/benchmark_evm_antehandler.go @@ -5,10 +5,9 @@ import ( "math/big" "testing" - chainante "github.com/cosmos/evm/evmd/ante" - "github.com/cosmos/evm/ante" ethante "github.com/cosmos/evm/ante/evm" + chainante "github.com/cosmos/evm/evmd/ante" basefactory "github.com/cosmos/evm/testutil/integration/base/factory" "github.com/cosmos/evm/testutil/integration/evm/factory" "github.com/cosmos/evm/testutil/integration/evm/grpc" diff --git a/tests/integration/ante/test_validate_handler_options.go b/tests/integration/ante/test_validate_handler_options.go index 2cc3be1e5..4a94362b2 100644 --- a/tests/integration/ante/test_validate_handler_options.go +++ b/tests/integration/ante/test_validate_handler_options.go @@ -3,11 +3,11 @@ package ante import ( "testing" - chainante "github.com/cosmos/evm/evmd/ante" "github.com/stretchr/testify/require" "github.com/cosmos/evm/ante" ethante "github.com/cosmos/evm/ante/evm" + chainante "github.com/cosmos/evm/evmd/ante" "github.com/cosmos/evm/testutil/integration/evm/network" "github.com/cosmos/evm/types" ) diff --git a/tests/integration/eips/test_eips.go b/tests/integration/eips/test_eips.go index 5b9705a42..351e406f0 100644 --- a/tests/integration/eips/test_eips.go +++ b/tests/integration/eips/test_eips.go @@ -5,8 +5,6 @@ import ( "math/big" "testing" - "github.com/cosmos/evm/evmd/eips" - "github.com/cosmos/evm/evmd/eips/testdata" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/params" @@ -15,6 +13,8 @@ import ( //nolint:revive,ST1001 // dot imports are fine for Ginkgo . "github.com/onsi/gomega" + "github.com/cosmos/evm/evmd/eips" + "github.com/cosmos/evm/evmd/eips/testdata" "github.com/cosmos/evm/testutil/integration/evm/factory" "github.com/cosmos/evm/testutil/integration/evm/grpc" "github.com/cosmos/evm/testutil/integration/evm/network" diff --git a/tests/integration/ledger/evmosd_suite_test.go b/tests/integration/ledger/evmosd_suite_test.go index 2808d3c4f..3257a2673 100644 --- a/tests/integration/ledger/evmosd_suite_test.go +++ b/tests/integration/ledger/evmosd_suite_test.go @@ -8,7 +8,6 @@ import ( "testing" "time" - exampleapp "github.com/cosmos/evm/evmd" "github.com/ethereum/go-ethereum/common" "github.com/spf13/cobra" "github.com/stretchr/testify/suite" @@ -27,6 +26,7 @@ import ( clientkeys "github.com/cosmos/evm/client/keys" "github.com/cosmos/evm/crypto/hd" cosmosevmkeyring "github.com/cosmos/evm/crypto/keyring" + exampleapp "github.com/cosmos/evm/evmd" "github.com/cosmos/evm/tests/integration/ledger/mocks" "github.com/cosmos/evm/testutil/constants" utiltx "github.com/cosmos/evm/testutil/tx" diff --git a/tests/integration/precompiles/erc20/test_integration.go b/tests/integration/precompiles/erc20/test_integration.go index c7926185c..ea7322f0c 100644 --- a/tests/integration/precompiles/erc20/test_integration.go +++ b/tests/integration/precompiles/erc20/test_integration.go @@ -330,7 +330,7 @@ func TestIntegrationTestSuite(t *testing.T, create network.CreateEvmApp, options Expect(res.GasUsed < expGasUsedUpperBound).To(BeTrue(), "expected different gas used") }, // FIXME: The gas used on the precompile is much higher than on the EVM - Entry(" - direct call", directCall, int64(3_021_000), int64(3_022_000)), + Entry(" - direct call", directCall, int64(30_000), int64(31_000)), Entry(" - through erc20 contract", erc20Call, int64(54_000), int64(54_500)), Entry(" - through erc20 v5 contract", erc20V5Call, int64(52_000), int64(52_200)), ) diff --git a/tests/integration/x/erc20/test_grpc_query.go b/tests/integration/x/erc20/test_grpc_query.go index 2d868e977..08838297d 100644 --- a/tests/integration/x/erc20/test_grpc_query.go +++ b/tests/integration/x/erc20/test_grpc_query.go @@ -4,7 +4,6 @@ import ( "fmt" exampleapp "github.com/cosmos/evm/evmd" - testconstants "github.com/cosmos/evm/testutil/constants" utiltx "github.com/cosmos/evm/testutil/tx" "github.com/cosmos/evm/x/erc20/types" diff --git a/tests/integration/x/erc20/test_ibc_callback.go b/tests/integration/x/erc20/test_ibc_callback.go index e1ed9cd81..2c5c4f7e3 100644 --- a/tests/integration/x/erc20/test_ibc_callback.go +++ b/tests/integration/x/erc20/test_ibc_callback.go @@ -381,7 +381,7 @@ func (s *KeeperTestSuite) TestConvertCoinToERC20FromPacket() { ) s.Require().NoError(err) - _, err = s.network.App.GetEVMKeeper().CallEVM(ctx, contracts.ERC20MinterBurnerDecimalsContract.ABI, s.keyring.GetAddr(0), contractAddr, true, "mint", types.ModuleAddress, big.NewInt(10)) + _, err = s.network.App.GetEVMKeeper().CallEVM(ctx, contracts.ERC20MinterBurnerDecimalsContract.ABI, s.keyring.GetAddr(0), contractAddr, true, nil, "mint", types.ModuleAddress, big.NewInt(10)) s.Require().NoError(err) return transfertypes.NewFungibleTokenPacketData(pair.Denom, "10", senderAddr, "", "") diff --git a/x/ibc/callbacks/keeper/keeper_test.go b/tests/integration/x/ibc/callbacks/test_keeper.go similarity index 83% rename from x/ibc/callbacks/keeper/keeper_test.go rename to tests/integration/x/ibc/callbacks/test_keeper.go index 2472c4be9..ec3c91f22 100644 --- a/x/ibc/callbacks/keeper/keeper_test.go +++ b/tests/integration/x/ibc/callbacks/test_keeper.go @@ -1,11 +1,11 @@ -package keeper_test +package callbacks import ( "fmt" "github.com/ethereum/go-ethereum/common" - "github.com/cosmos/evm/testutil/integration/os/keyring" + "github.com/cosmos/evm/testutil/keyring" "github.com/cosmos/evm/x/ibc/callbacks/types" cbtypes "github.com/cosmos/ibc-go/v10/modules/apps/callbacks/types" transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" @@ -16,7 +16,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -func (suite *KeeperTestSuite) TestOnRecvPacket() { +func (s *KeeperTestSuite) TestOnRecvPacket() { var ( contract common.Address ctx sdk.Context @@ -64,10 +64,10 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() { } for _, tc := range testCases { - suite.SetupTest() // reset - ctx = suite.network.GetContext() + s.SetupTest() // reset + ctx = s.network.GetContext() - senderKey = suite.keyring.GetKey(0) + senderKey = s.keyring.GetKey(0) receiverBz := types.GenerateIsolatedAddress("channel-1", senderKey.AccAddr.String()) receiver = sdk.AccAddress(receiverBz.Bytes()).String() contract = common.HexToAddress("0x1234567890abcdef1234567890abcdef12345678") // Example contract address @@ -95,16 +95,16 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() { tc.malleate() - err := suite.network.App.CallbackKeeper.IBCReceivePacketCallback(ctx, packet, ack, contract.Hex(), transfertypes.V1) + err := s.network.App.GetCallbackKeeper().IBCReceivePacketCallback(ctx, packet, ack, contract.Hex(), transfertypes.V1) if tc.expErr != nil { - suite.Require().Contains(err.Error(), tc.expErr.Error(), "expected error: %s, got: %s", tc.expErr.Error(), err.Error()) + s.Require().Contains(err.Error(), tc.expErr.Error(), "expected error: %s, got: %s", tc.expErr.Error(), err.Error()) } else { - suite.Require().NoError(err) + s.Require().NoError(err) } } } -func (suite *KeeperTestSuite) TestOnAcknowledgementPacket() { +func (s *KeeperTestSuite) TestOnAcknowledgementPacket() { var ( contract common.Address ctx sdk.Context @@ -151,10 +151,10 @@ func (suite *KeeperTestSuite) TestOnAcknowledgementPacket() { } for _, tc := range testCases { - suite.SetupTest() // reset - ctx = suite.network.GetContext() + s.SetupTest() // reset + ctx = s.network.GetContext() - senderKey = suite.keyring.GetKey(0) + senderKey = s.keyring.GetKey(0) receiver = types.GenerateIsolatedAddress("channel-1", senderKey.AccAddr.String()).String() transferData = transfertypes.NewFungibleTokenPacketData( @@ -180,18 +180,18 @@ func (suite *KeeperTestSuite) TestOnAcknowledgementPacket() { tc.malleate() - err := suite.network.App.CallbackKeeper.IBCOnAcknowledgementPacketCallback( + err := s.network.App.GetCallbackKeeper().IBCOnAcknowledgementPacketCallback( ctx, packet, ack.Acknowledgement(), senderKey.AccAddr, contract.Hex(), senderKey.AccAddr.String(), transfertypes.V1, ) if tc.expErr != nil { - suite.Require().Contains(err.Error(), tc.expErr.Error(), "expected error: %s, got: %s", tc.expErr.Error(), err.Error()) + s.Require().Contains(err.Error(), tc.expErr.Error(), "expected error: %s, got: %s", tc.expErr.Error(), err.Error()) } else { - suite.Require().NoError(err) + s.Require().NoError(err) } } } -func (suite *KeeperTestSuite) TestOnTimeoutPacket() { +func (s *KeeperTestSuite) TestOnTimeoutPacket() { var ( contract common.Address ctx sdk.Context @@ -238,10 +238,10 @@ func (suite *KeeperTestSuite) TestOnTimeoutPacket() { } for _, tc := range testCases { - suite.SetupTest() // reset - ctx = suite.network.GetContext() + s.SetupTest() // reset + ctx = s.network.GetContext() - senderKey = suite.keyring.GetKey(0) + senderKey = s.keyring.GetKey(0) receiver = types.GenerateIsolatedAddress("channel-1", senderKey.AccAddr.String()).String() transferData = transfertypes.NewFungibleTokenPacketData( @@ -266,13 +266,13 @@ func (suite *KeeperTestSuite) TestOnTimeoutPacket() { tc.malleate() - err := suite.network.App.CallbackKeeper.IBCOnTimeoutPacketCallback( + err := s.network.App.GetCallbackKeeper().IBCOnTimeoutPacketCallback( ctx, packet, senderKey.AccAddr, contract.Hex(), senderKey.AccAddr.String(), transfertypes.V1, ) if tc.expErr != nil { - suite.Require().Contains(err.Error(), tc.expErr.Error(), "expected error: %s, got: %s", tc.expErr.Error(), err.Error()) + s.Require().Contains(err.Error(), tc.expErr.Error(), "expected error: %s, got: %s", tc.expErr.Error(), err.Error()) } else { - suite.Require().NoError(err) + s.Require().NoError(err) } } } diff --git a/tests/integration/x/ibc/callbacks/test_setup.go b/tests/integration/x/ibc/callbacks/test_setup.go new file mode 100644 index 000000000..8ca3d2219 --- /dev/null +++ b/tests/integration/x/ibc/callbacks/test_setup.go @@ -0,0 +1,48 @@ +package callbacks + +import ( + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/keyring" +) + +type KeeperTestSuite struct { + suite.Suite + + create network.CreateEvmApp + options []network.ConfigOption + network *network.UnitTestNetwork + handler grpc.Handler + keyring keyring.Keyring + factory factory.TxFactory +} + +func NewKeeperTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *KeeperTestSuite { + return &KeeperTestSuite{ + create: create, + options: options, + } +} + +func (s *KeeperTestSuite) SetupTest() { + keys := keyring.New(2) + // Set custom balance based on test params + customGenesis := network.CustomGenesisState{} + + options := []network.ConfigOption{ + network.WithPreFundedAccounts(keys.GetAllAccAddrs()...), + network.WithCustomGenesis(customGenesis), + } + options = append(options, s.options...) + nw := network.NewUnitTestNetwork(s.create, options...) + gh := grpc.NewIntegrationHandler(nw) + tf := factory.New(nw, gh) + + s.network = nw + s.factory = tf + s.handler = gh + s.keyring = keys +} diff --git a/tests/integration/x/precisebank/test_send_integration.go b/tests/integration/x/precisebank/test_send_integration.go index d7e5fc69c..db069fc30 100644 --- a/tests/integration/x/precisebank/test_send_integration.go +++ b/tests/integration/x/precisebank/test_send_integration.go @@ -6,9 +6,9 @@ import ( "math/rand" "testing" - "github.com/cosmos/evm/evmd" "github.com/stretchr/testify/require" + "github.com/cosmos/evm/evmd" testconstants "github.com/cosmos/evm/testutil/constants" "github.com/cosmos/evm/x/precisebank/types" evmtypes "github.com/cosmos/evm/x/vm/types" diff --git a/tests/integration/x/vm/test_call_evm.go b/tests/integration/x/vm/test_call_evm.go index 3bf26e417..013b200f2 100644 --- a/tests/integration/x/vm/test_call_evm.go +++ b/tests/integration/x/vm/test_call_evm.go @@ -35,7 +35,7 @@ func (s *KeeperTestSuite) TestCallEVM() { erc20 := contracts.ERC20MinterBurnerDecimalsContract.ABI account := utiltx.GenerateAddress() - res, err := s.Network.App.GetEVMKeeper().CallEVM(s.Network.GetContext(), erc20, types.ModuleAddress, wcosmosEVMContract, false, tc.method, account) + res, err := s.Network.App.GetEVMKeeper().CallEVM(s.Network.GetContext(), erc20, types.ModuleAddress, wcosmosEVMContract, false, nil, tc.method, account) if tc.expPass { s.Require().IsTypef(&evmtypes.MsgEthereumTxResponse{}, res, tc.name) s.Require().NoError(err) @@ -134,9 +134,9 @@ func (s *KeeperTestSuite) TestCallEVMWithData() { var err error if tc.deploy { - res, err = s.Network.App.GetEVMKeeper().CallEVMWithData(s.Network.GetContext(), tc.from, nil, data, true) + res, err = s.Network.App.GetEVMKeeper().CallEVMWithData(s.Network.GetContext(), tc.from, nil, data, true, nil) } else { - res, err = s.Network.App.GetEVMKeeper().CallEVMWithData(s.Network.GetContext(), tc.from, &wcosmosEVMContract, data, false) + res, err = s.Network.App.GetEVMKeeper().CallEVMWithData(s.Network.GetContext(), tc.from, &wcosmosEVMContract, data, false, nil) } if tc.expPass { diff --git a/tests/integration/x/vm/test_params.go b/tests/integration/x/vm/test_params.go index 487894692..1bbaf9a91 100644 --- a/tests/integration/x/vm/test_params.go +++ b/tests/integration/x/vm/test_params.go @@ -2,7 +2,6 @@ package vm import ( exampleapp "github.com/cosmos/evm/evmd" - "github.com/cosmos/evm/x/vm/types" ) diff --git a/tests/integration/x/vm/test_state_transition.go b/tests/integration/x/vm/test_state_transition.go index 164bed363..ea933eb31 100644 --- a/tests/integration/x/vm/test_state_transition.go +++ b/tests/integration/x/vm/test_state_transition.go @@ -5,7 +5,6 @@ import ( "math" "math/big" - exampleapp "github.com/cosmos/evm/evmd" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" gethtypes "github.com/ethereum/go-ethereum/core/types" @@ -15,6 +14,7 @@ import ( tmproto "github.com/cometbft/cometbft/proto/tendermint/types" cmttypes "github.com/cometbft/cometbft/types" + exampleapp "github.com/cosmos/evm/evmd" "github.com/cosmos/evm/testutil/integration/evm/factory" "github.com/cosmos/evm/testutil/integration/evm/grpc" "github.com/cosmos/evm/testutil/integration/evm/network" diff --git a/testutil/ibc/coordinator.go b/testutil/ibc/coordinator.go index 9484202fe..0b5908002 100644 --- a/testutil/ibc/coordinator.go +++ b/testutil/ibc/coordinator.go @@ -6,9 +6,9 @@ import ( "testing" "time" - "github.com/cosmos/evm/evmd" "github.com/stretchr/testify/require" + "github.com/cosmos/evm/evmd" ibctesting "github.com/cosmos/ibc-go/v10/testing" ) diff --git a/testutil/ibc/testing_app.go b/testutil/ibc/testing_app.go index 3ec921953..f22679e33 100644 --- a/testutil/ibc/testing_app.go +++ b/testutil/ibc/testing_app.go @@ -3,9 +3,8 @@ package ibctesting import ( "encoding/json" - "github.com/cosmos/evm/evmd" - dbm "github.com/cosmos/cosmos-db" + "github.com/cosmos/evm/evmd" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" ibctesting "github.com/cosmos/ibc-go/v10/testing" diff --git a/testutil/network/network.go b/testutil/network/network.go index 6c366ddc3..7c0ed83fa 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -17,7 +17,6 @@ import ( "testing" "time" - exampleapp "github.com/cosmos/evm/evmd" "github.com/ethereum/go-ethereum/ethclient" "github.com/spf13/cobra" "golang.org/x/sync/errgroup" @@ -30,6 +29,7 @@ import ( dbm "github.com/cosmos/cosmos-db" chaincmd "github.com/cosmos/evm/cmd/evmd/cmd" "github.com/cosmos/evm/crypto/hd" + exampleapp "github.com/cosmos/evm/evmd" "github.com/cosmos/evm/server/config" testconstants "github.com/cosmos/evm/testutil/constants" cosmosevmtypes "github.com/cosmos/evm/types" diff --git a/x/erc20/types/params_test.go b/x/erc20/types/params_test.go index 60884705a..e6dca0918 100644 --- a/x/erc20/types/params_test.go +++ b/x/erc20/types/params_test.go @@ -4,11 +4,11 @@ import ( "slices" "testing" - "github.com/cosmos/evm/evmd" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" + "github.com/cosmos/evm/evmd" testconstants "github.com/cosmos/evm/testutil/constants" "github.com/cosmos/evm/x/erc20/types" ) diff --git a/x/ibc/callbacks/keeper/setup_test.go b/x/ibc/callbacks/keeper/setup_test.go deleted file mode 100644 index 780e51936..000000000 --- a/x/ibc/callbacks/keeper/setup_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package keeper_test - -import ( - "testing" - - "github.com/stretchr/testify/suite" - - "github.com/cosmos/evm/testutil/integration/os/factory" - "github.com/cosmos/evm/testutil/integration/os/grpc" - "github.com/cosmos/evm/testutil/integration/os/keyring" - "github.com/cosmos/evm/testutil/integration/os/network" -) - -type KeeperTestSuite struct { - suite.Suite - - network *network.UnitTestNetwork - handler grpc.Handler - keyring keyring.Keyring - factory factory.TxFactory -} - -func TestKeeperUnitTestSuite(t *testing.T) { - suite.Run(t, new(KeeperTestSuite)) -} - -func (suite *KeeperTestSuite) SetupTest() { - keys := keyring.New(2) - // Set custom balance based on test params - customGenesis := network.CustomGenesisState{} - - nw := network.NewUnitTestNetwork( - network.WithPreFundedAccounts(keys.GetAllAccAddrs()...), - network.WithCustomGenesis(customGenesis), - ) - gh := grpc.NewIntegrationHandler(nw) - tf := factory.New(nw, gh) - - suite.network = nw - suite.factory = tf - suite.handler = gh - suite.keyring = keys -} diff --git a/x/precisebank/keeper/keeper_test.go b/x/precisebank/keeper/keeper_test.go index 4fe0298b9..3a980c7ae 100644 --- a/x/precisebank/keeper/keeper_test.go +++ b/x/precisebank/keeper/keeper_test.go @@ -3,9 +3,8 @@ package keeper_test import ( "testing" - "github.com/cosmos/evm/evmd" - evmosencoding "github.com/cosmos/evm/encoding" + "github.com/cosmos/evm/evmd" testconstants "github.com/cosmos/evm/testutil/constants" "github.com/cosmos/evm/x/precisebank/keeper" "github.com/cosmos/evm/x/precisebank/types" diff --git a/x/vm/types/msg_test.go b/x/vm/types/msg_test.go index 1e46baca2..3483faf78 100644 --- a/x/vm/types/msg_test.go +++ b/x/vm/types/msg_test.go @@ -8,7 +8,6 @@ import ( "strings" "testing" - "github.com/cosmos/evm/evmd" "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" @@ -16,6 +15,7 @@ import ( "github.com/cosmos/evm/crypto/ethsecp256k1" "github.com/cosmos/evm/encoding" + "github.com/cosmos/evm/evmd" testconstants "github.com/cosmos/evm/testutil/constants" utiltx "github.com/cosmos/evm/testutil/tx" "github.com/cosmos/evm/x/vm/types" From fb4cc1466645cd4e2eac882aa03f6d1cccbebc55 Mon Sep 17 00:00:00 2001 From: zsystm Date: Thu, 12 Jun 2025 03:55:12 +0900 Subject: [PATCH 21/21] fix lint --- tests/integration/ante/ante_test_suite.go | 6 +++--- tests/integration/x/vm/keeper_test_suite.go | 6 +++--- tests/integration/x/vm/test_state_transition.go | 1 - 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/integration/ante/ante_test_suite.go b/tests/integration/ante/ante_test_suite.go index 61c49eb66..87df69095 100644 --- a/tests/integration/ante/ante_test_suite.go +++ b/tests/integration/ante/ante_test_suite.go @@ -114,9 +114,9 @@ func (s *AnteTestSuite) SetupTest() { // get the denom and decimals set when initialized the chain // to set them again // when resetting the chain config - denom := evmtypes.GetEVMCoinDenom() //nolint:staticcheck - extendedDenom := evmtypes.GetEVMCoinExtendedDenom() //nolint:staticcheck - decimals := evmtypes.GetEVMCoinDecimals() //nolint:staticcheck + denom := evmtypes.GetEVMCoinDenom() + extendedDenom := evmtypes.GetEVMCoinExtendedDenom() + decimals := evmtypes.GetEVMCoinDecimals() configurator := evmtypes.NewEVMConfigurator() configurator.ResetTestConfig() diff --git a/tests/integration/x/vm/keeper_test_suite.go b/tests/integration/x/vm/keeper_test_suite.go index 8b76b4718..8febaad16 100644 --- a/tests/integration/x/vm/keeper_test_suite.go +++ b/tests/integration/x/vm/keeper_test_suite.go @@ -101,9 +101,9 @@ func (s *KeeperTestSuite) SetupTest() { } // get the denom and decimals set on chain initialization // because we'll need to set them again when resetting the chain config - denom := evmtypes.GetEVMCoinDenom() //nolint:staticcheck - extendedDenom := evmtypes.GetEVMCoinExtendedDenom() //nolint:staticcheck - decimals := evmtypes.GetEVMCoinDecimals() //nolint:staticcheck + denom := evmtypes.GetEVMCoinDenom() + extendedDenom := evmtypes.GetEVMCoinExtendedDenom() + decimals := evmtypes.GetEVMCoinDecimals() configurator := evmtypes.NewEVMConfigurator() configurator.ResetTestConfig() diff --git a/tests/integration/x/vm/test_state_transition.go b/tests/integration/x/vm/test_state_transition.go index ea933eb31..de89a1500 100644 --- a/tests/integration/x/vm/test_state_transition.go +++ b/tests/integration/x/vm/test_state_transition.go @@ -350,7 +350,6 @@ func (s *KeeperTestSuite) TestGasToRefund() { if tc.expPanic { panicF := func() { - //nolint:staticcheck keeper.GasToRefund(vmdb.GetRefund(), tc.gasconsumed, tc.refundQuotient) } s.Require().Panics(panicF)