├── .clconfig.json ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── 01-bug-report.yml │ ├── 02-feature-request.yml │ ├── 03-docs-request.yml │ ├── 04-epic-template.md │ └── 05-issue-template.md ├── PULL_REQUEST_TEMPLATE.md ├── labeler.yml └── workflows │ ├── bsr-push.yml │ ├── changelog.yml │ ├── codeql-analysis.yml │ ├── dependencies.yml │ ├── labeler.yml │ ├── lint.yml │ ├── markdown-links.yml │ ├── proto.yml │ ├── security.yml │ ├── slither.yml │ ├── solhint.yml │ ├── solidity-test.yml │ ├── stale.yml │ ├── super-linter.yml │ └── test.yml ├── .gitignore ├── .gitleaks.toml ├── .golangci.yml ├── .govulncheck.yaml ├── .markdownlint.yml ├── .markdownlintignore ├── .mergify.yml ├── .protolint.yml ├── .pylintrc ├── .semgrepignore ├── .solhint.json ├── .yamllint ├── CHANGELOG.md ├── LICENSE ├── Makefile ├── README.md ├── SECURITY.md ├── ante ├── cosmos │ ├── authz.go │ ├── authz_test.go │ ├── eip712.go │ ├── min_gas_price.go │ ├── min_gas_price_test.go │ ├── reject_msgs.go │ ├── setup_test.go │ └── utils_test.go ├── evm │ ├── 01_setup_ctx.go │ ├── 01_setup_ctx_test.go │ ├── 02_mempool_fee.go │ ├── 02_mempool_fee_test.go │ ├── 03_global_fee.go │ ├── 03_global_fee_test.go │ ├── 04_validate.go │ ├── 04_validate_test.go │ ├── 05_signature_verification.go │ ├── 06_account_verification.go │ ├── 06_account_verification_test.go │ ├── 07_can_transfer.go │ ├── 07_can_transfer_test.go │ ├── 08_gas_consume.go │ ├── 08_gas_consume_test.go │ ├── 09_increment_sequence.go │ ├── 09_increment_sequence_test.go │ ├── 10_gas_wanted.go │ ├── 10_gas_wanted_test.go │ ├── 11_emit_event.go │ ├── ante_test.go │ ├── eth_benchmark_test.go │ ├── fee_checker.go │ ├── fee_checker_test.go │ ├── fee_market_test.go │ ├── mono_decorator.go │ ├── setup_test.go │ ├── signverify_test.go │ ├── sigs_test.go │ ├── suite_test.go │ ├── utils.go │ └── utils_test.go ├── interfaces │ ├── cosmos.go │ └── evm.go ├── sigverify.go ├── sigverify_test.go ├── testutils │ └── testutil.go └── utils_test.go ├── api └── cosmos │ └── evm │ ├── crypto │ └── v1 │ │ └── ethsecp256k1 │ │ └── keys.pulsar.go │ ├── erc20 │ └── v1 │ │ ├── erc20.pulsar.go │ │ ├── events.pulsar.go │ │ ├── genesis.pulsar.go │ │ ├── msg.go │ │ ├── query.pulsar.go │ │ ├── query_grpc.pb.go │ │ ├── tx.pulsar.go │ │ └── tx_grpc.pb.go │ ├── feemarket │ └── v1 │ │ ├── events.pulsar.go │ │ ├── feemarket.pulsar.go │ │ ├── genesis.pulsar.go │ │ ├── query.pulsar.go │ │ ├── query_grpc.pb.go │ │ ├── tx.pulsar.go │ │ └── tx_grpc.pb.go │ ├── precisebank │ └── v1 │ │ ├── genesis.pulsar.go │ │ ├── query.pulsar.go │ │ └── query_grpc.pb.go │ ├── types │ └── v1 │ │ ├── dynamic_fee.pulsar.go │ │ ├── indexer.pulsar.go │ │ └── web3.pulsar.go │ └── vm │ └── v1 │ ├── access_list_tx.go │ ├── dynamic_fee_tx.go │ ├── events.pulsar.go │ ├── evm.pulsar.go │ ├── genesis.pulsar.go │ ├── legacy_tx.go │ ├── msg.go │ ├── query.pulsar.go │ ├── query_grpc.pb.go │ ├── tx.pulsar.go │ ├── tx_data.go │ └── tx_grpc.pb.go ├── buf.gen.proto.yaml ├── buf.work.yaml ├── client ├── block │ ├── block.go │ └── store.go ├── config.go ├── config_test.go ├── context.go ├── debug │ └── debug.go ├── export.go ├── import.go ├── keys.go └── keys │ ├── add.go │ └── utils.go ├── cmd └── evmd │ ├── cmd │ └── root.go │ ├── config │ ├── chain_id.go │ ├── config.go │ ├── constants.go │ └── opendb.go │ └── main.go ├── codecov.yml ├── contracts ├── .gitignore ├── erc20.go ├── hardhat.config.js ├── package-lock.json ├── package.json ├── solidity │ ├── ERC20MinterBurnerDecimals.json │ ├── ERC20MinterBurnerDecimals.sol │ ├── WATOM.json │ ├── WATOM.sol │ ├── evmd │ │ └── eips │ │ │ └── testdata │ │ │ ├── Counter.sol │ │ │ └── CounterFactory.sol │ ├── precompiles │ │ ├── bank │ │ │ ├── IBank.sol │ │ │ └── testdata │ │ │ │ └── BankCaller.sol │ │ ├── bech32 │ │ │ └── Bech32I.sol │ │ ├── common │ │ │ └── Types.sol │ │ ├── distribution │ │ │ └── DistributionI.sol │ │ ├── erc20 │ │ │ ├── IERC20.sol │ │ │ ├── IERC20Metadata.sol │ │ │ ├── IERC20MetadataAllowance.sol │ │ │ └── testdata │ │ │ │ ├── ERC20AllowanceCaller.sol │ │ │ │ ├── ERC20NoMetadata.sol │ │ │ │ └── ERC20TestCaller.sol │ │ ├── evidence │ │ │ └── IEvidence.sol │ │ ├── gov │ │ │ └── IGov.sol │ │ ├── ics20 │ │ │ └── ICS20I.sol │ │ ├── slashing │ │ │ └── ISlashing.sol │ │ ├── staking │ │ │ ├── StakingI.sol │ │ │ └── testdata │ │ │ │ ├── StakingCaller.sol │ │ │ │ └── StakingCallerTwo.sol │ │ ├── testutil │ │ │ └── contracts │ │ │ │ ├── Counter.sol │ │ │ │ ├── DistributionCaller.sol │ │ │ │ ├── FlashLoan.sol │ │ │ │ ├── GovCaller.sol │ │ │ │ ├── ICounter.sol │ │ │ │ ├── InterchainSender.sol │ │ │ │ ├── InterchainSenderCaller.sol │ │ │ │ ├── Reverter.sol │ │ │ │ └── StakingReverter.sol │ │ └── werc20 │ │ │ ├── IWERC20.sol │ │ │ └── testdata │ │ │ └── WEVMOS9TestCaller.sol │ └── x │ │ └── erc20 │ │ └── keeper │ │ └── testdata │ │ ├── ERC20DirectBalanceManipulation.sol │ │ └── ERC20MaliciousDelayed.sol ├── utils │ └── utils.go └── watom.go ├── crypto ├── codec │ ├── amino.go │ └── codec.go ├── ethsecp256k1 │ ├── benchmark_test.go │ ├── ethsecp256k1.go │ ├── ethsecp256k1_test.go │ └── keys.pb.go ├── hd │ ├── algorithm.go │ ├── algorithm_test.go │ ├── benchmark_test.go │ └── utils_test.go ├── keyring │ └── options.go └── secp256r1 │ └── verify.go ├── encoding ├── codec │ └── codec.go ├── config.go └── config_test.go ├── ethereum └── eip712 │ ├── domain.go │ ├── eip712.go │ ├── eip712_fuzzer_test.go │ ├── eip712_legacy.go │ ├── eip712_legacy_test.go │ ├── eip712_test.go │ ├── encoding.go │ ├── encoding_legacy.go │ ├── message.go │ ├── preprocess.go │ ├── preprocess_test.go │ └── types.go ├── evmd ├── README.md ├── activators.go ├── ante │ ├── ante.go │ ├── cosmos_handler.go │ ├── evm_benchmark_test.go │ ├── evm_handler.go │ ├── handler_options.go │ ├── handler_options_test.go │ └── integration_test.go ├── app.go ├── config.go ├── config │ └── client.toml ├── config_testing.go ├── eips │ ├── README.md │ ├── eips.go │ ├── eips_test.go │ └── testdata │ │ ├── Counter.json │ │ ├── Counter.sol │ │ ├── CounterFactory.json │ │ ├── CounterFactory.sol │ │ └── contracts.go ├── export.go ├── genesis.go ├── guide │ ├── add_network.png │ ├── networks.png │ ├── rpc_url.png │ └── settings.png ├── interfaces.go ├── precompiles.go ├── test_helpers.go ├── testutil │ ├── abci.go │ ├── app.go │ ├── contract.go │ ├── eth_setup.go │ ├── fund.go │ ├── gas.go │ └── integration.go └── upgrades.go ├── go.mod ├── go.sum ├── ibc ├── errors.go ├── module.go ├── module_test.go ├── testing │ ├── README.md │ ├── chain.go │ ├── config.go │ ├── coordinator.go │ ├── endpoint.go │ ├── endpoint_v2.go │ ├── events.go │ ├── helpers.go │ ├── path.go │ ├── testing_app.go │ └── values.go ├── utils.go └── utils_test.go ├── indexer ├── kv_indexer.go └── kv_indexer_test.go ├── local_node.sh ├── mlc_config.json ├── precompiles ├── bank │ ├── IBank.sol │ ├── abi.json │ ├── bank.go │ ├── integration_test.go │ ├── query.go │ ├── query_test.go │ ├── setup_test.go │ ├── testdata │ │ ├── BankCaller.json │ │ ├── BankCaller.sol │ │ └── bank.go │ ├── types.go │ └── utils_test.go ├── bech32 │ ├── Bech32I.sol │ ├── abi.json │ ├── bech32.go │ ├── bech32_test.go │ ├── methods.go │ ├── methods_test.go │ └── setup_test.go ├── common │ ├── Types.sol │ ├── abi.go │ ├── abi_test.go │ ├── errors.go │ ├── interfaces.go │ ├── precompile.go │ ├── types.go │ └── types_test.go ├── distribution │ ├── DistributionI.sol │ ├── abi.json │ ├── distribution.go │ ├── distribution_test.go │ ├── errors.go │ ├── events.go │ ├── events_test.go │ ├── integration_test.go │ ├── query.go │ ├── query_test.go │ ├── setup_test.go │ ├── tx.go │ ├── tx_test.go │ ├── types.go │ └── utils_test.go ├── erc20 │ ├── IERC20.sol │ ├── IERC20Metadata.sol │ ├── IERC20MetadataAllowance.sol │ ├── abi.json │ ├── approve.go │ ├── approve_test.go │ ├── erc20.go │ ├── erc20_test.go │ ├── errors.go │ ├── errors_test.go │ ├── events.go │ ├── events_test.go │ ├── integration_test.go │ ├── interfaces.go │ ├── query.go │ ├── query_test.go │ ├── setup_test.go │ ├── testdata │ │ ├── ERC20AllowanceCaller.json │ │ ├── ERC20AllowanceCaller.sol │ │ ├── ERC20Minter_OpenZeppelinV5.json │ │ ├── ERC20Minter_OpenZeppelinV5.sol │ │ ├── ERC20NoMetadata.json │ │ ├── ERC20NoMetadata.sol │ │ ├── ERC20TestCaller.json │ │ ├── ERC20TestCaller.sol │ │ ├── erc20_allowance_caller.go │ │ ├── erc20_no_metadata.go │ │ ├── erc20_test_caller.go │ │ └── erc20minter_openzeppelinv5.go │ ├── tx.go │ ├── tx_test.go │ ├── types.go │ ├── types_test.go │ └── utils_test.go ├── evidence │ ├── IEvidence.sol │ ├── abi.json │ ├── errors.go │ ├── events.go │ ├── evidence.go │ ├── query.go │ ├── query_test.go │ ├── setup_test.go │ ├── tx.go │ ├── tx_test.go │ └── types.go ├── gov │ ├── IGov.sol │ ├── abi.json │ ├── errors.go │ ├── events.go │ ├── events_test.go │ ├── gov.go │ ├── gov_test.go │ ├── integration_test.go │ ├── query.go │ ├── query_test.go │ ├── setup_test.go │ ├── tx.go │ ├── tx_test.go │ ├── types.go │ └── utils_test.go ├── ics20 │ ├── ICS20I.sol │ ├── abi.json │ ├── errors.go │ ├── events.go │ ├── ics20.go │ ├── query.go │ ├── tx.go │ └── types.go ├── p256 │ ├── integration_test.go │ ├── p256.go │ ├── p256_test.go │ └── setup_test.go ├── slashing │ ├── ISlashing.sol │ ├── abi.json │ ├── events.go │ ├── events_test.go │ ├── query.go │ ├── query_test.go │ ├── setup_test.go │ ├── slashing.go │ ├── tx.go │ ├── tx_test.go │ └── types.go ├── staking │ ├── StakingI.sol │ ├── abi.json │ ├── errors.go │ ├── events.go │ ├── events_test.go │ ├── integration_test.go │ ├── query.go │ ├── query_test.go │ ├── setup_test.go │ ├── staking.go │ ├── staking_test.go │ ├── testdata │ │ ├── StakingCaller.json │ │ ├── StakingCaller.sol │ │ ├── StakingCallerTwo.json │ │ ├── StakingCallerTwo.sol │ │ ├── staking_caller.go │ │ └── staking_caller_two.go │ ├── tx.go │ ├── tx_test.go │ ├── types.go │ └── utils_test.go ├── testutil │ ├── contracts │ │ ├── Counter.json │ │ ├── Counter.sol │ │ ├── DistributionCaller.json │ │ ├── DistributionCaller.sol │ │ ├── FlashLoan.json │ │ ├── FlashLoan.sol │ │ ├── GovCaller.json │ │ ├── GovCaller.sol │ │ ├── ICounter.sol │ │ ├── InterchainSender.json │ │ ├── InterchainSender.sol │ │ ├── InterchainSenderCaller.json │ │ ├── InterchainSenderCaller.sol │ │ ├── Reverter.json │ │ ├── Reverter.sol │ │ ├── StakingReverter.json │ │ ├── StakingReverter.sol │ │ ├── contracts.go │ │ ├── counter.go │ │ ├── distribution_caller.go │ │ ├── flash_loan.go │ │ ├── gov_caller.go │ │ ├── interchain_sender.go │ │ ├── interchain_sender_caller.go │ │ ├── reverter.go │ │ ├── staking_reverter.go │ │ └── types.go │ ├── errors.go │ ├── events.go │ ├── ibc.go │ ├── logs.go │ ├── staking.go │ ├── testing.go │ └── tracking_multi_store.go └── werc20 │ ├── IWERC20.sol │ ├── abi.json │ ├── events.go │ ├── events_test.go │ ├── integration_test.go │ ├── interfaces.go │ ├── testdata │ ├── WEVMOS9.json │ ├── WEVMOS9TestCaller.json │ ├── WEVMOS9TestCaller.sol │ ├── wevmos9.go │ └── wevmos9_test_caller.go │ ├── tx.go │ ├── utils_test.go │ └── werc20.go ├── proto ├── buf.gen.gogo.yaml ├── buf.gen.pulsar.yaml ├── buf.lock ├── buf.yaml └── cosmos │ └── evm │ ├── crypto │ └── v1 │ │ └── ethsecp256k1 │ │ └── keys.proto │ ├── erc20 │ └── v1 │ │ ├── erc20.proto │ │ ├── events.proto │ │ ├── genesis.proto │ │ ├── query.proto │ │ └── tx.proto │ ├── feemarket │ └── v1 │ │ ├── events.proto │ │ ├── feemarket.proto │ │ ├── genesis.proto │ │ ├── query.proto │ │ └── tx.proto │ ├── precisebank │ └── v1 │ │ ├── genesis.proto │ │ └── query.proto │ ├── types │ └── v1 │ │ ├── dynamic_fee.proto │ │ ├── indexer.proto │ │ └── web3.proto │ └── vm │ └── v1 │ ├── events.proto │ ├── evm.proto │ ├── genesis.proto │ ├── query.proto │ └── tx.proto ├── repo_header.png ├── rpc ├── apis.go ├── backend │ ├── account_info.go │ ├── account_info_test.go │ ├── backend.go │ ├── backend_suite_test.go │ ├── blocks.go │ ├── blocks_test.go │ ├── call_tx.go │ ├── call_tx_test.go │ ├── chain_info.go │ ├── chain_info_test.go │ ├── client_test.go │ ├── evm_query_client_test.go │ ├── feemarket_query_client_test.go │ ├── filters.go │ ├── filters_test.go │ ├── mocks │ │ ├── client.go │ │ ├── evm_query_client.go │ │ └── feemarket_query_client.go │ ├── node_info.go │ ├── node_info_test.go │ ├── sign_tx.go │ ├── sign_tx_test.go │ ├── tracing.go │ ├── tracing_test.go │ ├── tx_info.go │ ├── tx_info_test.go │ ├── utils.go │ └── utils_test.go ├── ethereum │ └── pubsub │ │ ├── pubsub.go │ │ └── pubsub_test.go ├── namespaces │ └── ethereum │ │ ├── debug │ │ ├── api.go │ │ ├── trace.go │ │ ├── trace_fallback.go │ │ └── utils.go │ │ ├── eth │ │ ├── api.go │ │ └── filters │ │ │ ├── api.go │ │ │ ├── filter_system.go │ │ │ ├── filter_system_test.go │ │ │ ├── filters.go │ │ │ ├── subscription.go │ │ │ └── utils.go │ │ ├── miner │ │ ├── api.go │ │ └── unsupported.go │ │ ├── net │ │ └── api.go │ │ ├── personal │ │ └── api.go │ │ ├── txpool │ │ └── api.go │ │ └── web3 │ │ └── api.go ├── types │ ├── addrlock.go │ ├── block.go │ ├── block_test.go │ ├── events.go │ ├── events_test.go │ ├── query_client.go │ ├── types.go │ └── utils.go └── websockets.go ├── scripts ├── compile_smart_contracts │ ├── README.md │ ├── compile_smart_contracts.py │ ├── test_compile_smart_contracts.py │ └── testdata │ │ ├── hardhat.config.js │ │ ├── package.json │ │ └── solidity │ │ └── SimpleContract.sol ├── generate_protos.sh ├── generate_protos_pulsar.sh └── run-solidity-tests.sh ├── server ├── config │ ├── config.go │ ├── config_test.go │ ├── migration │ │ ├── migration.go │ │ └── v0.50-app.toml │ └── toml.go ├── flags │ └── flags.go ├── indexer_cmd.go ├── indexer_service.go ├── json_rpc.go ├── log_handler.go ├── start.go └── util.go ├── shell.nix ├── tests ├── ibc │ ├── helper.go │ ├── ibc_middleware_test.go │ ├── ics20_precompile_transfer_test.go │ ├── transfer_test.go │ ├── v2_ibc_middleware_test.go │ ├── v2_ics20_precompile_transfer_test.go │ └── v2_transfer_test.go ├── integration │ └── ledger │ │ ├── evmosd_suite_test.go │ │ ├── ledger_test.go │ │ └── mocks │ │ ├── AccountRetriever.go │ │ ├── SECP256K1.go │ │ ├── registry.go │ │ └── tendermint.go └── solidity │ ├── .gitattributes │ ├── .gitignore │ ├── init-node.sh │ ├── package.json │ ├── suites │ ├── basic │ │ ├── contracts │ │ │ ├── Counter.sol │ │ │ ├── EventTest.sol │ │ │ └── Storage.sol │ │ ├── package.json │ │ ├── test │ │ │ ├── .gitkeep │ │ │ ├── counter.js │ │ │ ├── events.js │ │ │ ├── revert.js │ │ │ └── storage.js │ │ └── truffle-config.js │ ├── eip1559 │ │ ├── package.json │ │ ├── test │ │ │ └── eip1559.js │ │ └── truffle-config.js │ ├── exception │ │ ├── contracts │ │ │ ├── TestRevert.sol │ │ │ └── test │ │ │ │ └── Migrations.sol │ │ ├── migrations │ │ │ └── 1_initial_migration.js │ │ ├── package.json │ │ ├── test │ │ │ ├── .gitkeep │ │ │ └── revert.js │ │ └── truffle-config.js │ ├── opcode │ │ ├── contracts │ │ │ ├── Migrations.sol │ │ │ └── OpCodes.sol │ │ ├── migrations │ │ │ ├── 1_initial_migration.js │ │ │ └── 2_opCodes_migration.js │ │ ├── package.json │ │ ├── test │ │ │ └── opCodes.js │ │ └── truffle-config.js │ └── precompiles │ │ ├── contracts │ │ └── .gitkeep │ │ ├── hardhat.config.js │ │ ├── package.json │ │ └── test │ │ └── staking.js │ ├── test-helper.js │ └── yarn.lock ├── testutil ├── ante.go ├── constants │ ├── constants.go │ └── constants_test.go ├── fund.go ├── ibc.go ├── integration │ ├── common │ │ ├── factory │ │ │ ├── base.go │ │ │ ├── distribution.go │ │ │ ├── factory.go │ │ │ ├── fund.go │ │ │ ├── helper.go │ │ │ ├── sign.go │ │ │ ├── staking.go │ │ │ └── types.go │ │ ├── grpc │ │ │ ├── account.go │ │ │ ├── authz.go │ │ │ ├── bank.go │ │ │ ├── distribution.go │ │ │ ├── grpc.go │ │ │ └── staking.go │ │ └── network │ │ │ └── network.go │ └── os │ │ ├── factory │ │ ├── broadcast.go │ │ ├── build.go │ │ ├── factory.go │ │ ├── helpers.go │ │ ├── sign.go │ │ └── types.go │ │ ├── grpc │ │ ├── evm.go │ │ ├── feemarket.go │ │ ├── gov.go │ │ └── grpc.go │ │ ├── keyring │ │ └── keyring.go │ │ ├── network │ │ ├── abci.go │ │ ├── amounts.go │ │ ├── chain_id_modifiers.go │ │ ├── clients.go │ │ ├── coins.go │ │ ├── config.go │ │ ├── config_test.go │ │ ├── example_contracts.go │ │ ├── ibc.go │ │ ├── network.go │ │ ├── setup.go │ │ └── unit_network.go │ │ └── utils │ │ ├── bank.go │ │ ├── bank_test.go │ │ ├── contracts.go │ │ ├── erc20.go │ │ ├── events.go │ │ ├── evm.go │ │ ├── evm_test.go │ │ ├── genesis.go │ │ ├── gov.go │ │ ├── params.go │ │ ├── staking.go │ │ ├── types.go │ │ └── unit.go ├── network │ ├── doc.go │ ├── network.go │ ├── network_test.go │ └── util.go ├── pair.go ├── setup.go ├── staking_rewards.go ├── statedb.go └── tx │ ├── cosmos.go │ ├── eip712.go │ ├── eth.go │ └── signer.go ├── tox.ini ├── types ├── block.go ├── codec.go ├── dynamic_fee.go ├── dynamic_fee.pb.go ├── errors.go ├── gasmeter.go ├── genesis.go ├── hdpath.go ├── indexer.go ├── indexer.pb.go ├── int.go ├── power.go ├── protocol.go ├── validation.go ├── validation_test.go └── web3.pb.go ├── utils ├── eth │ └── eth.go ├── utils.go └── utils_test.go ├── version └── version.go ├── wallets ├── accounts │ └── accounts.go ├── ledger │ ├── ledger.go │ ├── ledger_suite_test.go │ ├── ledger_test.go │ ├── mocks │ │ └── wallet.go │ └── wallet_test.go └── usbwallet │ ├── hub.go │ ├── ledger.go │ └── wallet.go └── x ├── erc20 ├── client │ └── cli │ │ ├── metadata │ │ ├── coin_metadata_test.json │ │ ├── coins_metadata_test.json │ │ └── invalid_metadata_test.json │ │ ├── query.go │ │ └── tx.go ├── genesis.go ├── genesis_test.go ├── ibc_middleware.go ├── keeper │ ├── allowance.go │ ├── allowance_test.go │ ├── dynamic_precompiles.go │ ├── dynamic_precompiles_test.go │ ├── erc20_utils_test.go │ ├── evm.go │ ├── evm_test.go │ ├── grpc_query.go │ ├── grpc_query_test.go │ ├── ibc_callbacks.go │ ├── ibc_callbacks_test.go │ ├── integration_test.go │ ├── keeper.go │ ├── mint.go │ ├── mint_test.go │ ├── msg_server.go │ ├── msg_server_test.go │ ├── params.go │ ├── params_test.go │ ├── precompiles.go │ ├── precompiles_test.go │ ├── proposals.go │ ├── proposals_test.go │ ├── setup_test.go │ ├── testdata │ │ ├── ERC20DirectBalanceManipulation.json │ │ ├── ERC20DirectBalanceManipulation.sol │ │ ├── ERC20MaliciousDelayed.json │ │ ├── ERC20MaliciousDelayed.sol │ │ ├── erc20DirectBalanceManipulation.go │ │ └── erc20maliciousdelayed.go │ ├── token_pairs.go │ ├── token_pairs_test.go │ └── utils_test.go ├── module.go ├── types │ ├── allowance.go │ ├── allowance_test.go │ ├── codec.go │ ├── constants.go │ ├── erc20.pb.go │ ├── errors.go │ ├── events.go │ ├── events.pb.go │ ├── evm.go │ ├── evm_test.go │ ├── genesis.go │ ├── genesis.pb.go │ ├── genesis_test.go │ ├── interfaces.go │ ├── keys.go │ ├── mocks │ │ ├── BankKeeper.go │ │ ├── EVMKeeper.go │ │ └── README.md │ ├── msg.go │ ├── msg_test.go │ ├── params.go │ ├── params_test.go │ ├── proposal.go │ ├── proposal_test.go │ ├── query.pb.go │ ├── query.pb.gw.go │ ├── token_pair.go │ ├── token_pair_test.go │ ├── tx.pb.go │ ├── tx.pb.gw.go │ ├── utils.go │ └── utils_test.go └── v2 │ └── ibc_middleware.go ├── feemarket ├── client │ └── cli │ │ └── query.go ├── genesis.go ├── keeper │ ├── abci.go │ ├── abci_test.go │ ├── eip1559.go │ ├── eip1559_test.go │ ├── grpc_query.go │ ├── grpc_query_test.go │ ├── integration_test.go │ ├── keeper.go │ ├── keeper_test.go │ ├── msg_server.go │ ├── msg_server_test.go │ ├── params.go │ ├── params_test.go │ └── setup_test.go ├── module.go └── types │ ├── codec.go │ ├── events.go │ ├── events.pb.go │ ├── feemarket.pb.go │ ├── genesis.go │ ├── genesis.pb.go │ ├── genesis_test.go │ ├── keys.go │ ├── msg.go │ ├── msg_test.go │ ├── params.go │ ├── params_test.go │ ├── query.pb.go │ ├── query.pb.gw.go │ ├── tx.pb.go │ └── tx.pb.gw.go ├── ibc └── transfer │ ├── ibc_module.go │ ├── keeper │ ├── keeper.go │ ├── keeper_test.go │ ├── msg_server.go │ └── msg_server_test.go │ ├── module.go │ ├── types │ ├── channels.go │ └── interfaces.go │ └── v2 │ └── ibc_module.go ├── precisebank ├── README.md ├── client │ └── cli │ │ └── query.go ├── genesis.go ├── genesis_test.go ├── keeper │ ├── burn.go │ ├── burn_integration_test.go │ ├── burn_test.go │ ├── fractional_balance.go │ ├── fractional_balance_test.go │ ├── grpc_query.go │ ├── grpc_query_test.go │ ├── integration_test.go │ ├── keeper.go │ ├── keeper_test.go │ ├── mint.go │ ├── mint_integration_test.go │ ├── mint_test.go │ ├── remainder_amount.go │ ├── remainder_amount_test.go │ ├── send.go │ ├── send_integration_test.go │ ├── send_test.go │ ├── setup_test.go │ ├── util_test.go │ ├── view.go │ ├── view_integration_test.go │ └── view_test.go ├── module.go ├── testutil │ └── fractional_balances.go └── types │ ├── codec.go │ ├── extended_balance.go │ ├── extended_balance_test.go │ ├── fractional_balance.go │ ├── fractional_balance_test.go │ ├── fractional_balances.go │ ├── fractional_balances_test.go │ ├── genesis.go │ ├── genesis.pb.go │ ├── genesis_test.go │ ├── interfaces.go │ ├── keys.go │ ├── keys_test.go │ ├── mocks │ ├── MockAccountKeeper.go │ └── MockBankKeeper.go │ ├── query.pb.go │ └── query.pb.gw.go └── vm ├── ante ├── ctx.go ├── ctx_test.go └── suite_test.go ├── client └── cli │ ├── query.go │ ├── tx.go │ ├── utils.go │ └── utils_test.go ├── genesis.go ├── genesis_test.go ├── keeper ├── abci.go ├── abci_test.go ├── benchmark_test.go ├── block_proposer.go ├── call_evm.go ├── call_evm_test.go ├── config.go ├── fees.go ├── fees_test.go ├── gas.go ├── grpc_query.go ├── grpc_query_test.go ├── hooks.go ├── hooks_test.go ├── integration_test.go ├── keeper.go ├── keeper_test.go ├── msg_server.go ├── msg_server_test.go ├── params.go ├── params_benchmark_test.go ├── params_test.go ├── precompiles.go ├── setup_test.go ├── state_transition.go ├── state_transition_benchmark_test.go ├── state_transition_test.go ├── statedb.go ├── statedb_benchmark_test.go ├── statedb_test.go ├── static_precompiles.go ├── testdata │ ├── ERC20Contract.json │ ├── TestMessageCall.json │ └── contracts.go ├── utils.go └── utils_test.go ├── module.go ├── statedb ├── access_list.go ├── config.go ├── integration_test.go ├── interfaces.go ├── journal.go ├── mock_test.go ├── state_object.go ├── statedb.go ├── statedb_test.go └── transient_storage.go ├── types ├── access_list.go ├── access_list_test.go ├── access_list_tx.go ├── access_list_tx_test.go ├── call.go ├── chain_config.go ├── chain_config_test.go ├── codec.go ├── codec_test.go ├── compiled_contract.go ├── compiled_contract_test.go ├── config.go ├── config_testing.go ├── configurator.go ├── configurator_test.go ├── denom.go ├── denom_config.go ├── denom_config_testing.go ├── dynamic_fee_tx.go ├── dynamic_fee_tx_test.go ├── errors.go ├── events.go ├── events.pb.go ├── evm.pb.go ├── genesis.go ├── genesis.pb.go ├── genesis_test.go ├── interfaces.go ├── key.go ├── legacy_tx.go ├── legacy_tx_test.go ├── logs.go ├── logs_test.go ├── msg.go ├── msg_test.go ├── opcodes_hooks.go ├── params.go ├── params_legacy.go ├── params_test.go ├── permissions.go ├── permissions_test.go ├── precompiles.go ├── query.go ├── query.pb.go ├── query.pb.gw.go ├── scaling.go ├── scaling_test.go ├── storage.go ├── storage_test.go ├── testdata │ └── SimpleContractHardhat.json ├── tracer.go ├── tx.go ├── tx.pb.go ├── tx.pb.gw.go ├── tx_args.go ├── tx_args_test.go ├── tx_data.go ├── tx_data_test.go ├── tx_types.go ├── utils.go └── utils_test.go └── wrappers ├── README.md ├── bank.go ├── bank_test.go ├── feemarket.go ├── feemarket_test.go └── testutil └── mock.go /.clconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "categories": [ 3 | "all", 4 | "ante", 5 | "bank-precompile", 6 | "ci", 7 | "cli", 8 | "contracts", 9 | "deps", 10 | "dist-precompile", 11 | "eip-712", 12 | "erc20", 13 | "erc20-precompile", 14 | "evm", 15 | "feemarket", 16 | "ibc", 17 | "ics20-precompile", 18 | "precompiles", 19 | "proto", 20 | "rpc", 21 | "server", 22 | "staking-precompile", 23 | "tests", 24 | "types" 25 | ], 26 | "change_types": { 27 | "API Breaking": "feat-api", 28 | "Bug Fixes": "fix", 29 | "Improvements": "imp", 30 | "State Machine Breaking": "feat-smb" 31 | }, 32 | "expected_spellings": { 33 | "ABI": "abi", 34 | "API": "api", 35 | "CI": "ci", 36 | "CLI": "cli", 37 | "Cosmos SDK": "cosmos[\\s-]*sdk", 38 | "EIP-712": "eip[\\s-]*712", 39 | "ERC-20": "erc[\\s-]*20", 40 | "EVM": "evm", 41 | "IBC": "ibc", 42 | "ICS": "ics", 43 | "ICS-20": "ics[\\s-]*20", 44 | "OS": "os", 45 | "PR": "pr", 46 | "RPC": "rpc", 47 | "SDK": "sdk" 48 | }, 49 | "legacy_version": null, 50 | "target_repo": "https://github.com/cosmos/evm" 51 | } 52 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # CODEOWNERS: https://help.github.com/articles/about-codeowners/ 2 | 3 | # Primary repo maintainers 4 | * @cosmos/interchain_inc_gaia_write -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/03-docs-request.yml: -------------------------------------------------------------------------------- 1 | name: Documentation Request 2 | description: Create an issue for missing or incorrect documentation 3 | title: "[Docs]: " 4 | labels: ["type: docs-req", "status: waiting-triage"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | ✰ Thanks for opening an issue! ✰ 10 | Tell us what you would like to see get added to the documentation or if there is an error in the documentation? 11 | 12 | - type: textarea 13 | id: what-happened 14 | attributes: 15 | label: Summary 16 | placeholder: Description of what you would like to see 17 | validations: 18 | required: true 19 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/04-epic-template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Epic Template 3 | about: Basic template for epics (used by the team) 4 | title: "[Epic]: " 5 | labels: ['admin: epic', 'status: waiting-triage'] 6 | --- 7 | 8 | ## Problem 9 | 10 | 11 | 12 | ## Closing criteria 13 | 14 | 15 | 16 | 17 | ## Problem details 18 | 19 | 20 | 21 | ## Task list 22 | 23 | ```[tasklist] 24 | ### Must have 25 | 26 | ``` 27 | 28 | ```[tasklist] 29 | ### Nice to have 30 | 31 | ``` -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/05-issue-template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Issue Template 3 | about: Basic template for issues (used by the team) 4 | labels: 'status: waiting-triage' 5 | --- 6 | 7 | 12 | 13 | ## Problem 14 | 15 | 16 | 17 | ## Closing criteria 18 | 19 | 20 | 21 | 22 | ## Problem details 23 | 24 | 25 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | Closes: #XXXX 11 | 12 | --- 13 | 14 | ## Author Checklist 15 | 16 | **All** items are required. Please add a note to the item if the item is not applicable and 17 | please add links to any relevant follow up issues. 18 | 19 | I have... 20 | 21 | - [ ] tackled an existing issue or discussed with a team member 22 | - [ ] left instructions on how to review the changes 23 | - [ ] targeted the `main` branch 24 | 25 | ## Reviewers Checklist 26 | 27 | **All** items are required. 28 | Please add a note if the item is not applicable 29 | and please add your handle next to the items reviewed 30 | if you only reviewed selected items. 31 | 32 | I have... 33 | 34 | - [ ] added a relevant changelog entry to the `Unreleased` section in `CHANGELOG.md` 35 | - [ ] confirmed all author checklist items have been addressed 36 | - [ ] confirmed that this PR does not change production code 37 | - [ ] reviewed content 38 | - [ ] tested instructions (if applicable) 39 | - [ ] confirmed all CI checks have passed 40 | -------------------------------------------------------------------------------- /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | proto: 2 | - changed-files: 3 | - any-glob-to-any-file: [ 4 | "proto/**/*", 5 | "**/*.pb.go", 6 | "**/*.pb.gw.go" 7 | ] 8 | types: 9 | - changed-files: 10 | - any-glob-to-any-file: [ 11 | "types/**/*", 12 | ] 13 | build: 14 | - changed-files: 15 | - any-glob-to-any-file: [ 16 | "Makefile", 17 | "Dockerfile", 18 | "docker-compose.yml", 19 | "scripts/*", 20 | "config.yml", 21 | ] 22 | CI: 23 | - changed-files: 24 | - any-glob-to-any-file: [ 25 | ".github/**/*", 26 | ".mergify.yml", 27 | ".golangci.yml", 28 | "buf.yaml", 29 | ] 30 | CLI: 31 | - changed-files: 32 | - any-glob-to-any-file: [ 33 | "client/**/*", 34 | "x/*/client/**/*", 35 | ] 36 | tests: 37 | - changed-files: 38 | - any-glob-to-any-file: [ 39 | "tests/**/*", 40 | "testutil/**/*", 41 | "**/*_test.go", 42 | ] 43 | contracts: 44 | - changed-files: 45 | - any-glob-to-any-file: [ 46 | "contracts/**/*", 47 | "*.sol", 48 | ] 49 | precompile: 50 | - changed-files: 51 | - any-glob-to-any-file: [ 52 | "precompiles/**/*", 53 | ] 54 | release: 55 | - base-branch: "^release/" 56 | feature: 57 | - head-branch: "^feat/" 58 | -------------------------------------------------------------------------------- /.github/workflows/bsr-push.yml: -------------------------------------------------------------------------------- 1 | name: Push to Buf Schema Registry 2 | # This workflow runs when a new version tag is pushed to the repository. 3 | # It then pushes the Protobuf files corresponding to that tag on to the 4 | # Buf Schema Registry at https://buf.build/cosmos/evm 5 | on: 6 | push: 7 | tags: 8 | - "v*.*.*" 9 | permissions: read-all 10 | 11 | jobs: 12 | push: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v4 16 | - uses: bufbuild/buf-setup-action@v1.50.0 17 | # Push Cosmos EVM protos to the Buf Schema Registry 18 | - uses: bufbuild/buf-push-action@v1.2.0 19 | with: 20 | input: ./proto 21 | buf_token: ${{ secrets.BUF_TOKEN }} 22 | -------------------------------------------------------------------------------- /.github/workflows/changelog.yml: -------------------------------------------------------------------------------- 1 | name: Changelog Linter 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | - release/** 8 | permissions: read-all 9 | 10 | jobs: 11 | check_diff: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Check Changelog for changes 15 | uses: tarides/changelog-check-action@v3 16 | with: 17 | changelog: CHANGELOG.md -------------------------------------------------------------------------------- /.github/workflows/dependencies.yml: -------------------------------------------------------------------------------- 1 | name: "Dependency Review" 2 | on: 3 | workflow_call: 4 | workflow_dispatch: 5 | schedule: 6 | # run every day at 3:00 UTC 7 | - cron: "0 3 * * *" 8 | 9 | permissions: read-all 10 | 11 | jobs: 12 | dependency-review: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/setup-go@v5 16 | with: 17 | go-version: '1.23.6' 18 | check-latest: true 19 | - name: "Checkout Repository" 20 | uses: actions/checkout@v4 21 | - uses: technote-space/get-diff-action@v6.1.2 22 | with: 23 | PATTERNS: | 24 | **/**.go 25 | go.mod 26 | go.sum 27 | *.toml 28 | - name: "Dependency Review" 29 | uses: actions/dependency-review-action@v4 30 | - name: "Get govulncheck" 31 | run: go install golang.org/x/vuln/cmd/govulncheck@latest 32 | - name: Run govulncheck 33 | run: govulncheck -show verbose ./... 34 | shell: bash 35 | -------------------------------------------------------------------------------- /.github/workflows/labeler.yml: -------------------------------------------------------------------------------- 1 | name: "Pull Request Labeler" 2 | on: 3 | pull_request: 4 | permissions: read-all 5 | 6 | jobs: 7 | triage: 8 | runs-on: ubuntu-latest 9 | permissions: 10 | pull-requests: write # For reading the PR and adding the label 11 | steps: 12 | - uses: actions/labeler@v5 13 | with: 14 | repo-token: "${{ secrets.GITHUB_TOKEN }}" 15 | -------------------------------------------------------------------------------- /.github/workflows/markdown-links.yml: -------------------------------------------------------------------------------- 1 | name: Check Markdown links 2 | on: 3 | pull_request: 4 | branches: 5 | - main 6 | - release/** 7 | permissions: read-all 8 | 9 | jobs: 10 | markdown-link-check: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: technote-space/get-diff-action@v6.1.2 15 | with: 16 | PATTERNS: | 17 | **.md 18 | - uses: gaurav-nelson/github-action-markdown-link-check@master 19 | with: 20 | check-modified-files-only: "yes" 21 | use-quiet-mode: "yes" 22 | base-branch: "main" 23 | config-file: "mlc_config.json" 24 | if: env.GIT_DIFF 25 | -------------------------------------------------------------------------------- /.github/workflows/security.yml: -------------------------------------------------------------------------------- 1 | name: Run Gosec 2 | on: 3 | pull_request: 4 | permissions: read-all 5 | 6 | jobs: 7 | Gosec: 8 | permissions: 9 | security-events: write 10 | 11 | runs-on: ubuntu-latest 12 | env: 13 | GO111MODULE: on 14 | steps: 15 | - name: Checkout Source 16 | uses: actions/checkout@v4 17 | - name: Get Diff 18 | uses: technote-space/get-diff-action@v6.1.2 19 | with: 20 | PATTERNS: | 21 | **/*.go 22 | go.mod 23 | go.sum 24 | *.toml 25 | - name: Run Gosec Security Scanner 26 | uses: cosmos/gosec@master 27 | with: 28 | # we let the report trigger content trigger a failure using the GitHub Security features. 29 | args: "-no-fail -fmt sarif -out results.sarif ./..." 30 | if: "env.GIT_DIFF_FILTERED != ''" 31 | - name: Upload SARIF file 32 | uses: github/codeql-action/upload-sarif@v3 33 | with: 34 | # Path to SARIF file relative to the root of the repository 35 | sarif_file: results.sarif 36 | if: "env.GIT_DIFF_FILTERED != ''" 37 | -------------------------------------------------------------------------------- /.github/workflows/slither.yml: -------------------------------------------------------------------------------- 1 | name: Slither Analysis 2 | 3 | on: 4 | pull_request: 5 | permissions: read-all 6 | 7 | jobs: 8 | analyze: 9 | name: Run Slither 10 | runs-on: ubuntu-latest 11 | permissions: 12 | contents: read 13 | security-events: write 14 | steps: 15 | - name: Checkout repository 16 | uses: actions/checkout@v4 17 | - name: Get Diff 18 | uses: technote-space/get-diff-action@v6.1.2 19 | with: 20 | PATTERNS: | 21 | **/*.sol 22 | - name: Node dependencies Install 23 | run: | 24 | cd contracts && npm i 25 | cp -r node_modules/@openzeppelin . 26 | - name: Run Slither Action 27 | uses: crytic/slither-action@v0.4.0 28 | continue-on-error: true 29 | id: slither 30 | with: 31 | target: contracts/ 32 | if: "env.GIT_DIFF" -------------------------------------------------------------------------------- /.github/workflows/solhint.yml: -------------------------------------------------------------------------------- 1 | name: Solhint 2 | # This workflow is only run when a .sol file has been changed 3 | on: 4 | pull_request: 5 | 6 | permissions: read-all 7 | 8 | jobs: 9 | solhint: 10 | name: runner / solhint 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: technote-space/get-diff-action@v6.1.2 15 | id: git_diff 16 | with: 17 | PATTERNS: | 18 | **/**.sol 19 | - uses: actions/setup-node@v4 20 | if: env.GIT_DIFF 21 | - run: npm install -g solhint@v5.0.5 22 | if: env.GIT_DIFF 23 | - run: solhint --version 24 | if: env.GIT_DIFF 25 | - run: solhint '**/*.sol' 26 | if: env.GIT_DIFF 27 | -------------------------------------------------------------------------------- /.github/workflows/solidity-test.yml: -------------------------------------------------------------------------------- 1 | name: Solidity Test 2 | on: 3 | pull_request: 4 | branches: 5 | - main 6 | - release/** 7 | permissions: read-all 8 | 9 | jobs: 10 | test-solidity: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/setup-go@v5 14 | with: 15 | go-version: '1.22' 16 | check-latest: true 17 | - uses: actions/checkout@v4 18 | - uses: technote-space/get-diff-action@v6.1.2 19 | with: 20 | PATTERNS: | 21 | **/**.sol 22 | **/**.go 23 | go.mod 24 | go.sum 25 | *.toml 26 | - name: Test Solidity 27 | run: | 28 | make test-solidity 29 | if: env.GIT_DIFF 30 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: "Close stale issues & pull requests" 2 | on: 3 | schedule: 4 | - cron: "0 0 * * *" 5 | permissions: read-all 6 | 7 | jobs: 8 | stale: 9 | permissions: 10 | pull-requests: write # For reading the PR and adding the label 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/stale@v9 14 | with: 15 | repo-token: ${{ secrets.GITHUB_TOKEN }} 16 | stale-pr-message: "This pull request has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days-before-close if no further activity occurs." 17 | stale-issue-message: "This issue is stale because it has been open 45 days with no activity. Remove `Status: Stale` label or comment or this will be closed in 7 days." 18 | days-before-stale: 45 19 | days-before-close: 7 20 | exempt-issue-labels: "Status: Blocked, Type: Bug, pinned, automerge" 21 | exempt-pr-labels: "Status: Blocked, Type: Bug, pinned, automerge" 22 | stale-pr-label: "Status: Stale" 23 | stale-issue-label: "Status: Stale" 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS 2 | .DS_Store 3 | *.swp 4 | *.swo 5 | *.swl 6 | *.swm 7 | *.swn 8 | *.pyc 9 | *.exe 10 | *.exe~ 11 | *.dll 12 | *.so 13 | *.dylib 14 | .dccache 15 | 16 | # Testing 17 | coverage.txt 18 | yarn.lock 19 | 20 | # IDE 21 | .idea/ 22 | .vscode/ 23 | *.iml 24 | *.code-workspace 25 | 26 | # Node.js 27 | **/node_modules 28 | 29 | # OpenZeppelin contracts 30 | contracts/@openzeppelin/* 31 | 32 | # Build files 33 | evmd/build/ 34 | 35 | build/ 36 | -------------------------------------------------------------------------------- /.govulncheck.yaml: -------------------------------------------------------------------------------- 1 | ignore: 2 | -id: GO-2025-3443 3 | reason: "Fixed in 0.38.16" 4 | -------------------------------------------------------------------------------- /.markdownlint.yml: -------------------------------------------------------------------------------- 1 | "default": true 2 | "MD001": false 3 | "MD004": false 4 | "MD007": 5 | "indent": 4 6 | "MD024": 7 | "siblings_only": true 8 | "MD025": false 9 | "MD026": 10 | "punctuation": ".;:" 11 | "MD029": false 12 | "MD033": false 13 | "MD034": false 14 | "MD036": false 15 | "MD040": false 16 | "MD041": false 17 | "MD051": false 18 | "MD049": 19 | "style": "asterisk" 20 | "MD013": 21 | "line_length": 120 22 | "code_blocks": false 23 | "tables": false 24 | "no-hard-tabs": false 25 | -------------------------------------------------------------------------------- /.markdownlintignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmos/evm/4f9b8c209314217a1dc8e6d5ff0674c87ed38768/.markdownlintignore -------------------------------------------------------------------------------- /.mergify.yml: -------------------------------------------------------------------------------- 1 | queue_rules: 2 | - name: default 3 | queue_conditions: 4 | - "#approved-reviews-by>1" 5 | - base=main 6 | - label=automerge 7 | merge_conditions: 8 | - "#approved-reviews-by>1" 9 | merge_method: squash 10 | commit_message_template: | 11 | {{ title }} (#{{ number }}) 12 | {{ body }} 13 | 14 | pull_request_rules: 15 | - name: backport patches to v6.0.x branch 16 | conditions: 17 | - base=main 18 | - label=backport/6.0.x 19 | actions: 20 | backport: 21 | branches: 22 | - release/v6.0.x 23 | - name: backport patches to v5.0.x branch 24 | conditions: 25 | - base=main 26 | - label=backport/5.0.x 27 | actions: 28 | backport: 29 | branches: 30 | - release/v5.0.x 31 | - name: backport patches to v4.0.x branch 32 | conditions: 33 | - base=main 34 | - label=backport/4.0.x 35 | actions: 36 | backport: 37 | branches: 38 | - release/v4.0.x 39 | - name: backport patches to v3.0.x branch 40 | conditions: 41 | - base=main 42 | - label=backport/3.0.x 43 | actions: 44 | backport: 45 | branches: 46 | - release/v3.0.x 47 | - name: refactored queue action rule 48 | conditions: [] 49 | actions: 50 | queue: 51 | -------------------------------------------------------------------------------- /.semgrepignore: -------------------------------------------------------------------------------- 1 | # Ignore git items 2 | .gitignore 3 | .git/ 4 | :include .gitignore 5 | 6 | # Common large paths 7 | node_modules/ 8 | build/ 9 | dist/ 10 | vendor/ 11 | .env/ 12 | .venv/ 13 | .tox/ 14 | *.min.js 15 | 16 | # Ignore proto 17 | *.proto 18 | 19 | # Common test paths 20 | test/ 21 | tests/ 22 | *_test.go 23 | *.pb.gw.go 24 | *.pb.go 25 | 26 | # Semgrep rules folder 27 | .semgrep 28 | 29 | # Semgrep-action log folder 30 | .semgrep_logs/ 31 | 32 | # GETH code 33 | x/evm/core/ 34 | -------------------------------------------------------------------------------- /.solhint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "solhint:default" 3 | } 4 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | yaml-files: 4 | - '*.yaml' 5 | - '*.yml' 6 | - '.yamllint' 7 | 8 | rules: 9 | braces: enable 10 | brackets: enable 11 | colons: enable 12 | commas: enable 13 | comments: 14 | level: warning 15 | comments-indentation: disable 16 | document-end: disable 17 | document-start: disable 18 | empty-lines: disable 19 | empty-values: disable 20 | float-values: disable 21 | hyphens: enable 22 | indentation: enable 23 | key-duplicates: enable 24 | key-ordering: disable 25 | line-length: disable 26 | new-line-at-end-of-file: enable 27 | new-lines: enable 28 | octal-values: disable 29 | quoted-strings: disable 30 | trailing-spaces: disable 31 | truthy: disable -------------------------------------------------------------------------------- /ante/cosmos/reject_msgs.go: -------------------------------------------------------------------------------- 1 | package cosmos 2 | 3 | import ( 4 | evmtypes "github.com/cosmos/evm/x/vm/types" 5 | 6 | errorsmod "cosmossdk.io/errors" 7 | 8 | sdk "github.com/cosmos/cosmos-sdk/types" 9 | errortypes "github.com/cosmos/cosmos-sdk/types/errors" 10 | ) 11 | 12 | // RejectMessagesDecorator prevents invalid msg types from being executed. 13 | type RejectMessagesDecorator struct{} 14 | 15 | // NewRejectMessagesDecorator creates a new RejectMessagesDecorator. 16 | func NewRejectMessagesDecorator() sdk.AnteDecorator { 17 | return RejectMessagesDecorator{} 18 | } 19 | 20 | // AnteHandle rejects messages that requires ethereum-specific authentication. 21 | // For example `MsgEthereumTx` requires fee to be deducted in the antehandler in 22 | // order to perform the refund. 23 | func (rmd RejectMessagesDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { 24 | for _, msg := range tx.GetMsgs() { 25 | if _, ok := msg.(*evmtypes.MsgEthereumTx); ok { 26 | return ctx, errorsmod.Wrapf( 27 | errortypes.ErrInvalidType, 28 | "MsgEthereumTx needs to be contained within a tx with 'ExtensionOptionsEthereumTx' option", 29 | ) 30 | } 31 | } 32 | return next(ctx, tx, simulate) 33 | } 34 | -------------------------------------------------------------------------------- /ante/cosmos/setup_test.go: -------------------------------------------------------------------------------- 1 | package cosmos_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/suite" 7 | 8 | "github.com/cosmos/evm/ante/testutils" 9 | ) 10 | 11 | type AnteTestSuite struct { 12 | *testutils.AnteTestSuite 13 | } 14 | 15 | func TestAnteTestSuite(t *testing.T) { 16 | baseSuite := new(testutils.AnteTestSuite) 17 | baseSuite.WithLondonHardForkEnabled(true) 18 | baseSuite.WithFeemarketEnabled(true) 19 | 20 | suite.Run(t, &AnteTestSuite{baseSuite}) 21 | } 22 | -------------------------------------------------------------------------------- /ante/evm/02_mempool_fee.go: -------------------------------------------------------------------------------- 1 | package evm 2 | 3 | import ( 4 | errorsmod "cosmossdk.io/errors" 5 | sdkmath "cosmossdk.io/math" 6 | 7 | errortypes "github.com/cosmos/cosmos-sdk/types/errors" 8 | ) 9 | 10 | // CheckMempoolFee checks if the provided fee is at least as large as the local 11 | // validator's configured value. The fee computation assumes that both price and fee are 12 | // represented in 18 decimals. 13 | func CheckMempoolFee(fee, mempoolMinGasPrice, gasLimit sdkmath.LegacyDec, isLondon bool) error { 14 | if isLondon { 15 | return nil 16 | } 17 | 18 | requiredFee := mempoolMinGasPrice.Mul(gasLimit) 19 | 20 | if fee.LT(requiredFee) { 21 | return errorsmod.Wrapf( 22 | errortypes.ErrInsufficientFee, 23 | "got: %s, minimum required: %s", 24 | fee, requiredFee, 25 | ) 26 | } 27 | 28 | return nil 29 | } 30 | -------------------------------------------------------------------------------- /ante/evm/09_increment_sequence.go: -------------------------------------------------------------------------------- 1 | package evm 2 | 3 | import ( 4 | anteinterfaces "github.com/cosmos/evm/ante/interfaces" 5 | 6 | errorsmod "cosmossdk.io/errors" 7 | 8 | sdk "github.com/cosmos/cosmos-sdk/types" 9 | errortypes "github.com/cosmos/cosmos-sdk/types/errors" 10 | ) 11 | 12 | // IncrementNonce increments the sequence of the account. 13 | func IncrementNonce( 14 | ctx sdk.Context, 15 | accountKeeper anteinterfaces.AccountKeeper, 16 | account sdk.AccountI, 17 | txNonce uint64, 18 | ) error { 19 | nonce := account.GetSequence() 20 | // we merged the nonce verification to nonce increment, so when tx includes multiple messages 21 | // with same sender, they'll be accepted. 22 | if txNonce != nonce { 23 | return errorsmod.Wrapf( 24 | errortypes.ErrInvalidSequence, 25 | "invalid nonce; got %d, expected %d", txNonce, nonce, 26 | ) 27 | } 28 | 29 | nonce++ 30 | 31 | if err := account.SetSequence(nonce); err != nil { 32 | return errorsmod.Wrapf(err, "failed to set sequence to %d", nonce) 33 | } 34 | 35 | accountKeeper.SetAccount(ctx, account) 36 | return nil 37 | } 38 | -------------------------------------------------------------------------------- /ante/evm/setup_test.go: -------------------------------------------------------------------------------- 1 | package evm_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/suite" 7 | 8 | "github.com/cosmos/evm/ante/testutils" 9 | ) 10 | 11 | type AnteTestSuite struct { 12 | *testutils.AnteTestSuite 13 | useLegacyEIP712TypedData bool 14 | } 15 | 16 | func TestAnteTestSuite(t *testing.T) { 17 | baseSuite := new(testutils.AnteTestSuite) 18 | baseSuite.WithLondonHardForkEnabled(true) 19 | 20 | suite.Run(t, &AnteTestSuite{ 21 | AnteTestSuite: baseSuite, 22 | }) 23 | 24 | // Re-run the tests with EIP-712 Legacy encodings to ensure backwards compatibility. 25 | // LegacyEIP712Extension should not be run with current TypedData encodings, since they are not compatible. 26 | suite.Run(t, &AnteTestSuite{ 27 | AnteTestSuite: baseSuite, 28 | useLegacyEIP712TypedData: true, 29 | }) 30 | } 31 | -------------------------------------------------------------------------------- /ante/evm/suite_test.go: -------------------------------------------------------------------------------- 1 | package evm_test 2 | 3 | import ( 4 | "testing" 5 | 6 | gethtypes "github.com/ethereum/go-ethereum/core/types" 7 | "github.com/stretchr/testify/suite" 8 | 9 | testconstants "github.com/cosmos/evm/testutil/constants" 10 | ) 11 | 12 | // EvmAnteTestSuite aims to test all EVM ante handler unit functions. 13 | // NOTE: the suite only holds properties related to global execution parameters 14 | // (what type of tx to run the tests with) not independent tests values. 15 | type EvmAnteTestSuite struct { 16 | suite.Suite 17 | 18 | // To make sure that every tests is run with all the tx types 19 | ethTxType int 20 | chainID string 21 | evmChainID uint64 22 | } 23 | 24 | func TestEvmAnteTestSuite(t *testing.T) { 25 | txTypes := []int{gethtypes.DynamicFeeTxType, gethtypes.LegacyTxType, gethtypes.AccessListTxType} 26 | chainIDs := []testconstants.ChainID{testconstants.ExampleChainID, testconstants.SixDecimalsChainID} 27 | for _, txType := range txTypes { 28 | for _, chainID := range chainIDs { 29 | suite.Run(t, &EvmAnteTestSuite{ 30 | ethTxType: txType, 31 | chainID: chainID.ChainID, 32 | evmChainID: chainID.EVMChainID, 33 | }) 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ante/interfaces/cosmos.go: -------------------------------------------------------------------------------- 1 | package interfaces 2 | 3 | import ( 4 | "context" 5 | "time" 6 | 7 | addresscodec "cosmossdk.io/core/address" 8 | 9 | sdk "github.com/cosmos/cosmos-sdk/types" 10 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 11 | ) 12 | 13 | type AccountKeeper interface { 14 | NewAccountWithAddress(ctx context.Context, addr sdk.AccAddress) sdk.AccountI 15 | GetModuleAddress(moduleName string) sdk.AccAddress 16 | GetAccount(ctx context.Context, addr sdk.AccAddress) sdk.AccountI 17 | SetAccount(ctx context.Context, account sdk.AccountI) 18 | RemoveAccount(ctx context.Context, account sdk.AccountI) 19 | GetParams(ctx context.Context) (params authtypes.Params) 20 | GetSequence(ctx context.Context, addr sdk.AccAddress) (uint64, error) 21 | AddressCodec() addresscodec.Codec 22 | UnorderedTransactionsEnabled() bool 23 | RemoveExpiredUnorderedNonces(ctx sdk.Context) error 24 | TryAddUnorderedNonce(ctx sdk.Context, sender []byte, timestamp time.Time) error 25 | } 26 | 27 | type BankKeeper interface { 28 | GetBalance(ctx context.Context, addr sdk.AccAddress, denom string) sdk.Coin 29 | IsSendEnabledCoins(ctx context.Context, coins ...sdk.Coin) error 30 | SendCoins(ctx context.Context, from, to sdk.AccAddress, amt sdk.Coins) error 31 | SendCoinsFromAccountToModule(ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error 32 | } 33 | -------------------------------------------------------------------------------- /ante/utils_test.go: -------------------------------------------------------------------------------- 1 | package ante_test 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/cosmos/evm/ante" 8 | "github.com/cosmos/evm/crypto/ethsecp256k1" 9 | 10 | cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" 11 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 12 | ) 13 | 14 | func generatePubKeysAndSignatures(n int, msg []byte, _ bool) (pubkeys []cryptotypes.PubKey, signatures [][]byte) { 15 | pubkeys = make([]cryptotypes.PubKey, n) 16 | signatures = make([][]byte, n) 17 | for i := 0; i < n; i++ { 18 | privkey, _ := ethsecp256k1.GenerateKey() 19 | pubkeys[i] = privkey.PubKey() 20 | signatures[i], _ = privkey.Sign(msg) 21 | } 22 | return 23 | } 24 | 25 | func expectedGasCostByKeys(pubkeys []cryptotypes.PubKey) uint64 { 26 | cost := uint64(0) 27 | for _, pubkey := range pubkeys { 28 | pubkeyType := strings.ToLower(fmt.Sprintf("%T", pubkey)) 29 | switch { 30 | case strings.Contains(pubkeyType, "ed25519"): 31 | cost += authtypes.DefaultSigVerifyCostED25519 32 | case strings.Contains(pubkeyType, "ethsecp256k1"): 33 | cost += ante.Secp256k1VerifyCost 34 | default: 35 | panic("unexpected key type") 36 | } 37 | } 38 | return cost 39 | } 40 | -------------------------------------------------------------------------------- /api/cosmos/evm/erc20/v1/msg.go: -------------------------------------------------------------------------------- 1 | package erc20v1 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/ethereum/go-ethereum/common" 7 | protov2 "google.golang.org/protobuf/proto" 8 | ) 9 | 10 | // GetSigners gets the signer's address from the Ethereum tx signature 11 | func GetSigners(msg protov2.Message) ([][]byte, error) { 12 | msgConvERC20, ok := msg.(*MsgConvertERC20) 13 | if !ok { 14 | return nil, fmt.Errorf("invalid type, expected MsgConvertERC20 and got %T", msg) 15 | } 16 | 17 | // The sender on the msg is a hex address 18 | sender := common.HexToAddress(msgConvERC20.Sender) 19 | 20 | return [][]byte{sender.Bytes()}, nil 21 | } 22 | -------------------------------------------------------------------------------- /api/cosmos/evm/vm/v1/legacy_tx.go: -------------------------------------------------------------------------------- 1 | package vmv1 2 | 3 | import ( 4 | "math/big" 5 | 6 | ethtypes "github.com/ethereum/go-ethereum/core/types" 7 | 8 | ethutils "github.com/cosmos/evm/utils/eth" 9 | ) 10 | 11 | // GetChainID returns the chain id field from the derived signature values 12 | func (tx *LegacyTx) GetChainID() *big.Int { 13 | v, _, _ := tx.GetRawSignatureValues() 14 | return ethutils.DeriveChainID(v) 15 | } 16 | 17 | // AsEthereumData returns an LegacyTx transaction tx from the proto-formatted 18 | // TxData defined on the Cosmos EVM. 19 | func (tx *LegacyTx) AsEthereumData() ethtypes.TxData { 20 | v, r, s := tx.GetRawSignatureValues() 21 | return ðtypes.LegacyTx{ 22 | Nonce: tx.GetNonce(), 23 | GasPrice: stringToBigInt(tx.GetGasPrice()), 24 | Gas: tx.GetGas(), 25 | To: stringToAddress(tx.GetTo()), 26 | Value: stringToBigInt(tx.GetValue()), 27 | Data: tx.GetData(), 28 | V: v, 29 | R: r, 30 | S: s, 31 | } 32 | } 33 | 34 | // GetRawSignatureValues returns the V, R, S signature values of the transaction. 35 | // The return values should not be modified by the caller. 36 | func (tx *LegacyTx) GetRawSignatureValues() (v, r, s *big.Int) { 37 | return ethutils.RawSignatureValues(tx.V, tx.R, tx.S) 38 | } 39 | 40 | // GetAccessList returns nil 41 | func (tx *LegacyTx) GetAccessList() ethtypes.AccessList { 42 | return nil 43 | } 44 | -------------------------------------------------------------------------------- /api/cosmos/evm/vm/v1/tx_data.go: -------------------------------------------------------------------------------- 1 | package vmv1 2 | 3 | import ( 4 | "math/big" 5 | 6 | "github.com/ethereum/go-ethereum/common" 7 | ethtypes "github.com/ethereum/go-ethereum/core/types" 8 | "google.golang.org/protobuf/reflect/protoreflect" 9 | 10 | sdkmath "cosmossdk.io/math" 11 | ) 12 | 13 | var ( 14 | _ TxDataV2 = &LegacyTx{} 15 | _ TxDataV2 = &AccessListTx{} 16 | _ TxDataV2 = &DynamicFeeTx{} 17 | ) 18 | 19 | // TxDataV2 implements the Ethereum transaction tx structure. It is used 20 | // solely to define the custom logic for getting signers on Ethereum transactions. 21 | type TxDataV2 interface { 22 | GetChainID() *big.Int 23 | AsEthereumData() ethtypes.TxData 24 | 25 | ProtoReflect() protoreflect.Message 26 | } 27 | 28 | // helper function to parse string to bigInt 29 | func stringToBigInt(str string) *big.Int { 30 | if str == "" { 31 | return nil 32 | } 33 | res, ok := sdkmath.NewIntFromString(str) 34 | if !ok { 35 | return nil 36 | } 37 | return res.BigInt() 38 | } 39 | 40 | func stringToAddress(toStr string) *common.Address { 41 | if toStr == "" { 42 | return nil 43 | } 44 | addr := common.HexToAddress(toStr) 45 | return &addr 46 | } 47 | -------------------------------------------------------------------------------- /buf.gen.proto.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | 3 | plugins: 4 | 5 | - name: gocosmos 6 | out: . 7 | opt: 8 | - plugins=interfacetype+grpc 9 | 10 | - name: grpc-gateway 11 | out: . 12 | opt: 13 | - logtostderr=true 14 | 15 | - name: doc 16 | out: ./docs/protocol 17 | opt: 18 | - ./docs/protodoc-markdown.tmpl,proto-docs.md 19 | strategy: all 20 | -------------------------------------------------------------------------------- /buf.work.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | directories: 3 | - proto 4 | -------------------------------------------------------------------------------- /client/config.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | 7 | "github.com/spf13/cobra" 8 | "github.com/spf13/viper" 9 | 10 | "github.com/cometbft/cometbft/libs/cli" 11 | 12 | "github.com/cosmos/cosmos-sdk/client/flags" 13 | ) 14 | 15 | // InitConfig adds the chain-id, encoding and output flags to the persistent flag set. 16 | func InitConfig(cmd *cobra.Command) error { 17 | home, err := cmd.PersistentFlags().GetString(cli.HomeFlag) 18 | if err != nil { 19 | return err 20 | } 21 | 22 | configFile := filepath.Join(home, "config", "config.toml") 23 | _, err = os.Stat(configFile) 24 | if err != nil && !os.IsNotExist(err) { 25 | // Immediately return if the error isn't related to the file not existing. 26 | // See issue https://github.com/evmos/ethermint/issues/539 27 | return err 28 | } 29 | if err == nil { 30 | viper.SetConfigFile(configFile) 31 | 32 | if err := viper.ReadInConfig(); err != nil { 33 | return err 34 | } 35 | } 36 | 37 | if err := viper.BindPFlag(flags.FlagChainID, cmd.PersistentFlags().Lookup(flags.FlagChainID)); err != nil { 38 | return err 39 | } 40 | 41 | if err := viper.BindPFlag(cli.EncodingFlag, cmd.PersistentFlags().Lookup(cli.EncodingFlag)); err != nil { 42 | return err 43 | } 44 | 45 | return viper.BindPFlag(cli.OutputFlag, cmd.PersistentFlags().Lookup(cli.OutputFlag)) 46 | } 47 | -------------------------------------------------------------------------------- /client/config_test.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | "testing" 7 | 8 | "github.com/spf13/cobra" 9 | 10 | "github.com/cosmos/cosmos-sdk/client/flags" 11 | ) 12 | 13 | func TestInitConfigNonNotExistError(t *testing.T) { 14 | tempDir := t.TempDir() 15 | subDir := filepath.Join(tempDir, "nonPerms") 16 | if err := os.Mkdir(subDir, 0o600); err != nil { 17 | t.Fatalf("Failed to create sub directory: %v", err) 18 | } 19 | cmd := &cobra.Command{} 20 | cmd.PersistentFlags().String(flags.FlagHome, "", "") 21 | if err := cmd.PersistentFlags().Set(flags.FlagHome, subDir); err != nil { 22 | t.Fatalf("Could not set home flag [%T] %v", err, err) 23 | } 24 | 25 | if err := InitConfig(cmd); !os.IsPermission(err) { 26 | t.Fatalf("Failed to catch permissions error, got: [%T] %v", err, err) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /client/context.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/client" // import the original package 5 | ) 6 | 7 | // EVMContext embeds the original Context and adds your own field 8 | type EVMContext struct { 9 | client.Context // Embedding the original Context 10 | EVMChainID uint64 `json:"evm_chain_id"` 11 | } 12 | 13 | func (ctx EVMContext) WithEVMChainID(evmChainID uint64) EVMContext { 14 | return EVMContext{ 15 | Context: ctx.Context, 16 | EVMChainID: evmChainID, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /client/keys/utils.go: -------------------------------------------------------------------------------- 1 | package keys 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | 8 | "sigs.k8s.io/yaml" 9 | 10 | "github.com/cosmos/cosmos-sdk/client/keys" 11 | cryptokeyring "github.com/cosmos/cosmos-sdk/crypto/keyring" 12 | ) 13 | 14 | // available output formats. 15 | const ( 16 | OutputFormatText = "text" 17 | OutputFormatJSON = "json" 18 | ) 19 | 20 | type bechKeyOutFn func(k *cryptokeyring.Record) (keys.KeyOutput, error) 21 | 22 | func printKeyringRecord(w io.Writer, k *cryptokeyring.Record, bechKeyOut bechKeyOutFn, output string) error { 23 | ko, err := bechKeyOut(k) 24 | if err != nil { 25 | return err 26 | } 27 | 28 | switch output { 29 | case OutputFormatText: 30 | if err := printTextRecords(w, []keys.KeyOutput{ko}); err != nil { 31 | return err 32 | } 33 | 34 | case OutputFormatJSON: 35 | out, err := json.Marshal(ko) 36 | if err != nil { 37 | return err 38 | } 39 | 40 | if _, err := fmt.Fprintln(w, string(out)); err != nil { 41 | return err 42 | } 43 | } 44 | 45 | return nil 46 | } 47 | 48 | func printTextRecords(w io.Writer, kos []keys.KeyOutput) error { 49 | out, err := yaml.Marshal(&kos) 50 | if err != nil { 51 | return err 52 | } 53 | 54 | if _, err := fmt.Fprintln(w, string(out)); err != nil { 55 | return err 56 | } 57 | 58 | return nil 59 | } 60 | -------------------------------------------------------------------------------- /cmd/evmd/config/chain_id.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "path/filepath" 5 | 6 | "github.com/spf13/viper" 7 | 8 | "github.com/cosmos/cosmos-sdk/client/config" 9 | ) 10 | 11 | // GetChainIDFromHome returns the chain ID from the client configuration 12 | // in the given home directory. 13 | func GetChainIDFromHome(home string) (string, error) { 14 | v := viper.New() 15 | v.AddConfigPath(filepath.Join(home, "config")) 16 | v.SetConfigName("client") 17 | v.SetConfigType("toml") 18 | 19 | if err := v.ReadInConfig(); err != nil { 20 | return "", err 21 | } 22 | conf := new(config.ClientConfig) 23 | 24 | if err := v.Unmarshal(conf); err != nil { 25 | return "", err 26 | } 27 | 28 | return conf.ChainID, nil 29 | } 30 | -------------------------------------------------------------------------------- /cmd/evmd/config/constants.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | const ( 4 | // ExampleChainDenom is the denomination of the Cosmos EVM example chain's base coin. 5 | ExampleChainDenom = "aatom" 6 | 7 | // ExampleDisplayDenom is the display denomination of the Cosmos EVM example chain's base coin. 8 | ExampleDisplayDenom = "atom" 9 | 10 | // EighteenDecimalsChainID is the chain ID for the 18 decimals chain. 11 | EighteenDecimalsChainID = 9001 12 | 13 | // SixDecimalsChainID is the chain ID for the 6 decimals chain. 14 | SixDecimalsChainID = 9002 15 | 16 | // TwelveDecimalsChainID is the chain ID for the 12 decimals chain. 17 | TwelveDecimalsChainID = 9003 18 | 19 | // TwoDecimalsChainID is the chain ID for the 2 decimals chain. 20 | TwoDecimalsChainID = 9004 21 | 22 | CosmosChainID = 262144 23 | 24 | // TestChainID1 is test chain IDs for IBC E2E test 25 | TestChainID1 = 9005 26 | // TestChainID2 is test chain IDs for IBC E2E test 27 | TestChainID2 = 9006 28 | 29 | // WEVMOSContractMainnet is the WEVMOS contract address for mainnet 30 | WEVMOSContractMainnet = "0xD4949664cD82660AaE99bEdc034a0deA8A0bd517" 31 | ) 32 | -------------------------------------------------------------------------------- /cmd/evmd/config/opendb.go: -------------------------------------------------------------------------------- 1 | //go:build !rocksdb 2 | // +build !rocksdb 3 | 4 | package config 5 | 6 | import ( 7 | "path/filepath" 8 | 9 | dbm "github.com/cosmos/cosmos-db" 10 | 11 | "github.com/cosmos/cosmos-sdk/server/types" 12 | ) 13 | 14 | // OpenDB opens a database based on the specified backend type. 15 | // It takes the home directory where the database data will be stored, along with the backend type. 16 | // It opens a database named "application" using the specified backend type and the data directory. 17 | // It returns the opened database and an error (if any). If the database opens successfully, the error will be nil. 18 | // 19 | // NOTE: this is included in builds without rocksdb. 20 | // When building the binary with rocksdb, the code in 'rocksdb.go' will be included 21 | // instead of this 22 | func OpenDB(_ types.AppOptions, home string, backendType dbm.BackendType) (dbm.DB, error) { 23 | dataDir := filepath.Join(home, "data") 24 | return dbm.NewDB("application", backendType, dataDir) 25 | } 26 | 27 | // OpenReadOnlyDB opens rocksdb backend in read-only mode. 28 | func OpenReadOnlyDB(home string, backendType dbm.BackendType) (dbm.DB, error) { 29 | return OpenDB(nil, home, backendType) 30 | } 31 | -------------------------------------------------------------------------------- /cmd/evmd/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/cosmos/evm/cmd/evmd/cmd" 8 | evmdconfig "github.com/cosmos/evm/cmd/evmd/config" 9 | examplechain "github.com/cosmos/evm/evmd" 10 | 11 | svrcmd "github.com/cosmos/cosmos-sdk/server/cmd" 12 | sdk "github.com/cosmos/cosmos-sdk/types" 13 | ) 14 | 15 | func main() { 16 | setupSDKConfig() 17 | 18 | rootCmd := cmd.NewRootCmd() 19 | if err := svrcmd.Execute(rootCmd, "evmd", examplechain.DefaultNodeHome); err != nil { 20 | fmt.Fprintln(rootCmd.OutOrStderr(), err) 21 | os.Exit(1) 22 | } 23 | } 24 | 25 | func setupSDKConfig() { 26 | config := sdk.GetConfig() 27 | evmdconfig.SetBech32Prefixes(config) 28 | config.Seal() 29 | } 30 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | # 2 | # This codecov.yml is the default configuration for 3 | # all repositories on Codecov. You may adjust the settings 4 | # below in your own codecov.yml in your repository. 5 | # 6 | coverage: 7 | precision: 2 8 | round: down 9 | range: 70...100 10 | 11 | status: 12 | # Learn more at https://docs.codecov.io/docs/commit-status 13 | project: 14 | default: 15 | threshold: 1% # allow this much decrease on project 16 | target: 90% 17 | changes: false 18 | 19 | comment: 20 | layout: "reach, diff, files" 21 | behavior: default # update if exists else create new 22 | require_changes: true 23 | 24 | ignore: 25 | - "**/*.md" 26 | - "cmd" 27 | - "client" 28 | - "proto" 29 | - "testutil" 30 | - "**/test_*.go" 31 | - "**/*.pb.go" 32 | - "**/*.pb.gw.go" 33 | - "x/**/module.go" 34 | - "scripts" 35 | - "ibc/testing" 36 | - "version" 37 | -------------------------------------------------------------------------------- /contracts/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled contracts 2 | artifacts/ 3 | 4 | # Cached files 5 | cache/ 6 | 7 | # Node modules 8 | node_modules/ 9 | -------------------------------------------------------------------------------- /contracts/erc20.go: -------------------------------------------------------------------------------- 1 | package contracts 2 | 3 | import ( 4 | _ "embed" 5 | 6 | contractutils "github.com/cosmos/evm/contracts/utils" 7 | evmtypes "github.com/cosmos/evm/x/vm/types" 8 | ) 9 | 10 | var ( 11 | // ERC20MinterBurnerDecimalsJSON are the compiled bytes of the ERC20MinterBurnerDecimalsContract 12 | // 13 | //go:embed solidity/ERC20MinterBurnerDecimals.json 14 | ERC20MinterBurnerDecimalsJSON []byte 15 | 16 | // ERC20MinterBurnerDecimalsContract is the compiled erc20 contract 17 | ERC20MinterBurnerDecimalsContract evmtypes.CompiledContract 18 | ) 19 | 20 | func init() { 21 | var err error 22 | if ERC20MinterBurnerDecimalsContract, err = contractutils.ConvertHardhatBytesToCompiledContract( 23 | ERC20MinterBurnerDecimalsJSON, 24 | ); err != nil { 25 | panic(err) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /contracts/hardhat.config.js: -------------------------------------------------------------------------------- 1 | /** @type import('hardhat/config').HardhatUserConfig */ 2 | module.exports = { 3 | solidity: { 4 | compilers: [ 5 | { 6 | version: "0.8.20", 7 | }, 8 | // This version is required to compile the werc9 contract. 9 | { 10 | version: "0.4.22", 11 | }, 12 | ], 13 | }, 14 | paths: { 15 | sources: "./solidity", 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /contracts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cosmos-evm-contracts", 3 | "version": "2.0.0", 4 | "description": "A collection of smart contracts used in the development of the Cosmos EVM blockchain.", 5 | "devDependencies": { 6 | "@openzeppelin/contracts": "^4.9.6", 7 | "hardhat": "^2.22.2" 8 | }, 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/cosmos/evm.git" 15 | }, 16 | "author": "Evmos Core Team", 17 | "license": "ISC", 18 | "bugs": { 19 | "url": "https://github.com/cosmos/evm/issues" 20 | }, 21 | "homepage": "https://github.com/cosmos/evm#readme" 22 | } 23 | -------------------------------------------------------------------------------- /contracts/solidity/WATOM.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | contract WATOM { 5 | string public name = "Wrapped Atom"; 6 | string public symbol = "WATOM"; 7 | uint8 public decimals = 18; 8 | 9 | mapping(address => uint256) public balanceOf; 10 | 11 | event Deposit(address indexed dst, uint256 amount); 12 | event Withdrawal(address indexed src, uint256 amount); 13 | event Transfer(address indexed src, address indexed dst, uint256 amount); 14 | 15 | // Receive ether and wrap it into ATOM 16 | receive() external payable { 17 | deposit(); 18 | } 19 | 20 | function deposit() public payable { 21 | balanceOf[msg.sender] += msg.value; 22 | emit Deposit(msg.sender, msg.value); 23 | } 24 | 25 | function withdraw(uint256 amount) public { 26 | require(balanceOf[msg.sender] >= amount, "insufficient balance"); 27 | balanceOf[msg.sender] -= amount; 28 | payable(msg.sender).transfer(amount); 29 | emit Withdrawal(msg.sender, amount); 30 | } 31 | 32 | function transfer(address to, uint256 amount) public returns (bool) { 33 | require(balanceOf[msg.sender] >= amount, "insufficient balance"); 34 | balanceOf[msg.sender] -= amount; 35 | balanceOf[to] += amount; 36 | emit Transfer(msg.sender, to, amount); 37 | return true; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /contracts/solidity/evmd/eips/testdata/Counter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-3.0-only 2 | 3 | pragma solidity >=0.7.0 <0.9.0; 4 | 5 | contract Counter { 6 | uint256 public counter = 1; 7 | 8 | function increment() external { 9 | counter++; 10 | } 11 | 12 | function decrement() external { 13 | counter--; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /contracts/solidity/evmd/eips/testdata/CounterFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-3.0-only 2 | 3 | pragma solidity >=0.7.0 <0.9.0; 4 | 5 | import "./Counter.sol"; 6 | 7 | contract Counterfactory { 8 | Counter public counterInstance; 9 | 10 | constructor() { 11 | counterInstance = new Counter(); 12 | } 13 | 14 | function incrementCounter() public { 15 | counterInstance.increment(); 16 | } 17 | 18 | function decrementCounter() public { 19 | counterInstance.decrement(); 20 | } 21 | 22 | function getCounterValue() public view returns (uint256) { 23 | return counterInstance.counter(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /contracts/solidity/precompiles/bank/testdata/BankCaller.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-3.0-only 2 | pragma solidity >=0.8.18; 3 | 4 | import "../IBank.sol"; 5 | 6 | contract BankCaller { 7 | 8 | function callBalances(address account) external view returns (Balance[] memory balances) { 9 | return IBANK_CONTRACT.balances(account); 10 | } 11 | 12 | function callTotalSupply() external view returns (Balance[] memory totalSupply) { 13 | return IBANK_CONTRACT.totalSupply(); 14 | } 15 | 16 | function callSupplyOf(address erc20Address) external view returns (uint256) { 17 | return IBANK_CONTRACT.supplyOf(erc20Address); 18 | } 19 | } -------------------------------------------------------------------------------- /contracts/solidity/precompiles/erc20/IERC20Metadata.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | import "./IERC20.sol"; 7 | 8 | /** 9 | * @dev Interface for the optional metadata functions from the ERC20 standard. 10 | * 11 | * _Available since v4.1._ 12 | */ 13 | interface IERC20Metadata is IERC20 { 14 | /** 15 | * @dev Returns the name of the token. 16 | */ 17 | function name() external view returns (string memory); 18 | 19 | /** 20 | * @dev Returns the symbol of the token. 21 | */ 22 | function symbol() external view returns (string memory); 23 | 24 | /** 25 | * @dev Returns the decimals places of the token. 26 | */ 27 | function decimals() external view returns (uint8); 28 | } 29 | -------------------------------------------------------------------------------- /contracts/solidity/precompiles/testutil/contracts/Counter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity >=0.7.0 <0.9.0; 4 | 5 | contract Counter { 6 | uint256 counter = 0; 7 | string internal constant ERROR_TOO_LOW = "COUNTER_TOO_LOW"; 8 | event Changed(uint256 counter); 9 | event Added(uint256 counter); 10 | 11 | function add() public { 12 | counter++; 13 | emit Added(counter); 14 | emit Changed(counter); 15 | } 16 | 17 | function subtract() public { 18 | require(counter > 0, ERROR_TOO_LOW); 19 | counter--; 20 | emit Changed(counter); 21 | } 22 | 23 | function getCounter() public view returns (uint256) { 24 | return counter; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /contracts/solidity/precompiles/testutil/contracts/ICounter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.17; 2 | 3 | interface ICounter { 4 | function add() external; 5 | function subtract() external; 6 | function getCounter() external view returns (uint256); 7 | event Changed(uint256 counter); 8 | event Added(uint256 counter); 9 | } 10 | -------------------------------------------------------------------------------- /contracts/solidity/precompiles/werc20/testdata/WEVMOS9TestCaller.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-3.0-only 2 | pragma solidity >=0.8.17; 3 | 4 | import "../IWERC20.sol"; 5 | 6 | contract WEVMOS9TestCaller { 7 | address payable public immutable WEVMOS; 8 | uint256 public counter; 9 | 10 | constructor(address payable _wrappedTokenAddress) { 11 | WEVMOS = _wrappedTokenAddress; 12 | counter = 0; 13 | } 14 | 15 | event Log(string message); 16 | 17 | function depositWithRevert(bool before, bool aft) public payable { 18 | counter++; 19 | 20 | uint amountIn = msg.value; 21 | IWERC20(WEVMOS).deposit{value: amountIn}(); 22 | 23 | if (before) { 24 | require(false, "revert here"); 25 | } 26 | 27 | counter--; 28 | 29 | if (aft) { 30 | require(false, "revert here"); 31 | } 32 | return; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /contracts/solidity/x/erc20/keeper/testdata/ERC20DirectBalanceManipulation.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol"; 6 | 7 | // This is an evil token. Whenever an A -> B transfer is called, half of the amount goes to B 8 | // and half to a predefined C 9 | contract ERC20DirectBalanceManipulation is ERC20PresetMinterPauser { 10 | address private _thief = 0x4dC6ac40Af078661fc43823086E1513635Eeab14; 11 | constructor(uint256 initialSupply) 12 | ERC20PresetMinterPauser("ERC20DirectBalanceManipulation", "ERC20DirectBalanceManipulation") { 13 | _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); 14 | _mint(msg.sender, initialSupply); 15 | } 16 | function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 17 | // Any time a transaction happens, the thief account siphons half. 18 | uint256 half = amount / 2; 19 | 20 | super.transfer(_thief, amount - half); // a - h for rounding 21 | return super.transfer(recipient, half); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /contracts/solidity/x/erc20/keeper/testdata/ERC20MaliciousDelayed.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol"; 6 | 7 | // This is an evil token. Whenever an A -> B transfer is called, 8 | // a predefined C is given a massive allowance on B. 9 | contract ERC20MaliciousDelayed is ERC20PresetMinterPauser { 10 | address private _thief = 0x4dC6ac40Af078661fc43823086E1513635Eeab14; 11 | uint256 private _bigNum = 1000000000000000000; // ~uint256(0) 12 | constructor(uint256 initialSupply) 13 | ERC20PresetMinterPauser("ERC20MaliciousDelayed", "ERC20MALICIOUSDELAYED") { 14 | _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); 15 | _mint(msg.sender, initialSupply); 16 | 17 | } 18 | function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 19 | // Any time a transaction happens, the thief account is granted allowance in secret. 20 | // Still emits an Approve! 21 | super._approve(recipient, _thief, _bigNum); 22 | return super.transfer(recipient, amount); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /contracts/watom.go: -------------------------------------------------------------------------------- 1 | package contracts 2 | 3 | import ( 4 | _ "embed" 5 | 6 | contractutils "github.com/cosmos/evm/contracts/utils" 7 | evmtypes "github.com/cosmos/evm/x/vm/types" 8 | ) 9 | 10 | var ( 11 | // WATOMJSON are the compiled bytes of the WATOMContract 12 | // 13 | //go:embed solidity/WATOM.json 14 | WATOMJSON []byte 15 | 16 | // WATOMContract is the compiled watom contract 17 | WATOMContract evmtypes.CompiledContract 18 | ) 19 | 20 | func init() { 21 | var err error 22 | if WATOMContract, err = contractutils.ConvertHardhatBytesToCompiledContract( 23 | WATOMJSON, 24 | ); err != nil { 25 | panic(err) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /crypto/codec/amino.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | import ( 4 | "github.com/cosmos/evm/crypto/ethsecp256k1" 5 | 6 | "github.com/cosmos/cosmos-sdk/codec" 7 | "github.com/cosmos/cosmos-sdk/codec/legacy" 8 | cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" 9 | "github.com/cosmos/cosmos-sdk/crypto/keyring" 10 | ) 11 | 12 | // RegisterCrypto registers all crypto dependency types with the provided Amino 13 | // codec. 14 | func RegisterCrypto(cdc *codec.LegacyAmino) { 15 | cdc.RegisterConcrete(ðsecp256k1.PubKey{}, 16 | ethsecp256k1.PubKeyName, nil) 17 | cdc.RegisterConcrete(ðsecp256k1.PrivKey{}, 18 | ethsecp256k1.PrivKeyName, nil) 19 | 20 | keyring.RegisterLegacyAminoCodec(cdc) 21 | cryptocodec.RegisterCrypto(cdc) 22 | 23 | // NOTE: update SDK's amino codec to include the ethsecp256k1 keys. 24 | // DO NOT REMOVE unless deprecated on the SDK. 25 | legacy.Cdc = cdc 26 | } 27 | -------------------------------------------------------------------------------- /crypto/codec/codec.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | import ( 4 | "github.com/cosmos/evm/crypto/ethsecp256k1" 5 | 6 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 7 | cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" 8 | ) 9 | 10 | // RegisterInterfaces register the Cosmos EVM key concrete types. 11 | func RegisterInterfaces(registry codectypes.InterfaceRegistry) { 12 | registry.RegisterImplementations((*cryptotypes.PubKey)(nil), ðsecp256k1.PubKey{}) 13 | registry.RegisterImplementations((*cryptotypes.PrivKey)(nil), ðsecp256k1.PrivKey{}) 14 | } 15 | -------------------------------------------------------------------------------- /crypto/ethsecp256k1/benchmark_test.go: -------------------------------------------------------------------------------- 1 | package ethsecp256k1 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func BenchmarkGenerateKey(b *testing.B) { 9 | b.ReportAllocs() 10 | for i := 0; i < b.N; i++ { 11 | if _, err := GenerateKey(); err != nil { 12 | b.Fatal(err) 13 | } 14 | } 15 | } 16 | 17 | func BenchmarkPubKey_VerifySignature(b *testing.B) { 18 | privKey, err := GenerateKey() 19 | if err != nil { 20 | b.Fatal(err) 21 | } 22 | pubKey := privKey.PubKey() 23 | 24 | b.ResetTimer() 25 | b.ReportAllocs() 26 | for i := 0; i < b.N; i++ { 27 | msg := []byte(fmt.Sprintf("%10d", i)) 28 | sig, err := privKey.Sign(msg) 29 | if err != nil { 30 | b.Fatal(err) 31 | } 32 | pubKey.VerifySignature(msg, sig) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /crypto/hd/benchmark_test.go: -------------------------------------------------------------------------------- 1 | package hd 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/cosmos/evm/types" 7 | 8 | "github.com/cosmos/cosmos-sdk/crypto/keyring" 9 | ) 10 | 11 | func BenchmarkEthSecp256k1Algo_Derive(b *testing.B) { 12 | b.ReportAllocs() 13 | for i := 0; i < b.N; i++ { 14 | deriveFn := EthSecp256k1.Derive() 15 | if _, err := deriveFn(mnemonic, keyring.DefaultBIP39Passphrase, types.BIP44HDPath); err != nil { 16 | b.Fatal(err) 17 | } 18 | } 19 | } 20 | 21 | func BenchmarkEthSecp256k1Algo_Generate(b *testing.B) { 22 | bz, err := EthSecp256k1.Derive()(mnemonic, keyring.DefaultBIP39Passphrase, types.BIP44HDPath) 23 | if err != nil { 24 | b.Fatal(err) 25 | } 26 | 27 | b.ResetTimer() 28 | b.ReportAllocs() 29 | for i := 0; i < b.N; i++ { 30 | (ðSecp256k1Algo{}).Generate()(bz) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /encoding/codec/codec.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | import ( 4 | cryptocodec "github.com/cosmos/evm/crypto/codec" 5 | "github.com/cosmos/evm/types" 6 | 7 | "github.com/cosmos/cosmos-sdk/codec" 8 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 9 | "github.com/cosmos/cosmos-sdk/std" 10 | sdk "github.com/cosmos/cosmos-sdk/types" 11 | ) 12 | 13 | // RegisterLegacyAminoCodec registers Interfaces from types, crypto, and SDK std. 14 | func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { 15 | sdk.RegisterLegacyAminoCodec(cdc) 16 | cryptocodec.RegisterCrypto(cdc) 17 | codec.RegisterEvidences(cdc) 18 | } 19 | 20 | // RegisterInterfaces registers Interfaces from types, crypto, and SDK std. 21 | func RegisterInterfaces(interfaceRegistry codectypes.InterfaceRegistry) { 22 | std.RegisterInterfaces(interfaceRegistry) 23 | cryptocodec.RegisterInterfaces(interfaceRegistry) 24 | types.RegisterInterfaces(interfaceRegistry) 25 | } 26 | -------------------------------------------------------------------------------- /encoding/config_test.go: -------------------------------------------------------------------------------- 1 | package encoding_test 2 | 3 | import ( 4 | "math/big" 5 | "testing" 6 | 7 | ethtypes "github.com/ethereum/go-ethereum/core/types" 8 | "github.com/stretchr/testify/require" 9 | 10 | "github.com/cosmos/evm/encoding" 11 | utiltx "github.com/cosmos/evm/testutil/tx" 12 | evmtypes "github.com/cosmos/evm/x/vm/types" 13 | ) 14 | 15 | func TestTxEncoding(t *testing.T) { 16 | addr, key := utiltx.NewAddrKey() 17 | signer := utiltx.NewSigner(key) 18 | 19 | ethTxParams := evmtypes.EvmTxArgs{ 20 | ChainID: big.NewInt(1), 21 | Nonce: 1, 22 | Amount: big.NewInt(10), 23 | GasLimit: 100000, 24 | GasFeeCap: big.NewInt(1), 25 | GasTipCap: big.NewInt(1), 26 | Input: []byte{}, 27 | } 28 | msg := evmtypes.NewTx(ðTxParams) 29 | msg.From = addr.Hex() 30 | 31 | ethSigner := ethtypes.LatestSignerForChainID(big.NewInt(1)) 32 | err := msg.Sign(ethSigner, signer) 33 | require.NoError(t, err) 34 | 35 | cfg := encoding.MakeConfig(big.NewInt(1).Uint64()) 36 | 37 | _, err = cfg.TxConfig.TxEncoder()(msg) 38 | require.Error(t, err, "encoding failed") 39 | 40 | // FIXME: transaction hashing is hardcoded on Tendermint: 41 | // See https://github.com/cometbft/cometbft/issues/6539 for reference 42 | // txHash := msg.AsTransaction().Hash() 43 | // tmTx := cmttypes.Tx(bz) 44 | 45 | // require.Equal(t, txHash.Bytes(), tmTx.Hash()) 46 | } 47 | -------------------------------------------------------------------------------- /ethereum/eip712/domain.go: -------------------------------------------------------------------------------- 1 | package eip712 2 | 3 | import ( 4 | "github.com/ethereum/go-ethereum/common/math" 5 | "github.com/ethereum/go-ethereum/signer/core/apitypes" 6 | ) 7 | 8 | // createEIP712Domain creates the typed data domain for the given chainID. 9 | func createEIP712Domain(chainID uint64) apitypes.TypedDataDomain { 10 | domain := apitypes.TypedDataDomain{ 11 | Name: "Cosmos Web3", 12 | Version: "1.0.0", 13 | ChainId: math.NewHexOrDecimal256(int64(chainID)), // #nosec G115 14 | VerifyingContract: "cosmos", 15 | Salt: "0", 16 | } 17 | 18 | return domain 19 | } 20 | -------------------------------------------------------------------------------- /ethereum/eip712/eip712.go: -------------------------------------------------------------------------------- 1 | package eip712 2 | 3 | import ( 4 | "github.com/ethereum/go-ethereum/signer/core/apitypes" 5 | ) 6 | 7 | // WrapTxToTypedData wraps an Amino-encoded Cosmos Tx JSON SignDoc 8 | // bytestream into an EIP712-compatible TypedData request. 9 | func WrapTxToTypedData( 10 | chainID uint64, 11 | data []byte, 12 | ) (apitypes.TypedData, error) { 13 | messagePayload, err := createEIP712MessagePayload(data) 14 | message := messagePayload.message 15 | if err != nil { 16 | return apitypes.TypedData{}, err 17 | } 18 | 19 | types, err := createEIP712Types(messagePayload) 20 | if err != nil { 21 | return apitypes.TypedData{}, err 22 | } 23 | 24 | domain := createEIP712Domain(chainID) 25 | 26 | typedData := apitypes.TypedData{ 27 | Types: types, 28 | PrimaryType: txField, 29 | Domain: domain, 30 | Message: message, 31 | } 32 | 33 | return typedData, nil 34 | } 35 | -------------------------------------------------------------------------------- /evmd/activators.go: -------------------------------------------------------------------------------- 1 | package evmd 2 | 3 | import ( 4 | "github.com/ethereum/go-ethereum/core/vm" 5 | 6 | "github.com/cosmos/evm/evmd/eips" 7 | ) 8 | 9 | // cosmosEVMActivators defines a map of opcode modifiers associated 10 | // with a key defining the corresponding EIP. 11 | var cosmosEVMActivators = map[int]func(*vm.JumpTable){ 12 | 0o000: eips.Enable0000, 13 | 0o001: eips.Enable0001, 14 | 0o002: eips.Enable0002, 15 | } 16 | -------------------------------------------------------------------------------- /evmd/ante/evm_handler.go: -------------------------------------------------------------------------------- 1 | package ante 2 | 3 | import ( 4 | evmante "github.com/cosmos/evm/ante/evm" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | ) 8 | 9 | // newMonoEVMAnteHandler creates the sdk.AnteHandler implementation for the EVM transactions. 10 | func newMonoEVMAnteHandler(options HandlerOptions) sdk.AnteHandler { 11 | return sdk.ChainAnteDecorators( 12 | evmante.NewEVMMonoDecorator( 13 | options.AccountKeeper, 14 | options.FeeMarketKeeper, 15 | options.EvmKeeper, 16 | options.MaxTxGasWanted, 17 | ), 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /evmd/config/client.toml: -------------------------------------------------------------------------------- 1 | # This is a TOML config file. 2 | # For more information, see https://github.com/toml-lang/toml 3 | 4 | ############################################################################### 5 | ### Client Configuration ### 6 | ############################################################################### 7 | 8 | # The network chain ID 9 | chain-id = "" 10 | # The keyring's backend, where the keys are stored (os|file|kwallet|pass|test|memory) 11 | keyring-backend = "os" 12 | # CLI output format (text|json) 13 | output = "text" 14 | # : to CometBFT RPC interface for this chain 15 | node = "tcp://localhost:26657" 16 | # Transaction broadcasting mode (sync|async) 17 | broadcast-mode = "sync" 18 | -------------------------------------------------------------------------------- /evmd/eips/eips.go: -------------------------------------------------------------------------------- 1 | package eips 2 | 3 | import ( 4 | "github.com/ethereum/go-ethereum/core/vm" 5 | ) 6 | 7 | var ( 8 | Multiplier = uint64(10) 9 | SstoreConstantGas = uint64(500) 10 | ) 11 | 12 | // enable0000 contains the logic to modify the CREATE and CREATE2 opcodes 13 | // constant gas value. 14 | func Enable0000(jt *vm.JumpTable) { 15 | currentValCreate := jt[vm.CREATE].GetConstantGas() 16 | jt[vm.CREATE].SetConstantGas(currentValCreate * Multiplier) 17 | 18 | currentValCreate2 := jt[vm.CREATE2].GetConstantGas() 19 | jt[vm.CREATE2].SetConstantGas(currentValCreate2 * Multiplier) 20 | } 21 | 22 | // enable0001 contains the logic to modify the CALL opcode 23 | // constant gas value. 24 | func Enable0001(jt *vm.JumpTable) { 25 | currentVal := jt[vm.CALL].GetConstantGas() 26 | jt[vm.CALL].SetConstantGas(currentVal * Multiplier) 27 | } 28 | 29 | // enable0002 contains the logic to modify the SSTORE opcode 30 | // constant gas value. 31 | func Enable0002(jt *vm.JumpTable) { 32 | jt[vm.SSTORE].SetConstantGas(SstoreConstantGas) 33 | } 34 | -------------------------------------------------------------------------------- /evmd/eips/testdata/Counter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-3.0-only 2 | 3 | pragma solidity >=0.7.0 <0.9.0; 4 | 5 | contract Counter { 6 | uint256 public counter = 1; 7 | 8 | function increment() external { 9 | counter++; 10 | } 11 | 12 | function decrement() external { 13 | counter--; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /evmd/eips/testdata/CounterFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-3.0-only 2 | 3 | pragma solidity >=0.7.0 <0.9.0; 4 | 5 | import "./Counter.sol"; 6 | 7 | contract Counterfactory { 8 | Counter public counterInstance; 9 | 10 | constructor() { 11 | counterInstance = new Counter(); 12 | } 13 | 14 | function incrementCounter() public { 15 | counterInstance.increment(); 16 | } 17 | 18 | function decrementCounter() public { 19 | counterInstance.decrement(); 20 | } 21 | 22 | function getCounterValue() public view returns (uint256) { 23 | return counterInstance.counter(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /evmd/eips/testdata/contracts.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import ( 4 | contractutils "github.com/cosmos/evm/contracts/utils" 5 | evmtypes "github.com/cosmos/evm/x/vm/types" 6 | ) 7 | 8 | func LoadCounterContract() (evmtypes.CompiledContract, error) { 9 | return contractutils.LoadContractFromJSONFile("Counter.json") 10 | } 11 | 12 | func LoadCounterFactoryContract() (evmtypes.CompiledContract, error) { 13 | return contractutils.LoadContractFromJSONFile("CounterFactory.json") 14 | } 15 | -------------------------------------------------------------------------------- /evmd/guide/add_network.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmos/evm/4f9b8c209314217a1dc8e6d5ff0674c87ed38768/evmd/guide/add_network.png -------------------------------------------------------------------------------- /evmd/guide/networks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmos/evm/4f9b8c209314217a1dc8e6d5ff0674c87ed38768/evmd/guide/networks.png -------------------------------------------------------------------------------- /evmd/guide/rpc_url.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmos/evm/4f9b8c209314217a1dc8e6d5ff0674c87ed38768/evmd/guide/rpc_url.png -------------------------------------------------------------------------------- /evmd/guide/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmos/evm/4f9b8c209314217a1dc8e6d5ff0674c87ed38768/evmd/guide/settings.png -------------------------------------------------------------------------------- /evmd/interfaces.go: -------------------------------------------------------------------------------- 1 | package evmd 2 | 3 | import ( 4 | cmn "github.com/cosmos/evm/precompiles/common" 5 | evmtypes "github.com/cosmos/evm/x/vm/types" 6 | ) 7 | 8 | type BankKeeper interface { 9 | evmtypes.BankKeeper 10 | cmn.BankKeeper 11 | } 12 | -------------------------------------------------------------------------------- /evmd/testutil/app.go: -------------------------------------------------------------------------------- 1 | package testutil 2 | 3 | func NoOpEvmAppOptions(_ uint64) error { 4 | return nil 5 | } 6 | -------------------------------------------------------------------------------- /evmd/testutil/gas.go: -------------------------------------------------------------------------------- 1 | package testutil 2 | 3 | import ( 4 | "cosmossdk.io/math" 5 | ) 6 | 7 | var ( 8 | // ExampleMinGasPrices defines 20B related to atto units as the minimum gas price value on the fee market module. 9 | // See https://commonwealth.im/evmos/discussion/5073-global-min-gas-price-value-for-cosmos-sdk-and-evm-transaction-choosing-a-value for reference 10 | ExampleMinGasPrices = math.LegacyNewDec(20_000_000_000) 11 | 12 | // ExampleMinGasMultiplier defines the min gas multiplier value on the fee market module. 13 | // 50% of the leftover gas will be refunded 14 | ExampleMinGasMultiplier = math.LegacyNewDecWithPrec(5, 1) 15 | ) 16 | -------------------------------------------------------------------------------- /evmd/upgrades.go: -------------------------------------------------------------------------------- 1 | package evmd 2 | 3 | func (app EVMD) RegisterUpgradeHandlers() { 4 | // No upgrades registered yet 5 | } 6 | -------------------------------------------------------------------------------- /ibc/errors.go: -------------------------------------------------------------------------------- 1 | package ibc 2 | 3 | import "errors" 4 | 5 | var ( 6 | ErrNoIBCVoucherDenom = errors.New("denom is not an IBC voucher") 7 | ErrDenomNotFound = errors.New("denom not found") 8 | ErrInvalidBaseDenom = errors.New("invalid base denomination") 9 | ) 10 | -------------------------------------------------------------------------------- /ibc/testing/testing_app.go: -------------------------------------------------------------------------------- 1 | package ibctesting 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | dbm "github.com/cosmos/cosmos-db" 7 | "github.com/cosmos/evm/evmd" 8 | feemarkettypes "github.com/cosmos/evm/x/feemarket/types" 9 | ibctesting "github.com/cosmos/ibc-go/v10/testing" 10 | 11 | "cosmossdk.io/log" 12 | 13 | simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" 14 | ) 15 | 16 | func SetupExampleApp() (ibctesting.TestingApp, map[string]json.RawMessage) { 17 | app := evmd.NewExampleApp( 18 | log.NewNopLogger(), 19 | dbm.NewMemDB(), 20 | nil, 21 | true, 22 | simtestutil.EmptyAppOptions{}, 23 | 9001, 24 | evmd.EvmAppOptions, 25 | ) 26 | // disable base fee for testing 27 | genesisState := app.DefaultGenesis() 28 | fmGen := feemarkettypes.DefaultGenesisState() 29 | fmGen.Params.NoBaseFee = true 30 | genesisState[feemarkettypes.ModuleName] = app.AppCodec().MustMarshalJSON(fmGen) 31 | 32 | return app, genesisState 33 | } 34 | -------------------------------------------------------------------------------- /mlc_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "retryOn429": true, 3 | "retryCount": 3, 4 | "fallbackRetryDelay": "20s", 5 | "ignorePatterns": [ 6 | { 7 | "pattern": "^https://twitter.com/.*" 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /precompiles/bank/testdata/BankCaller.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-3.0-only 2 | pragma solidity >=0.8.18; 3 | 4 | import "../IBank.sol"; 5 | 6 | contract BankCaller { 7 | 8 | function callBalances(address account) external view returns (Balance[] memory balances) { 9 | return IBANK_CONTRACT.balances(account); 10 | } 11 | 12 | function callTotalSupply() external view returns (Balance[] memory totalSupply) { 13 | return IBANK_CONTRACT.totalSupply(); 14 | } 15 | 16 | function callSupplyOf(address erc20Address) external view returns (uint256) { 17 | return IBANK_CONTRACT.supplyOf(erc20Address); 18 | } 19 | } -------------------------------------------------------------------------------- /precompiles/bank/testdata/bank.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import ( 4 | contractutils "github.com/cosmos/evm/contracts/utils" 5 | evmtypes "github.com/cosmos/evm/x/vm/types" 6 | ) 7 | 8 | func LoadBankCallerContract() (evmtypes.CompiledContract, error) { 9 | return contractutils.LoadContractFromJSONFile("BankCaller.json") 10 | } 11 | -------------------------------------------------------------------------------- /precompiles/bank/types.go: -------------------------------------------------------------------------------- 1 | package bank 2 | 3 | import ( 4 | "fmt" 5 | "math/big" 6 | 7 | "github.com/ethereum/go-ethereum/common" 8 | 9 | cmn "github.com/cosmos/evm/precompiles/common" 10 | 11 | sdk "github.com/cosmos/cosmos-sdk/types" 12 | ) 13 | 14 | // Balance contains the amount for a corresponding ERC-20 contract address. 15 | type Balance struct { 16 | ContractAddress common.Address 17 | Amount *big.Int 18 | } 19 | 20 | // ParseBalancesArgs parses the call arguments for the bank Balances query. 21 | func ParseBalancesArgs(args []interface{}) (sdk.AccAddress, error) { 22 | if len(args) != 1 { 23 | return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 1, len(args)) 24 | } 25 | 26 | account, ok := args[0].(common.Address) 27 | if !ok { 28 | return nil, fmt.Errorf(cmn.ErrInvalidType, "account", common.Address{}, args[0]) 29 | } 30 | 31 | return account.Bytes(), nil 32 | } 33 | 34 | // ParseSupplyOfArgs parses the call arguments for the bank SupplyOf query. 35 | func ParseSupplyOfArgs(args []interface{}) (common.Address, error) { 36 | if len(args) != 1 { 37 | return common.Address{}, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 1, len(args)) 38 | } 39 | 40 | erc20Address, ok := args[0].(common.Address) 41 | if !ok { 42 | return common.Address{}, fmt.Errorf(cmn.ErrInvalidType, "erc20Address", common.Address{}, args[0]) 43 | } 44 | 45 | return erc20Address, nil 46 | } 47 | -------------------------------------------------------------------------------- /precompiles/bech32/abi.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-artifact-1", 3 | "contractName": "Bech32I", 4 | "sourceName": "solidity/precompiles/bech32/Bech32I.sol", 5 | "abi": [ 6 | { 7 | "inputs": [ 8 | { 9 | "internalType": "string", 10 | "name": "bech32Address", 11 | "type": "string" 12 | } 13 | ], 14 | "name": "bech32ToHex", 15 | "outputs": [ 16 | { 17 | "internalType": "address", 18 | "name": "addr", 19 | "type": "address" 20 | } 21 | ], 22 | "stateMutability": "nonpayable", 23 | "type": "function" 24 | }, 25 | { 26 | "inputs": [ 27 | { 28 | "internalType": "address", 29 | "name": "addr", 30 | "type": "address" 31 | }, 32 | { 33 | "internalType": "string", 34 | "name": "prefix", 35 | "type": "string" 36 | } 37 | ], 38 | "name": "hexToBech32", 39 | "outputs": [ 40 | { 41 | "internalType": "string", 42 | "name": "bech32Address", 43 | "type": "string" 44 | } 45 | ], 46 | "stateMutability": "nonpayable", 47 | "type": "function" 48 | } 49 | ], 50 | "bytecode": "0x", 51 | "deployedBytecode": "0x", 52 | "linkReferences": {}, 53 | "deployedLinkReferences": {} 54 | } 55 | -------------------------------------------------------------------------------- /precompiles/bech32/setup_test.go: -------------------------------------------------------------------------------- 1 | package bech32_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/suite" 7 | 8 | "github.com/cosmos/evm/precompiles/bech32" 9 | testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" 10 | "github.com/cosmos/evm/testutil/integration/os/network" 11 | ) 12 | 13 | var s *PrecompileTestSuite 14 | 15 | // PrecompileTestSuite is the implementation of the TestSuite interface for ERC20 precompile 16 | // unit tests. 17 | type PrecompileTestSuite struct { 18 | suite.Suite 19 | 20 | network *network.UnitTestNetwork 21 | keyring testkeyring.Keyring 22 | 23 | precompile *bech32.Precompile 24 | } 25 | 26 | func TestPrecompileTestSuite(t *testing.T) { 27 | s = new(PrecompileTestSuite) 28 | suite.Run(t, s) 29 | } 30 | 31 | func (s *PrecompileTestSuite) SetupTest() { 32 | keyring := testkeyring.New(2) 33 | integrationNetwork := network.NewUnitTestNetwork( 34 | network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), 35 | ) 36 | 37 | s.keyring = keyring 38 | s.network = integrationNetwork 39 | 40 | precompile, err := bech32.NewPrecompile(6000) 41 | s.Require().NoError(err, "failed to create bech32 precompile") 42 | 43 | s.precompile = precompile 44 | } 45 | -------------------------------------------------------------------------------- /precompiles/common/interfaces.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "context" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | ) 8 | 9 | type BankKeeper interface { 10 | IterateAccountBalances(ctx context.Context, account sdk.AccAddress, cb func(coin sdk.Coin) bool) 11 | IterateTotalSupply(ctx context.Context, cb func(coin sdk.Coin) bool) 12 | GetSupply(ctx context.Context, denom string) sdk.Coin 13 | } 14 | -------------------------------------------------------------------------------- /precompiles/common/types_test.go: -------------------------------------------------------------------------------- 1 | package common_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | "github.com/cosmos/evm/precompiles/common" 9 | "github.com/cosmos/evm/testutil/constants" 10 | 11 | "cosmossdk.io/math" 12 | 13 | sdk "github.com/cosmos/cosmos-sdk/types" 14 | ) 15 | 16 | var largeAmt, _ = math.NewIntFromString("1000000000000000000000000000000000000000") 17 | 18 | func TestNewCoinsResponse(t *testing.T) { 19 | testCases := []struct { 20 | amount math.Int 21 | }{ 22 | {amount: math.NewInt(1)}, 23 | {amount: largeAmt}, 24 | } 25 | 26 | for _, tc := range testCases { 27 | coin := sdk.NewCoin(constants.ExampleAttoDenom, tc.amount) 28 | coins := sdk.NewCoins(coin) 29 | res := common.NewCoinsResponse(coins) 30 | require.Equal(t, 1, len(res)) 31 | require.Equal(t, tc.amount.BigInt(), res[0].Amount) 32 | } 33 | } 34 | 35 | func TestNewDecCoinsResponse(t *testing.T) { 36 | testCases := []struct { 37 | amount math.Int 38 | }{ 39 | {amount: math.NewInt(1)}, 40 | {amount: largeAmt}, 41 | } 42 | 43 | for _, tc := range testCases { 44 | coin := sdk.NewDecCoin(constants.ExampleAttoDenom, tc.amount) 45 | coins := sdk.NewDecCoins(coin) 46 | res := common.NewDecCoinsResponse(coins) 47 | require.Equal(t, 1, len(res)) 48 | require.Equal(t, tc.amount.BigInt(), res[0].Amount) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /precompiles/distribution/errors.go: -------------------------------------------------------------------------------- 1 | package distribution 2 | 3 | const ( 4 | // ErrDifferentValidator is raised when the origin address is not the same as the validator address. 5 | ErrDifferentValidator = "origin address %s is not the same as validator address %s" 6 | // ErrInvalidAmount is raised when the given sdk coins amount is invalid 7 | ErrInvalidAmount = "invalid amount %s" 8 | ) 9 | -------------------------------------------------------------------------------- /precompiles/erc20/IERC20Metadata.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | import "./IERC20.sol"; 7 | 8 | /** 9 | * @dev Interface for the optional metadata functions from the ERC20 standard. 10 | * 11 | * _Available since v4.1._ 12 | */ 13 | interface IERC20Metadata is IERC20 { 14 | /** 15 | * @dev Returns the name of the token. 16 | */ 17 | function name() external view returns (string memory); 18 | 19 | /** 20 | * @dev Returns the symbol of the token. 21 | */ 22 | function symbol() external view returns (string memory); 23 | 24 | /** 25 | * @dev Returns the decimals places of the token. 26 | */ 27 | function decimals() external view returns (uint8); 28 | } 29 | -------------------------------------------------------------------------------- /precompiles/erc20/errors_test.go: -------------------------------------------------------------------------------- 1 | package erc20_test 2 | 3 | import ( 4 | "github.com/cosmos/evm/precompiles/erc20" 5 | evmtypes "github.com/cosmos/evm/x/vm/types" 6 | ) 7 | 8 | // TODO: This is not yet producing the correct reason bytes so we skip this test for now, 9 | // until that's correctly implemented. 10 | func (s *PrecompileTestSuite) TestBuildExecRevertedError() { 11 | s.T().Skip("skipping until correctly implemented") 12 | 13 | reason := "ERC20: transfer amount exceeds balance" 14 | revErr, err := erc20.BuildExecRevertedErr(reason) 15 | s.Require().NoError(err, "should not error when building revert error") 16 | 17 | revertErr, ok := revErr.(*evmtypes.RevertError) 18 | s.Require().True(ok, "error should be a revert error") 19 | 20 | // Here we expect the correct revert reason that's returned by an ERC20 Solidity contract. 21 | s.Require().Equal( 22 | "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002645524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e63650000000000000000000000000000000000000000000000000000", 23 | revertErr.ErrorData(), 24 | "error data should be the revert reason") 25 | } 26 | -------------------------------------------------------------------------------- /precompiles/erc20/interfaces.go: -------------------------------------------------------------------------------- 1 | package erc20 2 | 3 | import ( 4 | "math/big" 5 | 6 | "github.com/ethereum/go-ethereum/common" 7 | 8 | sdk "github.com/cosmos/cosmos-sdk/types" 9 | ) 10 | 11 | // revive:disable-next-line exported 12 | type Erc20Keeper interface { 13 | GetAllowance(ctx sdk.Context, erc20 common.Address, owner common.Address, spender common.Address) (*big.Int, error) 14 | SetAllowance(ctx sdk.Context, erc20 common.Address, owner common.Address, spender common.Address, value *big.Int) error 15 | DeleteAllowance(ctx sdk.Context, erc20 common.Address, owner common.Address, spender common.Address) error 16 | } 17 | -------------------------------------------------------------------------------- /precompiles/erc20/testdata/ERC20Minter_OpenZeppelinV5.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // 3 | // Based on OpenZeppelin Contracts v5.0.0 (token/ERC20/ERC20.sol) 4 | // 5 | // NOTE: This was compiled using REMIX IDE. 6 | 7 | pragma solidity ^0.8.20; 8 | 9 | import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.0/contracts/token/ERC20/ERC20.sol"; 10 | 11 | /** 12 | * @dev {ERC20} token, including: 13 | * 14 | * - ability to mint tokens 15 | * 16 | * ATTENTION: This contract does not restrict minting tokens to any particular address 17 | * and should thus ONLY BE USED FOR TESTING. 18 | */ 19 | contract ERC20Minter_OpenZeppelinV5 is ERC20 { 20 | constructor(string memory name, string memory symbol) 21 | ERC20(name, symbol) {} 22 | 23 | function mint(address to, uint256 amount) public { 24 | _mint(to, amount); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /precompiles/erc20/testdata/erc20_allowance_caller.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import ( 4 | contractutils "github.com/cosmos/evm/contracts/utils" 5 | evmtypes "github.com/cosmos/evm/x/vm/types" 6 | ) 7 | 8 | func LoadERC20AllowanceCaller() (evmtypes.CompiledContract, error) { 9 | return contractutils.LoadContractFromJSONFile("ERC20AllowanceCaller.json") 10 | } 11 | -------------------------------------------------------------------------------- /precompiles/erc20/testdata/erc20_no_metadata.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import ( 4 | contractutils "github.com/cosmos/evm/contracts/utils" 5 | evmtypes "github.com/cosmos/evm/x/vm/types" 6 | ) 7 | 8 | func LoadERC20NoMetadataContract() (evmtypes.CompiledContract, error) { 9 | return contractutils.LoadContractFromJSONFile("ERC20NoMetadata.json") 10 | } 11 | -------------------------------------------------------------------------------- /precompiles/erc20/testdata/erc20_test_caller.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import ( 4 | contractutils "github.com/cosmos/evm/contracts/utils" 5 | evmtypes "github.com/cosmos/evm/x/vm/types" 6 | ) 7 | 8 | func LoadERC20TestCaller() (evmtypes.CompiledContract, error) { 9 | return contractutils.LoadContractFromJSONFile("ERC20TestCaller.json") 10 | } 11 | -------------------------------------------------------------------------------- /precompiles/erc20/testdata/erc20minter_openzeppelinv5.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import ( 4 | contractutils "github.com/cosmos/evm/contracts/utils" 5 | evmtypes "github.com/cosmos/evm/x/vm/types" 6 | ) 7 | 8 | func LoadERC20MinterV5Contract() (evmtypes.CompiledContract, error) { 9 | return contractutils.LegacyLoadContractFromJSONFile("ERC20Minter_OpenZeppelinV5.json") 10 | } 11 | -------------------------------------------------------------------------------- /precompiles/evidence/errors.go: -------------------------------------------------------------------------------- 1 | package evidence 2 | 3 | const ( 4 | // ErrInvalidEvidenceHash is raised when the evidence hash is invalid. 5 | ErrInvalidEvidenceHash = "invalid request; hash is empty" 6 | // ErrExpectedEquivocation is raised when the evidence is not an Equivocation. 7 | ErrExpectedEquivocation = "invalid evidence type: expected Equivocation" 8 | ) 9 | -------------------------------------------------------------------------------- /precompiles/evidence/tx.go: -------------------------------------------------------------------------------- 1 | package evidence 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/ethereum/go-ethereum/accounts/abi" 7 | "github.com/ethereum/go-ethereum/core/vm" 8 | 9 | cmn "github.com/cosmos/evm/precompiles/common" 10 | 11 | evidencekeeper "cosmossdk.io/x/evidence/keeper" 12 | 13 | sdk "github.com/cosmos/cosmos-sdk/types" 14 | ) 15 | 16 | // SubmitEvidence implements the evidence submission logic for the evidence precompile. 17 | func (p Precompile) SubmitEvidence( 18 | ctx sdk.Context, 19 | contract *vm.Contract, 20 | stateDB vm.StateDB, 21 | method *abi.Method, 22 | args []interface{}, 23 | ) ([]byte, error) { 24 | msg, submitterHexAddr, err := NewMsgSubmitEvidence(args) 25 | if err != nil { 26 | return nil, err 27 | } 28 | 29 | msgSender := contract.Caller() 30 | if msgSender != submitterHexAddr { 31 | return nil, fmt.Errorf(cmn.ErrRequesterIsNotMsgSender, msgSender.String(), submitterHexAddr.String()) 32 | } 33 | 34 | msgServer := evidencekeeper.NewMsgServerImpl(p.evidenceKeeper) 35 | res, err := msgServer.SubmitEvidence(ctx, msg) 36 | if err != nil { 37 | return nil, err 38 | } 39 | 40 | if err = p.EmitSubmitEvidenceEvent(ctx, stateDB, submitterHexAddr, res.Hash); err != nil { 41 | return nil, err 42 | } 43 | 44 | return method.Outputs.Pack(true) 45 | } 46 | -------------------------------------------------------------------------------- /precompiles/slashing/events.go: -------------------------------------------------------------------------------- 1 | package slashing 2 | 3 | import ( 4 | "github.com/ethereum/go-ethereum/common" 5 | ethtypes "github.com/ethereum/go-ethereum/core/types" 6 | "github.com/ethereum/go-ethereum/core/vm" 7 | 8 | cmn "github.com/cosmos/evm/precompiles/common" 9 | 10 | sdk "github.com/cosmos/cosmos-sdk/types" 11 | ) 12 | 13 | const ( 14 | // EventTypeValidatorUnjailed defines the event type for validator unjailing 15 | EventTypeValidatorUnjailed = "ValidatorUnjailed" 16 | ) 17 | 18 | // Add this struct after the existing constants 19 | type EventValidatorUnjailed struct { 20 | Validator common.Address 21 | } 22 | 23 | // EmitValidatorUnjailedEvent emits the ValidatorUnjailed event 24 | func (p Precompile) EmitValidatorUnjailedEvent(ctx sdk.Context, stateDB vm.StateDB, validator common.Address) error { 25 | // Prepare the event topics 26 | event := p.ABI.Events[EventTypeValidatorUnjailed] 27 | topics := make([]common.Hash, 2) 28 | 29 | // The first topic is always the signature of the event 30 | topics[0] = event.ID 31 | 32 | var err error 33 | topics[1], err = cmn.MakeTopic(validator) 34 | if err != nil { 35 | return err 36 | } 37 | 38 | stateDB.AddLog(ðtypes.Log{ 39 | Address: p.Address(), 40 | Topics: topics, 41 | BlockNumber: uint64(ctx.BlockHeight()), //nolint:gosec // G115 42 | }) 43 | 44 | return nil 45 | } 46 | -------------------------------------------------------------------------------- /precompiles/staking/errors.go: -------------------------------------------------------------------------------- 1 | package staking 2 | 3 | const ( 4 | // ErrNoDelegationFound is raised when no delegation is found for the given delegator and validator addresses. 5 | ErrNoDelegationFound = "delegation with delegator %s not found for validator %s" 6 | // ErrDifferentOriginFromValidator is raised when the origin address is not the same as the validator address. 7 | ErrDifferentOriginFromValidator = "origin address %s is not the same as validator operator address %s" 8 | // ErrCannotCallFromContract is raised when a function cannot be called from a smart contract. 9 | ErrCannotCallFromContract = "this method can only be called directly to the precompile, not from a smart contract" 10 | ) 11 | -------------------------------------------------------------------------------- /precompiles/staking/testdata/staking_caller.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import ( 4 | contractutils "github.com/cosmos/evm/contracts/utils" 5 | evmtypes "github.com/cosmos/evm/x/vm/types" 6 | ) 7 | 8 | func LoadStakingCallerContract() (evmtypes.CompiledContract, error) { 9 | return contractutils.LoadContractFromJSONFile("StakingCaller.json") 10 | } 11 | -------------------------------------------------------------------------------- /precompiles/staking/testdata/staking_caller_two.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import ( 4 | contractutils "github.com/cosmos/evm/contracts/utils" 5 | evmtypes "github.com/cosmos/evm/x/vm/types" 6 | ) 7 | 8 | func LoadStakingCallerTwoContract() (evmtypes.CompiledContract, error) { 9 | return contractutils.LoadContractFromJSONFile("StakingCallerTwo.json") 10 | } 11 | -------------------------------------------------------------------------------- /precompiles/testutil/contracts/Counter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity >=0.7.0 <0.9.0; 4 | 5 | contract Counter { 6 | uint256 counter = 0; 7 | string internal constant ERROR_TOO_LOW = "COUNTER_TOO_LOW"; 8 | event Changed(uint256 counter); 9 | event Added(uint256 counter); 10 | 11 | function add() public { 12 | counter++; 13 | emit Added(counter); 14 | emit Changed(counter); 15 | } 16 | 17 | function subtract() public { 18 | require(counter > 0, ERROR_TOO_LOW); 19 | counter--; 20 | emit Changed(counter); 21 | } 22 | 23 | function getCounter() public view returns (uint256) { 24 | return counter; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /precompiles/testutil/contracts/ICounter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.17; 2 | 3 | interface ICounter { 4 | function add() external; 5 | function subtract() external; 6 | function getCounter() external view returns (uint256); 7 | event Changed(uint256 counter); 8 | event Added(uint256 counter); 9 | } 10 | -------------------------------------------------------------------------------- /precompiles/testutil/contracts/counter.go: -------------------------------------------------------------------------------- 1 | package contracts 2 | 3 | import ( 4 | contractutils "github.com/cosmos/evm/contracts/utils" 5 | evmtypes "github.com/cosmos/evm/x/vm/types" 6 | ) 7 | 8 | func LoadCounterContract() (evmtypes.CompiledContract, error) { 9 | return contractutils.LoadContractFromJSONFile("Counter.json") 10 | } 11 | -------------------------------------------------------------------------------- /precompiles/testutil/contracts/distribution_caller.go: -------------------------------------------------------------------------------- 1 | package contracts 2 | 3 | import ( 4 | contractutils "github.com/cosmos/evm/contracts/utils" 5 | evmtypes "github.com/cosmos/evm/x/vm/types" 6 | ) 7 | 8 | func LoadDistributionCallerContract() (evmtypes.CompiledContract, error) { 9 | return contractutils.LoadContractFromJSONFile("DistributionCaller.json") 10 | } 11 | -------------------------------------------------------------------------------- /precompiles/testutil/contracts/flash_loan.go: -------------------------------------------------------------------------------- 1 | package contracts 2 | 3 | import ( 4 | contractutils "github.com/cosmos/evm/contracts/utils" 5 | evmtypes "github.com/cosmos/evm/x/vm/types" 6 | ) 7 | 8 | func LoadFlashLoanContract() (evmtypes.CompiledContract, error) { 9 | return contractutils.LoadContractFromJSONFile("FlashLoan.json") 10 | } 11 | -------------------------------------------------------------------------------- /precompiles/testutil/contracts/gov_caller.go: -------------------------------------------------------------------------------- 1 | package contracts 2 | 3 | import ( 4 | contractutils "github.com/cosmos/evm/contracts/utils" 5 | evmtypes "github.com/cosmos/evm/x/vm/types" 6 | ) 7 | 8 | func LoadGovCallerContract() (evmtypes.CompiledContract, error) { 9 | return contractutils.LoadContractFromJSONFile("GovCaller.json") 10 | } 11 | -------------------------------------------------------------------------------- /precompiles/testutil/contracts/interchain_sender.go: -------------------------------------------------------------------------------- 1 | package contracts 2 | 3 | import ( 4 | contractutils "github.com/cosmos/evm/contracts/utils" 5 | evmtypes "github.com/cosmos/evm/x/vm/types" 6 | ) 7 | 8 | func LoadInterchainSenderContract() (evmtypes.CompiledContract, error) { 9 | return contractutils.LoadContractFromJSONFile("InterchainSender.json") 10 | } 11 | -------------------------------------------------------------------------------- /precompiles/testutil/contracts/interchain_sender_caller.go: -------------------------------------------------------------------------------- 1 | package contracts 2 | 3 | import ( 4 | contractutils "github.com/cosmos/evm/contracts/utils" 5 | evmtypes "github.com/cosmos/evm/x/vm/types" 6 | ) 7 | 8 | func LoadInterchainSenderCallerContract() (evmtypes.CompiledContract, error) { 9 | return contractutils.LoadContractFromJSONFile("InterchainSenderCaller.json") 10 | } 11 | -------------------------------------------------------------------------------- /precompiles/testutil/contracts/reverter.go: -------------------------------------------------------------------------------- 1 | package contracts 2 | 3 | import ( 4 | contractutils "github.com/cosmos/evm/contracts/utils" 5 | evmtypes "github.com/cosmos/evm/x/vm/types" 6 | ) 7 | 8 | func LoadReverterContract() (evmtypes.CompiledContract, error) { 9 | return contractutils.LoadContractFromJSONFile("Reverter.json") 10 | } 11 | -------------------------------------------------------------------------------- /precompiles/testutil/contracts/staking_reverter.go: -------------------------------------------------------------------------------- 1 | package contracts 2 | 3 | import ( 4 | contractutils "github.com/cosmos/evm/contracts/utils" 5 | evmtypes "github.com/cosmos/evm/x/vm/types" 6 | ) 7 | 8 | func LoadStakingReverterContract() (evmtypes.CompiledContract, error) { 9 | return contractutils.LoadContractFromJSONFile("StakingReverter.json") 10 | } 11 | -------------------------------------------------------------------------------- /precompiles/testutil/errors.go: -------------------------------------------------------------------------------- 1 | package testutil 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | abci "github.com/cometbft/cometbft/abci/types" 8 | 9 | evmtypes "github.com/cosmos/evm/x/vm/types" 10 | ) 11 | 12 | // CheckVMError is a helper function used to check if the transaction is reverted with the expected error message 13 | // in the VmError field of the MsgEthereumResponse struct. 14 | func CheckVMError(res abci.ExecTxResult, expErrMsg string, args ...interface{}) error { 15 | if !res.IsOK() { 16 | return fmt.Errorf("code 0 was expected on response but got code %d", res.Code) 17 | } 18 | ethRes, err := evmtypes.DecodeTxResponse(res.Data) 19 | if err != nil { 20 | return fmt.Errorf("error occurred while decoding the TxResponse. %s", err) 21 | } 22 | expMsg := fmt.Sprintf(expErrMsg, args...) 23 | if !strings.Contains(ethRes.VmError, expMsg) { 24 | return fmt.Errorf("unexpected VmError on response. expected error to contain: %s, received: %s", expMsg, ethRes.VmError) 25 | } 26 | return nil 27 | } 28 | 29 | // CheckEthereumTxFailed checks if there is a VM error in the transaction response and returns the reason. 30 | func CheckEthereumTxFailed(ethRes *evmtypes.MsgEthereumTxResponse) (string, bool) { 31 | reason := ethRes.VmError 32 | return reason, reason != "" 33 | } 34 | -------------------------------------------------------------------------------- /precompiles/testutil/events.go: -------------------------------------------------------------------------------- 1 | package testutil 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/ethereum/go-ethereum/accounts/abi" 8 | ) 9 | 10 | // validateEvents checks if the provided event names are included as keys in the contract events. 11 | func validateEvents(contractEvents map[string]abi.Event, events []string) ([]abi.Event, error) { 12 | expEvents := make([]abi.Event, 0, len(events)) 13 | for _, eventStr := range events { 14 | event, found := contractEvents[eventStr] 15 | if !found { 16 | availableABIEvents := make([]string, 0, len(contractEvents)) 17 | for event := range contractEvents { 18 | availableABIEvents = append(availableABIEvents, event) 19 | } 20 | availableABIEventsStr := strings.Join(availableABIEvents, ", ") 21 | return nil, fmt.Errorf("unknown event %q is not contained in given ABI events:\n%s", eventStr, availableABIEventsStr) 22 | } 23 | expEvents = append(expEvents, event) 24 | } 25 | return expEvents, nil 26 | } 27 | -------------------------------------------------------------------------------- /precompiles/testutil/ibc.go: -------------------------------------------------------------------------------- 1 | package testutil 2 | 3 | import ( 4 | transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" 5 | ) 6 | 7 | var ( 8 | UosmoDenom = transfertypes.NewDenom("uosmo", transfertypes.NewHop(transfertypes.PortID, "channel-0")) 9 | UosmoIbcDenom = UosmoDenom.IBCDenom() 10 | 11 | UatomDenom = transfertypes.NewDenom("uatom", transfertypes.NewHop(transfertypes.PortID, "channel-1")) 12 | UatomIbcDenom = UatomDenom.IBCDenom() 13 | 14 | UAtomDenom = transfertypes.NewDenom("aatom", transfertypes.NewHop(transfertypes.PortID, "channel-0")) 15 | UAtomIbcDenom = UatomDenom.IBCDenom() 16 | 17 | UatomOsmoDenom = transfertypes.NewDenom( 18 | "uatom", 19 | transfertypes.NewHop(transfertypes.PortID, "channel-0"), 20 | transfertypes.NewHop(transfertypes.PortID, "channel-1"), 21 | ) 22 | UatomOsmoIbcDenom = UatomOsmoDenom.IBCDenom() 23 | 24 | AatomDenom = transfertypes.NewDenom("aatom", transfertypes.NewHop(transfertypes.PortID, "channel-0")) 25 | AatomIbcDenom = AatomDenom.IBCDenom() 26 | ) 27 | -------------------------------------------------------------------------------- /precompiles/testutil/testing.go: -------------------------------------------------------------------------------- 1 | package testutil 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/ethereum/go-ethereum/common" 7 | "github.com/ethereum/go-ethereum/core/vm" 8 | "github.com/holiman/uint256" 9 | "github.com/stretchr/testify/require" 10 | 11 | storetypes "cosmossdk.io/store/types" 12 | 13 | sdk "github.com/cosmos/cosmos-sdk/types" 14 | ) 15 | 16 | // NewPrecompileContract creates a new precompile contract and sets the gas meter. 17 | func NewPrecompileContract(t *testing.T, ctx sdk.Context, caller common.Address, precompile common.Address, 18 | gas uint64, 19 | ) (*vm.Contract, sdk.Context) { 20 | t.Helper() 21 | contract := vm.NewContract(caller, precompile, uint256.NewInt(0), gas, nil) 22 | ctx = ctx.WithGasMeter(storetypes.NewInfiniteGasMeter()) 23 | initialGas := ctx.GasMeter().GasConsumed() 24 | require.Equal(t, uint64(0), initialGas) 25 | return contract, ctx 26 | } 27 | -------------------------------------------------------------------------------- /precompiles/werc20/interfaces.go: -------------------------------------------------------------------------------- 1 | package werc20 2 | 3 | import ( 4 | "math/big" 5 | 6 | "github.com/ethereum/go-ethereum/common" 7 | 8 | sdk "github.com/cosmos/cosmos-sdk/types" 9 | ) 10 | 11 | type Erc20Keeper interface { 12 | GetAllowance(ctx sdk.Context, erc20 common.Address, owner common.Address, spender common.Address) (*big.Int, error) 13 | SetAllowance(ctx sdk.Context, erc20 common.Address, owner common.Address, spender common.Address, value *big.Int) error 14 | DeleteAllowance(ctx sdk.Context, erc20 common.Address, owner common.Address, spender common.Address) error 15 | } 16 | -------------------------------------------------------------------------------- /precompiles/werc20/testdata/WEVMOS9TestCaller.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-3.0-only 2 | pragma solidity >=0.8.17; 3 | 4 | import "../IWERC20.sol"; 5 | 6 | contract WEVMOS9TestCaller { 7 | address payable public immutable WEVMOS; 8 | uint256 public counter; 9 | 10 | constructor(address payable _wrappedTokenAddress) { 11 | WEVMOS = _wrappedTokenAddress; 12 | counter = 0; 13 | } 14 | 15 | event Log(string message); 16 | 17 | function depositWithRevert(bool before, bool aft) public payable { 18 | counter++; 19 | 20 | uint amountIn = msg.value; 21 | IWERC20(WEVMOS).deposit{value: amountIn}(); 22 | 23 | if (before) { 24 | require(false, "revert here"); 25 | } 26 | 27 | counter--; 28 | 29 | if (aft) { 30 | require(false, "revert here"); 31 | } 32 | return; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /precompiles/werc20/testdata/wevmos9.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import ( 4 | contractutils "github.com/cosmos/evm/contracts/utils" 5 | evmtypes "github.com/cosmos/evm/x/vm/types" 6 | ) 7 | 8 | // LoadWEVMOS9Contract load the WEVMOS9 contract from the json representation of 9 | // the Solidity contract. 10 | func LoadWEVMOS9Contract() (evmtypes.CompiledContract, error) { 11 | return contractutils.LoadContractFromJSONFile("WEVMOS9.json") 12 | } 13 | -------------------------------------------------------------------------------- /precompiles/werc20/testdata/wevmos9_test_caller.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import ( 4 | contractutils "github.com/cosmos/evm/contracts/utils" 5 | evmtypes "github.com/cosmos/evm/x/vm/types" 6 | ) 7 | 8 | func LoadWEVMOS9TestCaller() (evmtypes.CompiledContract, error) { 9 | return contractutils.LoadContractFromJSONFile("WEVMOS9TestCaller.json") 10 | } 11 | -------------------------------------------------------------------------------- /proto/buf.gen.gogo.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - name: gocosmos 4 | out: . 5 | opt: plugins=grpc,Mgoogle/protobuf/any.proto=github.com/cosmos/cosmos-sdk/codec/types 6 | - name: grpc-gateway 7 | out: . 8 | opt: logtostderr=true,allow_colon_final_segments=true 9 | -------------------------------------------------------------------------------- /proto/buf.gen.pulsar.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | managed: 3 | enabled: true 4 | go_package_prefix: 5 | default: cosmossdk.io/api 6 | except: 7 | - buf.build/googleapis/googleapis 8 | - buf.build/cosmos/gogo-proto 9 | - buf.build/cosmos/cosmos-proto 10 | override: 11 | plugins: 12 | - name: go-pulsar 13 | out: ../api 14 | opt: paths=source_relative 15 | - name: go-grpc 16 | out: ../api 17 | opt: paths=source_relative 18 | - name: go-cosmos-orm 19 | out: ../api 20 | opt: paths=source_relative 21 | -------------------------------------------------------------------------------- /proto/buf.lock: -------------------------------------------------------------------------------- 1 | # Generated by buf. DO NOT EDIT. 2 | version: v1 3 | deps: 4 | - remote: buf.build 5 | owner: cosmos 6 | repository: cosmos-proto 7 | commit: 1935555c206d4afb9e94615dfd0fad31 8 | - remote: buf.build 9 | owner: cosmos 10 | repository: cosmos-sdk 11 | commit: 508e19f5f37549e3a471a2a59b903c00 12 | - remote: buf.build 13 | owner: cosmos 14 | repository: gogo-proto 15 | commit: 34d970b699f84aa382f3c29773a60836 16 | - remote: buf.build 17 | owner: googleapis 18 | repository: googleapis 19 | commit: 783e4b5374fa488ab068d08af9658438 20 | -------------------------------------------------------------------------------- /proto/buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | name: buf.build/cosmos/evm 3 | deps: 4 | - buf.build/cosmos/cosmos-sdk 5 | - buf.build/cosmos/cosmos-proto 6 | - buf.build/cosmos/gogo-proto 7 | - buf.build/googleapis/googleapis 8 | lint: 9 | use: 10 | - DEFAULT 11 | - COMMENTS 12 | - FILE_LOWER_SNAKE_CASE 13 | except: 14 | - UNARY_RPC 15 | - COMMENT_FIELD 16 | - SERVICE_SUFFIX 17 | - PACKAGE_VERSION_SUFFIX 18 | - RPC_REQUEST_STANDARD_NAME 19 | - RPC_REQUEST_RESPONSE_UNIQUE 20 | - RPC_RESPONSE_STANDARD_NAME 21 | - RPC_REQUEST_RESPONSE_UNIQUE 22 | - COMMENT_MESSAGE 23 | - ENUM_ZERO_VALUE_SUFFIX 24 | breaking: 25 | use: 26 | - FILE 27 | -------------------------------------------------------------------------------- /proto/cosmos/evm/crypto/v1/ethsecp256k1/keys.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | package cosmos.evm.crypto.v1.ethsecp256k1; 4 | 5 | import "gogoproto/gogo.proto"; 6 | 7 | option go_package = "github.com/cosmos/evm/crypto/ethsecp256k1"; 8 | 9 | // PubKey defines a type alias for an ecdsa.PublicKey that implements 10 | // Tendermint's PubKey interface. It represents the 33-byte compressed public 11 | // key format. 12 | message PubKey { 13 | option (gogoproto.goproto_stringer) = false; 14 | 15 | // key is the public key in byte form 16 | bytes key = 1; 17 | } 18 | 19 | // PrivKey defines a type alias for an ecdsa.PrivateKey that implements 20 | // Tendermint's PrivateKey interface. 21 | message PrivKey { 22 | // key is the private key in byte form 23 | bytes key = 1; 24 | } 25 | -------------------------------------------------------------------------------- /proto/cosmos/evm/feemarket/v1/events.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | package cosmos.evm.feemarket.v1; 4 | 5 | option go_package = "github.com/cosmos/evm/x/feemarket/types"; 6 | 7 | // EventFeeMarket is the event type for the feemarket module 8 | message EventFeeMarket { 9 | // base_fee for EIP-1559 blocks 10 | string base_fee = 1; 11 | } 12 | 13 | // EventBlockGas defines an Ethereum block gas event 14 | message EventBlockGas { 15 | // height of the block 16 | string height = 1; 17 | // amount of gas wanted by the block 18 | string amount = 2; 19 | } 20 | -------------------------------------------------------------------------------- /proto/cosmos/evm/feemarket/v1/genesis.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | package cosmos.evm.feemarket.v1; 4 | 5 | import "amino/amino.proto"; 6 | import "gogoproto/gogo.proto"; 7 | import "cosmos/evm/feemarket/v1/feemarket.proto"; 8 | 9 | option go_package = "github.com/cosmos/evm/x/feemarket/types"; 10 | 11 | // GenesisState defines the feemarket module's genesis state. 12 | message GenesisState { 13 | // params defines all the parameters of the feemarket module. 14 | Params params = 1 15 | [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; 16 | // DEPRECATED: base fee is the exported value from previous software version. 17 | // Zero by default. 18 | reserved 2; 19 | reserved "base_fee"; 20 | // block_gas is the amount of gas wanted on the last block before the upgrade. 21 | // Zero by default. 22 | uint64 block_gas = 3; 23 | } 24 | -------------------------------------------------------------------------------- /proto/cosmos/evm/types/v1/dynamic_fee.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | package cosmos.evm.types.v1; 4 | 5 | import "amino/amino.proto"; 6 | import "gogoproto/gogo.proto"; 7 | 8 | option go_package = "github.com/cosmos/evm/types"; 9 | 10 | // ExtensionOptionDynamicFeeTx is an extension option that specifies the 11 | // maxPrioPrice for cosmos tx 12 | message ExtensionOptionDynamicFeeTx { 13 | // max_priority_price is the same as `max_priority_fee_per_gas` in eip-1559 14 | // spec 15 | string max_priority_price = 1 [ 16 | (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", 17 | (gogoproto.nullable) = false, 18 | (amino.dont_omitempty) = true 19 | ]; 20 | } 21 | -------------------------------------------------------------------------------- /proto/cosmos/evm/types/v1/indexer.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | package cosmos.evm.types.v1; 4 | 5 | import "gogoproto/gogo.proto"; 6 | 7 | option go_package = "github.com/cosmos/evm/types"; 8 | 9 | // TxResult is the value stored in eth tx indexer 10 | message TxResult { 11 | option (gogoproto.goproto_getters) = false; 12 | 13 | // height of the blockchain 14 | int64 height = 1; 15 | // tx_index of the cosmos transaction 16 | uint32 tx_index = 2; 17 | // msg_index in a batch transaction 18 | uint32 msg_index = 3; 19 | 20 | // eth_tx_index is the index in the list of valid eth tx in the block, 21 | // aka. the transaction list returned by eth_getBlock api. 22 | int32 eth_tx_index = 4; 23 | // failed is true if the eth transaction did not go succeed 24 | bool failed = 5; 25 | // gas_used by the transaction. If it exceeds the block gas limit, 26 | // it's set to gas limit, which is what's actually deducted by ante handler. 27 | uint64 gas_used = 6; 28 | // cumulative_gas_used specifies the cumulated amount of gas used for all 29 | // processed messages within the current batch transaction. 30 | uint64 cumulative_gas_used = 7; 31 | } 32 | -------------------------------------------------------------------------------- /proto/cosmos/evm/types/v1/web3.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | package cosmos.evm.types.v1; 4 | 5 | import "gogoproto/gogo.proto"; 6 | 7 | option go_package = "github.com/cosmos/evm/types"; 8 | 9 | // ExtensionOptionsWeb3Tx is an extension option that specifies the typed chain 10 | // id, the fee payer as well as its signature data. 11 | message ExtensionOptionsWeb3Tx { 12 | option (gogoproto.goproto_getters) = false; 13 | 14 | // typed_data_chain_id is used only in EIP712 Domain and should match 15 | // Ethereum network ID in a Web3 provider (e.g. Metamask). 16 | uint64 typed_data_chain_id = 1 [ 17 | (gogoproto.jsontag) = "typedDataChainID,omitempty", 18 | (gogoproto.customname) = "TypedDataChainID" 19 | ]; 20 | 21 | // fee_payer is an account address for the fee payer. It will be validated 22 | // during EIP712 signature checking. 23 | string fee_payer = 2 [ (gogoproto.jsontag) = "feePayer,omitempty" ]; 24 | 25 | // fee_payer_sig is a signature data from the fee paying account, 26 | // allows to perform fee delegation when using EIP712 Domain. 27 | bytes fee_payer_sig = 3 [ (gogoproto.jsontag) = "feePayerSig,omitempty" ]; 28 | } 29 | -------------------------------------------------------------------------------- /proto/cosmos/evm/vm/v1/events.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | package cosmos.evm.vm.v1; 4 | 5 | option go_package = "github.com/cosmos/evm/x/vm/types"; 6 | 7 | // EventEthereumTx defines the event for an Ethereum transaction 8 | message EventEthereumTx { 9 | // amount 10 | string amount = 1; 11 | // eth_hash is the Ethereum hash of the transaction 12 | string eth_hash = 2; 13 | // index of the transaction in the block 14 | string index = 3; 15 | // gas_used is the amount of gas used by the transaction 16 | string gas_used = 4; 17 | // hash is the Tendermint hash of the transaction 18 | string hash = 5; 19 | // recipient of the transaction 20 | string recipient = 6; 21 | // eth_tx_failed contains a VM error should it occur 22 | string eth_tx_failed = 7; 23 | } 24 | 25 | // EventTxLog defines the event for an Ethereum transaction log 26 | message EventTxLog { 27 | // tx_logs is an array of transaction logs 28 | repeated string tx_logs = 1; 29 | } 30 | 31 | // EventMessage 32 | message EventMessage { 33 | // module which emits the event 34 | string module = 1; 35 | // sender of the message 36 | string sender = 2; 37 | // tx_type is the type of the message 38 | string tx_type = 3; 39 | } 40 | 41 | // EventBlockBloom defines an Ethereum block bloom filter event 42 | message EventBlockBloom { 43 | // bloom is the bloom filter of the block 44 | string bloom = 1; 45 | } 46 | -------------------------------------------------------------------------------- /proto/cosmos/evm/vm/v1/genesis.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | package cosmos.evm.vm.v1; 4 | 5 | import "amino/amino.proto"; 6 | import "gogoproto/gogo.proto"; 7 | import "cosmos/evm/vm/v1/evm.proto"; 8 | 9 | option go_package = "github.com/cosmos/evm/x/vm/types"; 10 | 11 | // GenesisState defines the evm module's genesis state. 12 | message GenesisState { 13 | // accounts is an array containing the ethereum genesis accounts. 14 | repeated GenesisAccount accounts = 1 15 | [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; 16 | // params defines all the parameters of the module. 17 | Params params = 2 18 | [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; 19 | } 20 | 21 | // GenesisAccount defines an account to be initialized in the genesis state. 22 | // Its main difference between with Geth's GenesisAccount is that it uses a 23 | // custom storage type and that it doesn't contain the private key field. 24 | message GenesisAccount { 25 | // address defines an ethereum hex formated address of an account 26 | string address = 1; 27 | // code defines the hex bytes of the account code. 28 | string code = 2; 29 | // storage defines the set of state key values for the account. 30 | repeated State storage = 3 [ 31 | (gogoproto.nullable) = false, 32 | (amino.dont_omitempty) = true, 33 | (gogoproto.castrepeated) = "Storage" 34 | ]; 35 | } 36 | -------------------------------------------------------------------------------- /repo_header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmos/evm/4f9b8c209314217a1dc8e6d5ff0674c87ed38768/repo_header.png -------------------------------------------------------------------------------- /rpc/backend/feemarket_query_client_test.go: -------------------------------------------------------------------------------- 1 | package backend 2 | 3 | import ( 4 | "github.com/cosmos/evm/rpc/backend/mocks" 5 | rpc "github.com/cosmos/evm/rpc/types" 6 | feemarkettypes "github.com/cosmos/evm/x/feemarket/types" 7 | 8 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 9 | ) 10 | 11 | var _ feemarkettypes.QueryClient = &mocks.FeeMarketQueryClient{} 12 | 13 | // Params 14 | func RegisterFeeMarketParams(feeMarketClient *mocks.FeeMarketQueryClient, height int64) { 15 | feeMarketClient.On("Params", rpc.ContextWithHeight(height), &feemarkettypes.QueryParamsRequest{}). 16 | Return(&feemarkettypes.QueryParamsResponse{Params: feemarkettypes.DefaultParams()}, nil) 17 | } 18 | 19 | func RegisterFeeMarketParamsError(feeMarketClient *mocks.FeeMarketQueryClient, height int64) { 20 | feeMarketClient.On("Params", rpc.ContextWithHeight(height), &feemarkettypes.QueryParamsRequest{}). 21 | Return(nil, sdkerrors.ErrInvalidRequest) 22 | } 23 | -------------------------------------------------------------------------------- /rpc/backend/filters.go: -------------------------------------------------------------------------------- 1 | package backend 2 | 3 | import ( 4 | "github.com/ethereum/go-ethereum/common" 5 | ethtypes "github.com/ethereum/go-ethereum/core/types" 6 | "github.com/pkg/errors" 7 | ) 8 | 9 | // GetLogs returns all the logs from all the ethereum transactions in a block. 10 | func (b *Backend) GetLogs(hash common.Hash) ([][]*ethtypes.Log, error) { 11 | resBlock, err := b.TendermintBlockByHash(hash) 12 | if err != nil { 13 | return nil, err 14 | } 15 | if resBlock == nil { 16 | return nil, errors.Errorf("block not found for hash %s", hash) 17 | } 18 | return b.GetLogsByHeight(&resBlock.Block.Header.Height) 19 | } 20 | 21 | // GetLogsByHeight returns all the logs from all the ethereum transactions in a block. 22 | func (b *Backend) GetLogsByHeight(height *int64) ([][]*ethtypes.Log, error) { 23 | // NOTE: we query the state in case the tx result logs are not persisted after an upgrade. 24 | blockRes, err := b.rpcClient.BlockResults(b.ctx, height) 25 | if err != nil { 26 | return nil, err 27 | } 28 | 29 | return GetLogsFromBlockResults(blockRes) 30 | } 31 | 32 | // BloomStatus returns the BloomBitsBlocks and the number of processed sections maintained 33 | // by the chain indexer. 34 | func (b *Backend) BloomStatus() (uint64, uint64) { 35 | return 4096, 0 36 | } 37 | -------------------------------------------------------------------------------- /rpc/backend/utils_test.go: -------------------------------------------------------------------------------- 1 | package backend 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/cometbft/cometbft/proto/tendermint/crypto" 7 | ) 8 | 9 | func mookProofs(num int, withData bool) *crypto.ProofOps { 10 | var proofOps *crypto.ProofOps 11 | if num > 0 { 12 | proofOps = new(crypto.ProofOps) 13 | for i := 0; i < num; i++ { 14 | proof := crypto.ProofOp{} 15 | if withData { 16 | proof.Data = []byte("\n\031\n\003KEY\022\005VALUE\032\013\010\001\030\001 \001*\003\000\002\002") 17 | } 18 | proofOps.Ops = append(proofOps.Ops, proof) 19 | } 20 | } 21 | return proofOps 22 | } 23 | 24 | func (suite *BackendTestSuite) TestGetHexProofs() { 25 | defaultRes := []string{""} 26 | testCases := []struct { 27 | name string 28 | proof *crypto.ProofOps 29 | exp []string 30 | }{ 31 | { 32 | "no proof provided", 33 | mookProofs(0, false), 34 | defaultRes, 35 | }, 36 | { 37 | "no proof data provided", 38 | mookProofs(1, false), 39 | defaultRes, 40 | }, 41 | { 42 | "valid proof provided", 43 | mookProofs(1, true), 44 | []string{"0x0a190a034b4559120556414c55451a0b0801180120012a03000202"}, 45 | }, 46 | } 47 | for _, tc := range testCases { 48 | suite.Run(fmt.Sprintf("Case %s", tc.name), func() { 49 | suite.Require().Equal(tc.exp, GetHexProofs(tc.proof)) 50 | }) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /rpc/namespaces/ethereum/debug/trace_fallback.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The go-ethereum Authors 2 | // This file is part of the go-ethereum library. 3 | // 4 | // The go-ethereum library is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU Lesser General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // The go-ethereum library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU Lesser General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU Lesser General Public License 15 | // along with the go-ethereum library. If not, see . 16 | 17 | //go:build !go1.5 18 | // +build !go1.5 19 | 20 | // no-op implementation of tracing methods for Go < 1.5. 21 | 22 | package debug 23 | 24 | import ( 25 | "errors" 26 | ) 27 | 28 | func (*API) StartGoTrace(string file) error { 29 | a.logger.Debug("debug_stopGoTrace", "file", file) 30 | return errors.New("tracing is not supported on Go < 1.5") 31 | } 32 | 33 | func (*API) StopGoTrace() error { 34 | a.logger.Debug("debug_stopGoTrace") 35 | return errors.New("tracing is not supported on Go < 1.5") 36 | } 37 | -------------------------------------------------------------------------------- /rpc/namespaces/ethereum/miner/api.go: -------------------------------------------------------------------------------- 1 | package miner 2 | 3 | import ( 4 | "github.com/ethereum/go-ethereum/common" 5 | "github.com/ethereum/go-ethereum/common/hexutil" 6 | 7 | "github.com/cosmos/evm/rpc/backend" 8 | 9 | "cosmossdk.io/log" 10 | 11 | "github.com/cosmos/cosmos-sdk/server" 12 | ) 13 | 14 | // API is the private miner prefixed set of APIs in the Miner JSON-RPC spec. 15 | type API struct { 16 | ctx *server.Context 17 | logger log.Logger 18 | backend backend.EVMBackend 19 | } 20 | 21 | // NewPrivateAPI creates an instance of the Miner API. 22 | func NewPrivateAPI( 23 | ctx *server.Context, 24 | backend backend.EVMBackend, 25 | ) *API { 26 | return &API{ 27 | ctx: ctx, 28 | logger: ctx.Logger.With("api", "miner"), 29 | backend: backend, 30 | } 31 | } 32 | 33 | // SetEtherbase sets the etherbase of the miner 34 | func (api *API) SetEtherbase(etherbase common.Address) bool { 35 | api.logger.Debug("miner_setEtherbase") 36 | return api.backend.SetEtherbase(etherbase) 37 | } 38 | 39 | // SetGasPrice sets the minimum accepted gas price for the miner. 40 | func (api *API) SetGasPrice(gasPrice hexutil.Big) bool { 41 | api.logger.Info(api.ctx.Viper.ConfigFileUsed()) 42 | return api.backend.SetGasPrice(gasPrice) 43 | } 44 | -------------------------------------------------------------------------------- /rpc/namespaces/ethereum/web3/api.go: -------------------------------------------------------------------------------- 1 | package web3 2 | 3 | import ( 4 | "github.com/ethereum/go-ethereum/common/hexutil" 5 | "github.com/ethereum/go-ethereum/crypto" 6 | 7 | "github.com/cosmos/evm/version" 8 | ) 9 | 10 | // PublicAPI is the web3_ prefixed set of APIs in the Web3 JSON-RPC spec. 11 | type PublicAPI struct{} 12 | 13 | // NewPublicAPI creates an instance of the Web3 API. 14 | func NewPublicAPI() *PublicAPI { 15 | return &PublicAPI{} 16 | } 17 | 18 | // ClientVersion returns the client version in the Web3 user agent format. 19 | func (a *PublicAPI) ClientVersion() string { 20 | return version.Version() 21 | } 22 | 23 | // Sha3 returns the keccak-256 hash of the passed-in input. 24 | func (a *PublicAPI) Sha3(input string) hexutil.Bytes { 25 | return crypto.Keccak256(hexutil.Bytes(input)) 26 | } 27 | -------------------------------------------------------------------------------- /rpc/types/addrlock.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "sync" 5 | 6 | "github.com/ethereum/go-ethereum/common" 7 | ) 8 | 9 | // AddrLocker is a mutex structure used to avoid querying outdated account data 10 | type AddrLocker struct { 11 | mu sync.Mutex 12 | locks map[common.Address]*sync.Mutex 13 | } 14 | 15 | // lock returns the lock of the given address. 16 | func (l *AddrLocker) lock(address common.Address) *sync.Mutex { 17 | l.mu.Lock() 18 | defer l.mu.Unlock() 19 | if l.locks == nil { 20 | l.locks = make(map[common.Address]*sync.Mutex) 21 | } 22 | if _, ok := l.locks[address]; !ok { 23 | l.locks[address] = new(sync.Mutex) 24 | } 25 | return l.locks[address] 26 | } 27 | 28 | // LockAddr locks an account's mutex. This is used to prevent another tx getting the 29 | // same nonce until the lock is released. The mutex prevents the (an identical nonce) from 30 | // being read again during the time that the first transaction is being signed. 31 | func (l *AddrLocker) LockAddr(address common.Address) { 32 | l.lock(address).Lock() 33 | } 34 | 35 | // UnlockAddr unlocks the mutex of the given account. 36 | func (l *AddrLocker) UnlockAddr(address common.Address) { 37 | l.lock(address).Unlock() 38 | } 39 | -------------------------------------------------------------------------------- /scripts/compile_smart_contracts/README.md: -------------------------------------------------------------------------------- 1 | # Compiling Smart Contracts 2 | 3 | This tool compiles all smart contracts found in this repository using a Hardhat setup. 4 | The contracts are collected and then copied into the `contracts` directory for compilation. 5 | After compilation, the resulting JSON data is copied back to the source locations. 6 | 7 | **Note**: The tool will compile all smart contracts found 8 | (except for the ignored paths defined in the script) 9 | but only overwrite the compiled JSON data for contracts 10 | that already have a corresponding compiled JSON file in the same directory. 11 | If you want to add a new JSON file to the repository, use the `add` command 12 | described below. 13 | 14 | ## Usage 15 | 16 | To compile the smart contracts, run the following command: 17 | 18 | ```bash 19 | make contracts-compile 20 | ``` 21 | 22 | This will compile the smart contracts and generate the JSON files. 23 | 24 | To clean up the generated artifacts, installed dependencies and cached files, 25 | run: 26 | 27 | ```bash 28 | make contracts-clean 29 | ``` 30 | 31 | If you want to add a new smart contract and have a JSON file generated for it, 32 | run: 33 | 34 | ```bash 35 | make contracts-add CONTRACT=path/to/contract.sol 36 | ``` 37 | -------------------------------------------------------------------------------- /scripts/compile_smart_contracts/testdata/hardhat.config.js: -------------------------------------------------------------------------------- 1 | /** @type import('hardhat/config').HardhatUserConfig */ 2 | module.exports = { 3 | solidity: '0.8.19', 4 | paths: { 5 | sources: './solidity' 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /scripts/compile_smart_contracts/testdata/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "evmos-contracts", 3 | "version": "2.0.0", 4 | "description": "A collection of smart contracts used in the development of the Cosmos EVM blockchain.", 5 | "devDependencies": { 6 | "@openzeppelin/contracts": "^4.9.6", 7 | "hardhat": "^2.22.2" 8 | }, 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/evmos/evmos.git" 15 | }, 16 | "author": "Evmos Core Team", 17 | "license": "ISC", 18 | "bugs": { 19 | "url": "https://github.com/evmos/evmos/issues" 20 | }, 21 | "homepage": "https://github.com/evmos/evmos#readme" 22 | } 23 | -------------------------------------------------------------------------------- /scripts/compile_smart_contracts/testdata/solidity/SimpleContract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.17; 3 | 4 | contract SimpleContract { 5 | uint256 public value; 6 | 7 | function setValue(uint256 _value) public { 8 | value = _value; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /scripts/generate_protos.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -------------- 4 | # Commands to run locally 5 | # docker run --network host --rm -v $(CURDIR):/workspace --workdir /workspace ghcr.io/cosmos/proto-builder:v0.11.6 sh ./generate_protos.sh 6 | # 7 | set -eo pipefail 8 | 9 | proto_dirs=$(find ./proto -path -prune -o -name '*.proto' -print0 | xargs -0 -n1 dirname | sort | uniq) 10 | for dir in $proto_dirs; do 11 | proto_files=$(find "${dir}" -maxdepth 1 -name '*.proto') 12 | for file in $proto_files; do 13 | # Check if the go_package in the file is pointing to evmos 14 | if grep -q "option go_package.*cosmos/evm" "$file"; then 15 | buf generate --template proto/buf.gen.gogo.yaml "$file" 16 | fi 17 | done 18 | done 19 | 20 | # move proto files to the right places 21 | cp -r github.com/cosmos/evm/* ./ 22 | rm -rf github.com 23 | -------------------------------------------------------------------------------- /scripts/generate_protos_pulsar.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # this script is for generating protobuf files for the new google.golang.org/protobuf API 4 | set -eo pipefail 5 | 6 | echo "Cleaning API directory" 7 | ( 8 | cd api 9 | find ./ -type f \( -iname \*.pulsar.go -o -iname \*.pb.go -o -iname \*.cosmos_orm.go -o -iname \*.pb.gw.go \) -delete 10 | find . -empty -type d -delete 11 | cd .. 12 | ) 13 | 14 | echo "Generating API module" 15 | ( 16 | cd proto 17 | buf generate --template buf.gen.pulsar.yaml 18 | ) 19 | -------------------------------------------------------------------------------- /scripts/run-solidity-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export GOPATH="$HOME"/go 3 | export PATH="$PATH":"$GOPATH"/bin 4 | 5 | # remove existing data 6 | rm -rf "$HOME"/.tmp-evmd-solidity-tests 7 | 8 | # used to exit on first error (any non-zero exit code) 9 | set -e 10 | 11 | # build evmd binary 12 | make install 13 | 14 | cd tests/solidity || exit 15 | 16 | if command -v yarn &>/dev/null; then 17 | yarn install 18 | else 19 | curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - 20 | echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list 21 | sudo apt update && sudo apt install yarn 22 | yarn install 23 | fi 24 | 25 | yarn test --network cosmos "$@" 26 | -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | { pkgs ? import {} }: 2 | 3 | pkgs.mkShell { 4 | buildInputs = [ 5 | pkgs.nodejs 6 | pkgs.yarn 7 | ]; 8 | 9 | shellHook = '' 10 | echo "Node and Yarn are ready for Solidity tests." 11 | ''; 12 | } -------------------------------------------------------------------------------- /tests/integration/ledger/mocks/tendermint.go: -------------------------------------------------------------------------------- 1 | package mocks 2 | 3 | import ( 4 | "context" 5 | 6 | abci "github.com/cometbft/cometbft/abci/types" 7 | tmbytes "github.com/cometbft/cometbft/libs/bytes" 8 | rpcclient "github.com/cometbft/cometbft/rpc/client" 9 | rpcclientmock "github.com/cometbft/cometbft/rpc/client/mock" 10 | coretypes "github.com/cometbft/cometbft/rpc/core/types" 11 | cmttypes "github.com/cometbft/cometbft/types" 12 | ) 13 | 14 | type MockCometRPC struct { 15 | rpcclientmock.Client 16 | 17 | responseQuery abci.ResponseQuery 18 | } 19 | 20 | // NewMockCometRPC returns a mock CometRPC implementation. 21 | // It is used for CLI testing. 22 | func NewMockCometRPC(respQuery abci.ResponseQuery) MockCometRPC { 23 | return MockCometRPC{responseQuery: respQuery} 24 | } 25 | 26 | func (MockCometRPC) BroadcastTxSync(context.Context, cmttypes.Tx) (*coretypes.ResultBroadcastTx, error) { 27 | return &coretypes.ResultBroadcastTx{Code: 0}, nil 28 | } 29 | 30 | func (m MockCometRPC) ABCIQueryWithOptions( 31 | _ context.Context, 32 | _ string, 33 | _ tmbytes.HexBytes, 34 | _ rpcclient.ABCIQueryOptions, 35 | ) (*coretypes.ResultABCIQuery, error) { 36 | return &coretypes.ResultABCIQuery{Response: m.responseQuery}, nil 37 | } 38 | -------------------------------------------------------------------------------- /tests/solidity/.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity 2 | -------------------------------------------------------------------------------- /tests/solidity/.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | node_modules/ 3 | cache/ 4 | artifacts/ 5 | # don't track the contracts on evmos directory because these are copied from the precompiles pkg of this repo 6 | **/precompiles/contracts/evmos/* 7 | 8 | # ignore package-lock files (only use yarn.lock) 9 | package-lock.json 10 | !yarn.lock -------------------------------------------------------------------------------- /tests/solidity/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tests-solidity", 3 | "private": true, 4 | "version": "1.0.0", 5 | "author": "Aragon Association ", 6 | "license": "GPL-3.0-or-later", 7 | "workspaces": { 8 | "packages": [ 9 | "suites/*" 10 | ], 11 | "nohoist": [ 12 | "**/@aragon/contract-helpers-test" 13 | ] 14 | }, 15 | "dependencies": { 16 | "truffle": "5.5.8", 17 | "yargs": "^17.0.1", 18 | "patch-package": "^6.4.7" 19 | }, 20 | "scripts": { 21 | "test": "node test-helper.js", 22 | "postinstall": "patch-package" 23 | }, 24 | "standard": { 25 | "globals": [ 26 | "artifacts", 27 | "expect", 28 | "contract", 29 | "beforeEach", 30 | "before", 31 | "web3", 32 | "it", 33 | "assert", 34 | "describe" 35 | ] 36 | }, 37 | "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" 38 | } 39 | -------------------------------------------------------------------------------- /tests/solidity/suites/basic/contracts/Counter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity >=0.7.0 <0.9.0; 4 | 5 | contract Counter { 6 | uint256 counter = 0; 7 | string internal constant ERROR_TOO_LOW = "COUNTER_TOO_LOW"; 8 | event Changed(uint256 counter); 9 | event Added(uint256 counter); 10 | 11 | function add() public { 12 | counter++; 13 | emit Added(counter); 14 | emit Changed(counter); 15 | } 16 | 17 | function subtract() public { 18 | require(counter > 0, ERROR_TOO_LOW); 19 | counter--; 20 | emit Changed(counter); 21 | } 22 | 23 | function getCounter() public view returns (uint256) { 24 | return counter; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/solidity/suites/basic/contracts/EventTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity >=0.7.0 <0.9.0; 4 | 5 | /** 6 | * @title Storage 7 | * @dev Store & retrieve value in a variable 8 | */ 9 | contract EventTest { 10 | 11 | uint256 number; 12 | 13 | event ValueStored1( 14 | uint value1 15 | ); 16 | event ValueStored2( 17 | string msg, 18 | uint value1 19 | ); 20 | event ValueStored3( 21 | string msg, 22 | uint indexed value1, 23 | uint value2 24 | ); 25 | 26 | function store(uint256 num) public { 27 | number = num; 28 | } 29 | 30 | function storeWithEvent(uint256 num) public { 31 | number = num; 32 | emit ValueStored1(num); 33 | emit ValueStored2("TestMsg", num); 34 | emit ValueStored3("TestMsg", num, num); 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /tests/solidity/suites/basic/contracts/Storage.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity >=0.7.0 <0.9.0; 4 | 5 | /** 6 | * @title Storage 7 | * @dev Store & retrieve value in a variable 8 | */ 9 | contract Storage { 10 | 11 | uint256 number; 12 | 13 | /** 14 | * @dev Store value in variable 15 | * @param num value to store 16 | */ 17 | function store(uint256 num) public { 18 | number = num; 19 | } 20 | 21 | /** 22 | * @dev Return value 23 | * @return value of 'number' 24 | */ 25 | function retrieve() public view returns (uint256){ 26 | return number; 27 | } 28 | 29 | function shouldRevert() pure public { 30 | require(false, 'This must REVERT'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/solidity/suites/basic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "basic", 3 | "version": "1.0.0", 4 | "author": "Aragon Association ", 5 | "license": "GPL-3.0-or-later", 6 | "scripts": { 7 | "test-ganache": "yarn truffle test", 8 | "test-cosmos": "yarn truffle test --network cosmos" 9 | }, 10 | "devDependencies": { 11 | "truffle-assertions": "^0.9.2" 12 | }, 13 | "standard": { 14 | "globals": [ 15 | "artifacts", 16 | "expect", 17 | "contract", 18 | "beforeEach", 19 | "before", 20 | "web3", 21 | "it", 22 | "assert", 23 | "describe" 24 | ] 25 | } 26 | } -------------------------------------------------------------------------------- /tests/solidity/suites/basic/test/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmos/evm/4f9b8c209314217a1dc8e6d5ff0674c87ed38768/tests/solidity/suites/basic/test/.gitkeep -------------------------------------------------------------------------------- /tests/solidity/suites/basic/test/events.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | 3 | const EventTest = artifacts.require('EventTest') 4 | const truffleAssert = require('truffle-assertions') 5 | 6 | contract('Test EventTest Contract', async function (accounts) { 7 | let eventInstance 8 | 9 | it('should deploy EventTest contract', async function () { 10 | eventInstance = await EventTest.new() 11 | /* eslint-disable no-unused-expressions */ 12 | expect(eventInstance.address).not.to.be.undefined 13 | }) 14 | 15 | it('should emit events', async function () { 16 | const tx = await eventInstance.storeWithEvent(888) 17 | truffleAssert.eventEmitted(tx, 'ValueStored1', (events) => { 18 | return events['0'].toString() === '888' 19 | }) 20 | truffleAssert.eventEmitted(tx, 'ValueStored2', (events) => { 21 | return ( 22 | events['0'].toString() === 'TestMsg' && events['1'].toString() === '888' 23 | ) 24 | }) 25 | truffleAssert.eventEmitted(tx, 'ValueStored3', (events) => { 26 | return ( 27 | events['0'].toString() === 'TestMsg' && 28 | events['1'].toString() === '888' && 29 | events['2'].toString() === '888' 30 | ) 31 | }) 32 | }) 33 | }) 34 | -------------------------------------------------------------------------------- /tests/solidity/suites/basic/test/revert.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | 3 | const Storage = artifacts.require('Storage') 4 | 5 | async function expectRevert (promise) { 6 | try { 7 | await promise 8 | } catch (error) { 9 | if (error.message.indexOf('revert') === -1) { 10 | expect('revert').to.equal( 11 | error.message, 12 | 'Wrong kind of exception received' 13 | ) 14 | } 15 | return 16 | } 17 | expect.fail('Expected an exception but none was received') 18 | } 19 | 20 | contract('Test EVM Revert', async function (accounts) { 21 | let storageInstance 22 | it('should deploy Storage contract', async function () { 23 | storageInstance = await Storage.new() 24 | /* eslint-disable no-unused-expressions */ 25 | expect(storageInstance.address).not.to.be.undefined 26 | }) 27 | 28 | it('should revert when call `shouldRevert()`', async function () { 29 | await expectRevert(storageInstance.shouldRevert()) 30 | }) 31 | }) 32 | -------------------------------------------------------------------------------- /tests/solidity/suites/basic/test/storage.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | 3 | const Storage = artifacts.require('Storage') 4 | 5 | contract('Test Storage Contract', async function (accounts) { 6 | let storageInstance 7 | 8 | it('should deploy Storage contract', async function () { 9 | storageInstance = await Storage.new() 10 | /* eslint-disable no-unused-expressions */ 11 | expect(storageInstance.address).not.to.be.undefined 12 | }) 13 | 14 | it('should successfully store a value', async function () { 15 | const tx = await storageInstance.store(888) 16 | /* eslint-disable no-unused-expressions */ 17 | expect(tx.tx).not.to.be.undefined 18 | }) 19 | 20 | it('should successfully retrieve a value', async function () { 21 | const value = await storageInstance.retrieve() 22 | expect(value.toString()).to.equal('888') 23 | }) 24 | }) 25 | -------------------------------------------------------------------------------- /tests/solidity/suites/basic/truffle-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | // Development network is just left as truffle's default settings 4 | cosmos: { 5 | host: '127.0.0.1', // Localhost (default: none) 6 | port: 8545, // Standard Ethereum port (default: none) 7 | network_id: '*', // Any network (default: none) 8 | gas: 5000000, // Gas sent with each transaction 9 | gasPrice: 1000000000 // 1 gwei (in wei) 10 | } 11 | }, 12 | compilers: { 13 | solc: { 14 | version: '0.8.18' 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/solidity/suites/eip1559/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eip1559", 3 | "version": "1.0.0", 4 | "license": "GPL-3.0-or-later", 5 | "scripts": { 6 | "test-ganache": "yarn truffle test", 7 | "test-cosmos": "yarn truffle test --network cosmos" 8 | }, 9 | "devDependencies": { 10 | "truffle": "^5.4.14", 11 | "truffle-assertions": "^0.9.2" 12 | }, 13 | "dependencies": { 14 | "@truffle/hdwallet-provider": "^1.6.0" 15 | }, 16 | "standard": { 17 | "globals": [ 18 | "artifacts", 19 | "expect", 20 | "contract", 21 | "beforeEach", 22 | "before", 23 | "web3", 24 | "it", 25 | "assert", 26 | "describe" 27 | ] 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/solidity/suites/eip1559/test/eip1559.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | 3 | contract('Transaction', async function (accounts) { 4 | it('should send a transaction with EIP-1559 flag', async function () { 5 | const tx = await web3.eth.sendTransaction({ 6 | from: accounts[0], 7 | to: accounts[1] 8 | ? accounts[1] 9 | : '0x0000000000000000000000000000000000000000', 10 | value: '10000000', 11 | gas: '21000', 12 | type: '0x2', 13 | common: { 14 | hardfork: 'london' 15 | } 16 | }) 17 | assert.equal(tx.type, '0x2', 'Tx type should be 0x2') 18 | }) 19 | }) 20 | -------------------------------------------------------------------------------- /tests/solidity/suites/eip1559/truffle-config.js: -------------------------------------------------------------------------------- 1 | // const HDWalletProvider = require('@truffle/hdwallet-provider'); 2 | 3 | module.exports = { 4 | networks: { 5 | // Development network is just left as truffle's default settings 6 | cosmos: { 7 | host: '127.0.0.1', // Localhost (default: none) 8 | port: 8545, // Standard Ethereum port (default: none) 9 | network_id: '*', // Any network (default: none) 10 | gas: 5000000, // Gas sent with each transaction 11 | gasPrice: 1000000000 // 1 gwei (in wei) 12 | } 13 | }, 14 | compilers: { 15 | solc: { 16 | version: '0.8.18' 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/solidity/suites/exception/contracts/TestRevert.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.0; 3 | 4 | contract State { 5 | uint256 a = 0; 6 | function set(uint256 input) public { 7 | a = input; 8 | require(a < 10); 9 | } 10 | function force_set(uint256 input) public { 11 | a = input; 12 | } 13 | function query() public view returns(uint256) { 14 | return a; 15 | } 16 | } 17 | 18 | contract TestRevert { 19 | State state; 20 | uint256 b = 0; 21 | uint256 c = 0; 22 | constructor() { 23 | state = new State(); 24 | } 25 | function try_set(uint256 input) public { 26 | b = input; 27 | try state.set(input) { 28 | } catch (bytes memory) { 29 | } 30 | c = input; 31 | } 32 | function set(uint256 input) public { 33 | state.force_set(input); 34 | } 35 | function query_a() public view returns(uint256) { 36 | return state.query(); 37 | } 38 | function query_b() public view returns(uint256) { 39 | return b; 40 | } 41 | function query_c() public view returns(uint256) { 42 | return c; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/solidity/suites/exception/contracts/test/Migrations.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.0; 3 | 4 | contract Migrations { 5 | address public owner = msg.sender; 6 | uint public last_completed_migration; 7 | 8 | modifier restricted() { 9 | require( 10 | msg.sender == owner, 11 | "This function is restricted to the contract's owner" 12 | ); 13 | _; 14 | } 15 | 16 | function setCompleted(uint completed) public restricted { 17 | last_completed_migration = completed; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/solidity/suites/exception/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | 3 | const Migrations = artifacts.require('Migrations') 4 | 5 | module.exports = function (deployer) { 6 | deployer.deploy(Migrations) 7 | } 8 | -------------------------------------------------------------------------------- /tests/solidity/suites/exception/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "exception", 3 | "version": "1.0.0", 4 | "author": "huangyi ", 5 | "license": "GPL-3.0-or-later", 6 | "scripts": { 7 | "test-ganache": "yarn truffle test", 8 | "test-cosmos": "yarn truffle test --network cosmos" 9 | }, 10 | "devDependencies": { 11 | "truffle-assertions": "^0.9.2" 12 | }, 13 | "standard": { 14 | "globals": [ 15 | "artifacts", 16 | "expect", 17 | "contract", 18 | "beforeEach", 19 | "before", 20 | "web3", 21 | "it", 22 | "assert", 23 | "describe" 24 | ] 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/solidity/suites/exception/test/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmos/evm/4f9b8c209314217a1dc8e6d5ff0674c87ed38768/tests/solidity/suites/exception/test/.gitkeep -------------------------------------------------------------------------------- /tests/solidity/suites/exception/test/revert.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | 3 | const TestRevert = artifacts.require('TestRevert') 4 | 5 | contract('TestRevert', (accounts) => { 6 | let revert 7 | 8 | beforeEach(async () => { 9 | revert = await TestRevert.new() 10 | }) 11 | it('should revert', async () => { 12 | await revert.try_set(10) 13 | let no = await revert.query_a() 14 | assert.equal(no, '0', 'The modification on a should be reverted') 15 | no = await revert.query_b() 16 | assert.equal(no, '10', 'The modification on b should not be reverted') 17 | no = await revert.query_c() 18 | assert.equal(no, '10', 'The modification on c should not be reverted') 19 | 20 | await revert.set(10) 21 | no = await revert.query_a() 22 | assert.equal(no, '10', 'The force set should not be reverted') 23 | }) 24 | }) 25 | -------------------------------------------------------------------------------- /tests/solidity/suites/exception/truffle-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | // Development network is just left as truffle's default settings 4 | cosmos: { 5 | host: '127.0.0.1', // Localhost (default: none) 6 | port: 8545, // Standard Ethereum port (default: none) 7 | network_id: '*', // Any network (default: none) 8 | gas: 5000000, // Gas sent with each transaction 9 | gasPrice: 1000000000 // 1 gwei (in wei) 10 | } 11 | }, 12 | compilers: { 13 | solc: { 14 | version: '0.8.18' 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/solidity/suites/opcode/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.21 <0.6.0; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | constructor() public { 8 | owner = msg.sender; 9 | } 10 | 11 | modifier restricted() { 12 | if (msg.sender == owner) _; 13 | } 14 | 15 | function setCompleted(uint completed) public restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) public restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/solidity/suites/opcode/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | 3 | const Migrations = artifacts.require('Migrations') 4 | 5 | module.exports = function (deployer) { 6 | deployer.deploy(Migrations) 7 | } 8 | -------------------------------------------------------------------------------- /tests/solidity/suites/opcode/migrations/2_opCodes_migration.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | 3 | const OpCodes = artifacts.require('./OpCodes.sol') 4 | 5 | module.exports = function (deployer) { 6 | deployer.deploy(OpCodes) 7 | } 8 | -------------------------------------------------------------------------------- /tests/solidity/suites/opcode/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "opcode", 3 | "version": "1.0.0", 4 | "author": "Go Ethereum", 5 | "license": "GPL-3.0-or-later", 6 | "scripts": { 7 | "test-ganache": "yarn truffle test", 8 | "test-cosmos": "yarn truffle test --network cosmos" 9 | }, 10 | "devDependencies": { 11 | "truffle-assertions": "^0.9.2" 12 | }, 13 | "standard": { 14 | "globals": [ 15 | "artifacts", 16 | "expect", 17 | "contract", 18 | "beforeEach", 19 | "before", 20 | "web3", 21 | "it", 22 | "assert", 23 | "describe" 24 | ] 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/solidity/suites/opcode/test/opCodes.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | /* eslint-disable no-unused-expressions */ 3 | 4 | const TodoList = artifacts.require('./OpCodes.sol') 5 | let contractInstance 6 | 7 | contract('OpCodes', () => { 8 | beforeEach(async () => { 9 | contractInstance = await TodoList.deployed() 10 | }) 11 | it('Should run the majority of opcodes without errors', async () => { 12 | let error 13 | try { 14 | await contractInstance.test() 15 | await contractInstance.test_stop() 16 | } catch (err) { 17 | error = err 18 | } 19 | expect(error).to.be.undefined 20 | }) 21 | 22 | it('Should throw invalid op code', async () => { 23 | let error 24 | try { 25 | await contractInstance.test_invalid() 26 | } catch (err) { 27 | error = err 28 | } 29 | expect(error).not.to.be.undefined 30 | }) 31 | 32 | it('Should revert', async () => { 33 | let error 34 | try { 35 | await contractInstance.test_revert() 36 | } catch (err) { 37 | error = err 38 | } 39 | expect(error).not.to.be.undefined 40 | }) 41 | }) 42 | -------------------------------------------------------------------------------- /tests/solidity/suites/opcode/truffle-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | // Development network is just left as truffle's default settings 4 | cosmos: { 5 | host: '127.0.0.1', // Localhost (default: none) 6 | port: 8545, // Standard Ethereum port (default: none) 7 | network_id: '*', // Any network (default: none) 8 | gas: 5000000, // Gas sent with each transaction 9 | gasPrice: 1000000000 // 1 gwei (in wei) 10 | } 11 | }, 12 | compilers: { 13 | solc: { 14 | version: '0.5.17' 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/solidity/suites/precompiles/contracts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmos/evm/4f9b8c209314217a1dc8e6d5ff0674c87ed38768/tests/solidity/suites/precompiles/contracts/.gitkeep -------------------------------------------------------------------------------- /tests/solidity/suites/precompiles/hardhat.config.js: -------------------------------------------------------------------------------- 1 | require("@nomicfoundation/hardhat-toolbox"); 2 | 3 | /** @type import('hardhat/config').HardhatUserConfig */ 4 | module.exports = { 5 | solidity: { 6 | compilers: [ 7 | { 8 | version: "0.8.18", 9 | }, 10 | // This version is required to compile the werc9 contract. 11 | { 12 | version: "0.4.22", 13 | }, 14 | ], 15 | }, 16 | networks: { 17 | cosmos: { 18 | url: "http://127.0.0.1:8545", 19 | chainId: 4221, 20 | accounts: [ 21 | "0x88CBEAD91AEE890D27BF06E003ADE3D4E952427E88F88D31D61D3EF5E5D54305", 22 | "0x3B7955D25189C99A7468192FCBC6429205C158834053EBE3F78F4512AB432DB9", 23 | ], 24 | }, 25 | }, 26 | }; 27 | -------------------------------------------------------------------------------- /tests/solidity/suites/precompiles/test/staking.js: -------------------------------------------------------------------------------- 1 | const { expect } = require('chai') 2 | const hre = require('hardhat') 3 | 4 | describe('Staking', function () { 5 | it('should stake ATOM to a validator', async function () { 6 | const valAddr = 'cosmosvaloper10jmp6sgh4cc6zt3e8gw05wavvejgr5pw4xyrql' 7 | const stakeAmount = hre.ethers.parseEther('0.001') 8 | 9 | const staking = await hre.ethers.getContractAt( 10 | 'StakingI', 11 | '0x0000000000000000000000000000000000000800' 12 | ) 13 | 14 | const [signer] = await hre.ethers.getSigners() 15 | const tx = await staking 16 | .connect(signer) 17 | .delegate(signer, valAddr, stakeAmount) 18 | await tx.wait(1) 19 | 20 | // Query delegation 21 | const delegation = await staking.delegation(signer, valAddr) 22 | expect(delegation.balance.amount).to.equal( 23 | stakeAmount, 24 | 'Stake amount does not match' 25 | ) 26 | }) 27 | }) 28 | -------------------------------------------------------------------------------- /testutil/ante.go: -------------------------------------------------------------------------------- 1 | package testutil 2 | 3 | import sdk "github.com/cosmos/cosmos-sdk/types" 4 | 5 | // NoOpNextFn is a no-op function that returns the context and no error in order to mock 6 | // the next function in the AnteHandler chain. 7 | // 8 | // It can be used in unit tests when calling a decorator's AnteHandle method, e.g. 9 | // `dec.AnteHandle(ctx, tx, false, NoOpNextFn)` 10 | func NoOpNextFn(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) { 11 | return ctx, nil 12 | } 13 | -------------------------------------------------------------------------------- /testutil/constants/constants_test.go: -------------------------------------------------------------------------------- 1 | package constants_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | config2 "github.com/cosmos/evm/cmd/evmd/config" 9 | "github.com/cosmos/evm/testutil/constants" 10 | ) 11 | 12 | func TestRequireSameTestDenom(t *testing.T) { 13 | require.Equal(t, 14 | constants.ExampleAttoDenom, 15 | config2.ExampleChainDenom, 16 | "test denoms should be the same across the repo", 17 | ) 18 | } 19 | 20 | func TestRequireSameTestBech32Prefix(t *testing.T) { 21 | require.Equal(t, 22 | constants.ExampleBech32Prefix, 23 | config2.Bech32Prefix, 24 | "bech32 prefixes should be the same across the repo", 25 | ) 26 | } 27 | 28 | func TestRequireSameWEVMOSMainnet(t *testing.T) { 29 | require.Equal(t, 30 | constants.WEVMOSContractMainnet, 31 | config2.WEVMOSContractMainnet, 32 | "wevmos contract addresses should be the same across the repo", 33 | ) 34 | } 35 | -------------------------------------------------------------------------------- /testutil/ibc.go: -------------------------------------------------------------------------------- 1 | package testutil 2 | 3 | import ( 4 | transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" 5 | ) 6 | 7 | func GetVoucherDenomFromPacketData( 8 | data transfertypes.InternalTransferRepresentation, 9 | destPort string, 10 | destChannel string, 11 | ) string { 12 | token := data.Token 13 | trace := []transfertypes.Hop{transfertypes.NewHop(destPort, destChannel)} 14 | token.Denom.Trace = append(trace, token.Denom.Trace...) 15 | voucherDenom := token.Denom.IBCDenom() 16 | return voucherDenom 17 | } 18 | -------------------------------------------------------------------------------- /testutil/integration/common/factory/factory.go: -------------------------------------------------------------------------------- 1 | package factory 2 | 3 | import ( 4 | "github.com/cosmos/evm/testutil/integration/os/grpc" 5 | "github.com/cosmos/evm/testutil/integration/os/network" 6 | ) 7 | 8 | const ( 9 | GasAdjustment = float64(1.7) 10 | ) 11 | 12 | // CoreTxFactory is the interface that wraps the methods 13 | // to build and broadcast cosmos transactions, and also 14 | // includes module-specific transactions 15 | type CoreTxFactory interface { 16 | BaseTxFactory 17 | DistributionTxFactory 18 | StakingTxFactory 19 | FundTxFactory 20 | } 21 | 22 | var _ CoreTxFactory = (*IntegrationTxFactory)(nil) 23 | 24 | // IntegrationTxFactory is a helper struct to build and broadcast transactions 25 | // to the network on integration tests. This is to simulate the behavior of a real user. 26 | type IntegrationTxFactory struct { 27 | BaseTxFactory 28 | DistributionTxFactory 29 | StakingTxFactory 30 | FundTxFactory 31 | } 32 | 33 | // New creates a new IntegrationTxFactory instance 34 | func New( 35 | network network.Network, 36 | grpcHandler grpc.Handler, 37 | ) CoreTxFactory { 38 | bf := newBaseTxFactory(network, grpcHandler) 39 | return &IntegrationTxFactory{ 40 | bf, 41 | newDistrTxFactory(bf), 42 | newStakingTxFactory(bf), 43 | newFundTxFactory(bf), 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /testutil/integration/common/factory/types.go: -------------------------------------------------------------------------------- 1 | package factory 2 | 3 | import ( 4 | sdkmath "cosmossdk.io/math" 5 | 6 | sdktypes "github.com/cosmos/cosmos-sdk/types" 7 | ) 8 | 9 | // CosmosTxArgs contains the params to create a cosmos tx 10 | type CosmosTxArgs struct { 11 | // ChainID is the chain's id in cosmos format, e.g. 'evmos_9000-1' 12 | ChainID string 13 | // Gas to be used on the tx 14 | Gas *uint64 15 | // GasPrice to use on tx 16 | GasPrice *sdkmath.Int 17 | // Fees is the fee to be used on the tx (amount and denom) 18 | Fees sdktypes.Coins 19 | // FeeGranter is the account address of the fee granter 20 | FeeGranter sdktypes.AccAddress 21 | // Msgs slice of messages to include on the tx 22 | Msgs []sdktypes.Msg 23 | } 24 | -------------------------------------------------------------------------------- /testutil/integration/common/grpc/account.go: -------------------------------------------------------------------------------- 1 | package grpc 2 | 3 | import ( 4 | "context" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 8 | ) 9 | 10 | // GetAccount returns the account for the given address. 11 | func (gqh *IntegrationHandler) GetAccount(address string) (sdk.AccountI, error) { 12 | authClient := gqh.network.GetAuthClient() 13 | res, err := authClient.Account(context.Background(), &authtypes.QueryAccountRequest{ 14 | Address: address, 15 | }) 16 | if err != nil { 17 | return nil, err 18 | } 19 | 20 | encodingCgf := gqh.network.GetEncodingConfig() 21 | var acc sdk.AccountI 22 | if err = encodingCgf.InterfaceRegistry.UnpackAny(res.Account, &acc); err != nil { 23 | return nil, err 24 | } 25 | return acc, nil 26 | } 27 | -------------------------------------------------------------------------------- /testutil/integration/os/grpc/feemarket.go: -------------------------------------------------------------------------------- 1 | package grpc 2 | 3 | import ( 4 | "context" 5 | 6 | feemarkettypes "github.com/cosmos/evm/x/feemarket/types" 7 | ) 8 | 9 | // GetBaseFee returns the base fee from the feemarket module. 10 | func (gqh *IntegrationHandler) GetBaseFee() (*feemarkettypes.QueryBaseFeeResponse, error) { 11 | feeMarketClient := gqh.network.GetFeeMarketClient() 12 | return feeMarketClient.BaseFee(context.Background(), &feemarkettypes.QueryBaseFeeRequest{}) 13 | } 14 | 15 | // GetBaseFee returns the base fee from the feemarket module. 16 | func (gqh *IntegrationHandler) GetFeeMarketParams() (*feemarkettypes.QueryParamsResponse, error) { 17 | feeMarketClient := gqh.network.GetFeeMarketClient() 18 | return feeMarketClient.Params(context.Background(), &feemarkettypes.QueryParamsRequest{}) 19 | } 20 | -------------------------------------------------------------------------------- /testutil/integration/os/grpc/gov.go: -------------------------------------------------------------------------------- 1 | package grpc 2 | 3 | import ( 4 | "fmt" 5 | "slices" 6 | 7 | govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1" 8 | ) 9 | 10 | // GetGovParams returns the gov params from the gov module. 11 | func (gqh *IntegrationHandler) GetGovParams(paramsType string) (*govtypes.QueryParamsResponse, error) { 12 | possibleTypes := []string{"deposit", "tallying", "voting"} 13 | if !slices.Contains(possibleTypes, paramsType) { 14 | return nil, fmt.Errorf("invalid params type: %s\npossible types: %s", paramsType, possibleTypes) 15 | } 16 | 17 | govClient := gqh.network.GetGovClient() 18 | return govClient.Params(gqh.network.GetContext(), &govtypes.QueryParamsRequest{ParamsType: paramsType}) 19 | } 20 | 21 | // GetProposal returns the proposal from the gov module. 22 | func (gqh *IntegrationHandler) GetProposal(proposalID uint64) (*govtypes.QueryProposalResponse, error) { 23 | govClient := gqh.network.GetGovClient() 24 | return govClient.Proposal(gqh.network.GetContext(), &govtypes.QueryProposalRequest{ProposalId: proposalID}) 25 | } 26 | -------------------------------------------------------------------------------- /testutil/integration/os/network/example_contracts.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | testconstants "github.com/cosmos/evm/testutil/constants" 5 | ) 6 | 7 | // chainsWEVMOSHex is an utility map used to retrieve the WEVMOS contract 8 | // address in hex format from the chain ID. 9 | // 10 | // TODO: refactor to define this in the example chain initialization and pass as function argument 11 | var chainsWEVMOSHex = map[testconstants.ChainID]string{ 12 | testconstants.ExampleChainID: testconstants.WEVMOSContractMainnet, 13 | } 14 | 15 | // GetWEVMOSContractHex returns the hex format of address for the WEVMOS contract 16 | // given the chainID. If the chainID is not found, it defaults to the mainnet 17 | // address. 18 | func GetWEVMOSContractHex(chainID testconstants.ChainID) string { 19 | address, found := chainsWEVMOSHex[chainID] 20 | 21 | // default to mainnet address 22 | if !found { 23 | address = chainsWEVMOSHex[testconstants.ExampleChainID] 24 | } 25 | 26 | return address 27 | } 28 | -------------------------------------------------------------------------------- /testutil/integration/os/network/ibc.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | "testing" 5 | 6 | ibctesting "github.com/cosmos/ibc-go/v10/testing" 7 | ) 8 | 9 | // GetIBCChain returns a TestChain instance for the given network. 10 | // Note: the sender accounts are not populated. Do not use this accounts to send transactions during tests. 11 | // The keyring should be used instead. 12 | func (n *IntegrationNetwork) GetIBCChain(t *testing.T, coord *ibctesting.Coordinator) *ibctesting.TestChain { 13 | t.Helper() 14 | return &ibctesting.TestChain{ 15 | TB: t, 16 | Coordinator: coord, 17 | ChainID: n.GetChainID(), 18 | App: n.app, 19 | TxConfig: n.app.GetTxConfig(), 20 | Codec: n.app.AppCodec(), 21 | Vals: n.valSet, 22 | NextVals: n.valSet, 23 | Signers: n.valSigners, 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /testutil/integration/os/utils/types.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "github.com/ethereum/go-ethereum/common" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | ) 8 | 9 | func ValidatorConsAddressToHex(valAddress string) common.Address { 10 | coinbaseAddressBytes := sdk.ConsAddress(valAddress).Bytes() 11 | return common.BytesToAddress(coinbaseAddressBytes) 12 | } 13 | -------------------------------------------------------------------------------- /testutil/pair.go: -------------------------------------------------------------------------------- 1 | package testutil 2 | -------------------------------------------------------------------------------- /testutil/statedb.go: -------------------------------------------------------------------------------- 1 | package testutil 2 | 3 | import ( 4 | "github.com/ethereum/go-ethereum/common" 5 | 6 | anteinterfaces "github.com/cosmos/evm/ante/interfaces" 7 | "github.com/cosmos/evm/x/vm/statedb" 8 | 9 | sdk "github.com/cosmos/cosmos-sdk/types" 10 | ) 11 | 12 | // NewStateDB returns a new StateDB for testing purposes. 13 | func NewStateDB(ctx sdk.Context, evmKeeper anteinterfaces.EVMKeeper) *statedb.StateDB { 14 | return statedb.New(ctx, evmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash()))) 15 | } 16 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 120 3 | exclude = */node_modules 4 | ignore = E203,W503 -------------------------------------------------------------------------------- /types/block.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | math "math" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | ) 8 | 9 | // BlockGasLimit returns the max gas (limit) defined in the block gas meter. If the meter is not 10 | // set, it returns the max gas from the application consensus params. 11 | // NOTE: see https://github.com/cosmos/cosmos-sdk/issues/9514 for full reference 12 | func BlockGasLimit(ctx sdk.Context) uint64 { 13 | blockGasMeter := ctx.BlockGasMeter() 14 | 15 | // Get the limit from the gas meter only if its not null and not an InfiniteGasMeter 16 | if blockGasMeter != nil && blockGasMeter.Limit() != 0 { 17 | return blockGasMeter.Limit() 18 | } 19 | 20 | // Otherwise get from the consensus parameters 21 | cp := ctx.ConsensusParams() 22 | if cp.Block == nil { 23 | return 0 24 | } 25 | 26 | maxGas := cp.Block.MaxGas 27 | 28 | // Setting max_gas to -1 in Tendermint means there is no limit on the maximum gas consumption for transactions 29 | // https://github.com/cometbft/cometbft/blob/v0.37.2/proto/tendermint/types/params.proto#L25-L27 30 | if maxGas == -1 { 31 | return math.MaxUint64 32 | } 33 | 34 | if maxGas > 0 { 35 | return uint64(maxGas) // #nosec G115 -- maxGas is int64 type. It can never be greater than math.MaxUint64 36 | } 37 | 38 | return 0 39 | } 40 | -------------------------------------------------------------------------------- /types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 5 | sdktypes "github.com/cosmos/cosmos-sdk/types" 6 | "github.com/cosmos/cosmos-sdk/types/tx" 7 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 8 | ) 9 | 10 | // RegisterInterfaces registers the tendermint concrete client-related 11 | // implementations and interfaces. 12 | func RegisterInterfaces(registry codectypes.InterfaceRegistry) { 13 | registry.RegisterImplementations( 14 | (*sdktypes.AccountI)(nil), 15 | // TODO: uncomment after moving into migrations for EVM version 16 | // &EthAccount{}, 17 | ) 18 | registry.RegisterImplementations( 19 | (*authtypes.GenesisAccount)(nil), 20 | // TODO: uncomment after moving into migrations for EVM version 21 | // &EthAccount{}, 22 | ) 23 | registry.RegisterImplementations( 24 | (*tx.TxExtensionOptionI)(nil), 25 | &ExtensionOptionsWeb3Tx{}, 26 | &ExtensionOptionDynamicFeeTx{}, 27 | ) 28 | } 29 | -------------------------------------------------------------------------------- /types/dynamic_fee.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 5 | ) 6 | 7 | // HasDynamicFeeExtensionOption returns true if the tx implements the `ExtensionOptionDynamicFeeTx` extension option. 8 | func HasDynamicFeeExtensionOption(anyType *codectypes.Any) bool { 9 | _, ok := anyType.GetCachedValue().(*ExtensionOptionDynamicFeeTx) 10 | return ok 11 | } 12 | -------------------------------------------------------------------------------- /types/errors.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | errorsmod "cosmossdk.io/errors" 5 | ) 6 | 7 | // RootCodespace is the codespace for all errors defined in this package 8 | const RootCodespace = "Cosmos EVM" 9 | 10 | // ErrInvalidChainID returns an error resulting from an invalid chain ID. 11 | var ErrInvalidChainID = errorsmod.Register(RootCodespace, 3, "invalid chain ID") 12 | -------------------------------------------------------------------------------- /types/genesis.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import "encoding/json" 4 | 5 | // GenesisState of the blockchain is represented here as a map of raw json 6 | // messages key'd by a identifier string. 7 | // The identifier is used to determine which module genesis information belongs 8 | // to so it may be appropriately routed during init chain. 9 | // Within this application default genesis information is retrieved from 10 | // the ModuleBasicManager which populates json from each BasicModule 11 | // object provided to it during init. 12 | type GenesisState map[string]json.RawMessage 13 | -------------------------------------------------------------------------------- /types/hdpath.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | ethaccounts "github.com/ethereum/go-ethereum/accounts" 5 | ) 6 | 7 | var ( 8 | // Bip44CoinType satisfies EIP84. See https://github.com/ethereum/EIPs/issues/84 for more info. 9 | Bip44CoinType uint32 = 60 10 | 11 | // BIP44HDPath is the default BIP44 HD path used on Ethereum. 12 | BIP44HDPath = ethaccounts.DefaultBaseDerivationPath.String() 13 | ) 14 | 15 | type ( 16 | HDPathIterator func() ethaccounts.DerivationPath 17 | ) 18 | 19 | // NewHDPathIterator receives a base path as a string and a boolean for the desired iterator type and 20 | // returns a function that iterates over the base HD path, returning the string. 21 | func NewHDPathIterator(basePath string, ledgerIter bool) (HDPathIterator, error) { 22 | hdPath, err := ethaccounts.ParseDerivationPath(basePath) 23 | if err != nil { 24 | return nil, err 25 | } 26 | 27 | if ledgerIter { 28 | return ethaccounts.LedgerLiveIterator(hdPath), nil 29 | } 30 | 31 | return ethaccounts.DefaultIterator(hdPath), nil 32 | } 33 | -------------------------------------------------------------------------------- /types/indexer.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/ethereum/go-ethereum/common" 5 | 6 | abci "github.com/cometbft/cometbft/abci/types" 7 | cmttypes "github.com/cometbft/cometbft/types" 8 | ) 9 | 10 | // EVMTxIndexer defines the interface of custom eth tx indexer. 11 | type EVMTxIndexer interface { 12 | // LastIndexedBlock returns -1 if indexer db is empty 13 | LastIndexedBlock() (int64, error) 14 | IndexBlock(*cmttypes.Block, []*abci.ExecTxResult) error 15 | 16 | // GetByTxHash returns nil if tx not found. 17 | GetByTxHash(common.Hash) (*TxResult, error) 18 | // GetByBlockAndIndex returns nil if tx not found. 19 | GetByBlockAndIndex(int64, int32) (*TxResult, error) 20 | } 21 | -------------------------------------------------------------------------------- /types/int.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | fmt "fmt" 5 | math "math" 6 | "math/big" 7 | 8 | errorsmod "cosmossdk.io/errors" 9 | sdkmath "cosmossdk.io/math" 10 | 11 | errortypes "github.com/cosmos/cosmos-sdk/types/errors" 12 | ) 13 | 14 | const maxBitLen = 256 15 | 16 | // SafeInt64 checks for overflows while casting a uint64 to int64 value. 17 | func SafeInt64(value uint64) (int64, error) { 18 | if value > uint64(math.MaxInt64) { 19 | return 0, errorsmod.Wrapf(errortypes.ErrInvalidHeight, "uint64 value %v cannot exceed %v", value, int64(math.MaxInt64)) 20 | } 21 | 22 | return int64(value), nil // #nosec G115 -- checked for int overflow already 23 | } 24 | 25 | // SafeNewIntFromBigInt constructs Int from big.Int, return error if more than 256bits 26 | func SafeNewIntFromBigInt(i *big.Int) (sdkmath.Int, error) { 27 | if !IsValidInt256(i) { 28 | return sdkmath.NewInt(0), fmt.Errorf("big int out of bound: %s", i) 29 | } 30 | return sdkmath.NewIntFromBigInt(i), nil 31 | } 32 | 33 | // IsValidInt256 check the bound of 256 bit number 34 | func IsValidInt256(i *big.Int) bool { 35 | return i == nil || i.BitLen() <= maxBitLen 36 | } 37 | -------------------------------------------------------------------------------- /types/power.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "math/big" 5 | 6 | "cosmossdk.io/math" 7 | ) 8 | 9 | var ( 10 | // AttoPowerReduction defines the power reduction for att units (1e18) 11 | AttoPowerReduction = math.NewIntFromBigInt(new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)) 12 | 13 | // MicroPowerReduction defines the power reduction for micro units (1e6) 14 | MicroPowerReduction = math.NewIntFromBigInt(new(big.Int).Exp(big.NewInt(10), big.NewInt(6), nil)) 15 | ) 16 | -------------------------------------------------------------------------------- /types/protocol.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // Constants to match up protocol versions and messages 4 | const ( 5 | eth65 = 65 6 | 7 | // ProtocolVersion is the latest supported version of the eth protocol. 8 | ProtocolVersion = eth65 9 | ) 10 | -------------------------------------------------------------------------------- /utils/eth/eth.go: -------------------------------------------------------------------------------- 1 | package eth 2 | 3 | import "math/big" 4 | 5 | // DeriveChainID derives the chain id from the given v parameter. 6 | // 7 | // CONTRACT: v value is either: 8 | // 9 | // - {0,1} + CHAIN_ID * 2 + 35, if EIP155 is used 10 | // - {0,1} + 27, otherwise 11 | // 12 | // Ref: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md 13 | func DeriveChainID(v *big.Int) *big.Int { 14 | if v == nil || v.Sign() < 1 { 15 | return nil 16 | } 17 | 18 | if v.BitLen() <= 64 { 19 | v := v.Uint64() 20 | if v == 27 || v == 28 { 21 | return new(big.Int) 22 | } 23 | 24 | if v < 35 { 25 | return nil 26 | } 27 | 28 | // V MUST be of the form {0,1} + CHAIN_ID * 2 + 35 29 | return new(big.Int).SetUint64((v - 35) / 2) 30 | } 31 | v = new(big.Int).Sub(v, big.NewInt(35)) 32 | return v.Div(v, big.NewInt(2)) 33 | } 34 | 35 | // RawSignatureValues is a helper function 36 | // that parses the v,r and s fields of an Ethereum transaction 37 | func RawSignatureValues(vBz, rBz, sBz []byte) (v, r, s *big.Int) { 38 | if len(vBz) > 0 { 39 | v = new(big.Int).SetBytes(vBz) 40 | } 41 | if len(rBz) > 0 { 42 | r = new(big.Int).SetBytes(rBz) 43 | } 44 | if len(sBz) > 0 { 45 | s = new(big.Int).SetBytes(sBz) 46 | } 47 | return v, r, s 48 | } 49 | -------------------------------------------------------------------------------- /version/version.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | import ( 4 | "fmt" 5 | "runtime" 6 | ) 7 | 8 | var ( 9 | AppVersion = "" 10 | GitCommit = "" 11 | BuildDate = "" 12 | 13 | GoVersion = "" 14 | GoArch = "" 15 | ) 16 | 17 | func init() { 18 | if len(AppVersion) == 0 { 19 | AppVersion = "dev" 20 | } 21 | 22 | GoVersion = runtime.Version() 23 | GoArch = runtime.GOARCH 24 | } 25 | 26 | func Version() string { 27 | return fmt.Sprintf( 28 | "Version %s (%s)\nCompiled at %s using Go %s (%s)", 29 | AppVersion, 30 | GitCommit, 31 | BuildDate, 32 | GoVersion, 33 | GoArch, 34 | ) 35 | } 36 | -------------------------------------------------------------------------------- /x/erc20/client/cli/metadata/coin_metadata_test.json: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": [ 3 | { 4 | "description": "The native staking and governance token of the Cosmos EVM chain", 5 | "denom_units": [ 6 | { 7 | "denom": "aatom", 8 | "exponent": 0 9 | }, 10 | { 11 | "denom": "atom", 12 | "exponent": 18 13 | } 14 | ], 15 | "base": "aatom", 16 | "display": "aatom", 17 | "name": "aatom", 18 | "symbol": "ATOM" 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /x/erc20/client/cli/metadata/coins_metadata_test.json: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": [ 3 | { 4 | "description": "The native staking and governance token of the Cosmos EVM chain", 5 | "denom_units": [ 6 | { 7 | "denom": "aatom", 8 | "exponent": 0 9 | }, 10 | { 11 | "denom": "atom", 12 | "exponent": 18 13 | } 14 | ], 15 | "base": "aatom", 16 | "display": "aatom", 17 | "name": "aatom", 18 | "symbol": "ATOM" 19 | }, 20 | { 21 | "description": "The native staking and governance token of the Osmosis chain", 22 | "denom_units": [ 23 | { 24 | "denom": "ibc/0429A217F7AFD21E67CABA80049DD56BB0380B77E9C58C831366D6626D42F399", 25 | "exponent": 0, 26 | "aliases": [ 27 | "ibcuosmo" 28 | ] 29 | }, 30 | { 31 | "denom": "OSMO", 32 | "exponent": 6 33 | } 34 | ], 35 | "base": "ibc/0429A217F7AFD21E67CABA80049DD56BB0380B77E9C58C831366D6626D42F399", 36 | "display": "OSMO", 37 | "name": "Osmo", 38 | "symbol": "OSMO" 39 | } 40 | ] 41 | } -------------------------------------------------------------------------------- /x/erc20/client/cli/metadata/invalid_metadata_test.json: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": [ 3 | { 4 | "description": 1, 5 | "denom_units": [ 6 | { 7 | "denom": "aatom", 8 | "exponent": 0 9 | }, 10 | { 11 | "denom": "atom", 12 | "exponent": 18 13 | } 14 | ], 15 | "base": "aatom", 16 | "display": "aatom", 17 | "name": "aatom", 18 | "symbol": "ATOM" 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /x/erc20/keeper/testdata/ERC20DirectBalanceManipulation.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol"; 6 | 7 | // This is an evil token. Whenever an A -> B transfer is called, half of the amount goes to B 8 | // and half to a predefined C 9 | contract ERC20DirectBalanceManipulation is ERC20PresetMinterPauser { 10 | address private _thief = 0x4dC6ac40Af078661fc43823086E1513635Eeab14; 11 | constructor(uint256 initialSupply) 12 | ERC20PresetMinterPauser("ERC20DirectBalanceManipulation", "ERC20DirectBalanceManipulation") { 13 | _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); 14 | _mint(msg.sender, initialSupply); 15 | } 16 | function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 17 | // Any time a transaction happens, the thief account siphons half. 18 | uint256 half = amount / 2; 19 | 20 | super.transfer(_thief, amount - half); // a - h for rounding 21 | return super.transfer(recipient, half); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /x/erc20/keeper/testdata/ERC20MaliciousDelayed.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol"; 6 | 7 | // This is an evil token. Whenever an A -> B transfer is called, 8 | // a predefined C is given a massive allowance on B. 9 | contract ERC20MaliciousDelayed is ERC20PresetMinterPauser { 10 | address private _thief = 0x4dC6ac40Af078661fc43823086E1513635Eeab14; 11 | uint256 private _bigNum = 1000000000000000000; // ~uint256(0) 12 | constructor(uint256 initialSupply) 13 | ERC20PresetMinterPauser("ERC20MaliciousDelayed", "ERC20MALICIOUSDELAYED") { 14 | _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); 15 | _mint(msg.sender, initialSupply); 16 | 17 | } 18 | function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 19 | // Any time a transaction happens, the thief account is granted allowance in secret. 20 | // Still emits an Approve! 21 | super._approve(recipient, _thief, _bigNum); 22 | return super.transfer(recipient, amount); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /x/erc20/keeper/testdata/erc20DirectBalanceManipulation.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import ( 4 | contractutils "github.com/cosmos/evm/contracts/utils" 5 | evmtypes "github.com/cosmos/evm/x/vm/types" 6 | ) 7 | 8 | // LoadBalanceManipulationContract loads the ERC20DirectBalanceManipulation contract 9 | // from the compiled JSON data. 10 | // 11 | // This is an evil token. Whenever an A -> B transfer is called, 12 | // a predefined C is given a massive allowance on B. 13 | func LoadBalanceManipulationContract() (evmtypes.CompiledContract, error) { 14 | return contractutils.LoadContractFromJSONFile("ERC20DirectBalanceManipulation.json") 15 | } 16 | -------------------------------------------------------------------------------- /x/erc20/keeper/testdata/erc20maliciousdelayed.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import ( 4 | contractutils "github.com/cosmos/evm/contracts/utils" 5 | evmtypes "github.com/cosmos/evm/x/vm/types" 6 | ) 7 | 8 | // LoadMaliciousDelayedContract loads the ERC20MaliciousDelayed contract. 9 | // 10 | // This is an evil token. Whenever an A -> B transfer is called, 11 | // a predefined C is given a massive allowance on B. 12 | func LoadMaliciousDelayedContract() (evmtypes.CompiledContract, error) { 13 | return contractutils.LoadContractFromJSONFile("ERC20MaliciousDelayed.json") 14 | } 15 | -------------------------------------------------------------------------------- /x/erc20/types/allowance.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "math/big" 5 | 6 | "github.com/ethereum/go-ethereum/common" 7 | 8 | errorsmod "cosmossdk.io/errors" 9 | "cosmossdk.io/math" 10 | 11 | errortypes "github.com/cosmos/cosmos-sdk/types/errors" 12 | ) 13 | 14 | func NewAllowance(erc20 common.Address, owner common.Address, spender common.Address, value *big.Int) Allowance { 15 | return Allowance{ 16 | Erc20Address: erc20.Hex(), 17 | Owner: owner.Hex(), 18 | Spender: spender.Hex(), 19 | Value: math.NewIntFromBigInt(value), 20 | } 21 | } 22 | 23 | func (a Allowance) Validate() error { 24 | if !common.IsHexAddress(a.Erc20Address) { 25 | return errorsmod.Wrapf(errortypes.ErrInvalidAddress, "invalid erc20 hex address %s", a.Erc20Address) 26 | } 27 | 28 | if !common.IsHexAddress(a.Owner) { 29 | return errorsmod.Wrapf(errortypes.ErrInvalidAddress, "invalid owner hex address %s", a.Owner) 30 | } 31 | 32 | if !common.IsHexAddress(a.Spender) { 33 | return errorsmod.Wrapf(errortypes.ErrInvalidAddress, "invalid sender hex address %s", a.Spender) 34 | } 35 | 36 | if !a.Value.IsPositive() { 37 | return errorsmod.Wrap(ErrInvalidAllowance, "invalid allowance value") 38 | } 39 | 40 | return nil 41 | } 42 | -------------------------------------------------------------------------------- /x/erc20/types/events.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "math/big" 5 | 6 | "github.com/ethereum/go-ethereum/common" 7 | ) 8 | 9 | // erc20 events 10 | const ( 11 | EventTypeConvertERC20 = "convert_erc20" 12 | EventTypeRegisterERC20 = "register_erc20" 13 | EventTypeToggleTokenConversion = "toggle_token_conversion" // #nosec 14 | EventTypeRegisterERC20Extension = "register_erc20_extension" 15 | 16 | AttributeCoinSourceChannel = "source_channel" 17 | AttributeKeyCosmosCoin = "cosmos_coin" 18 | AttributeKeyERC20Token = "erc20_token" // #nosec 19 | AttributeKeyReceiver = "receiver" 20 | ) 21 | 22 | // LogTransfer Event type for Transfer(address from, address to, uint256 value) 23 | type LogTransfer struct { 24 | From common.Address 25 | To common.Address 26 | Tokens *big.Int 27 | } 28 | -------------------------------------------------------------------------------- /x/erc20/types/evm.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // ERC20Data represents the ERC20 token details used to map 4 | // the token to a Cosmos Coin 5 | type ERC20Data struct { 6 | Name string 7 | Symbol string 8 | Decimals uint8 9 | } 10 | 11 | // ERC20StringResponse defines the string value from the call response 12 | type ERC20StringResponse struct { 13 | Value string 14 | } 15 | 16 | // ERC20Uint8Response defines the uint8 value from the call response 17 | type ERC20Uint8Response struct { 18 | Value uint8 19 | } 20 | 21 | // ERC20BoolResponse defines the bool value from the call response 22 | type ERC20BoolResponse struct { 23 | Value bool 24 | } 25 | 26 | // NewERC20Data creates a new ERC20Data instance 27 | func NewERC20Data(name, symbol string, decimals uint8) ERC20Data { 28 | return ERC20Data{ 29 | Name: name, 30 | Symbol: symbol, 31 | Decimals: decimals, 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /x/erc20/types/evm_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | "github.com/cosmos/evm/x/erc20/types" 9 | ) 10 | 11 | func TestNewERC20Data(t *testing.T) { 12 | data := types.NewERC20Data("test", "ERC20", uint8(18)) 13 | exp := types.ERC20Data{Name: "test", Symbol: "ERC20", Decimals: 0x12} 14 | require.Equal(t, exp, data) 15 | } 16 | -------------------------------------------------------------------------------- /x/erc20/types/mocks/README.md: -------------------------------------------------------------------------------- 1 | # Mocks 2 | 3 | The mocks in this folder have been generated using the [mockery](https://vektra.github.io/mockery/latest/) tool. 4 | To regenerate the mocks, run the following commands at the root of this repository: 5 | 6 | - `BankKeeper` (from used version of Cosmos SDK): 7 | 8 | ```bash 9 | # update the currently used version 10 | COSMOS_VERSION="v0.50.9-evmos" 11 | CUR_DIR="$(pwd)" 12 | TMP_DIR="/tmp/tmp-sdk-mocks-$(date +%s)" 13 | 14 | echo "Cloning Cosmos SDK $COSMOS_VERSION into $TMP_DIR..." && 15 | git clone --depth 1 --branch "$COSMOS_VERSION" https://github.com/evmos/cosmos-sdk.git "$TMP_DIR" && 16 | cd "$TMP_DIR" && 17 | 18 | # Go into bank module and generate mock 19 | echo "Generating mocks for bank keeper..." && 20 | cd x/bank/keeper && 21 | mockery --name Keeper && 22 | sed -i '' 's/\([^a-zA-Z]\)Keeper/\1BankKeeper/g' mocks/Keeper.go && 23 | mv mocks/Keeper.go "$CUR_DIR/x/erc20/types/mocks/BankKeeper.go" && 24 | 25 | # Clean up 26 | echo "Cleaning up $TMP_DIR..." && 27 | cd "$CUR_DIR" && 28 | rm -rf "$TMP_DIR" 29 | 30 | echo "Done." 31 | ``` 32 | 33 | - `EVMKeeper` (reduced interface defined in ERC20 types): 34 | 35 | ```bash 36 | cd x/erc20/types 37 | mockery --name EVMKeeper 38 | ``` 39 | -------------------------------------------------------------------------------- /x/feemarket/genesis.go: -------------------------------------------------------------------------------- 1 | package feemarket 2 | 3 | import ( 4 | abci "github.com/cometbft/cometbft/abci/types" 5 | 6 | "github.com/cosmos/evm/x/feemarket/keeper" 7 | "github.com/cosmos/evm/x/feemarket/types" 8 | 9 | errorsmod "cosmossdk.io/errors" 10 | 11 | sdk "github.com/cosmos/cosmos-sdk/types" 12 | ) 13 | 14 | // InitGenesis initializes genesis state based on exported genesis 15 | func InitGenesis( 16 | ctx sdk.Context, 17 | k keeper.Keeper, 18 | data types.GenesisState, 19 | ) []abci.ValidatorUpdate { 20 | err := k.SetParams(ctx, data.Params) 21 | if err != nil { 22 | panic(errorsmod.Wrap(err, "could not set parameters at genesis")) 23 | } 24 | 25 | k.SetBlockGasWanted(ctx, data.BlockGas) 26 | 27 | return []abci.ValidatorUpdate{} 28 | } 29 | 30 | // ExportGenesis exports genesis state of the fee market module 31 | func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { 32 | return &types.GenesisState{ 33 | Params: k.GetParams(ctx), 34 | BlockGas: k.GetBlockGasWanted(ctx), 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /x/feemarket/keeper/msg_server.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/cosmos/evm/x/feemarket/types" 7 | 8 | errorsmod "cosmossdk.io/errors" 9 | 10 | sdk "github.com/cosmos/cosmos-sdk/types" 11 | govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" 12 | ) 13 | 14 | // UpdateParams implements the gRPC MsgServer interface. When an UpdateParams 15 | // proposal passes, it updates the module parameters. The update can only be 16 | // performed if the requested authority is the Cosmos SDK governance module 17 | // account. 18 | func (k *Keeper) UpdateParams(goCtx context.Context, req *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) { 19 | if k.authority.String() != req.Authority { 20 | return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", k.authority.String(), req.Authority) 21 | } 22 | 23 | ctx := sdk.UnwrapSDKContext(goCtx) 24 | if err := k.SetParams(ctx, req.Params); err != nil { 25 | return nil, err 26 | } 27 | 28 | return &types.MsgUpdateParamsResponse{}, nil 29 | } 30 | -------------------------------------------------------------------------------- /x/feemarket/keeper/setup_test.go: -------------------------------------------------------------------------------- 1 | package keeper_test 2 | 3 | import ( 4 | "github.com/stretchr/testify/suite" 5 | 6 | "github.com/cosmos/evm/testutil/integration/os/factory" 7 | "github.com/cosmos/evm/testutil/integration/os/grpc" 8 | testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" 9 | "github.com/cosmos/evm/testutil/integration/os/network" 10 | 11 | "github.com/cosmos/cosmos-sdk/baseapp" 12 | ) 13 | 14 | type KeeperTestSuite struct { 15 | suite.Suite 16 | 17 | network *network.UnitTestNetwork 18 | factory factory.TxFactory 19 | grpcHandler grpc.Handler 20 | keyring testkeyring.Keyring 21 | 22 | denom string 23 | } 24 | 25 | // SetupTest setup test environment 26 | func (suite *KeeperTestSuite) SetupTest() { 27 | keyring := testkeyring.New(2) 28 | nw := network.NewUnitTestNetwork( 29 | network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), 30 | network.WithCustomBaseAppOpts(baseapp.SetMinGasPrices("10aatom")), 31 | ) 32 | grpcHandler := grpc.NewIntegrationHandler(nw) 33 | txFactory := factory.New(nw, grpcHandler) 34 | 35 | ctx := nw.GetContext() 36 | sk := nw.App.StakingKeeper 37 | bondDenom, err := sk.BondDenom(ctx) 38 | if err != nil { 39 | panic(err) 40 | } 41 | 42 | suite.denom = bondDenom 43 | suite.factory = txFactory 44 | suite.grpcHandler = grpcHandler 45 | suite.keyring = keyring 46 | suite.network = nw 47 | } 48 | -------------------------------------------------------------------------------- /x/feemarket/types/events.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // feemarket module events 4 | const ( 5 | EventTypeFeeMarket = "fee_market" 6 | 7 | AttributeKeyBaseFee = "base_fee" 8 | ) 9 | -------------------------------------------------------------------------------- /x/feemarket/types/genesis.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // DefaultGenesisState sets default fee market genesis state. 4 | func DefaultGenesisState() *GenesisState { 5 | return &GenesisState{ 6 | Params: DefaultParams(), 7 | BlockGas: 0, 8 | } 9 | } 10 | 11 | // NewGenesisState creates a new genesis state. 12 | func NewGenesisState(params Params, blockGas uint64) *GenesisState { 13 | return &GenesisState{ 14 | Params: params, 15 | BlockGas: blockGas, 16 | } 17 | } 18 | 19 | // Validate performs basic genesis state validation returning an error upon any 20 | // failure. 21 | func (gs GenesisState) Validate() error { 22 | return gs.Params.Validate() 23 | } 24 | -------------------------------------------------------------------------------- /x/feemarket/types/genesis_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/suite" 7 | ) 8 | 9 | type GenesisTestSuite struct { 10 | suite.Suite 11 | } 12 | 13 | func TestGenesisTestSuite(t *testing.T) { 14 | suite.Run(t, new(GenesisTestSuite)) 15 | } 16 | 17 | func (suite *GenesisTestSuite) TestValidateGenesis() { 18 | testCases := []struct { 19 | name string 20 | genState *GenesisState 21 | expPass bool 22 | }{ 23 | { 24 | "default", 25 | DefaultGenesisState(), 26 | true, 27 | }, 28 | { 29 | "valid genesis", 30 | &GenesisState{ 31 | DefaultParams(), 32 | uint64(1), 33 | }, 34 | true, 35 | }, 36 | { 37 | "valid New genesis", 38 | NewGenesisState( 39 | DefaultParams(), 40 | uint64(1), 41 | ), 42 | true, 43 | }, 44 | { 45 | "empty genesis", 46 | &GenesisState{ 47 | Params: Params{}, 48 | BlockGas: 0, 49 | }, 50 | false, 51 | }, 52 | } 53 | 54 | for _, tc := range testCases { 55 | err := tc.genState.Validate() 56 | if tc.expPass { 57 | suite.Require().NoError(err, tc.name) 58 | } else { 59 | suite.Require().Error(err, tc.name) 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /x/feemarket/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ModuleName string name of module 5 | ModuleName = "feemarket" 6 | 7 | // StoreKey key for base fee and block gas used. 8 | // The Fee Market module should use a prefix store. 9 | StoreKey = ModuleName 10 | 11 | // RouterKey uses module name for routing 12 | RouterKey = ModuleName 13 | 14 | // TransientKey is the key to access the FeeMarket transient store, that is reset 15 | // during the Commit phase. 16 | TransientKey = "transient_" + ModuleName 17 | ) 18 | 19 | // prefix bytes for the feemarket persistent store 20 | const ( 21 | prefixBlockGasWanted = iota + 1 22 | deprecatedPrefixBaseFee // unused 23 | ) 24 | 25 | const ( 26 | prefixTransientBlockGasUsed = iota + 1 27 | ) 28 | 29 | // KVStore key prefixes 30 | var ( 31 | KeyPrefixBlockGasWanted = []byte{prefixBlockGasWanted} 32 | ) 33 | 34 | // Transient Store key prefixes 35 | var ( 36 | KeyPrefixTransientBlockGasWanted = []byte{prefixTransientBlockGasUsed} 37 | ) 38 | -------------------------------------------------------------------------------- /x/feemarket/types/msg.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | errorsmod "cosmossdk.io/errors" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | ) 8 | 9 | var _ sdk.Msg = &MsgUpdateParams{} 10 | 11 | // ValidateBasic does a sanity check of the provided data 12 | func (m *MsgUpdateParams) ValidateBasic() error { 13 | if _, err := sdk.AccAddressFromBech32(m.Authority); err != nil { 14 | return errorsmod.Wrap(err, "invalid authority address") 15 | } 16 | 17 | return m.Params.Validate() 18 | } 19 | 20 | // GetSignBytes implements the LegacyMsg interface. 21 | func (m MsgUpdateParams) GetSignBytes() []byte { 22 | return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&m)) 23 | } 24 | -------------------------------------------------------------------------------- /x/feemarket/types/msg_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/suite" 7 | 8 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 9 | govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" 10 | ) 11 | 12 | type MsgsTestSuite struct { 13 | suite.Suite 14 | } 15 | 16 | func TestMsgsTestSuite(t *testing.T) { 17 | suite.Run(t, new(MsgsTestSuite)) 18 | } 19 | 20 | func (suite *MsgsTestSuite) TestMsgUpdateValidateBasic() { 21 | testCases := []struct { 22 | name string 23 | msgUpdate *MsgUpdateParams 24 | expPass bool 25 | }{ 26 | { 27 | "fail - invalid authority address", 28 | &MsgUpdateParams{ 29 | Authority: "invalid", 30 | Params: DefaultParams(), 31 | }, 32 | false, 33 | }, 34 | { 35 | "pass - valid msg", 36 | &MsgUpdateParams{ 37 | Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(), 38 | Params: DefaultParams(), 39 | }, 40 | true, 41 | }, 42 | } 43 | 44 | for _, tc := range testCases { 45 | suite.Run(tc.name, func() { 46 | err := tc.msgUpdate.ValidateBasic() 47 | if tc.expPass { 48 | suite.NoError(err) 49 | } else { 50 | suite.Error(err) 51 | } 52 | }) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /x/ibc/transfer/ibc_module.go: -------------------------------------------------------------------------------- 1 | package transfer 2 | 3 | import ( 4 | "github.com/cosmos/evm/x/ibc/transfer/keeper" 5 | ibctransfer "github.com/cosmos/ibc-go/v10/modules/apps/transfer" 6 | porttypes "github.com/cosmos/ibc-go/v10/modules/core/05-port/types" 7 | ) 8 | 9 | var _ porttypes.IBCModule = IBCModule{} 10 | 11 | // IBCModule implements the ICS26 interface for transfer given the transfer keeper. 12 | type IBCModule struct { 13 | *ibctransfer.IBCModule 14 | } 15 | 16 | // NewIBCModule creates a new IBCModule given the keeper 17 | func NewIBCModule(k keeper.Keeper) IBCModule { 18 | transferModule := ibctransfer.NewIBCModule(*k.Keeper) 19 | return IBCModule{ 20 | IBCModule: &transferModule, 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /x/ibc/transfer/types/channels.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // Osmosis channels 4 | const ( 5 | OsmosisTestnetChannelID = "channel-215" 6 | OsmosisMainnetChannelID = "channel-0" 7 | ) 8 | 9 | // Stride channels 10 | const ( 11 | StrideTestnetChannelID = "channel-25" 12 | StrideMainnetChannelID = "channel-25" 13 | ) 14 | -------------------------------------------------------------------------------- /x/ibc/transfer/types/interfaces.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "context" 5 | 6 | erc20types "github.com/cosmos/evm/x/erc20/types" 7 | transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" 8 | 9 | sdk "github.com/cosmos/cosmos-sdk/types" 10 | ) 11 | 12 | // AccountKeeper defines the expected interface needed to retrieve account info. 13 | type AccountKeeper interface { 14 | transfertypes.AccountKeeper 15 | GetAccount(context.Context, sdk.AccAddress) sdk.AccountI 16 | } 17 | 18 | // BankKeeper defines the expected interface needed to check balances and send coins. 19 | type BankKeeper interface { 20 | transfertypes.BankKeeper 21 | GetBalance(ctx context.Context, addr sdk.AccAddress, denom string) sdk.Coin 22 | } 23 | 24 | // ERC20Keeper defines the expected ERC20 keeper interface for supporting 25 | // ERC20 token transfers via IBC. 26 | type ERC20Keeper interface { 27 | IsERC20Enabled(ctx sdk.Context) bool 28 | GetTokenPairID(ctx sdk.Context, token string) []byte 29 | GetTokenPair(ctx sdk.Context, id []byte) (erc20types.TokenPair, bool) 30 | ConvertERC20(ctx context.Context, msg *erc20types.MsgConvertERC20) (*erc20types.MsgConvertERC20Response, error) 31 | } 32 | -------------------------------------------------------------------------------- /x/ibc/transfer/v2/ibc_module.go: -------------------------------------------------------------------------------- 1 | package v2 2 | 3 | import ( 4 | "github.com/cosmos/evm/x/ibc/transfer/keeper" 5 | v2 "github.com/cosmos/ibc-go/v10/modules/apps/transfer/v2" 6 | ibcapi "github.com/cosmos/ibc-go/v10/modules/core/api" 7 | ) 8 | 9 | var _ ibcapi.IBCModule = IBCModule{} 10 | 11 | // IBCModule implements the ICS26 interface for transfer given the transfer keeper. 12 | type IBCModule struct { 13 | *v2.IBCModule 14 | } 15 | 16 | // NewIBCModule creates a new IBCModule given the keeper 17 | func NewIBCModule(k keeper.Keeper) IBCModule { 18 | transferModule := v2.NewIBCModule(*k.Keeper) 19 | return IBCModule{ 20 | IBCModule: transferModule, 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /x/precisebank/keeper/keeper.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/cosmos/evm/x/precisebank/types" 7 | evmtypes "github.com/cosmos/evm/x/vm/types" 8 | 9 | storetypes "cosmossdk.io/store/types" 10 | 11 | "github.com/cosmos/cosmos-sdk/codec" 12 | sdk "github.com/cosmos/cosmos-sdk/types" 13 | ) 14 | 15 | // Enforce that Keeper implements the expected keeper interfaces 16 | var _ evmtypes.BankKeeper = Keeper{} 17 | 18 | // Keeper defines the precisebank module's keeper 19 | type Keeper struct { 20 | cdc codec.BinaryCodec 21 | storeKey storetypes.StoreKey 22 | 23 | bk types.BankKeeper 24 | ak types.AccountKeeper 25 | } 26 | 27 | // NewKeeper creates a new keeper 28 | func NewKeeper( 29 | cdc codec.BinaryCodec, 30 | storeKey storetypes.StoreKey, 31 | bk types.BankKeeper, 32 | ak types.AccountKeeper, 33 | ) Keeper { 34 | return Keeper{ 35 | cdc: cdc, 36 | storeKey: storeKey, 37 | bk: bk, 38 | ak: ak, 39 | } 40 | } 41 | 42 | func (k Keeper) IterateTotalSupply(ctx context.Context, cb func(coin sdk.Coin) bool) { 43 | k.bk.IterateTotalSupply(ctx, cb) 44 | } 45 | 46 | func (k Keeper) GetSupply(ctx context.Context, denom string) sdk.Coin { 47 | return k.bk.GetSupply(ctx, denom) 48 | } 49 | -------------------------------------------------------------------------------- /x/precisebank/keeper/setup_test.go: -------------------------------------------------------------------------------- 1 | package keeper_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/suite" 7 | 8 | testconstants "github.com/cosmos/evm/testutil/constants" 9 | "github.com/cosmos/evm/testutil/integration/os/factory" 10 | "github.com/cosmos/evm/testutil/integration/os/grpc" 11 | "github.com/cosmos/evm/testutil/integration/os/keyring" 12 | "github.com/cosmos/evm/testutil/integration/os/network" 13 | ) 14 | 15 | const SEED = int64(42) 16 | 17 | type KeeperIntegrationTestSuite struct { 18 | suite.Suite 19 | 20 | network *network.UnitTestNetwork 21 | factory factory.TxFactory 22 | keyring keyring.Keyring 23 | } 24 | 25 | func TestKeeperIntegrationTestSuite(t *testing.T) { 26 | suite.Run(t, new(KeeperIntegrationTestSuite)) 27 | } 28 | 29 | func (suite *KeeperIntegrationTestSuite) SetupTest() { 30 | suite.SetupTestWithChainID(testconstants.SixDecimalsChainID) 31 | } 32 | 33 | func (suite *KeeperIntegrationTestSuite) SetupTestWithChainID(chainID testconstants.ChainID) { 34 | suite.keyring = keyring.New(2) 35 | 36 | nw := network.NewUnitTestNetwork( 37 | network.WithChainID(chainID), 38 | network.WithPreFundedAccounts(suite.keyring.GetAllAccAddrs()...), 39 | ) 40 | gh := grpc.NewIntegrationHandler(nw) 41 | tf := factory.New(nw, gh) 42 | 43 | suite.network = nw 44 | suite.factory = tf 45 | } 46 | -------------------------------------------------------------------------------- /x/precisebank/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | cdctypes "github.com/cosmos/cosmos-sdk/codec/types" 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | ) 8 | 9 | func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { 10 | registry.RegisterImplementations((*sdk.Msg)(nil)) 11 | } 12 | 13 | // RegisterLegacyAminoCodec registers the necessary evmutil interfaces and concrete types 14 | // on the provided LegacyAmino codec. These types are used for Amino JSON serialization. 15 | func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { 16 | } 17 | -------------------------------------------------------------------------------- /x/precisebank/types/extended_balance.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | ) 6 | 7 | // SumExtendedCoin returns a sdk.Coin of extended coin denomination 8 | // with all integer and fractional amounts combined. e.g. if amount contains 9 | // both coins of integer denom and extended denom, this will return the total 10 | // amount in extended coins. This is intended to get the full value to emit in 11 | // events. 12 | func SumExtendedCoin(amt sdk.Coins) sdk.Coin { 13 | // uatom converted to aatom 14 | integerAmount := amt.AmountOf(IntegerCoinDenom()).Mul(ConversionFactor()) 15 | // aatom as is 16 | extendedAmount := amt.AmountOf(ExtendedCoinDenom()) 17 | 18 | // total of uatom and aatom amounts 19 | fullEmissionAmount := integerAmount.Add(extendedAmount) 20 | 21 | return sdk.NewCoin( 22 | ExtendedCoinDenom(), 23 | fullEmissionAmount, 24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /x/precisebank/types/fractional_balances.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | fmt "fmt" 5 | "strings" 6 | 7 | sdkmath "cosmossdk.io/math" 8 | ) 9 | 10 | // FractionalBalances is a slice of FractionalBalance 11 | type FractionalBalances []FractionalBalance 12 | 13 | // Validate returns an error if any FractionalBalance in the slice is invalid. 14 | func (fbs FractionalBalances) Validate() error { 15 | seenAddresses := make(map[string]struct{}) 16 | 17 | for _, fb := range fbs { 18 | // Individual FractionalBalance validation 19 | if err := fb.Validate(); err != nil { 20 | return fmt.Errorf("invalid fractional balance for %s: %w", fb.Address, err) 21 | } 22 | 23 | // Make addresses all lowercase for unique check, as ALL UPPER is also 24 | // a valid address. 25 | lowerAddr := strings.ToLower(fb.Address) 26 | 27 | // If this is a duplicate address, return an error 28 | if _, found := seenAddresses[lowerAddr]; found { 29 | return fmt.Errorf("duplicate address %v", lowerAddr) 30 | } 31 | 32 | // Mark it as seen 33 | seenAddresses[lowerAddr] = struct{}{} 34 | } 35 | 36 | return nil 37 | } 38 | 39 | // SumAmount returns the sum of all the amounts in the slice. 40 | func (fbs FractionalBalances) SumAmount() sdkmath.Int { 41 | sum := sdkmath.ZeroInt() 42 | 43 | for _, fb := range fbs { 44 | sum = sum.Add(fb.Amount) 45 | } 46 | 47 | return sum 48 | } 49 | -------------------------------------------------------------------------------- /x/precisebank/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import sdk "github.com/cosmos/cosmos-sdk/types" 4 | 5 | const ( 6 | // ModuleName name that will be used throughout the module 7 | ModuleName = "precisebank" 8 | 9 | StoreKey = ModuleName 10 | 11 | // RouterKey Top level router key 12 | RouterKey = ModuleName 13 | ) 14 | 15 | // key prefixes for store 16 | var ( 17 | FractionalBalancePrefix = []byte{0x01} // address -> fractional balance 18 | ) 19 | 20 | // Keys for store that are not prefixed 21 | var ( 22 | RemainderBalanceKey = []byte{0x02} // fractional balance remainder 23 | ) 24 | 25 | // FractionalBalanceKey returns a key from an address 26 | func FractionalBalanceKey(address sdk.AccAddress) []byte { 27 | return address.Bytes() 28 | } 29 | -------------------------------------------------------------------------------- /x/precisebank/types/keys_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | "github.com/cosmos/evm/x/precisebank/types" 9 | 10 | sdk "github.com/cosmos/cosmos-sdk/types" 11 | ) 12 | 13 | func TestFractionalBalanceKey(t *testing.T) { 14 | addr := sdk.AccAddress([]byte("test-address")) 15 | 16 | key := types.FractionalBalanceKey(addr) 17 | require.Equal(t, addr.Bytes(), key) 18 | require.Equal(t, addr, sdk.AccAddress(key), "key should be able to be converted back to address") 19 | } 20 | -------------------------------------------------------------------------------- /x/vm/ante/ctx.go: -------------------------------------------------------------------------------- 1 | package ante 2 | 3 | import ( 4 | storetypes "cosmossdk.io/store/types" 5 | 6 | sdktypes "github.com/cosmos/cosmos-sdk/types" 7 | ) 8 | 9 | // BuildEvmExecutionCtx builds the context needed prior to executing an EVM transaction. 10 | // It does the following: 11 | // 1. Sets an empty KV gas config for gas to be calculated by opcodes 12 | // and not kvstore actions 13 | // 2. Setup an empty transient KV gas config for transient gas to be 14 | // calculated by opcodes 15 | func BuildEvmExecutionCtx(ctx sdktypes.Context) sdktypes.Context { 16 | // We need to setup an empty gas config so that the gas is consistent with Ethereum. 17 | return ctx.WithKVGasConfig(storetypes.GasConfig{}). 18 | WithTransientKVGasConfig(storetypes.GasConfig{}) 19 | } 20 | -------------------------------------------------------------------------------- /x/vm/ante/ctx_test.go: -------------------------------------------------------------------------------- 1 | package ante_test 2 | 3 | import ( 4 | "github.com/cosmos/evm/testutil/integration/os/network" 5 | evmante "github.com/cosmos/evm/x/vm/ante" 6 | 7 | storetypes "cosmossdk.io/store/types" 8 | ) 9 | 10 | func (suite *EvmAnteTestSuite) TestBuildEvmExecutionCtx() { 11 | network := network.New() 12 | 13 | ctx := evmante.BuildEvmExecutionCtx(network.GetContext()) 14 | 15 | suite.Equal(storetypes.GasConfig{}, ctx.KVGasConfig()) 16 | suite.Equal(storetypes.GasConfig{}, ctx.TransientKVGasConfig()) 17 | } 18 | -------------------------------------------------------------------------------- /x/vm/ante/suite_test.go: -------------------------------------------------------------------------------- 1 | package ante_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/suite" 7 | ) 8 | 9 | type EvmAnteTestSuite struct { 10 | suite.Suite 11 | } 12 | 13 | func TestEvmAnteTestSuite(t *testing.T) { 14 | suite.Run(t, &EvmAnteTestSuite{}) 15 | } 16 | -------------------------------------------------------------------------------- /x/vm/client/cli/utils.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/ethereum/go-ethereum/common" 8 | "github.com/pkg/errors" 9 | 10 | sdk "github.com/cosmos/cosmos-sdk/types" 11 | ) 12 | 13 | func accountToHex(addr string) (string, error) { 14 | if strings.HasPrefix(addr, sdk.GetConfig().GetBech32AccountAddrPrefix()) { 15 | // Check to see if address is Cosmos bech32 formatted 16 | toAddr, err := sdk.AccAddressFromBech32(addr) 17 | if err != nil { 18 | return "", errors.Wrap(err, "must provide a valid Bech32 address") 19 | } 20 | ethAddr := common.BytesToAddress(toAddr.Bytes()) 21 | return ethAddr.Hex(), nil 22 | } 23 | 24 | if !strings.HasPrefix(addr, "0x") { 25 | addr = "0x" + addr 26 | } 27 | 28 | valid := common.IsHexAddress(addr) 29 | if !valid { 30 | return "", fmt.Errorf("%s is not a valid Ethereum or Cosmos address", addr) 31 | } 32 | 33 | ethAddr := common.HexToAddress(addr) 34 | 35 | return ethAddr.Hex(), nil 36 | } 37 | 38 | func formatKeyToHash(key string) string { 39 | if !strings.HasPrefix(key, "0x") { 40 | key = "0x" + key 41 | } 42 | 43 | ethkey := common.HexToHash(key) 44 | 45 | return ethkey.Hex() 46 | } 47 | -------------------------------------------------------------------------------- /x/vm/keeper/abci_test.go: -------------------------------------------------------------------------------- 1 | package keeper_test 2 | 3 | import ( 4 | testkeyring "github.com/cosmos/evm/testutil/integration/os/keyring" 5 | "github.com/cosmos/evm/testutil/integration/os/network" 6 | evmtypes "github.com/cosmos/evm/x/vm/types" 7 | ) 8 | 9 | func (suite *KeeperTestSuite) TestEndBlock() { 10 | keyring := testkeyring.New(2) 11 | unitNetwork := network.NewUnitTestNetwork( 12 | network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), 13 | ) 14 | ctx := unitNetwork.GetContext() 15 | preEventManager := ctx.EventManager() 16 | suite.Require().Equal(0, len(preEventManager.Events())) 17 | 18 | err := unitNetwork.App.EVMKeeper.EndBlock(ctx) 19 | suite.Require().NoError(err) 20 | 21 | postEventManager := unitNetwork.GetContext().EventManager() 22 | // should emit 1 EventTypeBlockBloom event on EndBlock 23 | suite.Require().Equal(1, len(postEventManager.Events())) 24 | suite.Require().Equal(evmtypes.EventTypeBlockBloom, postEventManager.Events()[0].Type) 25 | } 26 | -------------------------------------------------------------------------------- /x/vm/keeper/block_proposer.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "github.com/ethereum/go-ethereum/common" 5 | 6 | errorsmod "cosmossdk.io/errors" 7 | 8 | sdk "github.com/cosmos/cosmos-sdk/types" 9 | stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" 10 | ) 11 | 12 | // GetCoinbaseAddress returns the block proposer's validator operator address. 13 | func (k Keeper) GetCoinbaseAddress(ctx sdk.Context, proposerAddress sdk.ConsAddress) (common.Address, error) { 14 | validator, err := k.stakingKeeper.GetValidatorByConsAddr(ctx, GetProposerAddress(ctx, proposerAddress)) 15 | if err != nil { 16 | return common.Address{}, errorsmod.Wrapf( 17 | stakingtypes.ErrNoValidatorFound, 18 | "failed to retrieve validator from block proposer address %s. Error: %s", 19 | proposerAddress.String(), 20 | err.Error(), 21 | ) 22 | } 23 | 24 | coinbase := common.BytesToAddress([]byte(validator.GetOperator())) 25 | return coinbase, nil 26 | } 27 | 28 | // GetProposerAddress returns current block proposer's address when provided proposer address is empty. 29 | func GetProposerAddress(ctx sdk.Context, proposerAddress sdk.ConsAddress) sdk.ConsAddress { 30 | if len(proposerAddress) == 0 { 31 | proposerAddress = ctx.BlockHeader().ProposerAddress 32 | } 33 | return proposerAddress 34 | } 35 | -------------------------------------------------------------------------------- /x/vm/keeper/hooks.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "github.com/ethereum/go-ethereum/common" 5 | "github.com/ethereum/go-ethereum/core" 6 | ethtypes "github.com/ethereum/go-ethereum/core/types" 7 | 8 | "github.com/cosmos/evm/x/vm/types" 9 | 10 | errorsmod "cosmossdk.io/errors" 11 | 12 | sdk "github.com/cosmos/cosmos-sdk/types" 13 | ) 14 | 15 | // Event Hooks 16 | // These can be utilized to customize evm transaction processing. 17 | 18 | var _ types.EvmHooks = MultiEvmHooks{} 19 | 20 | // MultiEvmHooks combine multiple evm hooks, all hook functions are run in array sequence 21 | type MultiEvmHooks []types.EvmHooks 22 | 23 | // NewMultiEvmHooks combine multiple evm hooks 24 | func NewMultiEvmHooks(hooks ...types.EvmHooks) MultiEvmHooks { 25 | return hooks 26 | } 27 | 28 | // PostTxProcessing delegate the call to underlying hooks 29 | func (mh MultiEvmHooks) PostTxProcessing(ctx sdk.Context, sender common.Address, msg core.Message, receipt *ethtypes.Receipt) error { 30 | for i := range mh { 31 | if err := mh[i].PostTxProcessing(ctx, sender, msg, receipt); err != nil { 32 | return errorsmod.Wrapf(err, "EVM hook %T failed", mh[i]) 33 | } 34 | } 35 | return nil 36 | } 37 | -------------------------------------------------------------------------------- /x/vm/keeper/params_benchmark_test.go: -------------------------------------------------------------------------------- 1 | package keeper_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/cosmos/evm/x/vm/types" 7 | ) 8 | 9 | func BenchmarkSetParams(b *testing.B) { 10 | suite := KeeperTestSuite{} 11 | suite.SetupTest() 12 | params := types.DefaultParams() 13 | 14 | b.ReportAllocs() 15 | b.ResetTimer() 16 | for i := 0; i < b.N; i++ { 17 | _ = suite.network.App.EVMKeeper.SetParams(suite.network.GetContext(), params) 18 | } 19 | } 20 | 21 | func BenchmarkGetParams(b *testing.B) { 22 | suite := KeeperTestSuite{} 23 | suite.SetupTest() 24 | 25 | b.ReportAllocs() 26 | b.ResetTimer() 27 | for i := 0; i < b.N; i++ { 28 | _ = suite.network.App.EVMKeeper.GetParams(suite.network.GetContext()) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /x/vm/keeper/testdata/contracts.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import ( 4 | contractutils "github.com/cosmos/evm/contracts/utils" 5 | evmtypes "github.com/cosmos/evm/x/vm/types" 6 | ) 7 | 8 | func LoadERC20Contract() (evmtypes.CompiledContract, error) { 9 | return contractutils.LegacyLoadContractFromJSONFile("ERC20Contract.json") 10 | } 11 | 12 | func LoadMessageCallContract() (evmtypes.CompiledContract, error) { 13 | return contractutils.LegacyLoadContractFromJSONFile("MessageCallContract.json") 14 | } 15 | -------------------------------------------------------------------------------- /x/vm/keeper/utils.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "github.com/ethereum/go-ethereum/common" 5 | 6 | "github.com/cosmos/evm/x/vm/types" 7 | 8 | "cosmossdk.io/store/prefix" 9 | 10 | sdk "github.com/cosmos/cosmos-sdk/types" 11 | ) 12 | 13 | // IsContract determines if the given address is a smart contract. 14 | func (k *Keeper) IsContract(ctx sdk.Context, addr common.Address) bool { 15 | store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixCodeHash) 16 | return store.Has(addr.Bytes()) 17 | } 18 | -------------------------------------------------------------------------------- /x/vm/types/access_list_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "github.com/ethereum/go-ethereum/common" 5 | ethtypes "github.com/ethereum/go-ethereum/core/types" 6 | 7 | "github.com/cosmos/evm/x/vm/types" 8 | ) 9 | 10 | func (suite *TxDataTestSuite) TestTestNewAccessList() { 11 | testCases := []struct { 12 | name string 13 | ethAccessList *ethtypes.AccessList 14 | expAl types.AccessList 15 | }{ 16 | { 17 | "ethAccessList is nil", 18 | nil, 19 | nil, 20 | }, 21 | { 22 | "non-empty ethAccessList", 23 | ðtypes.AccessList{{Address: suite.addr, StorageKeys: []common.Hash{{0}}}}, 24 | types.AccessList{{Address: suite.hexAddr, StorageKeys: []string{common.Hash{}.Hex()}}}, 25 | }, 26 | } 27 | for _, tc := range testCases { 28 | al := types.NewAccessList(tc.ethAccessList) 29 | 30 | suite.Require().Equal(tc.expAl, al) 31 | } 32 | } 33 | 34 | func (suite *TxDataTestSuite) TestAccessListToEthAccessList() { 35 | ethAccessList := ethtypes.AccessList{{Address: suite.addr, StorageKeys: []common.Hash{{0}}}} 36 | al := types.NewAccessList(ðAccessList) 37 | actual := al.ToEthAccessList() 38 | 39 | suite.Require().Equal(ðAccessList, actual) 40 | } 41 | -------------------------------------------------------------------------------- /x/vm/types/call.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | type CallType int 4 | 5 | const ( 6 | // RPC call type is used on requests to eth_estimateGas rpc API endpoint 7 | RPC CallType = iota + 1 8 | // Internal call type is used in case of smart contract methods calls 9 | Internal 10 | ) 11 | 12 | // MaxPrecompileCalls is the maximum number of precompile 13 | // calls within a transaction. We want to limit this because 14 | // for each precompile tx we're creating a cached context 15 | const MaxPrecompileCalls uint8 = 7 16 | -------------------------------------------------------------------------------- /x/vm/types/codec_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 9 | ) 10 | 11 | type caseAny struct { 12 | name string 13 | any *codectypes.Any 14 | expPass bool 15 | } 16 | 17 | func TestPackTxData(t *testing.T) { 18 | testCases := []struct { 19 | name string 20 | txData TxData 21 | expPass bool 22 | }{ 23 | { 24 | "access list tx", 25 | &AccessListTx{}, 26 | true, 27 | }, 28 | { 29 | "legacy tx", 30 | &LegacyTx{}, 31 | true, 32 | }, 33 | { 34 | "nil", 35 | nil, 36 | false, 37 | }, 38 | } 39 | 40 | testCasesAny := []caseAny{} 41 | 42 | for _, tc := range testCases { 43 | txDataAny, err := PackTxData(tc.txData) 44 | if tc.expPass { 45 | require.NoError(t, err, tc.name) 46 | } else { 47 | require.Error(t, err, tc.name) 48 | } 49 | 50 | testCasesAny = append(testCasesAny, caseAny{tc.name, txDataAny, tc.expPass}) 51 | } 52 | 53 | for i, tc := range testCasesAny { 54 | cs, err := UnpackTxData(tc.any) 55 | if tc.expPass { 56 | require.NoError(t, err, tc.name) 57 | require.Equal(t, testCases[i].txData, cs, tc.name) 58 | } else { 59 | require.Error(t, err, tc.name) 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /x/vm/types/compiled_contract_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "encoding/json" 5 | "os" 6 | "testing" 7 | 8 | "github.com/stretchr/testify/require" 9 | 10 | evmtypes "github.com/cosmos/evm/x/vm/types" 11 | ) 12 | 13 | func TestHardhatCompiledContract(t *testing.T) { 14 | contents, err := os.ReadFile("testdata/SimpleContractHardhat.json") 15 | require.NoError(t, err, "failed to read file") 16 | require.NotEmpty(t, contents, "expected contents not to be empty") 17 | 18 | var hardhatContract evmtypes.HardhatCompiledContract 19 | err = json.Unmarshal(contents, &hardhatContract) 20 | require.NoError(t, err, "failed to unmarshal contract") 21 | 22 | require.Equal(t, hardhatContract.ContractName, "SimpleContract") 23 | require.Contains(t, 24 | hardhatContract.ABI.Methods, 25 | "setValue", 26 | "missing setValue method in contract ABI methods", 27 | ) 28 | 29 | compiledContract, err := hardhatContract.ToCompiledContract() 30 | require.NoError(t, err, "failed to convert hardhat contract to compiled contract type") 31 | require.Equal(t, compiledContract.ABI, hardhatContract.ABI, "expected ABIs to be equal") 32 | require.NotEmpty(t, compiledContract.Bin, "expected bin data not to be empty") 33 | } 34 | -------------------------------------------------------------------------------- /x/vm/types/events.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // Evm module events 4 | const ( 5 | EventTypeEthereumTx = TypeMsgEthereumTx 6 | EventTypeBlockBloom = "block_bloom" 7 | EventTypeTxLog = "tx_log" 8 | EventTypeFeeMarket = "evm_fee_market" 9 | 10 | AttributeKeyBaseFee = "base_fee" 11 | AttributeKeyContractAddress = "contract" 12 | AttributeKeyRecipient = "recipient" 13 | AttributeKeyTxHash = "txHash" 14 | AttributeKeyEthereumTxHash = "ethereumTxHash" 15 | AttributeKeyTxIndex = "txIndex" 16 | AttributeKeyTxGasUsed = "txGasUsed" 17 | AttributeKeyTxType = "txType" 18 | AttributeKeyTxLog = "txLog" 19 | 20 | // tx failed in eth vm execution 21 | AttributeKeyEthereumTxFailed = "ethereumTxFailed" 22 | AttributeValueCategory = ModuleName 23 | AttributeKeyEthereumBloom = "bloom" 24 | 25 | MetricKeyTransitionDB = "transition_db" 26 | MetricKeyStaticCall = "static_call" 27 | ) 28 | -------------------------------------------------------------------------------- /x/vm/types/query.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 5 | ) 6 | 7 | // UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces 8 | func (m QueryTraceTxRequest) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { 9 | for _, msg := range m.Predecessors { 10 | if err := msg.UnpackInterfaces(unpacker); err != nil { 11 | return err 12 | } 13 | } 14 | return m.Msg.UnpackInterfaces(unpacker) 15 | } 16 | 17 | func (m QueryTraceBlockRequest) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { 18 | for _, msg := range m.Txs { 19 | if err := msg.UnpackInterfaces(unpacker); err != nil { 20 | return err 21 | } 22 | } 23 | return nil 24 | } 25 | 26 | // Failed returns if the contract execution failed in vm errors 27 | func (egr EstimateGasResponse) Failed() bool { 28 | return len(egr.VmError) > 0 29 | } 30 | -------------------------------------------------------------------------------- /x/vm/types/tx_types.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | gethtypes "github.com/ethereum/go-ethereum/core/types" 5 | ) 6 | 7 | func GetTxTypeName(txType int) string { 8 | switch txType { 9 | case gethtypes.DynamicFeeTxType: 10 | return "DynamicFeeTxType" 11 | case gethtypes.LegacyTxType: 12 | return "LegacyTxType" 13 | case gethtypes.AccessListTxType: 14 | return "AccessListTxType" 15 | default: 16 | panic("unknown tx type") 17 | } 18 | } 19 | --------------------------------------------------------------------------------