├── .dockerignore ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug-report.md │ └── feature-request.md ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yml ├── labeler.yml └── workflows │ ├── build.yml │ ├── clean-artifacts.yml │ ├── codeql-analysis.yml │ ├── deploy-contract.yml │ ├── docs.yml │ ├── goreleaser.yml │ ├── labeler.yml │ ├── linkchecker.yml │ ├── lint.yml │ ├── stale.yml │ └── test.yml ├── .gitignore ├── .golangci.yml ├── .goreleaser.yml ├── .mergify.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── app ├── ante │ ├── ante.go │ ├── ante_test.go │ ├── doc.go │ ├── eth.go │ ├── eth_test.go │ └── utils_test.go ├── app.go ├── app_test.go ├── export.go ├── simulation_test.go └── test_helpers.go ├── buf.yaml ├── clang-format ├── client ├── config.go ├── docs │ ├── config.json │ ├── statik │ │ ├── init.go │ │ └── statik.go │ └── swagger-ui │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── index.html │ │ ├── oauth2-redirect.html │ │ ├── swagger-ui-bundle.js │ │ ├── swagger-ui-standalone-preset.js │ │ ├── swagger-ui.css │ │ └── swagger.yaml ├── export.go ├── import.go ├── keys.go ├── keys │ ├── add.go │ ├── keys.go │ └── utils.go └── testnet.go ├── cmd ├── config │ ├── config.go │ └── config_test.go └── ethermintd │ ├── cmd_test.go │ ├── flags.go │ ├── genaccounts.go │ ├── main.go │ └── root.go ├── codecov.yml ├── config.yml ├── crypto ├── codec │ ├── amino.go │ └── codec.go ├── ethsecp256k1 │ ├── ethsecp256k1.go │ ├── ethsecp256k1_test.go │ └── keys.pb.go └── hd │ ├── algorithm.go │ └── algorithm_test.go ├── docker-compose.yml ├── docs ├── .vuepress │ ├── components │ │ ├── Home.vue │ │ ├── IconCode.vue │ │ ├── IconRocket.vue │ │ ├── TmIconEthereumIntro.vue │ │ ├── TmLogoEthereumBlack.vue │ │ └── TmLogoEthereumWhite.vue │ ├── config.js │ ├── public │ │ ├── ethermint-logo-horizontal-alpha.svg │ │ ├── logo-bw.svg │ │ └── logo.svg │ └── styles │ │ └── index.styl ├── DOCS_README.md ├── README.md ├── api │ ├── README.md │ ├── json-rpc │ │ ├── endpoints.md │ │ ├── events.md │ │ ├── namespaces.md │ │ └── running_server.md │ └── proto-docs.md ├── architecture │ ├── README.md │ ├── adr-001-state.md │ └── adr-template.md ├── basics │ ├── README.md │ ├── accounts.md │ ├── gas.md │ ├── img │ │ └── photon.png │ ├── tokens.md │ └── transactions.md ├── core │ ├── README.md │ ├── encoding.md │ └── pending_state.md ├── guides │ ├── README.md │ ├── img │ │ ├── metamask_import.png │ │ ├── metamask_network_settings.png │ │ ├── remix_deploy.png │ │ ├── remix_deployed.png │ │ └── remix_interact.png │ ├── keys-wallets │ │ ├── keyring.md │ │ └── metamask.md │ ├── localnet │ │ ├── multi_node.md │ │ └── single_node.md │ ├── tools │ │ ├── remix.md │ │ └── truffle.md │ └── upgrade.md ├── intro │ ├── README.md │ ├── architecture.md │ ├── clients.md │ ├── overview.md │ ├── resources.md │ └── use_cases.md ├── package-lock.json ├── package.json ├── post.sh ├── pre.sh ├── protodoc-markdown.tmpl ├── quickstart │ ├── README.md │ ├── binary.md │ ├── installation.md │ ├── interact_node.md │ └── run_node.md ├── testnet │ ├── README.md │ ├── cloud_providers.md │ ├── join.md │ ├── security.md │ ├── testnet.md │ └── validator-setup.md ├── versions └── yarn.lock ├── encoding ├── codec │ └── codec.go ├── config.go └── config_test.go ├── ethereum └── rpc │ ├── apis.go │ ├── backend │ ├── backend.go │ └── utils.go │ ├── doc.go │ ├── namespaces │ ├── debug │ │ ├── internal.go │ │ ├── trace.go │ │ ├── trace_fallback.go │ │ └── utils.go │ ├── eth │ │ ├── api.go │ │ └── filters │ │ │ ├── api.go │ │ │ ├── filter_system.go │ │ │ ├── filters.go │ │ │ ├── subscription.go │ │ │ └── utils.go │ ├── miner │ │ ├── api.go │ │ └── unsupported.go │ ├── net │ │ └── api.go │ ├── personal │ │ └── api.go │ ├── txpool │ │ └── api.go │ └── web3 │ │ └── api.go │ ├── pubsub │ ├── pubsub.go │ └── pubsub_test.go │ ├── types │ ├── addrlock.go │ ├── block.go │ ├── query_client.go │ ├── types.go │ └── utils.go │ └── websockets.go ├── go.mod ├── go.sum ├── gometalinter.json ├── init.bat ├── init.sh ├── networks └── local │ ├── Makefile │ └── ethermintnode │ └── Dockerfile ├── proto └── ethermint │ ├── crypto │ └── v1alpha1 │ │ └── ethsecp256k1 │ │ └── keys.proto │ ├── evm │ └── v1alpha1 │ │ ├── evm.proto │ │ ├── genesis.proto │ │ ├── query.proto │ │ └── tx.proto │ └── types │ └── v1alpha1 │ └── account.proto ├── scripts ├── contract-test.sh ├── gen-tests-artifacts.sh ├── integration-test-all.sh ├── proto-tools-installer.sh ├── protoc-swagger-gen.sh ├── protocgen.sh ├── run-solidity-tests.sh ├── start-docker.sh └── start.sh ├── server ├── config │ ├── config.go │ ├── config_test.go │ └── toml.go ├── evmrpc.go ├── flags.go ├── start.go └── util.go ├── tests ├── e2e │ └── integration_test.go ├── importer │ ├── chain_ctx.go │ ├── chain_ctx_test.go │ └── importer_test.go ├── rpc │ ├── net_test.go │ ├── personal_test.go │ ├── rpc_pending_test.go │ ├── rpc_test.go │ └── utils.go ├── signer.go ├── solidity │ ├── .gitattributes │ ├── .gitignore │ ├── README.md │ ├── init-test-node.sh │ ├── package.json │ ├── suites │ │ ├── basic │ │ │ ├── contracts │ │ │ │ ├── Counter.sol │ │ │ │ ├── Storage.sol │ │ │ │ └── test │ │ │ │ │ └── Migrations.sol │ │ │ ├── migrations │ │ │ │ └── 1_initial_migration.js │ │ │ ├── package.json │ │ │ ├── test │ │ │ │ ├── .gitkeep │ │ │ │ ├── counter.js │ │ │ │ └── estimateGas.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 │ │ ├── initializable-buidler │ │ │ ├── .gitignore │ │ │ ├── buidler.config.js │ │ │ ├── contracts │ │ │ │ ├── Initializable.sol │ │ │ │ ├── Petrifiable.sol │ │ │ │ ├── TimeHelpers.sol │ │ │ │ ├── Uint256Helpers.sol │ │ │ │ ├── UnstructuredStorage.sol │ │ │ │ └── test │ │ │ │ │ └── InitializableMock.sol │ │ │ ├── package.json │ │ │ └── test │ │ │ │ └── lifecycle.js │ │ ├── initializable │ │ │ ├── contracts │ │ │ │ ├── Initializable.sol │ │ │ │ ├── Petrifiable.sol │ │ │ │ ├── TimeHelpers.sol │ │ │ │ ├── Uint256Helpers.sol │ │ │ │ ├── UnstructuredStorage.sol │ │ │ │ └── test │ │ │ │ │ ├── InitializableMock.sol │ │ │ │ │ └── Migrations.sol │ │ │ ├── migrations │ │ │ │ └── 1_initial_migration.js │ │ │ ├── package.json │ │ │ ├── test │ │ │ │ ├── .gitkeep │ │ │ │ └── lifecycle.js │ │ │ └── truffle-config.js │ │ ├── opcode │ │ │ ├── bytecode.js │ │ │ ├── contracts │ │ │ │ ├── Migrations.sol │ │ │ │ └── OpCodes.sol │ │ │ ├── migrations │ │ │ │ ├── 1_initial_migration.js │ │ │ │ └── 2_opCodes_migration.js │ │ │ ├── package.json │ │ │ ├── test │ │ │ │ └── opCodes.js │ │ │ └── truffle-config.js │ │ ├── proxy │ │ │ ├── contracts │ │ │ │ ├── DelegateProxy.sol │ │ │ │ ├── DepositableDelegateProxy.sol │ │ │ │ ├── DepositableStorage.sol │ │ │ │ ├── ERCProxy.sol │ │ │ │ ├── IsContract.sol │ │ │ │ ├── UnstructuredStorage.sol │ │ │ │ └── test │ │ │ │ │ ├── DepositableDelegateProxyMock.sol │ │ │ │ │ ├── EthSender.sol │ │ │ │ │ ├── Migrations.sol │ │ │ │ │ └── ProxyTarget.sol │ │ │ ├── migrations │ │ │ │ └── 1_initial_migration.js │ │ │ ├── package.json │ │ │ ├── test │ │ │ │ ├── .gitkeep │ │ │ │ └── depositable_delegate_proxy.js │ │ │ └── truffle-config.js │ │ ├── staking │ │ │ ├── .github │ │ │ │ └── workflows │ │ │ │ │ └── ci_contracts.yml │ │ │ ├── contracts │ │ │ │ ├── Staking.sol │ │ │ │ ├── StakingFactory.sol │ │ │ │ ├── lib │ │ │ │ │ ├── Checkpointing.sol │ │ │ │ │ └── os │ │ │ │ │ │ ├── Autopetrified.sol │ │ │ │ │ │ ├── DelegateProxy.sol │ │ │ │ │ │ ├── ERC20.sol │ │ │ │ │ │ ├── ERCProxy.sol │ │ │ │ │ │ ├── Initializable.sol │ │ │ │ │ │ ├── IsContract.sol │ │ │ │ │ │ ├── Migrations.sol │ │ │ │ │ │ ├── Petrifiable.sol │ │ │ │ │ │ ├── SafeERC20.sol │ │ │ │ │ │ ├── SafeMath.sol │ │ │ │ │ │ ├── SafeMath64.sol │ │ │ │ │ │ ├── ScriptHelpers.sol │ │ │ │ │ │ ├── TimeHelpers.sol │ │ │ │ │ │ ├── Uint256Helpers.sol │ │ │ │ │ │ └── UnstructuredStorage.sol │ │ │ │ ├── locking │ │ │ │ │ ├── ILockManager.sol │ │ │ │ │ ├── IStakingLocking.sol │ │ │ │ │ └── TimeLockManager.sol │ │ │ │ ├── proxies │ │ │ │ │ ├── StakingProxy.sol │ │ │ │ │ └── ThinProxy.sol │ │ │ │ ├── standards │ │ │ │ │ └── ERC900.sol │ │ │ │ └── test │ │ │ │ │ ├── TestImports.sol │ │ │ │ │ ├── lib │ │ │ │ │ ├── EchidnaStaking.sol │ │ │ │ │ ├── ITokenController.sol │ │ │ │ │ └── MiniMeToken.sol │ │ │ │ │ └── mocks │ │ │ │ │ ├── BadTokenMock.sol │ │ │ │ │ ├── CheckpointingMock.sol │ │ │ │ │ ├── ERC20.sol │ │ │ │ │ ├── LockManagerMock.sol │ │ │ │ │ ├── NoApproveTokenMock.sol │ │ │ │ │ ├── StakingMock.sol │ │ │ │ │ ├── StandardTokenMock.sol │ │ │ │ │ ├── TimeHelpersMock.sol │ │ │ │ │ └── TimeLockManagerMock.sol │ │ │ ├── package.json │ │ │ ├── test │ │ │ │ ├── approve_and_call.js │ │ │ │ ├── gas.js │ │ │ │ ├── helpers │ │ │ │ │ ├── constants.js │ │ │ │ │ ├── deploy.js │ │ │ │ │ ├── errors.js │ │ │ │ │ └── helpers.js │ │ │ │ ├── lib │ │ │ │ │ └── checkpointing.js │ │ │ │ ├── locking │ │ │ │ │ ├── funds_flows.js │ │ │ │ │ ├── locking.js │ │ │ │ │ └── locking_time.js │ │ │ │ ├── staking.js │ │ │ │ ├── staking_factory.js │ │ │ │ ├── staking_proxy.js │ │ │ │ └── transfers.js │ │ │ └── truffle-config.js │ │ └── storage │ │ │ ├── contracts │ │ │ ├── EventTest.sol │ │ │ └── Storage.sol │ │ │ ├── package.json │ │ │ ├── test │ │ │ ├── .gitkeep │ │ │ ├── 0_test_contracts.test.js │ │ │ ├── 1_test_evm_revert.test.js │ │ │ └── 2_test_events.test.js │ │ │ └── truffle-config.js │ ├── test-helper.js │ └── yarn.lock └── tooling │ └── ethers │ └── ethers.js ├── testutil └── network │ ├── doc.go │ ├── network.go │ ├── network_test.go │ └── util.go ├── third_party └── proto │ ├── cosmos │ ├── auth │ │ └── v1beta1 │ │ │ ├── auth.proto │ │ │ ├── genesis.proto │ │ │ └── query.proto │ ├── authz │ │ └── v1beta1 │ │ │ ├── authz.proto │ │ │ ├── genesis.proto │ │ │ ├── query.proto │ │ │ └── tx.proto │ ├── bank │ │ └── v1beta1 │ │ │ ├── bank.proto │ │ │ ├── genesis.proto │ │ │ ├── query.proto │ │ │ └── tx.proto │ ├── base │ │ ├── abci │ │ │ └── v1beta1 │ │ │ │ └── abci.proto │ │ ├── kv │ │ │ └── v1beta1 │ │ │ │ └── kv.proto │ │ ├── query │ │ │ └── v1beta1 │ │ │ │ └── pagination.proto │ │ ├── reflection │ │ │ └── v1beta1 │ │ │ │ └── reflection.proto │ │ ├── snapshots │ │ │ └── v1beta1 │ │ │ │ └── snapshot.proto │ │ ├── store │ │ │ └── v1beta1 │ │ │ │ ├── commit_info.proto │ │ │ │ └── snapshot.proto │ │ ├── tendermint │ │ │ └── v1beta1 │ │ │ │ └── query.proto │ │ └── v1beta1 │ │ │ └── coin.proto │ ├── capability │ │ └── v1beta1 │ │ │ ├── capability.proto │ │ │ └── genesis.proto │ ├── crisis │ │ └── v1beta1 │ │ │ ├── genesis.proto │ │ │ └── tx.proto │ ├── crypto │ │ ├── ed25519 │ │ │ └── keys.proto │ │ ├── multisig │ │ │ ├── keys.proto │ │ │ └── v1beta1 │ │ │ │ └── multisig.proto │ │ └── secp256k1 │ │ │ └── keys.proto │ ├── distribution │ │ └── v1beta1 │ │ │ ├── distribution.proto │ │ │ ├── genesis.proto │ │ │ ├── query.proto │ │ │ └── tx.proto │ ├── evidence │ │ └── v1beta1 │ │ │ ├── evidence.proto │ │ │ ├── genesis.proto │ │ │ ├── query.proto │ │ │ └── tx.proto │ ├── feegrant │ │ └── v1beta1 │ │ │ ├── feegrant.proto │ │ │ ├── genesis.proto │ │ │ ├── query.proto │ │ │ └── tx.proto │ ├── genutil │ │ └── v1beta1 │ │ │ └── genesis.proto │ ├── gov │ │ └── v1beta1 │ │ │ ├── genesis.proto │ │ │ ├── gov.proto │ │ │ ├── query.proto │ │ │ └── tx.proto │ ├── mint │ │ └── v1beta1 │ │ │ ├── genesis.proto │ │ │ ├── mint.proto │ │ │ └── query.proto │ ├── params │ │ └── v1beta1 │ │ │ ├── params.proto │ │ │ └── query.proto │ ├── slashing │ │ └── v1beta1 │ │ │ ├── genesis.proto │ │ │ ├── query.proto │ │ │ ├── slashing.proto │ │ │ └── tx.proto │ ├── staking │ │ └── v1beta1 │ │ │ ├── genesis.proto │ │ │ ├── query.proto │ │ │ ├── staking.proto │ │ │ └── tx.proto │ ├── tx │ │ ├── signing │ │ │ └── v1beta1 │ │ │ │ └── signing.proto │ │ └── v1beta1 │ │ │ ├── service.proto │ │ │ └── tx.proto │ ├── upgrade │ │ └── v1beta1 │ │ │ ├── query.proto │ │ │ └── upgrade.proto │ └── vesting │ │ └── v1beta1 │ │ ├── tx.proto │ │ └── vesting.proto │ ├── cosmos_proto │ └── cosmos.proto │ ├── gogoproto │ └── gogo.proto │ ├── google │ ├── api │ │ ├── annotations.proto │ │ ├── http.proto │ │ └── httpbody.proto │ └── protobuf │ │ ├── any.proto │ │ └── descriptor.proto │ └── tendermint │ ├── abci │ └── types.proto │ ├── crypto │ ├── keys.proto │ └── proof.proto │ ├── libs │ └── bits │ │ └── types.proto │ ├── p2p │ └── types.proto │ ├── types │ ├── block.proto │ ├── evidence.proto │ ├── params.proto │ ├── types.proto │ └── validator.proto │ └── version │ └── types.proto ├── types ├── account.go ├── account.pb.go ├── account_test.go ├── block.go ├── chain_id.go ├── chain_id_test.go ├── code.go ├── codec.go ├── coin.go ├── errors.go ├── hdpath.go ├── params.go ├── protocol.go ├── validation.go └── validation_test.go ├── version └── version.go └── x └── evm ├── atlas ├── atlas-v0.3.1.md └── atlas.toml ├── client ├── cli │ ├── query.go │ ├── utils.go │ └── utils_test.go └── rest │ └── rest.go ├── genesis.go ├── genesis_test.go ├── handler.go ├── handler_test.go ├── keeper ├── ERC20Contract.json ├── abci.go ├── context_stack.go ├── grpc_query.go ├── grpc_query_test.go ├── keeper.go ├── keeper_test.go ├── msg_server.go ├── params.go ├── params_test.go ├── state_transition.go ├── state_transition_test.go ├── statedb.go └── statedb_test.go ├── module.go ├── spec ├── 01_concepts.md ├── 02_state.md ├── 03_state_transitions.md ├── 04_messages.md ├── 05_abci.md ├── 06_events.md ├── 07_params.md └── README.md └── types ├── access_list.go ├── access_list_tx.go ├── callargs.go ├── chain_config.go ├── chain_config_test.go ├── codec.go ├── codec_test.go ├── dynamic_fee_tx.go ├── errors.go ├── errors_test.go ├── events.go ├── evm.pb.go ├── genesis.go ├── genesis.pb.go ├── genesis_test.go ├── interfaces.go ├── key.go ├── legacy_tx.go ├── logs.go ├── logs_test.go ├── msg.go ├── msg_test.go ├── params.go ├── params_test.go ├── query.pb.go ├── query.pb.gw.go ├── storage.go ├── storage_test.go ├── tx.go ├── tx.pb.go ├── tx_data.go ├── tx_data_test.go ├── utils.go └── utils_test.go /.dockerignore: -------------------------------------------------------------------------------- 1 | # localnet-setup 2 | localnet-setup 3 | 4 | # build 5 | build -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # CODEOWNERS: https://help.github.com/articles/about-codeowners/ 2 | 3 | # Primary repo maintainers 4 | * @fedekunze @khoslaventures 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug Report 3 | about: create a bug report 4 | --- 5 | 6 | __System info:__ [Include Ethermint commit, operating system name, and other relevant details] 7 | 8 | __Steps to reproduce:__ 9 | 10 | 1. [First Step] 11 | 2. [Second Step] 12 | 3. [and so on...] 13 | 14 | __Expected behavior:__ [What you expected to happen] 15 | 16 | __Actual behavior:__ [What actually happened] 17 | 18 | __Additional info:__ [Include gist of relevant config, logs, etc.] 19 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Opening a feature request kicks off a discussion 4 | 5 | --- 6 | 7 | __Proposal:__ [Description of the feature] 8 | 9 | __Current behavior:__ [What currently happens] 10 | 11 | __Desired behavior:__ [What you would like to happen] 12 | 13 | __Use case:__ [Why is this important (helps with prioritizing requests)] 14 | 15 | Requests may be closed if we're not actively planning to work on them. 16 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | Closes: #XXX 8 | 9 | ## Description 10 | 11 | 14 | 15 | ______ 16 | 17 | For contributor use: 18 | 19 | - [ ] Targeted PR against correct branch (see [CONTRIBUTING.md](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) 20 | - [ ] Linked to Github issue with discussion and accepted design OR link to spec that describes this work. 21 | - [ ] Code follows the [module structure standards](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules/structure.md). 22 | - [ ] Wrote unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) 23 | - [ ] Updated relevant documentation (`docs/`) or specification (`x//spec/`) 24 | - [ ] Added relevant `godoc` [comments](https://blog.golang.org/godoc-documenting-go-code). 25 | - [ ] Added a relevant changelog entry to the `Unreleased` section in `CHANGELOG.md` 26 | - [ ] Re-reviewed `Files changed` in the Github PR explorer 27 | 28 | ______ 29 | 30 | For admin use: 31 | 32 | - [ ] Added appropriate labels to PR (ex. `WIP`, `R4R`, `docs`, etc) 33 | - [ ] Reviewers assigned 34 | - [ ] Squashed all commits, uses message "Merge pull request #XYZ: [title]" ([coding standards](https://github.com/tendermint/coding/blob/master/README.md#merging-a-pr)) 35 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "10:00" 8 | open-pull-requests-limit: 10 9 | reviewers: 10 | - fedekunze 11 | - khoslaventures 12 | labels: 13 | - dependencies 14 | - package-ecosystem: docker 15 | directory: "/" 16 | schedule: 17 | interval: daily 18 | time: "10:00" 19 | open-pull-requests-limit: 10 20 | reviewers: 21 | - fedekunze 22 | - khoslaventures 23 | - package-ecosystem: gomod 24 | directory: "/" 25 | schedule: 26 | interval: daily 27 | time: "10:00" 28 | open-pull-requests-limit: 10 29 | -------------------------------------------------------------------------------- /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | "C:Crypto": 2 | - crypto/**/* 3 | "C:Encoding": 4 | - encoding/**/* 5 | "C:JSON-RPC": 6 | - ethereum/rpc/**/* 7 | "C:Proto": 8 | - proto/**/* 9 | - third_party/**/* 10 | - /**/*.pb.go 11 | - /**/*.pb.gw.go 12 | "C:Types": 13 | - types/**/* 14 | "C:x/evm": 15 | - x/evm/**/*/ 16 | "Type: Build": 17 | - Makefile 18 | - Dockerfile 19 | - docker-compose.yml 20 | - scripts/* 21 | - config.yml 22 | "Type: CI": 23 | - .github/**/*.yml 24 | - buf.yaml 25 | - .mergify.yml 26 | - .golangci.yml 27 | "C:CLI": 28 | - client/**/* 29 | - x/*/client/**/* 30 | "Type: Tests": 31 | - tests/**/* 32 | - /**/*/*_test.go 33 | "Type: Docs": 34 | - docs/**/* 35 | - x/*/spec/**/* 36 | "Type: ADR": 37 | - docs/architecture/**/* -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: 3 | pull_request: 4 | branches: 5 | - main 6 | 7 | jobs: 8 | cleanup-runs: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: rokroskar/workflow-run-cleanup-action@master 12 | env: 13 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 14 | if: "!startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/main'" 15 | 16 | build: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: actions/checkout@v2.3.4 20 | - uses: technote-space/get-diff-action@v5 21 | id: git_diff 22 | with: 23 | SUFFIX_FILTER: | 24 | .go 25 | .mod 26 | .sum 27 | - run: | 28 | make build 29 | if: "env.GIT_DIFF != ''" 30 | -------------------------------------------------------------------------------- /.github/workflows/clean-artifacts.yml: -------------------------------------------------------------------------------- 1 | name: Remove old artifacts 2 | # Remove old artifacts runs a crob job that removes old artifacts 3 | # generated from the split tests workflow. 4 | 5 | on: 6 | schedule: 7 | # Every day at 1am 8 | - cron: "0 1 * * *" 9 | 10 | jobs: 11 | remove-old-artifacts: 12 | runs-on: ubuntu-latest 13 | timeout-minutes: 10 14 | 15 | steps: 16 | - name: Remove old artifacts 17 | uses: c-hive/gha-remove-artifacts@v1.2.0 18 | with: 19 | age: "7 days" 20 | -------------------------------------------------------------------------------- /.github/workflows/deploy-contract.yml: -------------------------------------------------------------------------------- 1 | name: Deploy Contract 2 | on: 3 | pull_request: 4 | branches: 5 | - main 6 | 7 | jobs: 8 | cleanup-runs: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: rokroskar/workflow-run-cleanup-action@master 12 | env: 13 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 14 | if: "!startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/main'" 15 | 16 | deploy: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: actions/checkout@v2.3.4 20 | - name: Use Node.js 21 | uses: actions/setup-node@v2.4.0 22 | with: 23 | node-version: '12.x' 24 | - name: Install dependencies 25 | run: npm install 26 | - uses: technote-space/get-diff-action@v5 27 | id: git_diff 28 | with: 29 | SUFFIX_FILTER: | 30 | .go 31 | .mod 32 | .sum 33 | .sol 34 | - name: Test contract 35 | run: | 36 | sudo make contract-tools 37 | sudo make test-contract 38 | if: "env.GIT_DIFF != ''" 39 | -------------------------------------------------------------------------------- /.github/workflows/goreleaser.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | # This workflow helps with creating releases. 3 | # This job will only be triggered when a tag (vX.X.x) is pushed 4 | on: 5 | push: 6 | # Sequence of patterns matched against refs/tags 7 | tags: 8 | - "v[0-9]+.[0-9]+.[0-9]+" # Push events to matching v*, i.e. v1.0, v20.15.10 9 | 10 | jobs: 11 | release: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v2 15 | - name: Install Go 16 | uses: actions/setup-go@v2.1.3 17 | with: 18 | go-version: 1.16 19 | - name: Unshallow 20 | run: git fetch --prune --unshallow 21 | - name: Create release 22 | uses: goreleaser/goreleaser-action@v2.7.0 23 | with: 24 | args: release --rm-dist --release-notes ./RELEASE_CHANGELOG.md 25 | env: 26 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 27 | -------------------------------------------------------------------------------- /.github/workflows/labeler.yml: -------------------------------------------------------------------------------- 1 | name: "Pull Request Labeler" 2 | on: 3 | pull_request: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | triage: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/labeler@v3 13 | with: 14 | repo-token: "${{ secrets.GITHUB_TOKEN }}" 15 | -------------------------------------------------------------------------------- /.github/workflows/linkchecker.yml: -------------------------------------------------------------------------------- 1 | name: Check Markdown links 2 | on: 3 | schedule: 4 | - cron: "* */24 * * *" 5 | jobs: 6 | markdown-link-check: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v2.3.4 10 | - uses: gaurav-nelson/github-action-markdown-link-check@1.0.13 11 | with: 12 | folder-path: "docs" 13 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Run Lint 2 | # Lint runs golangci-lint over the entire ethermint repository This workflow is 3 | # run on every pull request and push to main The `golangci` will pass without 4 | # running if no *.{go, mod, sum} files have been changed. 5 | on: 6 | pull_request: 7 | push: 8 | branches: 9 | - main 10 | jobs: 11 | golangci: 12 | name: Run golangci-lint 13 | runs-on: ubuntu-latest 14 | timeout-minutes: 10 15 | steps: 16 | - uses: actions/checkout@v2.3.4 17 | - uses: technote-space/get-diff-action@v5 18 | with: 19 | SUFFIX_FILTER: | 20 | .go 21 | .mod 22 | .sum 23 | - uses: golangci/golangci-lint-action@v2.5.2 24 | with: 25 | # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. 26 | version: v1.29 27 | args: --timeout 10m 28 | github-token: ${{ secrets.github_token }} 29 | # Check only if there are differences in the source code 30 | if: "env.GIT_DIFF" 31 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: "Close stale issues & pull requests" 2 | on: 3 | schedule: 4 | - cron: "0 0 * * *" 5 | 6 | jobs: 7 | stale: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/stale@v4 11 | with: 12 | repo-token: ${{ secrets.GITHUB_TOKEN }} 13 | stale-pr-message: "This pull request has been automatically marked as stale because it has not had 14 | recent activity. It will be closed in 7 days-before-close if no further activity occurs." 15 | 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." 16 | days-before-stale: 45 17 | days-before-close: 7 18 | exempt-issue-labels: "Status: Blocked, Type: Bug, pinned, automerge" 19 | exempt-pr-labels: "Status: Blocked, Type: Bug, pinned, automerge" 20 | stale-pr-label: "Status: Stale" 21 | stale-issue-label: "Status: Stale" 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS 2 | .DS_Store 3 | *.swp 4 | *.swo 5 | *.swl 6 | *.swm 7 | *.swn 8 | .vscode 9 | .idea 10 | *.pyc 11 | *.exe 12 | *.exe~ 13 | *.dll 14 | *.so 15 | *.dylib 16 | 17 | # Build 18 | *.test 19 | .glide/ 20 | vendor 21 | build 22 | bin 23 | tools/bin/* 24 | docs/_build 25 | docs/tutorial 26 | docs/node_modules 27 | docs/modules 28 | dist 29 | tools-stamp 30 | docs-tools-stamp 31 | proto-tools-stamp 32 | golangci-lint 33 | keyring_test_cosmos 34 | ./**/node_modules 35 | ./**/dist 36 | secret.yml 37 | # vue/ 38 | 39 | # Local docker volume mappings 40 | localnet-setup 41 | 42 | # Testing 43 | coverage.txt 44 | *.out 45 | sim_log_file 46 | tests/**/tmp/* 47 | yarn.lock 48 | 49 | # Vagrant 50 | .vagrant/ 51 | *.box 52 | *.log 53 | vagrant 54 | 55 | # IDE 56 | .idea/ 57 | *.iml 58 | 59 | # Graphviz 60 | dependency-graph.png 61 | 62 | # Latex 63 | *.aux 64 | *.out 65 | *.synctex.gz 66 | 67 | # Contracts 68 | *.bin 69 | *.abi 70 | 71 | # Node.js 72 | tests/**/node_modules/* 73 | tests-solidity/**/node_modules/* -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | run: 2 | tests: false 3 | # # timeout for analysis, e.g. 30s, 5m, default is 1m 4 | # timeout: 5m 5 | 6 | linters: 7 | disable-all: true 8 | enable: 9 | - bodyclose 10 | - deadcode 11 | - depguard 12 | - dogsled 13 | - errcheck 14 | - goconst 15 | - gocritic 16 | - gofmt 17 | - goimports 18 | - golint 19 | - gosec 20 | - gosimple 21 | - govet 22 | - ineffassign 23 | - interfacer 24 | - maligned 25 | - misspell 26 | - nakedret 27 | - prealloc 28 | - scopelint 29 | - staticcheck 30 | - structcheck 31 | - stylecheck 32 | - typecheck 33 | - unconvert 34 | - unused 35 | - unparam 36 | - misspell 37 | # TODO: address these lint issues 38 | # - wsl 39 | # - nolintlint 40 | 41 | issues: 42 | exclude-rules: 43 | - text: "Use of weak random number generator" 44 | linters: 45 | - gosec 46 | - text: "comment on exported var" 47 | linters: 48 | - golint 49 | - text: "don't use an underscore in package name" 50 | linters: 51 | - golint 52 | - text: "ST1003:" 53 | linters: 54 | - stylecheck 55 | - text: "SA1019:" 56 | linters: 57 | - staticcheck 58 | max-issues-per-linter: 10000 59 | max-same-issues: 10000 60 | 61 | linters-settings: 62 | dogsled: 63 | max-blank-identifiers: 3 64 | maligned: 65 | # print struct with more effective memory layout or not, false by default 66 | suggest-new: true 67 | nolintlint: 68 | allow-unused: false 69 | allow-leading-space: true 70 | require-explanation: false 71 | require-specific: false 72 | -------------------------------------------------------------------------------- /.mergify.yml: -------------------------------------------------------------------------------- 1 | pull_request_rules: 2 | - name: automerge to base branch with label automerge and branch protection passing 3 | conditions: 4 | - "#approved-reviews-by>1" 5 | - base=main 6 | - label=automerge 7 | actions: 8 | merge: 9 | method: squash 10 | strict: true 11 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:alpine AS build-env 2 | 3 | # Set up dependencies 4 | ENV PACKAGES git build-base 5 | 6 | # Set working directory for the build 7 | WORKDIR /go/src/github.com/tharsis/ethermint 8 | 9 | # Install dependencies 10 | RUN apk add --update $PACKAGES 11 | RUN apk add linux-headers 12 | 13 | # Add source files 14 | COPY . . 15 | 16 | # Make the binary 17 | RUN make build 18 | 19 | # Final image 20 | FROM alpine 21 | 22 | # Install ca-certificates 23 | RUN apk add --update ca-certificates jq 24 | WORKDIR / 25 | 26 | # Copy over binaries from the build-env 27 | COPY --from=build-env /go/src/github.com/tharsis/ethermint/build/ethermintd /usr/bin/ethermintd 28 | 29 | # Run ethermintd by default 30 | CMD ["ethermintd"] 31 | -------------------------------------------------------------------------------- /app/ante/doc.go: -------------------------------------------------------------------------------- 1 | /*Package ante defines the SDK auth module's AnteHandler as well as an internal 2 | AnteHandler for an Ethereum transaction (i.e MsgEthereumTx). 3 | 4 | During CheckTx, the transaction is passed through a series of 5 | pre-message execution validation checks such as signature and account 6 | verification in addition to minimum fees being checked. Otherwise, during 7 | DeliverTx, the transaction is simply passed to the EVM which will also 8 | perform the same series of checks. The distinction is made in CheckTx to 9 | prevent spam and DoS attacks. 10 | */ 11 | package ante 12 | -------------------------------------------------------------------------------- /app/app_test.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "encoding/json" 5 | "os" 6 | "testing" 7 | 8 | "github.com/stretchr/testify/require" 9 | 10 | "github.com/cosmos/cosmos-sdk/simapp" 11 | 12 | abci "github.com/tendermint/tendermint/abci/types" 13 | "github.com/tendermint/tendermint/libs/log" 14 | dbm "github.com/tendermint/tm-db" 15 | 16 | "github.com/tharsis/ethermint/encoding" 17 | ) 18 | 19 | func TestEthermintAppExport(t *testing.T) { 20 | db := dbm.NewMemDB() 21 | app := NewEthermintApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{}) 22 | 23 | genesisState := NewDefaultGenesisState() 24 | stateBytes, err := json.MarshalIndent(genesisState, "", " ") 25 | require.NoError(t, err) 26 | 27 | // Initialize the chain 28 | app.InitChain( 29 | abci.RequestInitChain{ 30 | ChainId: "ethermint-1", 31 | Validators: []abci.ValidatorUpdate{}, 32 | AppStateBytes: stateBytes, 33 | }, 34 | ) 35 | app.Commit() 36 | 37 | // Making a new app object with the db, so that initchain hasn't been called 38 | app2 := NewEthermintApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{}) 39 | _, err = app2.ExportAppStateAndValidators(false, []string{}) 40 | require.NoError(t, err, "ExportAppStateAndValidators should not have an error") 41 | } 42 | -------------------------------------------------------------------------------- /buf.yaml: -------------------------------------------------------------------------------- 1 | build: 2 | roots: 3 | - proto 4 | - third_party/proto 5 | excludes: 6 | - third_party/proto/google/protobuf 7 | lint: 8 | use: 9 | - DEFAULT 10 | - COMMENTS 11 | - FILE_LOWER_SNAKE_CASE 12 | except: 13 | - UNARY_RPC 14 | - COMMENT_FIELD 15 | - SERVICE_SUFFIX 16 | - PACKAGE_VERSION_SUFFIX 17 | - RPC_REQUEST_STANDARD_NAME 18 | - RPC_REQUEST_RESPONSE_UNIQUE 19 | - RPC_RESPONSE_STANDARD_NAME 20 | - RPC_REQUEST_RESPONSE_UNIQUE 21 | - COMMENT_MESSAGE 22 | ignore: 23 | - tendermint 24 | - gogoproto 25 | - cosmos_proto 26 | - google 27 | - confio 28 | breaking: 29 | use: 30 | - FILE 31 | ignore: 32 | - tendermint 33 | - gogoproto 34 | - cosmos_proto 35 | - google 36 | -------------------------------------------------------------------------------- /client/docs/statik/init.go: -------------------------------------------------------------------------------- 1 | package statik 2 | 3 | // This just for fixing the error in importing empty github.com/tharsis/ethermint/client/docs/statik 4 | -------------------------------------------------------------------------------- /client/docs/swagger-ui/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web3validator/ethermint/10f0164181cbf6ce4c551fd47b4a7231d4eac53c/client/docs/swagger-ui/favicon-16x16.png -------------------------------------------------------------------------------- /client/docs/swagger-ui/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web3validator/ethermint/10f0164181cbf6ce4c551fd47b4a7231d4eac53c/client/docs/swagger-ui/favicon-32x32.png -------------------------------------------------------------------------------- /client/docs/swagger-ui/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Swagger UI 7 | 8 | 9 | 10 | 31 | 32 | 33 | 34 |
35 | 36 | 37 | 38 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /client/import.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "bufio" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | "github.com/cosmos/cosmos-sdk/client/flags" 9 | "github.com/cosmos/cosmos-sdk/client/input" 10 | "github.com/cosmos/cosmos-sdk/crypto" 11 | "github.com/cosmos/cosmos-sdk/crypto/keyring" 12 | sdk "github.com/cosmos/cosmos-sdk/types" 13 | "github.com/ethereum/go-ethereum/common" 14 | "github.com/tharsis/ethermint/crypto/ethsecp256k1" 15 | 16 | "github.com/tharsis/ethermint/crypto/hd" 17 | ) 18 | 19 | // UnsafeImportKeyCommand imports private keys from a keyfile. 20 | func UnsafeImportKeyCommand() *cobra.Command { 21 | return &cobra.Command{ 22 | Use: "unsafe-import-eth-key ", 23 | Short: "**UNSAFE** Import Ethereum private keys into the local keybase", 24 | Long: "**UNSAFE** Import a hex-encoded Ethereum private key into the local keybase.", 25 | Args: cobra.ExactArgs(2), 26 | RunE: runImportCmd, 27 | } 28 | } 29 | 30 | func runImportCmd(cmd *cobra.Command, args []string) error { 31 | inBuf := bufio.NewReader(cmd.InOrStdin()) 32 | keyringBackend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend) 33 | rootDir, _ := cmd.Flags().GetString(flags.FlagHome) 34 | 35 | kb, err := keyring.New( 36 | sdk.KeyringServiceName(), 37 | keyringBackend, 38 | rootDir, 39 | inBuf, 40 | hd.EthSecp256k1Option(), 41 | ) 42 | if err != nil { 43 | return err 44 | } 45 | 46 | passphrase, err := input.GetPassword("Enter passphrase to encrypt your key:", inBuf) 47 | if err != nil { 48 | return err 49 | } 50 | 51 | privKey := ðsecp256k1.PrivKey{ 52 | Key: common.FromHex(args[1]), 53 | } 54 | 55 | armor := crypto.EncryptArmorPrivKey(privKey, passphrase, "eth_secp256k1") 56 | 57 | return kb.ImportPrivKey(args[0], armor, passphrase) 58 | } 59 | -------------------------------------------------------------------------------- /cmd/ethermintd/cmd_test.go: -------------------------------------------------------------------------------- 1 | package main_test 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/require" 8 | 9 | "github.com/cosmos/cosmos-sdk/client/flags" 10 | svrcmd "github.com/cosmos/cosmos-sdk/server/cmd" 11 | "github.com/cosmos/cosmos-sdk/x/genutil/client/cli" 12 | 13 | "github.com/tharsis/ethermint/app" 14 | ethermintd "github.com/tharsis/ethermint/cmd/ethermintd" 15 | ) 16 | 17 | func TestInitCmd(t *testing.T) { 18 | rootCmd, _ := ethermintd.NewRootCmd() 19 | rootCmd.SetArgs([]string{ 20 | "init", // Test the init cmd 21 | "ethermint-test", // Moniker 22 | fmt.Sprintf("--%s=%s", cli.FlagOverwrite, "true"), // Overwrite genesis.json, in case it already exists 23 | fmt.Sprintf("--%s=%s", flags.FlagChainID, "ethermint-1"), 24 | }) 25 | 26 | err := svrcmd.Execute(rootCmd, app.DefaultNodeHome) 27 | require.NoError(t, err) 28 | } 29 | -------------------------------------------------------------------------------- /cmd/ethermintd/flags.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | "github.com/tharsis/ethermint/version" 9 | ) 10 | 11 | const ( 12 | flagLong = "long" 13 | ) 14 | 15 | func init() { 16 | infoCmd.Flags().Bool(flagLong, false, "Print full information") 17 | } 18 | 19 | var ( 20 | infoCmd = &cobra.Command{ 21 | Use: "info", 22 | Short: "Print version info", 23 | RunE: func(_ *cobra.Command, _ []string) error { 24 | fmt.Println(version.Version()) 25 | return nil 26 | }, 27 | } 28 | ) 29 | -------------------------------------------------------------------------------- /cmd/ethermintd/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/cosmos/cosmos-sdk/server" 7 | svrcmd "github.com/cosmos/cosmos-sdk/server/cmd" 8 | sdk "github.com/cosmos/cosmos-sdk/types" 9 | 10 | "github.com/tharsis/ethermint/app" 11 | cmdcfg "github.com/tharsis/ethermint/cmd/config" 12 | ) 13 | 14 | func main() { 15 | setupConfig() 16 | cmdcfg.RegisterDenoms() 17 | 18 | rootCmd, _ := NewRootCmd() 19 | 20 | if err := svrcmd.Execute(rootCmd, app.DefaultNodeHome); err != nil { 21 | switch e := err.(type) { 22 | case server.ErrorCode: 23 | os.Exit(e.Code) 24 | 25 | default: 26 | os.Exit(1) 27 | } 28 | } 29 | } 30 | 31 | func setupConfig() { 32 | // set the address prefixes 33 | config := sdk.GetConfig() 34 | cmdcfg.SetBech32Prefixes(config) 35 | cmdcfg.SetBip44CoinType(config) 36 | config.Seal() 37 | } 38 | -------------------------------------------------------------------------------- /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 | app: 17 | target: 70% 18 | flags: 19 | - app 20 | modules: 21 | target: 70% 22 | flags: 23 | - modules 24 | core: 25 | target: 50% 26 | flags: 27 | - core 28 | client: 29 | flags: 30 | - client 31 | changes: false 32 | 33 | comment: 34 | layout: "reach, diff, files" 35 | behavior: default # update if exists else create new 36 | require_changes: true 37 | 38 | flags: 39 | app: 40 | paths: 41 | - "app/" 42 | modules: 43 | paths: 44 | - "x/" 45 | - "!x/**/client/" # ignore client package 46 | core: 47 | paths: 48 | - "core/" 49 | - "crypto/" 50 | - "types/" 51 | clients: 52 | paths: 53 | - "rpc/" 54 | - "client/" 55 | - "x/**/client/" 56 | 57 | ignore: 58 | - "docs" 59 | - "*.md" 60 | - "cmd" 61 | - "**/*.pb.go" 62 | - "types/*.pb.go" 63 | - "tests/*" 64 | - "x/**/*.pb.go" 65 | - "scripts/" 66 | -------------------------------------------------------------------------------- /config.yml: -------------------------------------------------------------------------------- 1 | accounts: 2 | - name: alice 3 | coins: ["100000000uatom", "100000000000000000000aphoton"] 4 | - name: bob 5 | coins: ["5000000000000aphoton"] 6 | validator: 7 | name: alice 8 | staked: "100000000000000000000aphoton" 9 | faucet: 10 | name: bob 11 | coins: ["10aphoton"] 12 | build: 13 | binary: "ethermintd" 14 | init: 15 | home: "$HOME/.ethermintd" 16 | app: 17 | evm-rpc: 18 | address: "0.0.0.0:8545" # change the JSON-RPC address and port 19 | ws-address: "0.0.0.0:8546" # change the JSON-RPC websocket address and port 20 | genesis: 21 | chain_id: "ethermint-2" 22 | app_state: 23 | staking: 24 | params: 25 | bond_denom: "aphoton" 26 | mint: 27 | params: 28 | mint_denom: "aphoton" 29 | crisis: 30 | constant_fee: 31 | denom: "aphoton" 32 | gov: 33 | deposit_params: 34 | min_deposit: 35 | - amount: "10000000" 36 | denom: "aphoton" 37 | evm: 38 | params: 39 | evm_denom: "aphoton" 40 | -------------------------------------------------------------------------------- /crypto/codec/amino.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/client/keys" 5 | "github.com/cosmos/cosmos-sdk/codec" 6 | "github.com/cosmos/cosmos-sdk/codec/legacy" 7 | cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" 8 | "github.com/cosmos/cosmos-sdk/crypto/keyring" 9 | 10 | "github.com/tharsis/ethermint/crypto/ethsecp256k1" 11 | ) 12 | 13 | // RegisterCrypto registers all crypto dependency types with the provided Amino 14 | // codec. 15 | func RegisterCrypto(cdc *codec.LegacyAmino) { 16 | cdc.RegisterConcrete(ðsecp256k1.PubKey{}, 17 | ethsecp256k1.PubKeyName, nil) 18 | cdc.RegisterConcrete(ðsecp256k1.PrivKey{}, 19 | ethsecp256k1.PrivKeyName, nil) 20 | 21 | keyring.RegisterLegacyAminoCodec(cdc) 22 | cryptocodec.RegisterCrypto(cdc) 23 | 24 | // NOTE: update SDK's amino codec to include the ethsecp256k1 keys. 25 | // DO NOT REMOVE unless deprecated on the SDK. 26 | legacy.Cdc = cdc 27 | keys.KeysCdc = cdc 28 | } 29 | -------------------------------------------------------------------------------- /crypto/codec/codec.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | import ( 4 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 5 | cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" 6 | 7 | "github.com/tharsis/ethermint/crypto/ethsecp256k1" 8 | ) 9 | 10 | // RegisterInterfaces register the Ethermint key concrete types. 11 | func RegisterInterfaces(registry codectypes.InterfaceRegistry) { 12 | registry.RegisterImplementations((*cryptotypes.PubKey)(nil), ðsecp256k1.PubKey{}) 13 | } 14 | -------------------------------------------------------------------------------- /docs/.vuepress/components/TmIconEthereumIntro.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/.vuepress/components/TmLogoEthereumBlack.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/.vuepress/styles/index.styl: -------------------------------------------------------------------------------- 1 | :root 2 | --color-link #3171B0 3 | --color-primary #7499BF -------------------------------------------------------------------------------- /docs/api/README.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # API 8 | 9 | This section contains different client and API reference document. 10 | 11 | 1. [JSON-RPC](./JSON-RPC) 12 | 1. [Protobuf Docs](./proto-docs) 13 | -------------------------------------------------------------------------------- /docs/api/json-rpc/running_server.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Running the Server 6 | 7 | Learn how to run and setup the JSON-RPC server on Ethermint. {synopsis} 8 | 9 | ## Enable Server 10 | 11 | To enable RPC server use the following flag (set to true by default). 12 | 13 | ```bash 14 | ethermintd start --evm-rpc.enable 15 | ``` 16 | 17 | ## Defining Namespaces 18 | 19 | `Eth`,`Net` and `Web3` [namespaces](./namespaces) are enabled by default. In order to enable other namespaces use flag `--evm-rpc.api`. 20 | 21 | ```bash 22 | ethermintd start --evm-rpc.api eth,txpool,personal,net,debug,web3,miner 23 | ``` 24 | 25 | ### CORS 26 | 27 | If accessing the RPC from a browser, CORS will need to be enabled with the appropriate domain set. Otherwise, JavaScript calls are limit by the same-origin policy and requests will fail: 28 | 29 | ```bash 30 | ethermintd start --evm-rpc.enable-unsafe-cors 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/architecture/README.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # Architecture Decision Records (ADR) 8 | 9 | This is a location to record all high-level architecture decisions in Ethermint. 10 | 11 | You can read more about the ADR concept in this blog posts: 12 | 13 | - [GitHub - Why Write ADRs](https://github.blog/2020-08-13-why-write-adrs/) 14 | - [Reverb - Documenting architecture decisions, the Reverb way](https://product.reverb.com/documenting-architecture-decisions-the-reverb-way-a3563bb24bd0#.78xhdix6t) 15 | 16 | An ADR should provide: 17 | 18 | - Context on the relevant goals and the current state 19 | - Proposed changes to achieve the goals 20 | - Summary of pros and cons 21 | - References 22 | - Changelog 23 | 24 | Note the distinction between an ADR and a spec. The ADR provides the context, intuition, reasoning, and 25 | justification for a change in architecture, or for the architecture of something 26 | new. The spec is much more compressed and streamlined summary of everything as 27 | it stands today. 28 | 29 | If recorded decisions turned out to be lacking, convene a discussion, record the new decisions here, and then modify the code to match. 30 | 31 | Note the context/background should be written in the present tense. 32 | 33 | Please add a entry below in your Pull Request for an ADR. 34 | 35 | ## ADR Table of Contents 36 | 37 | 41 | -------------------------------------------------------------------------------- /docs/basics/README.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # Basics 8 | 9 | This repository contains reference documentation on the basic concepts of Ethermint. 10 | 11 | 1. [Accounts](./accounts) 12 | 2. [Gas and Fees](./gas) 13 | 3. [Lifecycle of a transaction](./transactions) 14 | 4. [Tokens](./tokens) 15 | 16 | After reading the basics, head on to the [Core Reference](../core/README) for more advanced material. 17 | -------------------------------------------------------------------------------- /docs/basics/img/photon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web3validator/ethermint/10f0164181cbf6ce4c551fd47b4a7231d4eac53c/docs/basics/img/photon.png -------------------------------------------------------------------------------- /docs/basics/tokens.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Tokens 6 | 7 | Learn about the the different types of tokens available in Ethermint. {synopsis} 8 | 9 | ## Introduction 10 | 11 | Ethermint is a Cosmos SDK-based chain with full EVM support. Because of this architecture, tokens and assets in the network may come from different independent sources: the `bank` module and the `evm` module. 12 | 13 | ## Cosmos Coins 14 | 15 | Accounts can own SDK coins in their balance, which are used for operations with other Cosmos modules and transactions. Examples of these are using the coins for staking, IBC transfers, governance deposits and EVM 16 | 17 | ### Photon 18 | 19 | The denomination used for staking, governance and gas consumption on the EVM is the Photon. The Photon provides the utility of: securing the Proof-of-Stake chain, token used for governance proposals, fee distribution and as a mean of gas for running smart contracts on the EVM. 20 | 21 | Ethermint uses [Atto](https://en.wikipedia.org/wiki/Atto-) Photon as the base denomination to maintain parity with Ethereum. 22 | 23 | ``` 24 | 1 photon = 1×10⁻¹⁸ aphoton 25 | ``` 26 | 27 | This matches Ethereum denomination of: 28 | 29 | ``` 30 | 1 ETH = 1x10⁻¹⁸ wei 31 | ``` 32 | 33 | ### EVM Tokens 34 | 35 | Ethermint is compatible with ERC20 tokens and other non-fungible token standards (EIP721, EIP1155) 36 | that are natively supported by the EVM. 37 | 38 | ## Next {hide} 39 | 40 | Learn about the supported [JSON-RPC](./json_rpc.md) methods on Ethermint {hide} 41 | -------------------------------------------------------------------------------- /docs/core/README.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # Core Concepts 8 | 9 | This repository contains reference documentation on the core concepts of Ethermint. 10 | 11 | 1. [Encoding](./encoding.md) 12 | 2. [Pending State](./pending_state.md) 13 | 14 | After reading the core concepts, head on to the [guides](../guides/README.md) to learn how to use Ethereum tooling with Ethermint. 15 | -------------------------------------------------------------------------------- /docs/guides/README.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # Guides 8 | 9 | This section contains different guides to use wallets and popular Ethereum tools with Ethermint. 10 | 11 | 1. [Single Node Localnet](./localnet/single_node) 12 | 1. [Multi Node Localnet](./localnet/multi_node) 13 | 1. [Keyring](./keys-wallets/keyring) 14 | 1. [Metamask](./keys-wallets/metamask) 15 | 1. [Truffle](./tools/truffle) 16 | 1. [Remix](./tools/remix) 17 | -------------------------------------------------------------------------------- /docs/guides/img/metamask_import.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web3validator/ethermint/10f0164181cbf6ce4c551fd47b4a7231d4eac53c/docs/guides/img/metamask_import.png -------------------------------------------------------------------------------- /docs/guides/img/metamask_network_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web3validator/ethermint/10f0164181cbf6ce4c551fd47b4a7231d4eac53c/docs/guides/img/metamask_network_settings.png -------------------------------------------------------------------------------- /docs/guides/img/remix_deploy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web3validator/ethermint/10f0164181cbf6ce4c551fd47b4a7231d4eac53c/docs/guides/img/remix_deploy.png -------------------------------------------------------------------------------- /docs/guides/img/remix_deployed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web3validator/ethermint/10f0164181cbf6ce4c551fd47b4a7231d4eac53c/docs/guides/img/remix_deployed.png -------------------------------------------------------------------------------- /docs/guides/img/remix_interact.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web3validator/ethermint/10f0164181cbf6ce4c551fd47b4a7231d4eac53c/docs/guides/img/remix_interact.png -------------------------------------------------------------------------------- /docs/intro/README.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # Introduction 8 | 9 | This folder contains introduction material for Ethermint. 10 | 11 | 1. [Overview](./overview) 12 | 1. [Architecture](./architecture) 13 | 1. [Clients](./clients) 14 | 1. [Use Cases](./use_cases) 15 | 1. [Resources](./resources) 16 | 17 | After reading the introduction material, head over to the [basics](../basics/README) to learn more. 18 | 19 | ## Next {hide} 20 | 21 | Get an high-level [overview](./overview) of Ethermint {hide} 22 | -------------------------------------------------------------------------------- /docs/intro/clients.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Clients 6 | 7 | Learn about the client supported by your Ethermint node. {synopsis} 8 | 9 | ## Client Servers 10 | 11 | The Ethermint client supports both [gRPC endpoints](https://cosmos.network/rpc) from the SDK and [Ethereum's JSON-RPC](https://eth.wiki/json-rpc/API). 12 | 13 | ### Cosmos gRPC and Tendermint RPC 14 | 15 | Ethermint exposes gRPC endpoints (and REST) for all the integrated Cosmos-SDK modules. This makes it easier for 16 | wallets and block explorers to interact with the proof-of-stake logic and native Cosmos transactions and queries: 17 | 18 | ### Ethereum JSON-RPC server 19 | 20 | Ethermint also supports most of the standard web3 [JSON-RPC 21 | APIs](./../api/JSON-RPC/running_server) to connect with existing web3 tooling. 22 | 23 | ::: tip 24 | See the list of supported JSON-RPC API [endpoints](./../api/JSON-RPC/endpoints) and [namespaces](./../api/JSON-RPC/namespaces). 25 | ::: 26 | 27 | To connect to the JSON-PRC server, start the node with the `--evm-rpc.enable=true` flag and define the namespaces that you would like to run using the `--evm.rpc.api` flag (e.g. `"txpool,eth,web3,net,personal"`. Then, you can point any Ethereum development tooling to `http://localhost:8545` or whatever port you choose with the listen address flag (`--evm-rpc.address`). 28 | 29 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "version": "1.0.0", 4 | "description": "Ethermint Documentation", 5 | "main": "index.js", 6 | "scripts": { 7 | "preserve": "./pre.sh", 8 | "serve": "vuepress dev", 9 | "build": "vuepress build", 10 | "docs:build": "vuepress build docs", 11 | "postserve": "./post.sh", 12 | "prebuild": "./pre.sh", 13 | "postbuild": "./post.sh" 14 | }, 15 | "keywords": [ 16 | "ethermint", 17 | "cosmos", 18 | "ethereum", 19 | "blockchain", 20 | "cryptocurrency", 21 | "evm" 22 | ], 23 | "author": "Tharsis", 24 | "license": "ISC", 25 | "dependencies": { 26 | "entities": "^2.0.3", 27 | "markdown-it": "^12.0.6", 28 | "markdown-it-katex": "^2.0.3", 29 | "vuepress-theme-cosmos": "^1.0.182" 30 | }, 31 | "devDependencies": { 32 | "watchpack": "^1.7.2" 33 | }, 34 | "resolutions": { 35 | "serialize-javascript": "^4.0.0" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /docs/post.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Modules 4 | rm -rf modules 5 | -------------------------------------------------------------------------------- /docs/pre.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | mkdir -p modules 4 | 5 | for D in ../x/*; do 6 | if [ -d "${D}" ]; then 7 | rm -rf "modules/$(echo $D | awk -F/ '{print $NF}')" 8 | mkdir -p "modules/$(echo $D | awk -F/ '{print $NF}')" && cp -r $D/spec/* "$_" 9 | fi 10 | done 11 | 12 | cat ../x/README.md | sed 's/\.\/x/\/modules/g' | sed 's/spec\/README.md//g' | sed 's/\.\.\/docs\/building-modules\/README\.md/\/building-modules\/intro\.html/g' > ./modules/README.md -------------------------------------------------------------------------------- /docs/quickstart/README.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # Quick Start 8 | 9 | This repository contains reference documentation on how to install and run an Ethermint full node. 10 | 11 | 1. [Installation](./installation) 12 | 1. [Build and Configuration](./binary) 13 | 1. [Run a Node](./run_node) 14 | 1. [Interacting with the Node](./interact_node) 15 | 16 | After going through the Quick Start contents, head over to the [basics](./../basics/README) to learn more. 17 | 18 | ## Next {hide} 19 | 20 | Learn how to [install](./../quickstart/installation) Ethermint {hide} 21 | -------------------------------------------------------------------------------- /docs/quickstart/installation.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Installation 6 | 7 | ## Pre-requisites 8 | 9 | ### Install [`jq`](https://stedolan.github.io/jq) 10 | 11 | On Mac `brew install jq` or download the official binaries on the project [website](https://stedolan.github.io/jq/download/). 12 | 13 | ## Install Binaries 14 | 15 | ### GitHub 16 | 17 | Clone and build Ethermint using `git`: 18 | 19 | ```bash 20 | git clone https://github.com/tharsis/ethermint.git 21 | cd ethermint 22 | make install 23 | ``` 24 | 25 | Check that the binaries have been successfully installed: 26 | 27 | ```bash 28 | ethermintd version 29 | ``` 30 | 31 | ## Docker 32 | 33 | You can build Ethermint using Docker by running: 34 | 35 | ```bash 36 | make docker-build 37 | ``` 38 | 39 | This will install the binaries on the `./build` directory. Now, check that the binaries have been 40 | successfully installed: 41 | 42 | ```bash 43 | ethermintd version 44 | ``` 45 | 46 | ## Releases 47 | 48 | ::: warning 49 | Ethermint is under VERY ACTIVE DEVELOPMENT and should be treated as pre-alpha software. This means it is not meant to be run in production, its APIs are subject to change without warning and should not be relied upon, and it should not be used to hold any value. We will remove this warning when we have a release that is stable, secure, and properly tested. 50 | ::: 51 | 52 | You can also download a specific release available on the Ethermint [repository](https://github.com/tharsis/ethermint/releases) or via command line: 53 | 54 | ```bash 55 | go install github.com/tharsis/ethermint@latest 56 | ``` 57 | 58 | ## Next {hide} 59 | 60 | Learn how to [run a node](./.run_node.md) {hide} 61 | -------------------------------------------------------------------------------- /docs/testnet/README.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # Testnet 8 | 9 | This section contains different client and API reference document. 10 | 11 | 1. [Join Testnet](./join) 12 | 1. [Cloud Providers](./cloud_providers) 13 | 1. [Testnet](./testnet) 14 | 1. [Validator Setup](./validator-setup) 15 | 1. [Security Checklist](./security) 16 | -------------------------------------------------------------------------------- /docs/testnet/join.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Joining a Testnet 6 | 7 | This document outlines the steps to join an existing testnet 8 | 9 | ## Steps 10 | 11 | 1. [Install](./../quickstart/installation) the Ethermint binary `ethermintd` 12 | 13 | ```bash 14 | go install https://github.com/tharsis/ethermint 15 | ``` 16 | 17 | 2. Create an Ethermint [account](./../basics/accounts) 18 | 19 | ```bash 20 | ethermintd keys add --keyring-backend=test 21 | ``` 22 | 23 | 3. Copy genesis file 24 | 25 | Follow this [link](https://gist.github.com/araskachoi/43f86f3edff23729b817e8b0bb86295a) and copy it over to the directory `~/.ethermintd/config/genesis.json` 26 | 27 | 4. Add peers 28 | 29 | Edit the file located in `~/.ethermintd/config/config.toml` and the `persistent_peers` to the following: 30 | 31 | ```toml 32 | "05aa6587f07a0c6a9a8213f0138c4a76d476418a@18.204.206.179:26656,13d4a1c16d1f427988b7c499b6d150726aaf3aa0@3.86.104.251:26656,a00db749fa51e485c8376276d29d599258052f3e@54.210.246.165:26656" 33 | ``` 34 | 35 | 5. Validate genesis and start the Ethermint network 36 | 37 | ```bash 38 | ethermintd validate-genesis 39 | 40 | ethermintd start --pruning=nothing --rpc.unsafe --log_level "main:info,state:info,mempool:info" 41 | ``` 42 | -------------------------------------------------------------------------------- /docs/versions: -------------------------------------------------------------------------------- 1 | main main 2 | -------------------------------------------------------------------------------- /encoding/codec/codec.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 6 | "github.com/cosmos/cosmos-sdk/std" 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | 9 | cryptocodec "github.com/tharsis/ethermint/crypto/codec" 10 | ethermint "github.com/tharsis/ethermint/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 | } 18 | 19 | // RegisterInterfaces registers Interfaces from types, crypto, and SDK std. 20 | func RegisterInterfaces(interfaceRegistry codectypes.InterfaceRegistry) { 21 | std.RegisterInterfaces(interfaceRegistry) 22 | cryptocodec.RegisterInterfaces(interfaceRegistry) 23 | ethermint.RegisterInterfaces(interfaceRegistry) 24 | } 25 | -------------------------------------------------------------------------------- /encoding/config_test.go: -------------------------------------------------------------------------------- 1 | package encoding_test 2 | 3 | import ( 4 | "math/big" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/require" 8 | 9 | ethtypes "github.com/ethereum/go-ethereum/core/types" 10 | 11 | "github.com/tharsis/ethermint/app" 12 | "github.com/tharsis/ethermint/encoding" 13 | "github.com/tharsis/ethermint/tests" 14 | evmtypes "github.com/tharsis/ethermint/x/evm/types" 15 | ) 16 | 17 | func TestTxEncoding(t *testing.T) { 18 | addr, key := tests.NewAddrKey() 19 | signer := tests.NewSigner(key) 20 | 21 | msg := evmtypes.NewTxContract(big.NewInt(1), 1, big.NewInt(10), 100000, big.NewInt(1), []byte{}, nil) 22 | msg.From = addr.Hex() 23 | 24 | ethSigner := ethtypes.LatestSignerForChainID(big.NewInt(1)) 25 | err := msg.Sign(ethSigner, signer) 26 | require.NoError(t, err) 27 | 28 | cfg := encoding.MakeConfig(app.ModuleBasics) 29 | 30 | bz, err := cfg.TxConfig.TxEncoder()(msg) 31 | require.NoError(t, err, "encoding failed") 32 | 33 | tx, err := cfg.TxConfig.TxDecoder()(bz) 34 | require.NoError(t, err, "decoding failed") 35 | require.IsType(t, &evmtypes.MsgEthereumTx{}, tx) 36 | require.Equal(t, msg.Data, tx.(*evmtypes.MsgEthereumTx).Data) 37 | 38 | // FIXME: transaction hashing is hardcoded on Terndermint: 39 | // See https://github.com/tendermint/tendermint/issues/6539 for reference 40 | // txHash := msg.AsTransaction().Hash() 41 | // tmTx := tmtypes.Tx(bz) 42 | 43 | // require.Equal(t, txHash.Bytes(), tmTx.Hash()) 44 | } 45 | -------------------------------------------------------------------------------- /ethereum/rpc/doc.go: -------------------------------------------------------------------------------- 1 | // Package rpc contains RPC handler methods, namespaces and utilities to start 2 | // Ethermint's Web3-compatible JSON-RPC server. 3 | // 4 | // The list of available namespaces are: 5 | // 6 | // * `rpc/namespaces/eth`: `eth` namespace. Exposes the `PublicEthereumAPI` and the `PublicFilterAPI`. 7 | // * `rpc/namespaces/personal`: `personal` namespace. Exposes the `PrivateAccountAPI`. 8 | // * `rpc/namespaces/net`: `net` namespace. Exposes the `PublicNetAPI`. 9 | // * `rpc/namespaces/web3`: `web3` namespace. Exposes the `PublicWeb3API` 10 | package rpc 11 | -------------------------------------------------------------------------------- /ethereum/rpc/namespaces/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 | //+build !go1.5 18 | 19 | // no-op implementation of tracing methods for Go < 1.5. 20 | 21 | package debug 22 | 23 | import ( 24 | "errors" 25 | ) 26 | 27 | func (*InternalAPI) StartGoTrace(string file) error { 28 | a.logger.Debug("debug_stopGoTrace", "file", file) 29 | return errors.New("tracing is not supported on Go < 1.5") 30 | } 31 | 32 | func (*InternalAPI) StopGoTrace() error { 33 | a.logger.Debug("debug_stopGoTrace") 34 | return errors.New("tracing is not supported on Go < 1.5") 35 | } 36 | -------------------------------------------------------------------------------- /ethereum/rpc/namespaces/debug/utils.go: -------------------------------------------------------------------------------- 1 | package debug 2 | 3 | import ( 4 | "os" 5 | "os/user" 6 | "path/filepath" 7 | "runtime/pprof" 8 | "strings" 9 | 10 | "github.com/cosmos/cosmos-sdk/server" 11 | "github.com/tendermint/tendermint/libs/log" 12 | ) 13 | 14 | // isCPUProfileConfigurationActivated checks if cpuprofile was configured via flag 15 | func isCPUProfileConfigurationActivated(ctx *server.Context) bool { 16 | // TODO: use same constants as server/start.go 17 | // constant declared in start.go cannot be imported (cyclical dependency) 18 | const flagCPUProfile = "cpu-profile" 19 | if cpuProfile := ctx.Viper.GetString(flagCPUProfile); cpuProfile != "" { 20 | return true 21 | } 22 | return false 23 | } 24 | 25 | // ExpandHome expands home directory in file paths. 26 | // ~someuser/tmp will not be expanded. 27 | func ExpandHome(p string) string { 28 | if strings.HasPrefix(p, "~/") || strings.HasPrefix(p, "~\\") { 29 | home := os.Getenv("HOME") 30 | if home == "" { 31 | if usr, err := user.Current(); err == nil { 32 | home = usr.HomeDir 33 | } 34 | } 35 | if home != "" { 36 | p = home + p[1:] 37 | } 38 | } 39 | return filepath.Clean(p) 40 | } 41 | 42 | // writeProfile writes the data to a file 43 | func writeProfile(name, file string, log log.Logger) error { 44 | p := pprof.Lookup(name) 45 | log.Info("Writing profile records", "count", p.Count(), "type", name, "dump", file) 46 | f, err := os.Create(ExpandHome(file)) 47 | if err != nil { 48 | return err 49 | } 50 | defer f.Close() 51 | 52 | return p.WriteTo(f, 0) 53 | } 54 | -------------------------------------------------------------------------------- /ethereum/rpc/namespaces/net/api.go: -------------------------------------------------------------------------------- 1 | package net 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/cosmos/cosmos-sdk/client" 8 | rpcclient "github.com/tendermint/tendermint/rpc/client" 9 | ethermint "github.com/tharsis/ethermint/types" 10 | ) 11 | 12 | // PublicAPI is the eth_ prefixed set of APIs in the Web3 JSON-RPC spec. 13 | type PublicAPI struct { 14 | networkVersion uint64 15 | tmClient rpcclient.Client 16 | } 17 | 18 | // NewPublicAPI creates an instance of the public Net Web3 API. 19 | func NewPublicAPI(clientCtx client.Context) *PublicAPI { 20 | // parse the chainID from a integer string 21 | chainIDEpoch, err := ethermint.ParseChainID(clientCtx.ChainID) 22 | if err != nil { 23 | panic(err) 24 | } 25 | 26 | return &PublicAPI{ 27 | networkVersion: chainIDEpoch.Uint64(), 28 | tmClient: clientCtx.Client, 29 | } 30 | } 31 | 32 | // Version returns the current ethereum protocol version. 33 | func (s *PublicAPI) Version() string { 34 | return fmt.Sprintf("%d", s.networkVersion) 35 | } 36 | 37 | // Listening returns if client is actively listening for network connections. 38 | func (s *PublicAPI) Listening() bool { 39 | ctx := context.Background() 40 | netInfo, err := s.tmClient.NetInfo(ctx) 41 | if err != nil { 42 | return false 43 | } 44 | return netInfo.Listening 45 | } 46 | 47 | // PeerCount returns the number of peers currently connected to the client. 48 | func (s *PublicAPI) PeerCount() int { 49 | ctx := context.Background() 50 | netInfo, err := s.tmClient.NetInfo(ctx) 51 | if err != nil { 52 | return 0 53 | } 54 | return len(netInfo.Peers) 55 | } 56 | -------------------------------------------------------------------------------- /ethereum/rpc/namespaces/web3/api.go: -------------------------------------------------------------------------------- 1 | package web3 2 | 3 | import ( 4 | "github.com/tharsis/ethermint/version" 5 | 6 | "github.com/ethereum/go-ethereum/common/hexutil" 7 | "github.com/ethereum/go-ethereum/crypto" 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 hexutil.Bytes) hexutil.Bytes { 25 | return crypto.Keccak256(input) 26 | } 27 | -------------------------------------------------------------------------------- /ethereum/rpc/pubsub/pubsub_test.go: -------------------------------------------------------------------------------- 1 | package pubsub 2 | 3 | // func TestAddTopic(t *testing.T) { 4 | // q := NewEventBus() 5 | // err := q.AddTopic("kek", make(<-chan coretypes.ResultEvent)) 6 | // require.NoError(t, err) 7 | 8 | // err = q.AddTopic("lol", make(<-chan coretypes.ResultEvent)) 9 | // require.NoError(t, err) 10 | 11 | // err = q.AddTopic("lol", make(<-chan coretypes.ResultEvent)) 12 | // require.Error(t, err) 13 | 14 | // require.EqualValues(t, []string{"kek", "lol"}, q.Topics()) 15 | // } 16 | 17 | // func TestSubscribe(t *testing.T) { 18 | // q := NewEventBus() 19 | // kekSrc := make(chan coretypes.ResultEvent) 20 | // q.AddTopic("kek", kekSrc) 21 | 22 | // lolSrc := make(chan coretypes.ResultEvent) 23 | // q.AddTopic("lol", lolSrc) 24 | 25 | // kekSubC, err := q.Subscribe("kek") 26 | // require.NoError(t, err) 27 | 28 | // lolSubC, err := q.Subscribe("lol") 29 | // require.NoError(t, err) 30 | 31 | // lol2SubC, err := q.Subscribe("lol") 32 | // require.NoError(t, err) 33 | 34 | // wg := new(sync.WaitGroup) 35 | // wg.Add(4) 36 | 37 | // go func() { 38 | // defer wg.Done() 39 | // msg := <-kekSubC 40 | // log.Println("kek:", msg) 41 | // require.EqualValues(t, 1, msg) 42 | // }() 43 | 44 | // go func() { 45 | // defer wg.Done() 46 | // msg := <-lolSubC 47 | // log.Println("lol:", msg) 48 | // require.EqualValues(t, 1, msg) 49 | // }() 50 | 51 | // go func() { 52 | // defer wg.Done() 53 | // msg := <-lol2SubC 54 | // log.Println("lol2:", msg) 55 | // require.EqualValues(t, 1, msg) 56 | // }() 57 | 58 | // go func() { 59 | // defer wg.Done() 60 | 61 | // time.Sleep(time.Second) 62 | 63 | // close(kekSrc) 64 | // close(lolSrc) 65 | // }() 66 | 67 | // wg.Wait() 68 | // time.Sleep(time.Second) 69 | // } 70 | -------------------------------------------------------------------------------- /ethereum/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 | -------------------------------------------------------------------------------- /gometalinter.json: -------------------------------------------------------------------------------- 1 | { 2 | "Linters": { 3 | "vet": "go tool vet -composites=false :PATH:LINE:MESSAGE" 4 | }, 5 | "Enable": [ 6 | "golint", 7 | "vet", 8 | "ineffassign", 9 | "unparam", 10 | "unconvert", 11 | "misspell" 12 | ], 13 | "Deadline": "500s", 14 | "Vendor": true, 15 | "Cyclo": 11 16 | } -------------------------------------------------------------------------------- /networks/local/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | docker build --no-cache --tag ethermintd/node ../.. -f ethermintnode/Dockerfile 3 | 4 | .PHONY: all 5 | -------------------------------------------------------------------------------- /networks/local/ethermintnode/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:stretch as build-env 2 | 3 | # Install minimum necessary dependencies 4 | ENV PACKAGES curl make git libc-dev bash gcc 5 | RUN apt-get update && apt-get upgrade -y && \ 6 | apt-get install -y $PACKAGES 7 | 8 | # Set working directory for the build 9 | WORKDIR /go/src/github.com/tharsis/ethermint 10 | 11 | # Add source files 12 | COPY . . 13 | 14 | # build Ethermint 15 | RUN make build-linux 16 | 17 | # Final image 18 | FROM golang:1.14 as final 19 | 20 | WORKDIR / 21 | 22 | RUN apt-get update 23 | 24 | # Copy over binaries from the build-env 25 | COPY --from=build-env /go/src/github.com/tharsis/ethermint/build/ethermintd / 26 | COPY --from=build-env /go/src/github.com/tharsis/ethermint/scripts/start-docker.sh / 27 | 28 | EXPOSE 26656 26657 1317 8545 8546 29 | 30 | # Run ethermintd by default, omit entrypoint to ease using container with ethermintd 31 | ENTRYPOINT ["/bin/bash", "-c"] -------------------------------------------------------------------------------- /proto/ethermint/crypto/v1alpha1/ethsecp256k1/keys.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package ethermint.crypto.v1alpha1.ethsecp256k1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | 6 | option go_package = "github.com/tharsis/ethermint/crypto/ethsecp256k1"; 7 | 8 | // PubKey defines a type alias for an ecdsa.PublicKey that implements 9 | // Tendermint's PubKey interface. It represents the 33-byte compressed public 10 | // key format. 11 | message PubKey { 12 | option (gogoproto.goproto_stringer) = false; 13 | 14 | bytes key = 1; 15 | } 16 | 17 | // PrivKey defines a type alias for an ecdsa.PrivateKey that implements 18 | // Tendermint's PrivateKey interface. 19 | message PrivKey { 20 | bytes key = 1; 21 | } 22 | -------------------------------------------------------------------------------- /proto/ethermint/evm/v1alpha1/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package ethermint.evm.v1alpha1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "ethermint/evm/v1alpha1/evm.proto"; 6 | 7 | option go_package = "github.com/tharsis/ethermint/x/evm/types"; 8 | 9 | // GenesisState defines the evm module's genesis state. 10 | message GenesisState { 11 | // accounts is an array containing the ethereum genesis accounts. 12 | repeated GenesisAccount accounts = 1 [(gogoproto.nullable) = false]; 13 | // params defines all the paramaters of the module. 14 | Params params = 3 [(gogoproto.nullable) = false]; 15 | 16 | repeated TransactionLogs txs_logs = 4 [(gogoproto.moretags) = "yaml:\"txs_logs\"", (gogoproto.nullable) = false]; 17 | } 18 | 19 | // GenesisAccount defines an account to be initialized in the genesis state. 20 | // Its main difference between with Geth's GenesisAccount is that it uses a 21 | // custom storage type and that it doesn't contain the private key field. 22 | message GenesisAccount { 23 | // address defines an ethereum hex formated address of an account 24 | string address = 1; 25 | // code defines the hex bytes of the account code. 26 | string code = 2; 27 | // storage defines the set of state key values for the account. 28 | repeated State storage = 3 [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "Storage"]; 29 | } 30 | -------------------------------------------------------------------------------- /proto/ethermint/types/v1alpha1/account.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package ethermint.types.v1alpha1; 3 | 4 | import "cosmos/auth/v1beta1/auth.proto"; 5 | import "cosmos_proto/cosmos.proto"; 6 | import "gogoproto/gogo.proto"; 7 | 8 | option go_package = "github.com/tharsis/ethermint/types"; 9 | 10 | // EthAccount implements the authtypes.AccountI interface and embeds an 11 | // authtypes.BaseAccount type. It is compatible with the auth AccountKeeper. 12 | message EthAccount { 13 | option (gogoproto.goproto_getters) = false; 14 | option (gogoproto.goproto_stringer) = false; 15 | option (gogoproto.equal) = false; 16 | 17 | option (cosmos_proto.implements_interface) = "github.com/cosmos/cosmos-sdk/x/auth/types.AccountI"; 18 | 19 | cosmos.auth.v1beta1.BaseAccount base_account = 1 20 | [(gogoproto.embed) = true, (gogoproto.moretags) = "yaml:\"base_account\""]; 21 | string code_hash = 2 [(gogoproto.moretags) = "yaml:\"code_hash\""]; 22 | } 23 | -------------------------------------------------------------------------------- /scripts/gen-tests-artifacts.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # prepare sloc v0.5.17 in PATH 4 | solc --combined-json bin,abi --allow-paths . ./tests/solidity/suites/staking/contracts/test/mocks/StandardTokenMock.sol \ 5 | | jq ".contracts.\"./tests/solidity/suites/staking/contracts/test/mocks/StandardTokenMock.sol:StandardTokenMock\"" \ 6 | > x/evm/keeper/ERC20Contract.json 7 | -------------------------------------------------------------------------------- /scripts/protoc-swagger-gen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eo pipefail 4 | 5 | mkdir -p ./tmp-swagger-gen 6 | proto_dirs=$(find ./proto ./third_party/proto -path -prune -o -name '*.proto' -print0 | xargs -0 -n1 dirname | sort | uniq) 7 | for dir in $proto_dirs; do 8 | 9 | # generate swagger files (filter query files) 10 | query_file=$(find "${dir}" -maxdepth 1 -name 'query.proto') 11 | if [[ ! -z "$query_file" ]]; then 12 | protoc \ 13 | -I "proto" \ 14 | -I "third_party/proto" \ 15 | "$query_file" \ 16 | --swagger_out ./tmp-swagger-gen \ 17 | --swagger_opt logtostderr=true --swagger_opt fqn_for_swagger_name=true --swagger_opt simple_operation_ids=true 18 | fi 19 | done 20 | 21 | # combine swagger files 22 | # uses nodejs package `swagger-combine`. 23 | # all the individual swagger files need to be configured in `config.json` for merging 24 | swagger-combine ./client/docs/config.json -o ./client/docs/swagger-ui/swagger.yaml -f yaml --continueOnConflictingPaths true --includeDefinitions true 25 | 26 | # clean swagger files 27 | rm -rf ./tmp-swagger-gen 28 | 29 | # generate binary for static server 30 | statik -src=./client/docs/swagger-ui -dest=./client/docs 31 | -------------------------------------------------------------------------------- /scripts/protocgen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eo pipefail 4 | 5 | protoc_gen_gocosmos() { 6 | if ! grep "github.com/gogo/protobuf => github.com/regen-network/protobuf" go.mod &>/dev/null ; then 7 | echo -e "\tPlease run this command from somewhere inside the sommelier folder." 8 | return 1 9 | fi 10 | 11 | go get github.com/regen-network/cosmos-proto/protoc-gen-gocosmos 2>/dev/null 12 | } 13 | 14 | protoc_gen_doc() { 15 | go get -u github.com/pseudomuto/protoc-gen-doc/cmd/protoc-gen-doc 2>/dev/null 16 | } 17 | 18 | protoc_gen_gocosmos 19 | protoc_gen_doc 20 | 21 | proto_dirs=$(find ./proto -path -prune -o -name '*.proto' -print0 | xargs -0 -n1 dirname | sort | uniq) 22 | for dir in $proto_dirs; do 23 | buf protoc \ 24 | -I "proto" \ 25 | -I "third_party/proto" \ 26 | --gocosmos_out=plugins=interfacetype+grpc,\ 27 | Mgoogle/protobuf/any.proto=github.com/cosmos/cosmos-sdk/codec/types:. \ 28 | --grpc-gateway_out=logtostderr=true:. \ 29 | $(find "${dir}" -maxdepth 1 -name '*.proto') 30 | 31 | done 32 | 33 | # command to generate docs using protoc-gen-doc 34 | buf protoc \ 35 | -I "proto" \ 36 | -I "third_party/proto" \ 37 | --doc_out=./docs/api \ 38 | --doc_opt=./docs/protodoc-markdown.tmpl,proto-docs.md \ 39 | $(find "$(pwd)/proto" -maxdepth 5 -name '*.proto') 40 | # go mod tidy 41 | 42 | # move proto files to the right places 43 | cp -r github.com/tharsis/ethermint/* ./ 44 | rm -rf github.com 45 | -------------------------------------------------------------------------------- /scripts/start-docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "prepare genesis: Run validate-genesis to ensure everything worked and that the genesis file is setup correctly" 4 | ./ethermintd validate-genesis --home /ethermint 5 | 6 | echo "starting ethermint node $ID in background ..." 7 | ./ethermintd start \ 8 | --home /ethermint \ 9 | --keyring-backend test 10 | 11 | echo "started ethermint node" 12 | tail -f /dev/null -------------------------------------------------------------------------------- /server/config/config_test.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | ) 8 | 9 | func TestDefaultConfig(t *testing.T) { 10 | cfg := DefaultEVMConfig() 11 | require.True(t, cfg.Enable) 12 | require.Equal(t, cfg.RPCAddress, DefaultEVMAddress) 13 | require.Equal(t, cfg.WsAddress, DefaultEVMWSAddress) 14 | } 15 | -------------------------------------------------------------------------------- /server/config/toml.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | // DefaultConfigTemplate defines the configuration template for the EVM RPC configuration 4 | const DefaultConfigTemplate = ` 5 | ############################################################################### 6 | ### EVM RPC Configuration ### 7 | ############################################################################### 8 | 9 | [evm-rpc] 10 | 11 | # Enable defines if the gRPC server should be enabled. 12 | enable = {{ .EVMRPC.Enable }} 13 | 14 | # Address defines the EVM RPC HTTP server address to bind to. 15 | address = "{{ .EVMRPC.RPCAddress }}" 16 | 17 | # Address defines the EVM WebSocket server address to bind to. 18 | ws-address = "{{ .EVMRPC.WsAddress }}" 19 | 20 | # API defines a list of JSON-RPC namespaces that should be enabled 21 | # Example: "eth,txpool,personal,net,debug,web3" 22 | api = "{{range $index, $elmt := .EVMRPC.API}}{{if $index}},{{$elmt}}{{else}}{{$elmt}}{{end}}{{end}}" 23 | 24 | # EnableUnsafeCORS defines if CORS should be enabled (unsafe - use it at your own risk) 25 | enable-unsafe-cors = "{{ .EVMRPC.EnableUnsafeCORS }}" 26 | ` 27 | -------------------------------------------------------------------------------- /tests/e2e/integration_test.go: -------------------------------------------------------------------------------- 1 | package e2e 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | "github.com/ethereum/go-ethereum/ethclient" 8 | "github.com/stretchr/testify/suite" 9 | 10 | "github.com/tharsis/ethermint/testutil/network" 11 | ethermint "github.com/tharsis/ethermint/types" 12 | ) 13 | 14 | type IntegrationTestSuite struct { 15 | suite.Suite 16 | 17 | ctx context.Context 18 | cfg network.Config 19 | network *network.Network 20 | } 21 | 22 | func (s *IntegrationTestSuite) SetupSuite() { 23 | s.T().Log("setting up integration test suite") 24 | 25 | cfg := network.DefaultConfig() 26 | cfg.NumValidators = 1 27 | 28 | s.ctx = context.Background() 29 | s.cfg = cfg 30 | s.network = network.New(s.T(), cfg) 31 | s.Require().NotNil(s.network) 32 | 33 | _, err := s.network.WaitForHeight(1) 34 | s.Require().NoError(err) 35 | 36 | cl, err := ethclient.Dial(s.network.Validators[0].JSONRPCAddress) 37 | s.Require().NoError(err, "failed to dial JSON-RPC at %s", s.network.Validators[0].JSONRPCAddress) 38 | s.network.Validators[0].JSONRPCClient = cl 39 | } 40 | 41 | func (s *IntegrationTestSuite) TestChainID() { 42 | chainID, err := s.network.Validators[0].JSONRPCClient.ChainID(s.ctx) 43 | s.Require().NoError(err) 44 | s.Require().NotNil(chainID) 45 | 46 | s.T().Log(chainID.Int64()) 47 | 48 | eip155ChainID, err := ethermint.ParseChainID(s.network.Config.ChainID) 49 | s.Require().NoError(err) 50 | s.Require().Equal(chainID, eip155ChainID) 51 | } 52 | 53 | func TestIntegrationTestSuite(t *testing.T) { 54 | suite.Run(t, new(IntegrationTestSuite)) 55 | } 56 | -------------------------------------------------------------------------------- /tests/rpc/net_test.go: -------------------------------------------------------------------------------- 1 | package rpc 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | func TestNet_Version(t *testing.T) { 11 | rpcRes := Call(t, "net_version", []string{}) 12 | 13 | var res string 14 | err := json.Unmarshal(rpcRes.Result, &res) 15 | require.NoError(t, err) 16 | require.Equal(t, "2", res) 17 | } 18 | 19 | func TestNet_Listening(t *testing.T) { 20 | rpcRes := Call(t, "net_listening", []string{}) 21 | 22 | var res bool 23 | err := json.Unmarshal(rpcRes.Result, &res) 24 | require.NoError(t, err) 25 | require.True(t, res) 26 | } 27 | 28 | func TestNet_PeerCount(t *testing.T) { 29 | rpcRes := Call(t, "net_peerCount", []string{}) 30 | 31 | var res int 32 | err := json.Unmarshal(rpcRes.Result, &res) 33 | require.NoError(t, err) 34 | require.Equal(t, 0, res) 35 | } 36 | -------------------------------------------------------------------------------- /tests/solidity/.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity 2 | -------------------------------------------------------------------------------- /tests/solidity/.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | node_modules/ 3 | 4 | # ignore package-lock files (only use yarn.lock) 5 | package-lock.json 6 | !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 | "yargs": "^17.0.1" 17 | }, 18 | "scripts": { 19 | "test": "node test-helper.js" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/solidity/suites/basic/contracts/Counter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.11; 2 | 3 | contract Counter { 4 | uint256 counter = 0; 5 | string internal constant ERROR_TOO_LOW = "COUNTER_TOO_LOW"; 6 | event Changed(uint256 counter); 7 | event Added(uint256 counter); 8 | 9 | function add() public { 10 | counter++; 11 | emit Added(counter); 12 | emit Changed(counter); 13 | } 14 | 15 | function subtract() public { 16 | require(counter > 0, ERROR_TOO_LOW); 17 | counter--; 18 | emit Changed(counter); 19 | } 20 | 21 | function getCounter() public view returns (uint256) { 22 | return counter; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/solidity/suites/basic/contracts/Storage.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity ^0.5.11; 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 + 1; 19 | number = num; 20 | } 21 | 22 | /** 23 | * @dev Return value 24 | * @return value of 'number' 25 | */ 26 | function retrieve() public view returns (uint256){ 27 | return number; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/solidity/suites/basic/contracts/test/Migrations.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.22 <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/basic/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | const Migrations = artifacts.require("Migrations"); 2 | 3 | module.exports = function (deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /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-ethermint": "yarn truffle test --network ethermint" 9 | }, 10 | "devDependencies": { 11 | "truffle": "^5.1.42", 12 | "truffle-assertions": "^0.9.2", 13 | "web3": "^1.2.11" 14 | } 15 | } -------------------------------------------------------------------------------- /tests/solidity/suites/basic/test/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web3validator/ethermint/10f0164181cbf6ce4c551fd47b4a7231d4eac53c/tests/solidity/suites/basic/test/.gitkeep -------------------------------------------------------------------------------- /tests/solidity/suites/basic/test/estimateGas.js: -------------------------------------------------------------------------------- 1 | const Storage = artifacts.require("Storage") 2 | 3 | contract('Storage', (accounts) => { 4 | 5 | let storage 6 | beforeEach(async () => { 7 | storage = await Storage.new() 8 | }) 9 | 10 | it('estimated gas should match', async () => { 11 | // set new value 12 | let gasUsage = await storage.store.estimateGas(10); 13 | expect(gasUsage.toString()).to.equal('43754'); 14 | 15 | await storage.store(10); 16 | 17 | // set existing value 18 | gasUsage = await storage.store.estimateGas(10); 19 | expect(gasUsage.toString()).to.equal('28754'); 20 | }) 21 | 22 | }) 23 | -------------------------------------------------------------------------------- /tests/solidity/suites/basic/truffle-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | // Development network is just left as truffle's default settings 4 | ethermint: { 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/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 | const Migrations = artifacts.require("Migrations"); 2 | 3 | module.exports = function (deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /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-ethermint": "yarn truffle test --network ethermint" 9 | }, 10 | "devDependencies": { 11 | "truffle": "^5.1.42", 12 | "truffle-assertions": "^0.9.2", 13 | "web3": "^1.2.11" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/solidity/suites/exception/test/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web3validator/ethermint/10f0164181cbf6ce4c551fd47b4a7231d4eac53c/tests/solidity/suites/exception/test/.gitkeep -------------------------------------------------------------------------------- /tests/solidity/suites/exception/test/revert.js: -------------------------------------------------------------------------------- 1 | const TestRevert = artifacts.require("TestRevert") 2 | const truffleAssert = require('truffle-assertions'); 3 | 4 | async function expectRevert(promise) { 5 | try { 6 | await promise; 7 | } catch (error) { 8 | if (error.message.indexOf('revert') === -1) { 9 | expect('revert').to.equal(error.message, 'Wrong kind of exception received'); 10 | } 11 | return; 12 | } 13 | expect.fail('Expected an exception but none was received'); 14 | } 15 | 16 | contract('TestRevert', (accounts) => { 17 | let revert 18 | 19 | beforeEach(async () => { 20 | revert = await TestRevert.new() 21 | }) 22 | it('should revert', async () => { 23 | await revert.try_set(10) 24 | no = await revert.query_a() 25 | assert.equal(no, '0', 'The modification on a should be reverted') 26 | no = await revert.query_b() 27 | assert.equal(no, '10', 'The modification on b should not be reverted') 28 | no = await revert.query_c() 29 | assert.equal(no, '10', 'The modification on c should not be reverted') 30 | 31 | await revert.set(10) 32 | no = await revert.query_a() 33 | assert.equal(no, '10', 'The force set should not be reverted') 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /tests/solidity/suites/exception/truffle-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | // Development network is just left as truffle's default settings 4 | ethermint: { 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.6", 15 | }, 16 | }, 17 | } 18 | -------------------------------------------------------------------------------- /tests/solidity/suites/initializable-buidler/.gitignore: -------------------------------------------------------------------------------- 1 | # Buidler 2 | artifacts 3 | cache 4 | -------------------------------------------------------------------------------- /tests/solidity/suites/initializable-buidler/buidler.config.js: -------------------------------------------------------------------------------- 1 | const { usePlugin } = require('@nomiclabs/buidler/config') 2 | 3 | usePlugin("@nomiclabs/buidler-ganache") 4 | usePlugin('@nomiclabs/buidler-truffle5') 5 | 6 | module.exports = { 7 | networks: { 8 | // Development network is just left as truffle's default settings 9 | ganache: { 10 | url: 'http://localhost:8545', 11 | gasLimit: 5000000, 12 | gasPrice: 1000000000, // 1 gwei (in wei) 13 | defaultBalanceEther: 100 14 | }, 15 | ethermint: { 16 | url: 'http://localhost:8545', 17 | gasLimit: 5000000, // Gas sent with each transaction 18 | gasPrice: 1000000000, // 1 gwei (in wei) 19 | }, 20 | }, 21 | solc: { 22 | version: '0.4.24', 23 | optimizer: { 24 | enabled: true, 25 | runs: 10000, 26 | }, 27 | }, 28 | } 29 | -------------------------------------------------------------------------------- /tests/solidity/suites/initializable-buidler/contracts/Petrifiable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | import "./Initializable.sol"; 4 | 5 | 6 | contract Petrifiable is Initializable { 7 | // Use block UINT256_MAX (which should be never) as the initializable date 8 | uint256 internal constant PETRIFIED_BLOCK = uint256(-1); 9 | 10 | function isPetrified() public view returns (bool) { 11 | return getInitializationBlock() == PETRIFIED_BLOCK; 12 | } 13 | 14 | /** 15 | * @dev Function to be called by top level contract to prevent being initialized. 16 | * Useful for freezing base contracts when they're used behind proxies. 17 | */ 18 | function petrify() internal onlyInit { 19 | initializedAt(PETRIFIED_BLOCK); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/solidity/suites/initializable-buidler/contracts/TimeHelpers.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | import "./Uint256Helpers.sol"; 4 | 5 | 6 | contract TimeHelpers { 7 | using Uint256Helpers for uint256; 8 | 9 | /** 10 | * @dev Returns the current block number. 11 | * Using a function rather than `block.number` allows us to easily mock the block number in 12 | * tests. 13 | */ 14 | function getBlockNumber() internal view returns (uint256) { 15 | return block.number; 16 | } 17 | 18 | /** 19 | * @dev Returns the current block number, converted to uint64. 20 | * Using a function rather than `block.number` allows us to easily mock the block number in 21 | * tests. 22 | */ 23 | function getBlockNumber64() internal view returns (uint64) { 24 | return getBlockNumber().toUint64(); 25 | } 26 | 27 | /** 28 | * @dev Returns the current timestamp. 29 | * Using a function rather than `block.timestamp` allows us to easily mock it in 30 | * tests. 31 | */ 32 | function getTimestamp() internal view returns (uint256) { 33 | return block.timestamp; // solium-disable-line security/no-block-members 34 | } 35 | 36 | /** 37 | * @dev Returns the current timestamp, converted to uint64. 38 | * Using a function rather than `block.timestamp` allows us to easily mock it in 39 | * tests. 40 | */ 41 | function getTimestamp64() internal view returns (uint64) { 42 | return getTimestamp().toUint64(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/solidity/suites/initializable-buidler/contracts/Uint256Helpers.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | 4 | library Uint256Helpers { 5 | uint256 private constant MAX_UINT64 = uint64(-1); 6 | 7 | string private constant ERROR_NUMBER_TOO_BIG = "UINT64_NUMBER_TOO_BIG"; 8 | 9 | function toUint64(uint256 a) internal pure returns (uint64) { 10 | require(a <= MAX_UINT64, ERROR_NUMBER_TOO_BIG); 11 | return uint64(a); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/solidity/suites/initializable-buidler/contracts/UnstructuredStorage.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | 4 | library UnstructuredStorage { 5 | function getStorageBool(bytes32 position) internal view returns (bool data) { 6 | assembly { data := sload(position) } 7 | } 8 | 9 | function getStorageAddress(bytes32 position) internal view returns (address data) { 10 | assembly { data := sload(position) } 11 | } 12 | 13 | function getStorageBytes32(bytes32 position) internal view returns (bytes32 data) { 14 | assembly { data := sload(position) } 15 | } 16 | 17 | function getStorageUint256(bytes32 position) internal view returns (uint256 data) { 18 | assembly { data := sload(position) } 19 | } 20 | 21 | function setStorageBool(bytes32 position, bool data) internal { 22 | assembly { sstore(position, data) } 23 | } 24 | 25 | function setStorageAddress(bytes32 position, address data) internal { 26 | assembly { sstore(position, data) } 27 | } 28 | 29 | function setStorageBytes32(bytes32 position, bytes32 data) internal { 30 | assembly { sstore(position, data) } 31 | } 32 | 33 | function setStorageUint256(bytes32 position, uint256 data) internal { 34 | assembly { sstore(position, data) } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/solidity/suites/initializable-buidler/contracts/test/InitializableMock.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.24; 2 | 3 | import "../Initializable.sol"; 4 | import "../Petrifiable.sol"; 5 | 6 | 7 | contract LifecycleMock is Initializable, Petrifiable { 8 | function initializeMock() public { 9 | initialized(); 10 | } 11 | 12 | function petrifyMock() public { 13 | petrify(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/solidity/suites/initializable-buidler/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "initializable-buidler", 3 | "version": "1.0.0", 4 | "author": "Aragon Association ", 5 | "license": "GPL-3.0-or-later", 6 | "scripts": { 7 | "test-ganache": "yarn buidler test --network ganache", 8 | "test-ethermint": "yarn buidler test --network ethermint" 9 | }, 10 | "devDependencies": { 11 | "@aragon/contract-helpers-test": "^0.1.0", 12 | "@nomiclabs/buidler": "^1.4.3", 13 | "@nomiclabs/buidler-ganache": "^1.3.3", 14 | "@nomiclabs/buidler-truffle5": "^1.3.4", 15 | "@nomiclabs/buidler-web3": "^1.3.4", 16 | "chai": "^4.2.0", 17 | "web3": "^1.2.11" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/solidity/suites/initializable/contracts/Petrifiable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | import "./Initializable.sol"; 4 | 5 | 6 | contract Petrifiable is Initializable { 7 | // Use block UINT256_MAX (which should be never) as the initializable date 8 | uint256 internal constant PETRIFIED_BLOCK = uint256(-1); 9 | 10 | function isPetrified() public view returns (bool) { 11 | return getInitializationBlock() == PETRIFIED_BLOCK; 12 | } 13 | 14 | /** 15 | * @dev Function to be called by top level contract to prevent being initialized. 16 | * Useful for freezing base contracts when they're used behind proxies. 17 | */ 18 | function petrify() internal onlyInit { 19 | initializedAt(PETRIFIED_BLOCK); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/solidity/suites/initializable/contracts/TimeHelpers.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | import "./Uint256Helpers.sol"; 4 | 5 | 6 | contract TimeHelpers { 7 | using Uint256Helpers for uint256; 8 | 9 | /** 10 | * @dev Returns the current block number. 11 | * Using a function rather than `block.number` allows us to easily mock the block number in 12 | * tests. 13 | */ 14 | function getBlockNumber() internal view returns (uint256) { 15 | return block.number; 16 | } 17 | 18 | /** 19 | * @dev Returns the current block number, converted to uint64. 20 | * Using a function rather than `block.number` allows us to easily mock the block number in 21 | * tests. 22 | */ 23 | function getBlockNumber64() internal view returns (uint64) { 24 | return getBlockNumber().toUint64(); 25 | } 26 | 27 | /** 28 | * @dev Returns the current timestamp. 29 | * Using a function rather than `block.timestamp` allows us to easily mock it in 30 | * tests. 31 | */ 32 | function getTimestamp() internal view returns (uint256) { 33 | return block.timestamp; // solium-disable-line security/no-block-members 34 | } 35 | 36 | /** 37 | * @dev Returns the current timestamp, converted to uint64. 38 | * Using a function rather than `block.timestamp` allows us to easily mock it in 39 | * tests. 40 | */ 41 | function getTimestamp64() internal view returns (uint64) { 42 | return getTimestamp().toUint64(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/solidity/suites/initializable/contracts/Uint256Helpers.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | 4 | library Uint256Helpers { 5 | uint256 private constant MAX_UINT64 = uint64(-1); 6 | 7 | string private constant ERROR_NUMBER_TOO_BIG = "UINT64_NUMBER_TOO_BIG"; 8 | 9 | function toUint64(uint256 a) internal pure returns (uint64) { 10 | require(a <= MAX_UINT64, ERROR_NUMBER_TOO_BIG); 11 | return uint64(a); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/solidity/suites/initializable/contracts/UnstructuredStorage.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | 4 | library UnstructuredStorage { 5 | function getStorageBool(bytes32 position) internal view returns (bool data) { 6 | assembly { data := sload(position) } 7 | } 8 | 9 | function getStorageAddress(bytes32 position) internal view returns (address data) { 10 | assembly { data := sload(position) } 11 | } 12 | 13 | function getStorageBytes32(bytes32 position) internal view returns (bytes32 data) { 14 | assembly { data := sload(position) } 15 | } 16 | 17 | function getStorageUint256(bytes32 position) internal view returns (uint256 data) { 18 | assembly { data := sload(position) } 19 | } 20 | 21 | function setStorageBool(bytes32 position, bool data) internal { 22 | assembly { sstore(position, data) } 23 | } 24 | 25 | function setStorageAddress(bytes32 position, address data) internal { 26 | assembly { sstore(position, data) } 27 | } 28 | 29 | function setStorageBytes32(bytes32 position, bytes32 data) internal { 30 | assembly { sstore(position, data) } 31 | } 32 | 33 | function setStorageUint256(bytes32 position, uint256 data) internal { 34 | assembly { sstore(position, data) } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/solidity/suites/initializable/contracts/test/InitializableMock.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.24; 2 | 3 | import "../Initializable.sol"; 4 | import "../Petrifiable.sol"; 5 | 6 | 7 | contract LifecycleMock is Initializable, Petrifiable { 8 | function initializeMock() public { 9 | initialized(); 10 | } 11 | 12 | function petrifyMock() public { 13 | petrify(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/solidity/suites/initializable/contracts/test/Migrations.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.22 <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/initializable/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | const Migrations = artifacts.require("Migrations"); 2 | 3 | module.exports = function (deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /tests/solidity/suites/initializable/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "initializable", 3 | "version": "1.0.0", 4 | "author": "Aragon Association ", 5 | "license": "GPL-3.0-or-later", 6 | "scripts": { 7 | "contract-compile": "yarn truffle compile", 8 | "contract-migrate": "yarn truffle migrate --network ethermint", 9 | "test-ganache": "yarn truffle test", 10 | "test-ethermint": "yarn truffle test --network ethermint" 11 | }, 12 | "devDependencies": { 13 | "@aragon/contract-helpers-test": "^0.1.0", 14 | "chai": "^4.2.0", 15 | "truffle": "^5.2.5", 16 | "web3": "^1.3.4", 17 | "sleep": "^6.3.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/solidity/suites/initializable/test/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web3validator/ethermint/10f0164181cbf6ce4c551fd47b4a7231d4eac53c/tests/solidity/suites/initializable/test/.gitkeep -------------------------------------------------------------------------------- /tests/solidity/suites/initializable/truffle-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | // Development network is just left as truffle's default settings 4 | ethermint: { 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.4.24", 15 | settings: { 16 | optimizer: { 17 | enabled: true, 18 | runs: 10000, 19 | }, 20 | }, 21 | }, 22 | }, 23 | } 24 | -------------------------------------------------------------------------------- /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 | const Migrations = artifacts.require("Migrations"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /tests/solidity/suites/opcode/migrations/2_opCodes_migration.js: -------------------------------------------------------------------------------- 1 | var OpCodes = artifacts.require("./OpCodes.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(OpCodes); 5 | }; 6 | -------------------------------------------------------------------------------- /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-ethermint": "yarn truffle test --network ethermint" 9 | }, 10 | "devDependencies": { 11 | "truffle": "^5.1.42", 12 | "truffle-assertions": "^0.9.2", 13 | "web3": "^1.2.11" 14 | } 15 | } -------------------------------------------------------------------------------- /tests/solidity/suites/opcode/test/opCodes.js: -------------------------------------------------------------------------------- 1 | const TodoList = artifacts.require('./OpCodes.sol') 2 | const assert = require('assert') 3 | let contractInstance 4 | const Web3 = require('web3'); 5 | const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); 6 | // const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:9545')); 7 | 8 | contract('OpCodes', (accounts) => { 9 | beforeEach(async () => { 10 | contractInstance = await TodoList.deployed() 11 | }) 12 | // it('Should run without errors the majorit of opcodes', async () => { 13 | // await contractInstance.test() 14 | // await contractInstance.test_stop() 15 | 16 | // }) 17 | 18 | it('Should throw invalid op code', async () => { 19 | try{ 20 | await contractInstance.test_invalid() 21 | } 22 | catch(error) { 23 | console.error(error); 24 | } 25 | }) 26 | 27 | it('Should revert', async () => { 28 | try{ 29 | await contractInstance.test_revert() } 30 | catch(error) { 31 | console.error(error); 32 | } 33 | }) 34 | }) 35 | -------------------------------------------------------------------------------- /tests/solidity/suites/opcode/truffle-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | // Development network is just left as truffle's default settings 4 | ethermint: { 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/proxy/contracts/DelegateProxy.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.24; 2 | 3 | import "./IsContract.sol"; 4 | import "./ERCProxy.sol"; 5 | 6 | 7 | contract DelegateProxy is ERCProxy, IsContract { 8 | uint256 internal constant FWD_GAS_LIMIT = 10000; 9 | 10 | /** 11 | * @dev Performs a delegatecall and returns whatever the delegatecall returned (entire context execution will return!) 12 | * @param _dst Destination address to perform the delegatecall 13 | * @param _calldata Calldata for the delegatecall 14 | */ 15 | function delegatedFwd(address _dst, bytes _calldata) internal { 16 | require(isContract(_dst)); 17 | uint256 fwdGasLimit = FWD_GAS_LIMIT; 18 | 19 | assembly { 20 | let result := delegatecall(sub(gas, fwdGasLimit), _dst, add(_calldata, 0x20), mload(_calldata), 0, 0) 21 | let size := returndatasize 22 | let ptr := mload(0x40) 23 | returndatacopy(ptr, 0, size) 24 | 25 | // revert instead of invalid() bc if the underlying call failed with invalid() it already wasted gas. 26 | // if the call returned error data, forward it 27 | switch result case 0 { revert(ptr, size) } 28 | default { return(ptr, size) } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/solidity/suites/proxy/contracts/DepositableStorage.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.24; 2 | 3 | import "./UnstructuredStorage.sol"; 4 | 5 | 6 | contract DepositableStorage { 7 | using UnstructuredStorage for bytes32; 8 | 9 | // keccak256("aragonOS.depositableStorage.depositable") 10 | bytes32 internal constant DEPOSITABLE_POSITION = 0x665fd576fbbe6f247aff98f5c94a561e3f71ec2d3c988d56f12d342396c50cea; 11 | 12 | function isDepositable() public view returns (bool) { 13 | return DEPOSITABLE_POSITION.getStorageBool(); 14 | } 15 | 16 | function setDepositable(bool _depositable) internal { 17 | DEPOSITABLE_POSITION.setStorageBool(_depositable); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/solidity/suites/proxy/contracts/ERCProxy.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | 4 | contract ERCProxy { 5 | uint256 internal constant FORWARDING = 1; 6 | uint256 internal constant UPGRADEABLE = 2; 7 | 8 | function proxyType() public pure returns (uint256 proxyTypeId); 9 | function implementation() public view returns (address codeAddr); 10 | } 11 | -------------------------------------------------------------------------------- /tests/solidity/suites/proxy/contracts/IsContract.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | 4 | contract IsContract { 5 | /* 6 | * NOTE: this should NEVER be used for authentication 7 | * (see pitfalls: https://github.com/fergarrui/ethereum-security/tree/master/contracts/extcodesize). 8 | * 9 | * This is only intended to be used as a sanity check that an address is actually a contract, 10 | * RATHER THAN an address not being a contract. 11 | */ 12 | function isContract(address _target) internal view returns (bool) { 13 | if (_target == address(0)) { 14 | return false; 15 | } 16 | 17 | uint256 size; 18 | assembly { size := extcodesize(_target) } 19 | return size > 0; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/solidity/suites/proxy/contracts/UnstructuredStorage.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | 4 | library UnstructuredStorage { 5 | function getStorageBool(bytes32 position) internal view returns (bool data) { 6 | assembly { data := sload(position) } 7 | } 8 | 9 | function getStorageAddress(bytes32 position) internal view returns (address data) { 10 | assembly { data := sload(position) } 11 | } 12 | 13 | function getStorageBytes32(bytes32 position) internal view returns (bytes32 data) { 14 | assembly { data := sload(position) } 15 | } 16 | 17 | function getStorageUint256(bytes32 position) internal view returns (uint256 data) { 18 | assembly { data := sload(position) } 19 | } 20 | 21 | function setStorageBool(bytes32 position, bool data) internal { 22 | assembly { sstore(position, data) } 23 | } 24 | 25 | function setStorageAddress(bytes32 position, address data) internal { 26 | assembly { sstore(position, data) } 27 | } 28 | 29 | function setStorageBytes32(bytes32 position, bytes32 data) internal { 30 | assembly { sstore(position, data) } 31 | } 32 | 33 | function setStorageUint256(bytes32 position, uint256 data) internal { 34 | assembly { sstore(position, data) } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/solidity/suites/proxy/contracts/test/DepositableDelegateProxyMock.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.24; 2 | 3 | import "../DepositableDelegateProxy.sol"; 4 | 5 | 6 | contract DepositableDelegateProxyMock is DepositableDelegateProxy { 7 | address private implementationMock; 8 | 9 | function enableDepositsOnMock() external { 10 | setDepositable(true); 11 | } 12 | 13 | function setImplementationOnMock(address _implementationMock) external { 14 | implementationMock = _implementationMock; 15 | } 16 | 17 | function implementation() public view returns (address) { 18 | return implementationMock; 19 | } 20 | 21 | function proxyType() public pure returns (uint256 proxyTypeId) { 22 | return UPGRADEABLE; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/solidity/suites/proxy/contracts/test/EthSender.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.24; 2 | 3 | 4 | contract EthSender { 5 | function sendEth(address to) external payable { 6 | to.transfer(msg.value); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/solidity/suites/proxy/contracts/test/Migrations.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.22 <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/proxy/contracts/test/ProxyTarget.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.24; 2 | 3 | contract ProxyTargetWithoutFallback { 4 | event Pong(); 5 | 6 | function ping() external { 7 | emit Pong(); 8 | } 9 | } 10 | 11 | contract ProxyTargetWithFallback is ProxyTargetWithoutFallback { 12 | event ReceivedEth(); 13 | 14 | function () external payable { 15 | emit ReceivedEth(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/solidity/suites/proxy/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | const Migrations = artifacts.require("Migrations"); 2 | 3 | module.exports = function (deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /tests/solidity/suites/proxy/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "proxy", 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-ethermint": "yarn truffle test --network ethermint" 9 | }, 10 | "devDependencies": { 11 | "@aragon/contract-helpers-test": "^0.1.0", 12 | "chai": "^4.2.0", 13 | "truffle": "^5.1.42", 14 | "web3": "^1.2.11" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/solidity/suites/proxy/test/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web3validator/ethermint/10f0164181cbf6ce4c551fd47b4a7231d4eac53c/tests/solidity/suites/proxy/test/.gitkeep -------------------------------------------------------------------------------- /tests/solidity/suites/proxy/truffle-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | // Development network is just left as truffle's default settings 4 | ethermint: { 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.4.24", 15 | settings: { 16 | optimizer: { 17 | enabled: true, 18 | runs: 10000, 19 | }, 20 | }, 21 | }, 22 | }, 23 | } 24 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/.github/workflows/ci_contracts.yml: -------------------------------------------------------------------------------- 1 | name: contracts 2 | 3 | on: 4 | push: 5 | branches: master 6 | pull_request: 7 | branches: '*' 8 | 9 | jobs: 10 | CI: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: Install node 15 | uses: actions/setup-node@v1 16 | with: 17 | node-version: 12 18 | - name: Install 19 | run: yarn 20 | - name: Lint 21 | run: yarn lint 22 | - name: Test 23 | run: yarn test 24 | - name: coverage 25 | continue-on-error: true 26 | run: yarn coverage 27 | env: 28 | CI: true 29 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/contracts/StakingFactory.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.17; 2 | 3 | import "./lib/os/ERC20.sol"; 4 | 5 | import "./Staking.sol"; 6 | import "./proxies/StakingProxy.sol"; 7 | 8 | 9 | contract StakingFactory { 10 | Staking public baseImplementation; 11 | mapping (address => address) internal instances; 12 | 13 | event NewStaking(address indexed instance, address token); 14 | 15 | constructor() public { 16 | baseImplementation = new Staking(); 17 | } 18 | 19 | function existsInstance(ERC20 token) external view returns (bool) { 20 | return _getInstance(token) != address(0); 21 | } 22 | 23 | function getInstance(ERC20 token) external view returns (Staking) { 24 | return Staking(_getInstance(token)); 25 | } 26 | 27 | function getOrCreateInstance(ERC20 token) external returns (Staking) { 28 | address instance = _getInstance(token); 29 | return instance != address(0) ? Staking(instance) : _createInstance(token); 30 | } 31 | 32 | function _getInstance(ERC20 token) internal view returns (address) { 33 | return instances[address(token)]; 34 | } 35 | 36 | function _createInstance(ERC20 token) internal returns (Staking) { 37 | StakingProxy instance = new StakingProxy(baseImplementation, token); 38 | address tokenAddress = address(token); 39 | address instanceAddress = address(instance); 40 | instances[tokenAddress] = instanceAddress; 41 | emit NewStaking(instanceAddress, tokenAddress); 42 | return Staking(instanceAddress); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/contracts/lib/os/Autopetrified.sol: -------------------------------------------------------------------------------- 1 | // Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/common/Autopetrified.sol 2 | // Adapted to use pragma ^0.5.17 and satisfy our linter rules 3 | 4 | pragma solidity ^0.5.17; 5 | 6 | import "./Petrifiable.sol"; 7 | 8 | 9 | contract Autopetrified is Petrifiable { 10 | constructor() public { 11 | // Immediately petrify base (non-proxy) instances of inherited contracts on deploy. 12 | // This renders them uninitializable (and unusable without a proxy). 13 | petrify(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/contracts/lib/os/DelegateProxy.sol: -------------------------------------------------------------------------------- 1 | // Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/common/Autopetrified.sol 2 | // Adapted to use pragma ^0.5.17 and satisfy our linter rules 3 | 4 | pragma solidity 0.5.17; 5 | 6 | import "./ERCProxy.sol"; 7 | import "./IsContract.sol"; 8 | 9 | 10 | contract DelegateProxy is ERCProxy, IsContract { 11 | uint256 internal constant FWD_GAS_LIMIT = 10000; 12 | 13 | /** 14 | * @dev Performs a delegatecall and returns whatever the delegatecall returned (entire context execution will return!) 15 | * @param _dst Destination address to perform the delegatecall 16 | * @param _calldata Calldata for the delegatecall 17 | */ 18 | function delegatedFwd(address _dst, bytes memory _calldata) internal { 19 | require(isContract(_dst)); 20 | uint256 fwdGasLimit = FWD_GAS_LIMIT; 21 | 22 | assembly { 23 | let result := delegatecall(sub(gas, fwdGasLimit), _dst, add(_calldata, 0x20), mload(_calldata), 0, 0) 24 | let size := returndatasize 25 | let ptr := mload(0x40) 26 | returndatacopy(ptr, 0, size) 27 | 28 | // revert instead of invalid() bc if the underlying call failed with invalid() it already wasted gas. 29 | // if the call returned error data, forward it 30 | switch result case 0 { revert(ptr, size) } 31 | default { return(ptr, size) } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/contracts/lib/os/ERC20.sol: -------------------------------------------------------------------------------- 1 | // Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/lib/token/ERC20.sol 2 | // Adapted to use pragma ^0.5.8 and satisfy our linter rules 3 | 4 | pragma solidity ^0.5.8; 5 | 6 | 7 | /** 8 | * @title ERC20 interface 9 | * @dev see https://github.com/ethereum/EIPs/issues/20 10 | */ 11 | contract ERC20 { 12 | function totalSupply() public view returns (uint256); 13 | 14 | function balanceOf(address _who) public view returns (uint256); 15 | 16 | function allowance(address _owner, address _spender) public view returns (uint256); 17 | 18 | function transfer(address _to, uint256 _value) public returns (bool); 19 | 20 | function approve(address _spender, uint256 _value) public returns (bool); 21 | 22 | function transferFrom(address _from, address _to, uint256 _value) public returns (bool); 23 | 24 | event Transfer( 25 | address indexed from, 26 | address indexed to, 27 | uint256 value 28 | ); 29 | 30 | event Approval( 31 | address indexed owner, 32 | address indexed spender, 33 | uint256 value 34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/contracts/lib/os/ERCProxy.sol: -------------------------------------------------------------------------------- 1 | // Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/lib/misc/ERCProxy.sol 2 | // Adapted to use pragma ^0.5.17 and satisfy our linter rules 3 | 4 | pragma solidity ^0.5.17; 5 | 6 | 7 | contract ERCProxy { 8 | uint256 internal constant FORWARDING = 1; 9 | uint256 internal constant UPGRADEABLE = 2; 10 | 11 | function proxyType() public pure returns (uint256 proxyTypeId); 12 | function implementation() public view returns (address codeAddr); 13 | } 14 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/contracts/lib/os/IsContract.sol: -------------------------------------------------------------------------------- 1 | // Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/common/IsContract.sol 2 | // Adapted to use pragma ^0.5.8 and satisfy our linter rules 3 | 4 | pragma solidity ^0.5.8; 5 | 6 | 7 | contract IsContract { 8 | /* 9 | * NOTE: this should NEVER be used for authentication 10 | * (see pitfalls: https://github.com/fergarrui/ethereum-security/tree/master/contracts/extcodesize). 11 | * 12 | * This is only intended to be used as a sanity check that an address is actually a contract, 13 | * RATHER THAN an address not being a contract. 14 | */ 15 | function isContract(address _target) internal view returns (bool) { 16 | if (_target == address(0)) { 17 | return false; 18 | } 19 | 20 | uint256 size; 21 | assembly { size := extcodesize(_target) } 22 | return size > 0; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/contracts/lib/os/Migrations.sol: -------------------------------------------------------------------------------- 1 | // Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/lib/misc/Migrations.sol 2 | // Adapted to use pragma ^0.5.8 and satisfy our linter rules 3 | 4 | pragma solidity ^0.5.8; 5 | 6 | 7 | contract Migrations { 8 | address public owner; 9 | uint256 public lastCompletedMigration; 10 | 11 | modifier restricted() { 12 | if (msg.sender == owner) { 13 | _; 14 | } 15 | } 16 | 17 | constructor() public { 18 | owner = msg.sender; 19 | } 20 | 21 | function setCompleted(uint256 completed) public restricted { 22 | lastCompletedMigration = completed; 23 | } 24 | 25 | function upgrade(address newAddress) public restricted { 26 | Migrations upgraded = Migrations(newAddress); 27 | upgraded.setCompleted(lastCompletedMigration); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/contracts/lib/os/Petrifiable.sol: -------------------------------------------------------------------------------- 1 | // Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/common/Petrifiable.sol 2 | // Adapted to use pragma ^0.5.17 and satisfy our linter rules 3 | 4 | pragma solidity ^0.5.17; 5 | 6 | import "./Initializable.sol"; 7 | 8 | 9 | contract Petrifiable is Initializable { 10 | // Use block UINT256_MAX (which should be never) as the initializable date 11 | uint256 internal constant PETRIFIED_BLOCK = uint256(-1); 12 | 13 | function isPetrified() public view returns (bool) { 14 | return getInitializationBlock() == PETRIFIED_BLOCK; 15 | } 16 | 17 | /** 18 | * @dev Function to be called by top level contract to prevent being initialized. 19 | * Useful for freezing base contracts when they're used behind proxies. 20 | */ 21 | function petrify() internal onlyInit { 22 | initializedAt(PETRIFIED_BLOCK); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/contracts/lib/os/TimeHelpers.sol: -------------------------------------------------------------------------------- 1 | // Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/common/TimeHelpers.sol 2 | // Adapted to use pragma ^0.5.8 and satisfy our linter rules 3 | 4 | pragma solidity ^0.5.8; 5 | 6 | import "./Uint256Helpers.sol"; 7 | 8 | 9 | contract TimeHelpers { 10 | using Uint256Helpers for uint256; 11 | 12 | /** 13 | * @dev Returns the current block number. 14 | * Using a function rather than `block.number` allows us to easily mock the block number in 15 | * tests. 16 | */ 17 | function getBlockNumber() internal view returns (uint256) { 18 | return block.number; 19 | } 20 | 21 | /** 22 | * @dev Returns the current block number, converted to uint64. 23 | * Using a function rather than `block.number` allows us to easily mock the block number in 24 | * tests. 25 | */ 26 | function getBlockNumber64() internal view returns (uint64) { 27 | return getBlockNumber().toUint64(); 28 | } 29 | 30 | /** 31 | * @dev Returns the current timestamp. 32 | * Using a function rather than `block.timestamp` allows us to easily mock it in 33 | * tests. 34 | */ 35 | function getTimestamp() internal view returns (uint256) { 36 | return block.timestamp; // solium-disable-line security/no-block-members 37 | } 38 | 39 | /** 40 | * @dev Returns the current timestamp, converted to uint64. 41 | * Using a function rather than `block.timestamp` allows us to easily mock it in 42 | * tests. 43 | */ 44 | function getTimestamp64() internal view returns (uint64) { 45 | return getTimestamp().toUint64(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/contracts/lib/os/Uint256Helpers.sol: -------------------------------------------------------------------------------- 1 | // Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/common/Uint256Helpers.sol 2 | // Adapted to use pragma ^0.5.8 and satisfy our linter rules 3 | 4 | pragma solidity ^0.5.8; 5 | 6 | 7 | library Uint256Helpers { 8 | uint256 private constant MAX_UINT8 = uint8(-1); 9 | uint256 private constant MAX_UINT64 = uint64(-1); 10 | 11 | string private constant ERROR_UINT8_NUMBER_TOO_BIG = "UINT8_NUMBER_TOO_BIG"; 12 | string private constant ERROR_UINT64_NUMBER_TOO_BIG = "UINT64_NUMBER_TOO_BIG"; 13 | 14 | function toUint8(uint256 a) internal pure returns (uint8) { 15 | require(a <= MAX_UINT8, ERROR_UINT8_NUMBER_TOO_BIG); 16 | return uint8(a); 17 | } 18 | 19 | function toUint64(uint256 a) internal pure returns (uint64) { 20 | require(a <= MAX_UINT64, ERROR_UINT64_NUMBER_TOO_BIG); 21 | return uint64(a); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/contracts/lib/os/UnstructuredStorage.sol: -------------------------------------------------------------------------------- 1 | // Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/common/UnstructuredStorage.sol 2 | // Adapted to use pragma ^0.5.17 and satisfy our linter rules 3 | 4 | pragma solidity ^0.5.17; 5 | 6 | 7 | library UnstructuredStorage { 8 | function getStorageBool(bytes32 position) internal view returns (bool data) { 9 | assembly { data := sload(position) } 10 | } 11 | 12 | function getStorageAddress(bytes32 position) internal view returns (address data) { 13 | assembly { data := sload(position) } 14 | } 15 | 16 | function getStorageBytes32(bytes32 position) internal view returns (bytes32 data) { 17 | assembly { data := sload(position) } 18 | } 19 | 20 | function getStorageUint256(bytes32 position) internal view returns (uint256 data) { 21 | assembly { data := sload(position) } 22 | } 23 | 24 | function setStorageBool(bytes32 position, bool data) internal { 25 | assembly { sstore(position, data) } 26 | } 27 | 28 | function setStorageAddress(bytes32 position, address data) internal { 29 | assembly { sstore(position, data) } 30 | } 31 | 32 | function setStorageBytes32(bytes32 position, bytes32 data) internal { 33 | assembly { sstore(position, data) } 34 | } 35 | 36 | function setStorageUint256(bytes32 position, uint256 data) internal { 37 | assembly { sstore(position, data) } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/contracts/locking/ILockManager.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.17; 2 | 3 | 4 | interface ILockManager { 5 | /** 6 | * @notice Check if `_user`'s by `_lockManager` can be unlocked 7 | * @param _user Owner of lock 8 | * @param _amount Amount of locked tokens to unlock 9 | * @return Whether given lock of given owner can be unlocked by given sender 10 | */ 11 | function canUnlock(address _user, uint256 _amount) external view returns (bool); 12 | } 13 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/contracts/proxies/StakingProxy.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.17; 2 | 3 | import "../lib/os/ERC20.sol"; 4 | 5 | import "../Staking.sol"; 6 | import "./ThinProxy.sol"; 7 | 8 | 9 | contract StakingProxy is ThinProxy { 10 | // keccak256("aragon.network.staking") 11 | bytes32 internal constant IMPLEMENTATION_SLOT = 0xbd536e2e005accda865e2f0d1827f83ec8824f3ea04ecd6131b7c10058635814; 12 | 13 | constructor(Staking _implementation, ERC20 _token) ThinProxy(address(_implementation)) public { 14 | bytes4 selector = _implementation.initialize.selector; 15 | bytes memory initializeData = abi.encodeWithSelector(selector, _token); 16 | (bool success,) = address(_implementation).delegatecall(initializeData); 17 | 18 | if (!success) { 19 | assembly { 20 | let output := mload(0x40) 21 | mstore(0x40, add(output, returndatasize)) 22 | returndatacopy(output, 0, returndatasize) 23 | revert(output, returndatasize) 24 | } 25 | } 26 | } 27 | 28 | function _implementationSlot() internal pure returns (bytes32) { 29 | return IMPLEMENTATION_SLOT; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/contracts/proxies/ThinProxy.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.17; 2 | 3 | import "../lib/os/DelegateProxy.sol"; 4 | import "../lib/os/UnstructuredStorage.sol"; 5 | 6 | 7 | contract ThinProxy is DelegateProxy { 8 | using UnstructuredStorage for bytes32; 9 | 10 | constructor(address _implementation) public { 11 | _implementationSlot().setStorageAddress(_implementation); 12 | } 13 | 14 | function () external { 15 | delegatedFwd(implementation(), msg.data); 16 | } 17 | 18 | function proxyType() public pure returns (uint256) { 19 | return FORWARDING; 20 | } 21 | 22 | function implementation() public view returns (address) { 23 | return _implementationSlot().getStorageAddress(); 24 | } 25 | 26 | function _implementationSlot() internal pure returns (bytes32); 27 | } 28 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/contracts/test/TestImports.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import "./lib/MiniMeToken.sol"; 4 | import "../lib/os/Migrations.sol"; 5 | 6 | // You might think this file is a bit odd, but let me explain. 7 | // We only use some contracts in our tests, which means Truffle 8 | // will not compile it for us, because it is from an external 9 | // dependency. 10 | // 11 | // We are now left with three options: 12 | // - Copy/paste these contracts 13 | // - Run the tests with `truffle compile --all` on 14 | // - Or trick Truffle by claiming we use it in a Solidity test 15 | // 16 | // You know which one I went for. 17 | 18 | 19 | contract TestImports { 20 | constructor() public { 21 | // solium-disable-previous-line no-empty-blocks 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/contracts/test/lib/ITokenController.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.17; 2 | 3 | /// @dev The token controller contract must implement these functions 4 | 5 | 6 | interface ITokenController { 7 | /// @notice Called when `_owner` sends ether to the MiniMe Token contract 8 | /// @param _owner The address that sent the ether to create tokens 9 | /// @return True if the ether is accepted, false if it throws 10 | function proxyPayment(address _owner) external payable returns(bool); 11 | 12 | /// @notice Notifies the controller about a token transfer allowing the 13 | /// controller to react if desired 14 | /// @param _from The origin of the transfer 15 | /// @param _to The destination of the transfer 16 | /// @param _amount The amount of the transfer 17 | /// @return False if the controller does not authorize the transfer 18 | function onTransfer(address _from, address _to, uint _amount) external returns(bool); 19 | 20 | /// @notice Notifies the controller about an approval allowing the 21 | /// controller to react if desired 22 | /// @param _owner The address that calls `approve()` 23 | /// @param _spender The spender in the `approve()` call 24 | /// @param _amount The amount in the `approve()` call 25 | /// @return False if the controller does not authorize the approval 26 | function onApprove(address _owner, address _spender, uint _amount) external returns(bool); 27 | } 28 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/contracts/test/mocks/CheckpointingMock.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import "../../lib/Checkpointing.sol"; 4 | 5 | 6 | contract CheckpointingMock { 7 | using Checkpointing for Checkpointing.History; 8 | 9 | Checkpointing.History history; 10 | 11 | function add(uint64 value, uint256 time) public { 12 | history.add(value, time); 13 | } 14 | 15 | function getLast() public view returns (uint256) { 16 | return history.getLast(); 17 | } 18 | 19 | function get(uint64 time) public view returns (uint256) { 20 | return history.get(time); 21 | } 22 | 23 | function getHistorySize() public view returns (uint256) { 24 | return history.history.length; 25 | } 26 | 27 | function lastUpdate() public view returns (uint256) { 28 | return history.lastUpdate(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/contracts/test/mocks/ERC20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.17; 2 | 3 | 4 | /** 5 | * @title ERC20 interface 6 | * @dev see https://github.com/ethereum/EIPs/issues/20 7 | */ 8 | contract ERC20 { 9 | function totalSupply() public view returns (uint256); 10 | 11 | function balanceOf(address _who) public view returns (uint256); 12 | 13 | function allowance(address _owner, address _spender) 14 | public view returns (uint256); 15 | 16 | function transfer(address _to, uint256 _value) public returns (bool); 17 | 18 | function approve(address _spender, uint256 _value) 19 | public returns (bool); 20 | 21 | function transferFrom(address _from, address _to, uint256 _value) 22 | public returns (bool); 23 | 24 | event Transfer(address indexed from, address indexed to, uint256 value); 25 | event Approval(address indexed owner, address indexed spender, uint256 value); 26 | } 27 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/contracts/test/mocks/LockManagerMock.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import "../../locking/ILockManager.sol"; 4 | import "../../Staking.sol"; 5 | 6 | 7 | contract LockManagerMock is ILockManager { 8 | bool result; 9 | 10 | function slash(Staking _staking, address _from, address _to, uint256 _amount) external { 11 | _staking.slash(_from, _to, _amount); 12 | } 13 | 14 | function slashAndUnstake(Staking _staking, address _from, address _to, uint256 _amount) external { 15 | _staking.slashAndUnstake(_from, _to, _amount); 16 | } 17 | 18 | function unlock(Staking _staking, address _account, uint256 _amount) external { 19 | _staking.unlock(_account, address(this), _amount); 20 | } 21 | 22 | function unlockAndRemoveManager(Staking _staking, address _account) external { 23 | _staking.unlockAndRemoveManager(_account, address(this)); 24 | } 25 | 26 | function setLockManager(Staking _staking, address _account, ILockManager _newManager) external { 27 | _staking.setLockManager(_account, address(_newManager)); 28 | } 29 | 30 | function canUnlock(address, uint256) external view returns (bool) { 31 | return result; 32 | } 33 | 34 | function setResult(bool _result) public { 35 | result = _result; 36 | } 37 | 38 | function unlockAndRemoveManager(Staking _staking, address _account, address _manager) public { 39 | _staking.unlockAndRemoveManager(_account, _manager); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/contracts/test/mocks/TimeLockManagerMock.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import "../../locking/TimeLockManager.sol"; 4 | import "../../Staking.sol"; 5 | 6 | 7 | contract TimeLockManagerMock is TimeLockManager { 8 | uint64 public constant MAX_UINT64 = uint64(-1); 9 | 10 | uint256 _mockTime = now; 11 | uint256 _mockBlockNumber = block.number; 12 | 13 | function getTimestampExt() external view returns (uint256) { 14 | return getTimestamp(); 15 | } 16 | 17 | function getBlockNumberExt() external view returns (uint256) { 18 | return getBlockNumber(); 19 | } 20 | 21 | function setTimestamp(uint256 i) public { 22 | _mockTime = i; 23 | } 24 | 25 | function setBlockNumber(uint256 i) public { 26 | _mockBlockNumber = i; 27 | } 28 | 29 | function getTimestamp() internal view returns (uint256) { 30 | return _mockTime; 31 | } 32 | 33 | function getBlockNumber() internal view returns (uint256) { 34 | return _mockBlockNumber; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "staking", 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-ethermint": "yarn truffle test --network ethermint" 9 | }, 10 | "devDependencies": { 11 | "@aragon/contract-helpers-test": "^0.0.3", 12 | "chai": "^4.2.0", 13 | "ganache-cli": "^6.1.0", 14 | "truffle": "^5.1.42", 15 | "web3-eth-abi": "^1.2.11", 16 | "web3-utils": "^1.2.11" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/test/helpers/constants.js: -------------------------------------------------------------------------------- 1 | const { bn, bigExp } = require('@aragon/contract-helpers-test/numbers') 2 | const DEFAULT_STAKE_AMOUNT = bigExp(120, 18) 3 | 4 | module.exports = { 5 | DEFAULT_STAKE_AMOUNT, 6 | DEFAULT_LOCK_AMOUNT: DEFAULT_STAKE_AMOUNT.div(bn(3)), 7 | EMPTY_DATA: '0x', 8 | ZERO_ADDRESS: '0x' + '0'.repeat(40), 9 | ACTIVATED_LOCK: '0x01' 10 | } 11 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/test/helpers/deploy.js: -------------------------------------------------------------------------------- 1 | const { bn } = require('@aragon/contract-helpers-test/numbers') 2 | 3 | const { DEFAULT_STAKE_AMOUNT } = require('./constants') 4 | 5 | module.exports = (artifacts) => { 6 | const StakingFactory = artifacts.require('StakingFactory') 7 | const Staking = artifacts.require('Staking') 8 | const StandardTokenMock = artifacts.require('StandardTokenMock') 9 | const LockManagerMock = artifacts.require('LockManagerMock') 10 | 11 | const getEvent = (receipt, event, arg) => { return receipt.logs.filter(l => l.event === event)[0].args[arg] } 12 | 13 | const deploy = async (owner, initialAmount = DEFAULT_STAKE_AMOUNT.mul(bn(1000))) => { 14 | const token = await StandardTokenMock.new(owner, initialAmount) 15 | 16 | const staking = await deployStaking(token) 17 | 18 | const lockManager = await LockManagerMock.new() 19 | 20 | return { token, staking, lockManager } 21 | } 22 | 23 | const deployStaking = async (token) => { 24 | const factory = await StakingFactory.new() 25 | const receipt = await factory.getOrCreateInstance(token.address) 26 | const stakingAddress = getEvent(receipt, 'NewStaking', 'instance') 27 | const staking = await Staking.at(stakingAddress) 28 | 29 | return staking 30 | } 31 | 32 | return { 33 | deploy 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/test/helpers/errors.js: -------------------------------------------------------------------------------- 1 | const CHECKPOINT_ERRORS = { 2 | ERROR_VALUE_TOO_BIG: 'CHECKPOINT_VALUE_TOO_BIG', 3 | ERROR_CANNOT_ADD_PAST_VALUE: 'CHECKPOINT_CANNOT_ADD_PAST_VALUE', 4 | } 5 | 6 | const STAKING_ERRORS = { 7 | ERROR_TOKEN_NOT_CONTRACT: 'STAKING_TOKEN_NOT_CONTRACT', 8 | ERROR_AMOUNT_ZERO: 'STAKING_AMOUNT_ZERO', 9 | ERROR_TOKEN_TRANSFER: 'STAKING_TOKEN_TRANSFER_FAIL', 10 | ERROR_TOKEN_DEPOSIT: 'STAKING_TOKEN_DEPOSIT_FAIL', 11 | ERROR_TOKEN_NOT_SENDER: 'STAKING_TOKEN_NOT_SENDER', 12 | ERROR_WRONG_TOKEN: 'STAKING_WRONG_TOKEN', 13 | ERROR_NOT_ENOUGH_BALANCE: 'STAKING_NOT_ENOUGH_BALANCE', 14 | ERROR_NOT_ENOUGH_ALLOWANCE: 'STAKING_NOT_ENOUGH_ALLOWANCE', 15 | ERROR_SENDER_NOT_ALLOWED: 'STAKING_SENDER_NOT_ALLOWED', 16 | ERROR_ALLOWANCE_ZERO: 'STAKING_ALLOWANCE_ZERO', 17 | ERROR_LOCK_ALREADY_EXISTS: 'STAKING_LOCK_ALREADY_EXISTS', 18 | ERROR_LOCK_DOES_NOT_EXIST: 'STAKING_LOCK_DOES_NOT_EXIST', 19 | ERROR_NOT_ENOUGH_LOCK: 'STAKING_NOT_ENOUGH_LOCK', 20 | ERROR_CANNOT_UNLOCK: 'STAKING_CANNOT_UNLOCK', 21 | ERROR_CANNOT_CHANGE_ALLOWANCE: 'STAKING_CANNOT_CHANGE_ALLOWANCE', 22 | ERROR_LOCKMANAGER_CALL_FAIL: 'STAKING_LOCKMANAGER_CALL_FAIL', 23 | ERROR_BLOCKNUMBER_TOO_BIG: 'STAKING_BLOCKNUMBER_TOO_BIG', 24 | } 25 | 26 | const TIME_LOCK_MANAGER_ERRORS = { 27 | ERROR_ALREADY_LOCKED: 'TLM_ALREADY_LOCKED', 28 | ERROR_WRONG_INTERVAL: 'TLM_WRONG_INTERVAL', 29 | } 30 | 31 | module.exports = { 32 | CHECKPOINT_ERRORS, 33 | STAKING_ERRORS, 34 | TIME_LOCK_MANAGER_ERRORS, 35 | } 36 | -------------------------------------------------------------------------------- /tests/solidity/suites/staking/truffle-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | // Development network is just left as truffle's default settings 4 | ethermint: { 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: 7000000, // Gas sent with each transaction 9 | gasPrice: 1000000000, // 1 gwei (in wei) 10 | }, 11 | }, 12 | compilers: { 13 | solc: { 14 | version: "0.5.17", // A version or constraint - Ex. "^0.5.0". 15 | settings: { 16 | optimizer: { 17 | enabled: true, 18 | runs: 10000, 19 | }, 20 | }, 21 | }, 22 | }, 23 | } 24 | -------------------------------------------------------------------------------- /tests/solidity/suites/storage/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/storage/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() public { 30 | require(false, 'This must REVERT'); 31 | } 32 | } -------------------------------------------------------------------------------- /tests/solidity/suites/storage/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eth-call-test", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "dependencies": { 7 | "@truffle/hdwallet-provider": "^1.4.1", 8 | "concurrently": "^6.2.0", 9 | "ganache-cli": "^6.12.2", 10 | "truffle": "^5.3.3", 11 | "truffle-assertions": "^0.9.2" 12 | }, 13 | "scripts": { 14 | "test-ganache": "yarn truffle test", 15 | "test-ethermint": "yarn truffle test --network ethermint" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/solidity/suites/storage/test/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web3validator/ethermint/10f0164181cbf6ce4c551fd47b4a7231d4eac53c/tests/solidity/suites/storage/test/.gitkeep -------------------------------------------------------------------------------- /tests/solidity/suites/storage/test/0_test_contracts.test.js: -------------------------------------------------------------------------------- 1 | const Storage = artifacts.require('Storage'); 2 | 3 | 4 | contract('Test Storage Contract', async function (accounts) { 5 | 6 | let storageInstance; 7 | 8 | before(function () { 9 | console.log(`Using Accounts (${accounts.length}): \n${accounts.join('\n')}`); 10 | console.log('==========================\n'); 11 | }) 12 | 13 | it('should deploy Stroage contract', async function () { 14 | storageInstance = await Storage.new(); 15 | console.log(`Deployed Storage at: ${storageInstance.address}`); 16 | expect(storageInstance.address).not.to.be.undefined; 17 | }); 18 | 19 | it('should succesfully stored a value', async function () { 20 | const tx = await storageInstance.store(888); 21 | console.log(`Stored value 888 by tx: ${tx.tx}`); 22 | expect(tx.tx).not.to.be.undefined; 23 | }); 24 | 25 | it('should succesfully retrieve a value', async function () { 26 | const value = await storageInstance.retrieve(); 27 | expect(value.toString()).to.equal('888'); 28 | }); 29 | 30 | }) -------------------------------------------------------------------------------- /tests/solidity/suites/storage/test/1_test_evm_revert.test.js: -------------------------------------------------------------------------------- 1 | const Storage = artifacts.require('Storage'); 2 | 3 | async function expectRevert(promise) { 4 | try { 5 | await promise; 6 | } catch (error) { 7 | if (error.message.indexOf('revert') === -1) { 8 | expect('revert').to.equal(error.message, 'Wrong kind of exception received'); 9 | } 10 | return; 11 | } 12 | expect.fail('Expected an exception but none was received'); 13 | } 14 | 15 | 16 | contract('Test EVM Revert', async function (accounts) { 17 | 18 | before(function () { 19 | console.log(`Using Accounts (${accounts.length}): \n${accounts.join('\n')}`); 20 | console.log('==========================\n'); 21 | }) 22 | 23 | let storageInstance; 24 | it('should deploy Stroage contract', async function () { 25 | storageInstance = await Storage.new(); 26 | console.log(`Deployed Storage at: ${storageInstance.address}`); 27 | expect(storageInstance.address).not.to.be.undefined; 28 | }); 29 | 30 | it('should revert when call `shouldRevert()`', async function () { 31 | await expectRevert(storageInstance.shouldRevert()); 32 | }); 33 | 34 | }) -------------------------------------------------------------------------------- /tests/solidity/suites/storage/test/2_test_events.test.js: -------------------------------------------------------------------------------- 1 | const EventTest = artifacts.require('EventTest'); 2 | const truffleAssert = require('truffle-assertions'); 3 | 4 | contract('Test EventTest Contract', async function (accounts) { 5 | 6 | let eventInstance; 7 | 8 | before(function () { 9 | console.log(`Using Accounts (${accounts.length}): \n${accounts.join('\n')}`); 10 | console.log('==========================\n'); 11 | }) 12 | 13 | it('should deploy EventTest contract', async function () { 14 | eventInstance = await EventTest.new(); 15 | console.log(`Deployed EventTest at: ${eventInstance.address}`); 16 | expect(eventInstance.address).not.to.be.undefined; 17 | }); 18 | 19 | it('should emit events', async function () { 20 | const tx = await eventInstance.storeWithEvent(888); 21 | truffleAssert.eventEmitted(tx, 'ValueStored1', events => { 22 | return events['0'].toString() === '888'; 23 | }); 24 | truffleAssert.eventEmitted(tx, 'ValueStored2', events => { 25 | return events['0'].toString() === 'TestMsg' && events['1'].toString() === '888'; 26 | }); 27 | truffleAssert.eventEmitted(tx, 'ValueStored3', events => { 28 | return events['0'].toString() === 'TestMsg' && events['1'].toString() === '888' && events['2'].toString() === '888'; 29 | }); 30 | 31 | }); 32 | 33 | }) -------------------------------------------------------------------------------- /tests/solidity/suites/storage/truffle-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | // Development network is just left as truffle's default settings 4 | ethermint: { 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.3", 15 | }, 16 | }, 17 | } 18 | -------------------------------------------------------------------------------- /tests/tooling/ethers/ethers.js: -------------------------------------------------------------------------------- 1 | import { ethers } from "ethers"; 2 | 3 | // connects to localhost:8545 4 | const provider = new ethers.providers.JsonRpcProvider() 5 | 6 | // const signer = provider.getSigner(); 7 | 8 | const blockNumber = await provider.getBlockNumber() -------------------------------------------------------------------------------- /testutil/network/network_test.go: -------------------------------------------------------------------------------- 1 | // +build norace 2 | 3 | package network_test 4 | 5 | import ( 6 | "testing" 7 | "time" 8 | 9 | "github.com/stretchr/testify/suite" 10 | 11 | "github.com/tharsis/ethermint/testutil/network" 12 | ) 13 | 14 | type IntegrationTestSuite struct { 15 | suite.Suite 16 | 17 | network *network.Network 18 | } 19 | 20 | func (s *IntegrationTestSuite) SetupSuite() { 21 | s.T().Log("setting up integration test suite") 22 | 23 | s.network = network.New(s.T(), network.DefaultConfig()) 24 | s.Require().NotNil(s.network) 25 | 26 | _, err := s.network.WaitForHeight(1) 27 | s.Require().NoError(err) 28 | } 29 | 30 | func (s *IntegrationTestSuite) TearDownSuite() { 31 | s.T().Log("tearing down integration test suite") 32 | s.network.Cleanup() 33 | } 34 | 35 | func (s *IntegrationTestSuite) TestNetwork_Liveness() { 36 | h, err := s.network.WaitForHeightWithTimeout(10, time.Minute) 37 | s.Require().NoError(err, "expected to reach 10 blocks; got %d", h) 38 | 39 | latestHeight, err := s.network.LatestHeight() 40 | s.Require().NoError(err, "latest height failed") 41 | s.Require().GreaterOrEqual(latestHeight, h) 42 | } 43 | 44 | func TestIntegrationTestSuite(t *testing.T) { 45 | suite.Run(t, new(IntegrationTestSuite)) 46 | } 47 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/auth/v1beta1/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.auth.v1beta1; 3 | 4 | import "google/protobuf/any.proto"; 5 | import "gogoproto/gogo.proto"; 6 | import "cosmos/auth/v1beta1/auth.proto"; 7 | 8 | option go_package = "github.com/cosmos/cosmos-sdk/x/auth/types"; 9 | 10 | // GenesisState defines the auth module's genesis state. 11 | message GenesisState { 12 | // params defines all the paramaters of the module. 13 | Params params = 1 [(gogoproto.nullable) = false]; 14 | 15 | // accounts are the accounts present at genesis. 16 | repeated google.protobuf.Any accounts = 2; 17 | } 18 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/authz/v1beta1/authz.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.authz.v1beta1; 3 | 4 | import "cosmos/base/v1beta1/coin.proto"; 5 | import "cosmos_proto/cosmos.proto"; 6 | import "google/protobuf/timestamp.proto"; 7 | import "gogoproto/gogo.proto"; 8 | import "google/protobuf/any.proto"; 9 | 10 | option go_package = "github.com/cosmos/cosmos-sdk/x/authz/types"; 11 | 12 | // SendAuthorization allows the grantee to spend up to spend_limit coins from 13 | // the granter's account. 14 | message SendAuthorization { 15 | option (cosmos_proto.implements_interface) = "Authorization"; 16 | 17 | repeated cosmos.base.v1beta1.Coin spend_limit = 1 18 | [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; 19 | } 20 | 21 | // GenericAuthorization gives the grantee unrestricted permissions to execute 22 | // the provided method on behalf of the granter's account. 23 | message GenericAuthorization { 24 | option (cosmos_proto.implements_interface) = "Authorization"; 25 | 26 | // method name to grant unrestricted permissions to execute 27 | // Note: MethodName() is already a method on `GenericAuthorization` type, 28 | // we need some custom naming here so using `MessageName` 29 | string method_name = 1 [(gogoproto.customname) = "MessageName"]; 30 | } 31 | 32 | // AuthorizationGrant gives permissions to execute 33 | // the provide method with expiration time. 34 | message AuthorizationGrant { 35 | google.protobuf.Any authorization = 1 [(cosmos_proto.accepts_interface) = "Authorization"]; 36 | google.protobuf.Timestamp expiration = 2 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false]; 37 | } 38 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/authz/v1beta1/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.authz.v1beta1; 3 | 4 | import "google/protobuf/timestamp.proto"; 5 | import "google/protobuf/any.proto"; 6 | import "gogoproto/gogo.proto"; 7 | import "cosmos_proto/cosmos.proto"; 8 | import "cosmos/authz/v1beta1/tx.proto"; 9 | 10 | option go_package = "github.com/cosmos/cosmos-sdk/x/authz/types"; 11 | 12 | // GenesisState defines the authz module's genesis state. 13 | message GenesisState { 14 | repeated GrantAuthorization authorization = 1 [(gogoproto.nullable) = false]; 15 | } 16 | 17 | // GrantAuthorization defines the GenesisState/GrantAuthorization type. 18 | message GrantAuthorization { 19 | string granter = 1; 20 | string grantee = 2; 21 | 22 | google.protobuf.Any authorization = 3 [(cosmos_proto.accepts_interface) = "Authorization"]; 23 | google.protobuf.Timestamp expiration = 4 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; 24 | } 25 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/bank/v1beta1/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.bank.v1beta1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "cosmos/base/v1beta1/coin.proto"; 6 | import "cosmos/bank/v1beta1/bank.proto"; 7 | 8 | option go_package = "github.com/cosmos/cosmos-sdk/x/bank/types"; 9 | 10 | // GenesisState defines the bank module's genesis state. 11 | message GenesisState { 12 | // params defines all the paramaters of the module. 13 | Params params = 1 [(gogoproto.nullable) = false]; 14 | 15 | // balances is an array containing the balances of all the accounts. 16 | repeated Balance balances = 2 [(gogoproto.nullable) = false]; 17 | 18 | // supply represents the total supply. 19 | repeated cosmos.base.v1beta1.Coin supply = 3 20 | [(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (gogoproto.nullable) = false]; 21 | 22 | // denom_metadata defines the metadata of the differents coins. 23 | repeated Metadata denom_metadata = 4 [(gogoproto.moretags) = "yaml:\"denom_metadata\"", (gogoproto.nullable) = false]; 24 | } 25 | 26 | // Balance defines an account address and balance pair used in the bank module's 27 | // genesis state. 28 | message Balance { 29 | option (gogoproto.equal) = false; 30 | option (gogoproto.goproto_getters) = false; 31 | 32 | // address is the address of the balance holder. 33 | string address = 1; 34 | 35 | // coins defines the different coins this balance holds. 36 | repeated cosmos.base.v1beta1.Coin coins = 2 37 | [(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (gogoproto.nullable) = false]; 38 | } 39 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/bank/v1beta1/tx.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.bank.v1beta1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "cosmos/base/v1beta1/coin.proto"; 6 | import "cosmos/bank/v1beta1/bank.proto"; 7 | 8 | option go_package = "github.com/cosmos/cosmos-sdk/x/bank/types"; 9 | 10 | // Msg defines the bank Msg service. 11 | service Msg { 12 | // Send defines a method for sending coins from one account to another account. 13 | rpc Send(MsgSend) returns (MsgSendResponse); 14 | 15 | // MultiSend defines a method for sending coins from some accounts to other accounts. 16 | rpc MultiSend(MsgMultiSend) returns (MsgMultiSendResponse); 17 | } 18 | 19 | // MsgSend represents a message to send coins from one account to another. 20 | message MsgSend { 21 | option (gogoproto.equal) = false; 22 | option (gogoproto.goproto_getters) = false; 23 | 24 | string from_address = 1 [(gogoproto.moretags) = "yaml:\"from_address\""]; 25 | string to_address = 2 [(gogoproto.moretags) = "yaml:\"to_address\""]; 26 | repeated cosmos.base.v1beta1.Coin amount = 3 27 | [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; 28 | } 29 | 30 | // MsgSendResponse defines the Msg/Send response type. 31 | message MsgSendResponse {} 32 | 33 | // MsgMultiSend represents an arbitrary multi-in, multi-out send message. 34 | message MsgMultiSend { 35 | option (gogoproto.equal) = false; 36 | 37 | repeated Input inputs = 1 [(gogoproto.nullable) = false]; 38 | repeated Output outputs = 2 [(gogoproto.nullable) = false]; 39 | } 40 | 41 | // MsgMultiSendResponse defines the Msg/MultiSend response type. 42 | message MsgMultiSendResponse {} 43 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/base/kv/v1beta1/kv.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.base.kv.v1beta1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | 6 | option go_package = "github.com/cosmos/cosmos-sdk/types/kv"; 7 | 8 | // Pairs defines a repeated slice of Pair objects. 9 | message Pairs { 10 | repeated Pair pairs = 1 [(gogoproto.nullable) = false]; 11 | } 12 | 13 | // Pair defines a key/value bytes tuple. 14 | message Pair { 15 | bytes key = 1; 16 | bytes value = 2; 17 | } 18 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/base/snapshots/v1beta1/snapshot.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.base.snapshots.v1beta1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | 6 | option go_package = "github.com/cosmos/cosmos-sdk/snapshots/types"; 7 | 8 | // Snapshot contains Tendermint state sync snapshot info. 9 | message Snapshot { 10 | uint64 height = 1; 11 | uint32 format = 2; 12 | uint32 chunks = 3; 13 | bytes hash = 4; 14 | Metadata metadata = 5 [(gogoproto.nullable) = false]; 15 | } 16 | 17 | // Metadata contains SDK-specific snapshot metadata. 18 | message Metadata { 19 | repeated bytes chunk_hashes = 1; // SHA-256 chunk hashes 20 | } -------------------------------------------------------------------------------- /third_party/proto/cosmos/base/store/v1beta1/commit_info.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.base.store.v1beta1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | 6 | option go_package = "github.com/cosmos/cosmos-sdk/store/types"; 7 | 8 | // CommitInfo defines commit information used by the multi-store when committing 9 | // a version/height. 10 | message CommitInfo { 11 | int64 version = 1; 12 | repeated StoreInfo store_infos = 2 [(gogoproto.nullable) = false]; 13 | } 14 | 15 | // StoreInfo defines store-specific commit information. It contains a reference 16 | // between a store name and the commit ID. 17 | message StoreInfo { 18 | string name = 1; 19 | CommitID commit_id = 2 [(gogoproto.nullable) = false]; 20 | } 21 | 22 | // CommitID defines the committment information when a specific store is 23 | // committed. 24 | message CommitID { 25 | option (gogoproto.goproto_stringer) = false; 26 | 27 | int64 version = 1; 28 | bytes hash = 2; 29 | } 30 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/base/store/v1beta1/snapshot.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.base.store.v1beta1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | 6 | option go_package = "github.com/cosmos/cosmos-sdk/store/types"; 7 | 8 | // SnapshotItem is an item contained in a rootmulti.Store snapshot. 9 | message SnapshotItem { 10 | // item is the specific type of snapshot item. 11 | oneof item { 12 | SnapshotStoreItem store = 1; 13 | SnapshotIAVLItem iavl = 2 [(gogoproto.customname) = "IAVL"]; 14 | } 15 | } 16 | 17 | // SnapshotStoreItem contains metadata about a snapshotted store. 18 | message SnapshotStoreItem { 19 | string name = 1; 20 | } 21 | 22 | // SnapshotIAVLItem is an exported IAVL node. 23 | message SnapshotIAVLItem { 24 | bytes key = 1; 25 | bytes value = 2; 26 | int64 version = 3; 27 | int32 height = 4; 28 | } -------------------------------------------------------------------------------- /third_party/proto/cosmos/base/v1beta1/coin.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.base.v1beta1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | 6 | option go_package = "github.com/cosmos/cosmos-sdk/types"; 7 | option (gogoproto.goproto_stringer_all) = false; 8 | option (gogoproto.stringer_all) = false; 9 | 10 | // Coin defines a token with a denomination and an amount. 11 | // 12 | // NOTE: The amount field is an Int which implements the custom method 13 | // signatures required by gogoproto. 14 | message Coin { 15 | option (gogoproto.equal) = true; 16 | 17 | string denom = 1; 18 | string amount = 2 [(gogoproto.customtype) = "Int", (gogoproto.nullable) = false]; 19 | } 20 | 21 | // DecCoin defines a token with a denomination and a decimal amount. 22 | // 23 | // NOTE: The amount field is an Dec which implements the custom method 24 | // signatures required by gogoproto. 25 | message DecCoin { 26 | option (gogoproto.equal) = true; 27 | 28 | string denom = 1; 29 | string amount = 2 [(gogoproto.customtype) = "Dec", (gogoproto.nullable) = false]; 30 | } 31 | 32 | // IntProto defines a Protobuf wrapper around an Int object. 33 | message IntProto { 34 | string int = 1 [(gogoproto.customtype) = "Int", (gogoproto.nullable) = false]; 35 | } 36 | 37 | // DecProto defines a Protobuf wrapper around a Dec object. 38 | message DecProto { 39 | string dec = 1 [(gogoproto.customtype) = "Dec", (gogoproto.nullable) = false]; 40 | } 41 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/capability/v1beta1/capability.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.capability.v1beta1; 3 | 4 | option go_package = "github.com/cosmos/cosmos-sdk/x/capability/types"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | 8 | // Capability defines an implementation of an object capability. The index 9 | // provided to a Capability must be globally unique. 10 | message Capability { 11 | option (gogoproto.goproto_stringer) = false; 12 | 13 | uint64 index = 1 [(gogoproto.moretags) = "yaml:\"index\""]; 14 | } 15 | 16 | // Owner defines a single capability owner. An owner is defined by the name of 17 | // capability and the module name. 18 | message Owner { 19 | option (gogoproto.goproto_stringer) = false; 20 | option (gogoproto.goproto_getters) = false; 21 | 22 | string module = 1 [(gogoproto.moretags) = "yaml:\"module\""]; 23 | string name = 2 [(gogoproto.moretags) = "yaml:\"name\""]; 24 | } 25 | 26 | // CapabilityOwners defines a set of owners of a single Capability. The set of 27 | // owners must be unique. 28 | message CapabilityOwners { 29 | repeated Owner owners = 1 [(gogoproto.nullable) = false]; 30 | } 31 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/capability/v1beta1/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.capability.v1beta1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "cosmos/capability/v1beta1/capability.proto"; 6 | 7 | option go_package = "github.com/cosmos/cosmos-sdk/x/capability/types"; 8 | 9 | // GenesisOwners defines the capability owners with their corresponding index. 10 | message GenesisOwners { 11 | // index is the index of the capability owner. 12 | uint64 index = 1; 13 | 14 | // index_owners are the owners at the given index. 15 | CapabilityOwners index_owners = 2 [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"index_owners\""]; 16 | } 17 | 18 | // GenesisState defines the capability module's genesis state. 19 | message GenesisState { 20 | // index is the capability global index. 21 | uint64 index = 1; 22 | 23 | // owners represents a map from index to owners of the capability index 24 | // index key is string to allow amino marshalling. 25 | repeated GenesisOwners owners = 2 [(gogoproto.nullable) = false]; 26 | } 27 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/crisis/v1beta1/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.crisis.v1beta1; 3 | 4 | option go_package = "github.com/cosmos/cosmos-sdk/x/crisis/types"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "cosmos/base/v1beta1/coin.proto"; 8 | 9 | // GenesisState defines the crisis module's genesis state. 10 | message GenesisState { 11 | // constant_fee is the fee used to verify the invariant in the crisis 12 | // module. 13 | cosmos.base.v1beta1.Coin constant_fee = 3 14 | [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"constant_fee\""]; 15 | } 16 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/crisis/v1beta1/tx.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.crisis.v1beta1; 3 | 4 | option go_package = "github.com/cosmos/cosmos-sdk/x/crisis/types"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | 8 | // Msg defines the bank Msg service. 9 | service Msg { 10 | // VerifyInvariant defines a method to verify a particular invariance. 11 | rpc VerifyInvariant(MsgVerifyInvariant) returns (MsgVerifyInvariantResponse); 12 | } 13 | 14 | // MsgVerifyInvariant represents a message to verify a particular invariance. 15 | message MsgVerifyInvariant { 16 | option (gogoproto.equal) = false; 17 | option (gogoproto.goproto_getters) = false; 18 | 19 | string sender = 1; 20 | string invariant_module_name = 2 [(gogoproto.moretags) = "yaml:\"invariant_module_name\""]; 21 | string invariant_route = 3 [(gogoproto.moretags) = "yaml:\"invariant_route\""]; 22 | } 23 | 24 | // MsgVerifyInvariantResponse defines the Msg/VerifyInvariant response type. 25 | message MsgVerifyInvariantResponse {} 26 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/crypto/ed25519/keys.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.crypto.ed25519; 3 | 4 | import "gogoproto/gogo.proto"; 5 | 6 | option go_package = "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"; 7 | 8 | // PubKey defines a ed25519 public key 9 | // Key is the compressed form of the pubkey. The first byte depends is a 0x02 byte 10 | // if the y-coordinate is the lexicographically largest of the two associated with 11 | // the x-coordinate. Otherwise the first byte is a 0x03. 12 | // This prefix is followed with the x-coordinate. 13 | message PubKey { 14 | option (gogoproto.goproto_stringer) = false; 15 | 16 | bytes key = 1 [(gogoproto.casttype) = "crypto/ed25519.PublicKey"]; 17 | } 18 | 19 | // PrivKey defines a ed25519 private key. 20 | message PrivKey { 21 | bytes key = 1 [(gogoproto.casttype) = "crypto/ed25519.PrivateKey"]; 22 | } 23 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/crypto/multisig/keys.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.crypto.multisig; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "google/protobuf/any.proto"; 6 | 7 | option go_package = "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"; 8 | 9 | // LegacyAminoPubKey specifies a public key type 10 | // which nests multiple public keys and a threshold, 11 | // it uses legacy amino address rules. 12 | message LegacyAminoPubKey { 13 | option (gogoproto.goproto_getters) = false; 14 | 15 | uint32 threshold = 1 [(gogoproto.moretags) = "yaml:\"threshold\""]; 16 | repeated google.protobuf.Any public_keys = 2 17 | [(gogoproto.customname) = "PubKeys", (gogoproto.moretags) = "yaml:\"pubkeys\""]; 18 | } 19 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/crypto/multisig/v1beta1/multisig.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.crypto.multisig.v1beta1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | 6 | option go_package = "github.com/cosmos/cosmos-sdk/crypto/types"; 7 | 8 | // MultiSignature wraps the signatures from a multisig.LegacyAminoPubKey. 9 | // See cosmos.tx.v1betata1.ModeInfo.Multi for how to specify which signers 10 | // signed and with which modes. 11 | message MultiSignature { 12 | option (gogoproto.goproto_unrecognized) = true; 13 | repeated bytes signatures = 1; 14 | } 15 | 16 | // CompactBitArray is an implementation of a space efficient bit array. 17 | // This is used to ensure that the encoded data takes up a minimal amount of 18 | // space after proto encoding. 19 | // This is not thread safe, and is not intended for concurrent usage. 20 | message CompactBitArray { 21 | option (gogoproto.goproto_stringer) = false; 22 | 23 | uint32 extra_bits_stored = 1; 24 | bytes elems = 2; 25 | } 26 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/crypto/secp256k1/keys.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.crypto.secp256k1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | 6 | option go_package = "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"; 7 | 8 | // PubKey defines a secp256k1 public key 9 | // Key is the compressed form of the pubkey. The first byte depends is a 0x02 byte 10 | // if the y-coordinate is the lexicographically largest of the two associated with 11 | // the x-coordinate. Otherwise the first byte is a 0x03. 12 | // This prefix is followed with the x-coordinate. 13 | message PubKey { 14 | option (gogoproto.goproto_stringer) = false; 15 | 16 | bytes key = 1; 17 | } 18 | 19 | // PrivKey defines a secp256k1 private key. 20 | message PrivKey { 21 | bytes key = 1; 22 | } 23 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/evidence/v1beta1/evidence.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.evidence.v1beta1; 3 | 4 | option go_package = "github.com/cosmos/cosmos-sdk/x/evidence/types"; 5 | option (gogoproto.equal_all) = true; 6 | 7 | import "gogoproto/gogo.proto"; 8 | import "google/protobuf/timestamp.proto"; 9 | 10 | // Equivocation implements the Evidence interface and defines evidence of double 11 | // signing misbehavior. 12 | message Equivocation { 13 | option (gogoproto.goproto_stringer) = false; 14 | option (gogoproto.goproto_getters) = false; 15 | option (gogoproto.equal) = false; 16 | 17 | int64 height = 1; 18 | google.protobuf.Timestamp time = 2 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; 19 | int64 power = 3; 20 | string consensus_address = 4 [(gogoproto.moretags) = "yaml:\"consensus_address\""]; 21 | } -------------------------------------------------------------------------------- /third_party/proto/cosmos/evidence/v1beta1/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.evidence.v1beta1; 3 | 4 | option go_package = "github.com/cosmos/cosmos-sdk/x/evidence/types"; 5 | 6 | import "google/protobuf/any.proto"; 7 | 8 | // GenesisState defines the evidence module's genesis state. 9 | message GenesisState { 10 | // evidence defines all the evidence at genesis. 11 | repeated google.protobuf.Any evidence = 1; 12 | } 13 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/evidence/v1beta1/tx.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.evidence.v1beta1; 3 | 4 | option go_package = "github.com/cosmos/cosmos-sdk/x/evidence/types"; 5 | option (gogoproto.equal_all) = true; 6 | 7 | import "gogoproto/gogo.proto"; 8 | import "google/protobuf/any.proto"; 9 | import "cosmos_proto/cosmos.proto"; 10 | 11 | // Msg defines the evidence Msg service. 12 | service Msg { 13 | // SubmitEvidence submits an arbitrary Evidence of misbehavior such as equivocation or 14 | // counterfactual signing. 15 | rpc SubmitEvidence(MsgSubmitEvidence) returns (MsgSubmitEvidenceResponse); 16 | } 17 | 18 | // MsgSubmitEvidence represents a message that supports submitting arbitrary 19 | // Evidence of misbehavior such as equivocation or counterfactual signing. 20 | message MsgSubmitEvidence { 21 | option (gogoproto.equal) = false; 22 | option (gogoproto.goproto_getters) = false; 23 | 24 | string submitter = 1; 25 | google.protobuf.Any evidence = 2 [(cosmos_proto.accepts_interface) = "Evidence"]; 26 | } 27 | 28 | // MsgSubmitEvidenceResponse defines the Msg/SubmitEvidence response type. 29 | message MsgSubmitEvidenceResponse { 30 | // hash defines the hash of the evidence. 31 | bytes hash = 4; 32 | } 33 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/feegrant/v1beta1/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.feegrant.v1beta1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "cosmos/feegrant/v1beta1/feegrant.proto"; 6 | 7 | option go_package = "github.com/cosmos/cosmos-sdk/x/feegrant/types"; 8 | 9 | // GenesisState contains a set of fee allowances, persisted from the store 10 | message GenesisState { 11 | repeated FeeAllowanceGrant fee_allowances = 1 [(gogoproto.nullable) = false]; 12 | } 13 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/feegrant/v1beta1/tx.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.feegrant.v1beta1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "google/protobuf/any.proto"; 6 | import "cosmos_proto/cosmos.proto"; 7 | 8 | option go_package = "github.com/cosmos/cosmos-sdk/x/feegrant/types"; 9 | 10 | // Msg defines the feegrant msg service. 11 | service Msg { 12 | 13 | // GrantFeeAllowance grants fee allowance to the grantee on the granter's 14 | // account with the provided expiration time. 15 | rpc GrantFeeAllowance(MsgGrantFeeAllowance) returns (MsgGrantFeeAllowanceResponse); 16 | 17 | // RevokeFeeAllowance revokes any fee allowance of granter's account that 18 | // has been granted to the grantee. 19 | rpc RevokeFeeAllowance(MsgRevokeFeeAllowance) returns (MsgRevokeFeeAllowanceResponse); 20 | } 21 | 22 | // MsgGrantFeeAllowance adds permission for Grantee to spend up to Allowance 23 | // of fees from the account of Granter. 24 | message MsgGrantFeeAllowance { 25 | string granter = 1; 26 | string grantee = 2; 27 | google.protobuf.Any allowance = 3 [(cosmos_proto.accepts_interface) = "FeeAllowanceI"]; 28 | } 29 | 30 | // MsgGrantFeeAllowanceResponse defines the Msg/GrantFeeAllowanceResponse response type. 31 | message MsgGrantFeeAllowanceResponse {} 32 | 33 | // MsgRevokeFeeAllowance removes any existing FeeAllowance from Granter to Grantee. 34 | message MsgRevokeFeeAllowance { 35 | string granter = 1; 36 | string grantee = 2; 37 | } 38 | 39 | // MsgRevokeFeeAllowanceResponse defines the Msg/RevokeFeeAllowanceResponse response type. 40 | message MsgRevokeFeeAllowanceResponse {} 41 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/genutil/v1beta1/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.genutil.v1beta1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | 6 | option go_package = "github.com/cosmos/cosmos-sdk/x/genutil/types"; 7 | 8 | // GenesisState defines the raw genesis transaction in JSON. 9 | message GenesisState { 10 | // gen_txs defines the genesis transactions. 11 | repeated bytes gen_txs = 1 [ 12 | (gogoproto.casttype) = "encoding/json.RawMessage", 13 | (gogoproto.jsontag) = "gentxs", 14 | (gogoproto.moretags) = "yaml:\"gentxs\"" 15 | ]; 16 | } 17 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/gov/v1beta1/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package cosmos.gov.v1beta1; 4 | 5 | import "gogoproto/gogo.proto"; 6 | import "cosmos/gov/v1beta1/gov.proto"; 7 | 8 | option go_package = "github.com/cosmos/cosmos-sdk/x/gov/types"; 9 | 10 | // GenesisState defines the gov module's genesis state. 11 | message GenesisState { 12 | // starting_proposal_id is the ID of the starting proposal. 13 | uint64 starting_proposal_id = 1 [(gogoproto.moretags) = "yaml:\"starting_proposal_id\""]; 14 | // deposits defines all the deposits present at genesis. 15 | repeated Deposit deposits = 2 [(gogoproto.castrepeated) = "Deposits", (gogoproto.nullable) = false]; 16 | // votes defines all the votes present at genesis. 17 | repeated Vote votes = 3 [(gogoproto.castrepeated) = "Votes", (gogoproto.nullable) = false]; 18 | // proposals defines all the proposals present at genesis. 19 | repeated Proposal proposals = 4 [(gogoproto.castrepeated) = "Proposals", (gogoproto.nullable) = false]; 20 | // params defines all the paramaters of related to deposit. 21 | DepositParams deposit_params = 5 [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"deposit_params\""]; 22 | // params defines all the paramaters of related to voting. 23 | VotingParams voting_params = 6 [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"voting_params\""]; 24 | // params defines all the paramaters of related to tally. 25 | TallyParams tally_params = 7 [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"tally_params\""]; 26 | } 27 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/mint/v1beta1/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.mint.v1beta1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "cosmos/mint/v1beta1/mint.proto"; 6 | 7 | option go_package = "github.com/cosmos/cosmos-sdk/x/mint/types"; 8 | 9 | // GenesisState defines the mint module's genesis state. 10 | message GenesisState { 11 | // minter is a space for holding current inflation information. 12 | Minter minter = 1 [(gogoproto.nullable) = false]; 13 | 14 | // params defines all the paramaters of the module. 15 | Params params = 2 [(gogoproto.nullable) = false]; 16 | } 17 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/params/v1beta1/params.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.params.v1beta1; 3 | 4 | option go_package = "github.com/cosmos/cosmos-sdk/x/params/types/proposal"; 5 | option (gogoproto.equal_all) = true; 6 | 7 | import "gogoproto/gogo.proto"; 8 | 9 | // ParameterChangeProposal defines a proposal to change one or more parameters. 10 | message ParameterChangeProposal { 11 | option (gogoproto.goproto_getters) = false; 12 | option (gogoproto.goproto_stringer) = false; 13 | 14 | string title = 1; 15 | string description = 2; 16 | repeated ParamChange changes = 3 [(gogoproto.nullable) = false]; 17 | } 18 | 19 | // ParamChange defines an individual parameter change, for use in 20 | // ParameterChangeProposal. 21 | message ParamChange { 22 | option (gogoproto.goproto_stringer) = false; 23 | 24 | string subspace = 1; 25 | string key = 2; 26 | string value = 3; 27 | } 28 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/params/v1beta1/query.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.params.v1beta1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "google/api/annotations.proto"; 6 | import "cosmos/params/v1beta1/params.proto"; 7 | 8 | option go_package = "github.com/cosmos/cosmos-sdk/x/params/types/proposal"; 9 | 10 | // Query defines the gRPC querier service. 11 | service Query { 12 | // Params queries a specific parameter of a module, given its subspace and 13 | // key. 14 | rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { 15 | option (google.api.http).get = "/cosmos/params/v1beta1/params"; 16 | } 17 | } 18 | 19 | // QueryParamsRequest is request type for the Query/Params RPC method. 20 | message QueryParamsRequest { 21 | // subspace defines the module to query the parameter for. 22 | string subspace = 1; 23 | 24 | // key defines the key of the parameter in the subspace. 25 | string key = 2; 26 | } 27 | 28 | // QueryParamsResponse is response type for the Query/Params RPC method. 29 | message QueryParamsResponse { 30 | // param defines the queried parameter. 31 | ParamChange param = 1 [(gogoproto.nullable) = false]; 32 | } 33 | -------------------------------------------------------------------------------- /third_party/proto/cosmos/slashing/v1beta1/tx.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.slashing.v1beta1; 3 | 4 | option go_package = "github.com/cosmos/cosmos-sdk/x/slashing/types"; 5 | option (gogoproto.equal_all) = true; 6 | 7 | import "gogoproto/gogo.proto"; 8 | 9 | // Msg defines the slashing Msg service. 10 | service Msg { 11 | // Unjail defines a method for unjailing a jailed validator, thus returning 12 | // them into the bonded validator set, so they can begin receiving provisions 13 | // and rewards again. 14 | rpc Unjail(MsgUnjail) returns (MsgUnjailResponse); 15 | } 16 | 17 | // MsgUnjail defines the Msg/Unjail request type 18 | message MsgUnjail { 19 | option (gogoproto.goproto_getters) = false; 20 | option (gogoproto.goproto_stringer) = true; 21 | 22 | string validator_addr = 1 [(gogoproto.moretags) = "yaml:\"address\"", (gogoproto.jsontag) = "address"]; 23 | } 24 | 25 | // MsgUnjailResponse defines the Msg/Unjail response type 26 | message MsgUnjailResponse {} -------------------------------------------------------------------------------- /third_party/proto/cosmos/vesting/v1beta1/tx.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos.vesting.v1beta1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "cosmos/base/v1beta1/coin.proto"; 6 | 7 | option go_package = "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"; 8 | 9 | // Msg defines the bank Msg service. 10 | service Msg { 11 | // CreateVestingAccount defines a method that enables creating a vesting 12 | // account. 13 | rpc CreateVestingAccount(MsgCreateVestingAccount) returns (MsgCreateVestingAccountResponse); 14 | } 15 | 16 | // MsgCreateVestingAccount defines a message that enables creating a vesting 17 | // account. 18 | message MsgCreateVestingAccount { 19 | option (gogoproto.equal) = true; 20 | 21 | string from_address = 1 [(gogoproto.moretags) = "yaml:\"from_address\""]; 22 | string to_address = 2 [(gogoproto.moretags) = "yaml:\"to_address\""]; 23 | repeated cosmos.base.v1beta1.Coin amount = 3 24 | [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; 25 | 26 | int64 end_time = 4 [(gogoproto.moretags) = "yaml:\"end_time\""]; 27 | bool delayed = 5; 28 | } 29 | 30 | // MsgCreateVestingAccountResponse defines the Msg/CreateVestingAccount response type. 31 | message MsgCreateVestingAccountResponse {} -------------------------------------------------------------------------------- /third_party/proto/cosmos_proto/cosmos.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cosmos_proto; 3 | 4 | import "google/protobuf/descriptor.proto"; 5 | 6 | option go_package = "github.com/regen-network/cosmos-proto"; 7 | 8 | extend google.protobuf.MessageOptions { 9 | string interface_type = 93001; 10 | 11 | string implements_interface = 93002; 12 | } 13 | 14 | extend google.protobuf.FieldOptions { 15 | string accepts_interface = 93001; 16 | } 17 | -------------------------------------------------------------------------------- /third_party/proto/google/api/annotations.proto: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | package google.api; 18 | 19 | import "google/api/http.proto"; 20 | import "google/protobuf/descriptor.proto"; 21 | 22 | option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; 23 | option java_multiple_files = true; 24 | option java_outer_classname = "AnnotationsProto"; 25 | option java_package = "com.google.api"; 26 | option objc_class_prefix = "GAPI"; 27 | 28 | extend google.protobuf.MethodOptions { 29 | // See `HttpRule`. 30 | HttpRule http = 72295728; 31 | } 32 | -------------------------------------------------------------------------------- /third_party/proto/tendermint/crypto/keys.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tendermint.crypto; 3 | 4 | option go_package = "github.com/tendermint/tendermint/proto/tendermint/crypto"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | 8 | // PublicKey defines the keys available for use with Tendermint Validators 9 | message PublicKey { 10 | option (gogoproto.compare) = true; 11 | option (gogoproto.equal) = true; 12 | 13 | oneof sum { 14 | bytes ed25519 = 1; 15 | bytes secp256k1 = 2; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /third_party/proto/tendermint/crypto/proof.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tendermint.crypto; 3 | 4 | option go_package = "github.com/tendermint/tendermint/proto/tendermint/crypto"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | 8 | message Proof { 9 | int64 total = 1; 10 | int64 index = 2; 11 | bytes leaf_hash = 3; 12 | repeated bytes aunts = 4; 13 | } 14 | 15 | message ValueOp { 16 | // Encoded in ProofOp.Key. 17 | bytes key = 1; 18 | 19 | // To encode in ProofOp.Data 20 | Proof proof = 2; 21 | } 22 | 23 | message DominoOp { 24 | string key = 1; 25 | string input = 2; 26 | string output = 3; 27 | } 28 | 29 | // ProofOp defines an operation used for calculating Merkle root 30 | // The data could be arbitrary format, providing nessecary data 31 | // for example neighbouring node hash 32 | message ProofOp { 33 | string type = 1; 34 | bytes key = 2; 35 | bytes data = 3; 36 | } 37 | 38 | // ProofOps is Merkle proof defined by the list of ProofOps 39 | message ProofOps { 40 | repeated ProofOp ops = 1 [(gogoproto.nullable) = false]; 41 | } 42 | -------------------------------------------------------------------------------- /third_party/proto/tendermint/libs/bits/types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tendermint.libs.bits; 3 | 4 | option go_package = "github.com/tendermint/tendermint/proto/tendermint/libs/bits"; 5 | 6 | message BitArray { 7 | int64 bits = 1; 8 | repeated uint64 elems = 2; 9 | } 10 | -------------------------------------------------------------------------------- /third_party/proto/tendermint/p2p/types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tendermint.p2p; 3 | 4 | option go_package = "github.com/tendermint/tendermint/proto/tendermint/p2p"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | 8 | message NetAddress { 9 | string id = 1 [(gogoproto.customname) = "ID"]; 10 | string ip = 2 [(gogoproto.customname) = "IP"]; 11 | uint32 port = 3; 12 | } 13 | 14 | message ProtocolVersion { 15 | uint64 p2p = 1 [(gogoproto.customname) = "P2P"]; 16 | uint64 block = 2; 17 | uint64 app = 3; 18 | } 19 | 20 | message DefaultNodeInfo { 21 | ProtocolVersion protocol_version = 1 [(gogoproto.nullable) = false]; 22 | string default_node_id = 2 [(gogoproto.customname) = "DefaultNodeID"]; 23 | string listen_addr = 3; 24 | string network = 4; 25 | string version = 5; 26 | bytes channels = 6; 27 | string moniker = 7; 28 | DefaultNodeInfoOther other = 8 [(gogoproto.nullable) = false]; 29 | } 30 | 31 | message DefaultNodeInfoOther { 32 | string tx_index = 1; 33 | string rpc_address = 2 [(gogoproto.customname) = "RPCAddress"]; 34 | } 35 | -------------------------------------------------------------------------------- /third_party/proto/tendermint/types/block.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tendermint.types; 3 | 4 | option go_package = "github.com/tendermint/tendermint/proto/tendermint/types"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "tendermint/types/types.proto"; 8 | import "tendermint/types/evidence.proto"; 9 | 10 | message Block { 11 | Header header = 1 [(gogoproto.nullable) = false]; 12 | Data data = 2 [(gogoproto.nullable) = false]; 13 | tendermint.types.EvidenceList evidence = 3 [(gogoproto.nullable) = false]; 14 | Commit last_commit = 4; 15 | } 16 | -------------------------------------------------------------------------------- /third_party/proto/tendermint/types/evidence.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tendermint.types; 3 | 4 | option go_package = "github.com/tendermint/tendermint/proto/tendermint/types"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "google/protobuf/timestamp.proto"; 8 | import "tendermint/types/types.proto"; 9 | import "tendermint/types/validator.proto"; 10 | 11 | message Evidence { 12 | oneof sum { 13 | DuplicateVoteEvidence duplicate_vote_evidence = 1; 14 | LightClientAttackEvidence light_client_attack_evidence = 2; 15 | } 16 | } 17 | 18 | // DuplicateVoteEvidence contains evidence of a validator signed two conflicting votes. 19 | message DuplicateVoteEvidence { 20 | tendermint.types.Vote vote_a = 1; 21 | tendermint.types.Vote vote_b = 2; 22 | int64 total_voting_power = 3; 23 | int64 validator_power = 4; 24 | google.protobuf.Timestamp timestamp = 5 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; 25 | } 26 | 27 | // LightClientAttackEvidence contains evidence of a set of validators attempting to mislead a light client. 28 | message LightClientAttackEvidence { 29 | tendermint.types.LightBlock conflicting_block = 1; 30 | int64 common_height = 2; 31 | repeated tendermint.types.Validator byzantine_validators = 3; 32 | int64 total_voting_power = 4; 33 | google.protobuf.Timestamp timestamp = 5 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; 34 | } 35 | 36 | message EvidenceList { 37 | repeated Evidence evidence = 1 [(gogoproto.nullable) = false]; 38 | } 39 | -------------------------------------------------------------------------------- /third_party/proto/tendermint/types/validator.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tendermint.types; 3 | 4 | option go_package = "github.com/tendermint/tendermint/proto/tendermint/types"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "tendermint/crypto/keys.proto"; 8 | 9 | message ValidatorSet { 10 | repeated Validator validators = 1; 11 | Validator proposer = 2; 12 | int64 total_voting_power = 3; 13 | } 14 | 15 | message Validator { 16 | bytes address = 1; 17 | tendermint.crypto.PublicKey pub_key = 2 [(gogoproto.nullable) = false]; 18 | int64 voting_power = 3; 19 | int64 proposer_priority = 4; 20 | } 21 | 22 | message SimpleValidator { 23 | tendermint.crypto.PublicKey pub_key = 1; 24 | int64 voting_power = 2; 25 | } 26 | -------------------------------------------------------------------------------- /third_party/proto/tendermint/version/types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tendermint.version; 3 | 4 | option go_package = "github.com/tendermint/tendermint/proto/tendermint/version"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | 8 | // App includes the protocol and software version for the application. 9 | // This information is included in ResponseInfo. The App.Protocol can be 10 | // updated in ResponseEndBlock. 11 | message App { 12 | uint64 protocol = 1; 13 | string software = 2; 14 | } 15 | 16 | // Consensus captures the consensus rules for processing a block in the blockchain, 17 | // including all blockchain data structures and the rules of the application's 18 | // state transition machine. 19 | message Consensus { 20 | option (gogoproto.equal) = true; 21 | 22 | uint64 block = 1; 23 | uint64 app = 2; 24 | } 25 | -------------------------------------------------------------------------------- /types/account.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 5 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 6 | 7 | "github.com/ethereum/go-ethereum/common" 8 | ethcrypto "github.com/ethereum/go-ethereum/crypto" 9 | ) 10 | 11 | var ( 12 | _ authtypes.AccountI = (*EthAccount)(nil) 13 | _ authtypes.GenesisAccount = (*EthAccount)(nil) 14 | _ codectypes.UnpackInterfacesMessage = (*EthAccount)(nil) 15 | ) 16 | 17 | // ---------------------------------------------------------------------------- 18 | // Main Ethermint account 19 | // ---------------------------------------------------------------------------- 20 | 21 | // ProtoAccount defines the prototype function for BaseAccount used for an 22 | // AccountKeeper. 23 | func ProtoAccount() authtypes.AccountI { 24 | return &EthAccount{ 25 | BaseAccount: &authtypes.BaseAccount{}, 26 | CodeHash: common.BytesToHash(ethcrypto.Keccak256(nil)).String(), 27 | } 28 | } 29 | 30 | // EthAddress returns the account address ethereum format. 31 | func (acc EthAccount) EthAddress() common.Address { 32 | return common.BytesToAddress(acc.GetAddress().Bytes()) 33 | } 34 | 35 | // GetCodeHash returns the account code hash in byte format 36 | func (acc EthAccount) GetCodeHash() common.Hash { 37 | return common.HexToHash(acc.CodeHash) 38 | } 39 | -------------------------------------------------------------------------------- /types/account_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/ethereum/go-ethereum/common" 7 | "github.com/stretchr/testify/suite" 8 | 9 | "github.com/cosmos/cosmos-sdk/codec" 10 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 11 | sdk "github.com/cosmos/cosmos-sdk/types" 12 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 13 | 14 | cryptocodec "github.com/tharsis/ethermint/crypto/codec" 15 | "github.com/tharsis/ethermint/crypto/ethsecp256k1" 16 | ethermintcodec "github.com/tharsis/ethermint/encoding/codec" 17 | "github.com/tharsis/ethermint/types" 18 | ) 19 | 20 | func init() { 21 | amino := codec.NewLegacyAmino() 22 | cryptocodec.RegisterCrypto(amino) 23 | } 24 | 25 | type AccountTestSuite struct { 26 | suite.Suite 27 | 28 | account *types.EthAccount 29 | cdc codec.JSONCodec 30 | } 31 | 32 | func (suite *AccountTestSuite) SetupTest() { 33 | privKey, err := ethsecp256k1.GenerateKey() 34 | suite.Require().NoError(err) 35 | pubKey := privKey.PubKey() 36 | addr := sdk.AccAddress(pubKey.Address()) 37 | baseAcc := authtypes.NewBaseAccount(addr, pubKey, 10, 50) 38 | suite.account = &types.EthAccount{ 39 | BaseAccount: baseAcc, 40 | CodeHash: common.Hash{}.String(), 41 | } 42 | 43 | interfaceRegistry := codectypes.NewInterfaceRegistry() 44 | ethermintcodec.RegisterInterfaces(interfaceRegistry) 45 | suite.cdc = codec.NewProtoCodec(interfaceRegistry) 46 | } 47 | 48 | func TestAccountTestSuite(t *testing.T) { 49 | suite.Run(t, new(AccountTestSuite)) 50 | } 51 | -------------------------------------------------------------------------------- /types/block.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import sdk "github.com/cosmos/cosmos-sdk/types" 4 | 5 | // BlockGasLimit returns the max gas (limit) defined in the block gas meter. If the meter is not 6 | // set, it returns the max gas from the application consensus params. 7 | // NOTE: see https://github.com/cosmos/cosmos-sdk/issues/9514 for full reference 8 | func BlockGasLimit(ctx sdk.Context) uint64 { 9 | blockGasMeter := ctx.BlockGasMeter() 10 | 11 | // Get the limit from the gas meter only if its not null and not an InfiniteGasMeter 12 | if blockGasMeter != nil && blockGasMeter.Limit() != 0 { 13 | return blockGasMeter.Limit() 14 | } 15 | 16 | // Otherwise get from the consensus parameters 17 | cp := ctx.ConsensusParams() 18 | if cp == nil || cp.Block == nil { 19 | return 0 20 | } 21 | 22 | maxGas := cp.Block.MaxGas 23 | if maxGas > 0 { 24 | return uint64(maxGas) 25 | } 26 | 27 | return 0 28 | } 29 | -------------------------------------------------------------------------------- /types/chain_id.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | "math/big" 6 | "regexp" 7 | "strings" 8 | 9 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 10 | ) 11 | 12 | var ( 13 | regexChainID = `[a-z]*` 14 | regexSeparator = `-{1}` 15 | regexEpoch = `[1-9][0-9]*` 16 | ethermintChainID = regexp.MustCompile(fmt.Sprintf(`^(%s)%s(%s)$`, regexChainID, regexSeparator, regexEpoch)) 17 | ) 18 | 19 | // IsValidChainID returns false if the given chain identifier is incorrectly formatted. 20 | func IsValidChainID(chainID string) bool { 21 | if len(chainID) > 48 { 22 | return false 23 | } 24 | 25 | return ethermintChainID.MatchString(chainID) 26 | } 27 | 28 | // ParseChainID parses a string chain identifier's epoch to an Ethereum-compatible 29 | // chain-id in *big.Int format. The function returns an error if the chain-id has an invalid format 30 | func ParseChainID(chainID string) (*big.Int, error) { 31 | chainID = strings.TrimSpace(chainID) 32 | if len(chainID) > 48 { 33 | return nil, sdkerrors.Wrapf(ErrInvalidChainID, "chain-id '%s' cannot exceed 48 chars", chainID) 34 | } 35 | 36 | matches := ethermintChainID.FindStringSubmatch(chainID) 37 | if matches == nil || len(matches) != 3 || matches[1] == "" { 38 | return nil, sdkerrors.Wrap(ErrInvalidChainID, chainID) 39 | } 40 | 41 | // verify that the chain-id entered is a base 10 integer 42 | chainIDInt, ok := new(big.Int).SetString(matches[2], 10) 43 | if !ok { 44 | return nil, sdkerrors.Wrapf(ErrInvalidChainID, "epoch %s must be base-10 integer format", matches[2]) 45 | } 46 | 47 | return chainIDInt, nil 48 | } 49 | -------------------------------------------------------------------------------- /types/code.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // ---------------------------------------------------------------------------- 4 | // Code 5 | // ---------------------------------------------------------------------------- 6 | 7 | // Code is account Code type alias 8 | type Code []byte 9 | 10 | func (c Code) String() string { 11 | return string(c) 12 | } 13 | -------------------------------------------------------------------------------- /types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 5 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 6 | ) 7 | 8 | // RegisterInterfaces registers the tendermint concrete client-related 9 | // implementations and interfaces. 10 | func RegisterInterfaces(registry codectypes.InterfaceRegistry) { 11 | registry.RegisterImplementations( 12 | (*authtypes.AccountI)(nil), 13 | &EthAccount{}, 14 | ) 15 | registry.RegisterImplementations( 16 | (*authtypes.GenesisAccount)(nil), 17 | &EthAccount{}, 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /types/errors.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 5 | ) 6 | 7 | const ( 8 | // RootCodespace is the codespace for all errors defined in this package 9 | RootCodespace = "ethermint" 10 | ) 11 | 12 | // NOTE: We can't use 1 since that error code is reserved for internal errors. 13 | 14 | var ( 15 | // ErrInvalidValue returns an error resulting from an invalid value. 16 | ErrInvalidValue = sdkerrors.Register(RootCodespace, 2, "invalid value") 17 | 18 | // ErrInvalidChainID returns an error resulting from an invalid chain ID. 19 | ErrInvalidChainID = sdkerrors.Register(RootCodespace, 3, "invalid chain ID") 20 | 21 | // ErrMarshalBigInt returns an error resulting from marshaling a big.Int to a string. 22 | ErrMarshalBigInt = sdkerrors.Register(RootCodespace, 5, "cannot marshal big.Int to string") 23 | 24 | // ErrUnmarshalBigInt returns an error resulting from unmarshaling a big.Int from a string. 25 | ErrUnmarshalBigInt = sdkerrors.Register(RootCodespace, 6, "cannot unmarshal big.Int from string") 26 | ) 27 | -------------------------------------------------------------------------------- /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 | // HDPathIterator 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/params.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // DefaultGasPrice is default gas price for evm transactions 5 | DefaultGasPrice = 20 6 | // DefaultRPCGasLimit is default gas limit for RPC call operations 7 | DefaultRPCGasLimit = 10000000 8 | ) 9 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /types/validation.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "bytes" 5 | 6 | ethcmn "github.com/ethereum/go-ethereum/common" 7 | 8 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 9 | ) 10 | 11 | // IsEmptyHash returns true if the hash corresponds to an empty ethereum hex hash. 12 | func IsEmptyHash(hash string) bool { 13 | return bytes.Equal(ethcmn.HexToHash(hash).Bytes(), ethcmn.Hash{}.Bytes()) 14 | } 15 | 16 | // IsZeroAddress returns true if the address corresponds to an empty ethereum hex address. 17 | func IsZeroAddress(address string) bool { 18 | return bytes.Equal(ethcmn.HexToAddress(address).Bytes(), ethcmn.Address{}.Bytes()) 19 | } 20 | 21 | // ValidateAddress returns an error if the provided string is either not a hex formatted string address 22 | func ValidateAddress(address string) error { 23 | if !ethcmn.IsHexAddress(address) { 24 | return sdkerrors.Wrapf( 25 | sdkerrors.ErrInvalidAddress, "address '%s' is not a valid ethereum hex address", 26 | address, 27 | ) 28 | } 29 | return nil 30 | } 31 | -------------------------------------------------------------------------------- /types/validation_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | ethcmn "github.com/ethereum/go-ethereum/common" 9 | ) 10 | 11 | func TestIsEmptyHash(t *testing.T) { 12 | testCases := []struct { 13 | name string 14 | hash string 15 | expEmpty bool 16 | }{ 17 | { 18 | "empty string", "", true, 19 | }, 20 | { 21 | "zero hash", ethcmn.Hash{}.String(), true, 22 | }, 23 | 24 | { 25 | "non-empty hash", ethcmn.BytesToHash([]byte{1, 2, 3, 4}).String(), false, 26 | }, 27 | } 28 | 29 | for _, tc := range testCases { 30 | require.Equal(t, tc.expEmpty, IsEmptyHash(tc.hash), tc.name) 31 | } 32 | } 33 | 34 | func TestIsZeroAddress(t *testing.T) { 35 | testCases := []struct { 36 | name string 37 | address string 38 | expEmpty bool 39 | }{ 40 | { 41 | "empty string", "", true, 42 | }, 43 | { 44 | "zero address", ethcmn.Address{}.String(), true, 45 | }, 46 | 47 | { 48 | "non-empty address", ethcmn.BytesToAddress([]byte{1, 2, 3, 4}).String(), false, 49 | }, 50 | } 51 | 52 | for _, tc := range testCases { 53 | require.Equal(t, tc.expEmpty, IsZeroAddress(tc.address), tc.name) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /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/evm/atlas/atlas.toml: -------------------------------------------------------------------------------- 1 | [module] 2 | description = "The evm module executes Ethereum Virtual Machine (EVM) state transitions." 3 | homepage = "https://github.com/tharsis/ethermint" 4 | keywords = [ 5 | "evm", 6 | "ethereum", 7 | "ethermint", 8 | ] 9 | 10 | name = "x/evm" 11 | 12 | [bug_tracker] 13 | url = "https://github.com/tharsis/ethermint/issues" 14 | 15 | [[authors]] 16 | name = "fedekunze" 17 | 18 | [[authors]] 19 | name = "austinabell" 20 | 21 | [[authors]] 22 | name = "alexanderbez" 23 | 24 | [[authors]] 25 | name = "noot" 26 | 27 | [[authors]] 28 | name = "araskachoi" 29 | 30 | [version] 31 | documentation = "https://raw.githubusercontent.com/tharsis/ethermint/main/x/evm/atlas/atlas-v0.3.1.md" 32 | repo = "https://github.com/tharsis/ethermint/releases/tag/v0.3.1" 33 | sdk_compat = "v0.39.x" 34 | version = "v0.3.1" -------------------------------------------------------------------------------- /x/evm/client/cli/utils.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/pkg/errors" 8 | 9 | "github.com/ethereum/go-ethereum/common" 10 | 11 | sdk "github.com/cosmos/cosmos-sdk/types" 12 | ) 13 | 14 | func accountToHex(addr string) (string, error) { 15 | if strings.HasPrefix(addr, sdk.GetConfig().GetBech32AccountAddrPrefix()) { 16 | // Check to see if address is Cosmos bech32 formatted 17 | toAddr, err := sdk.AccAddressFromBech32(addr) 18 | if err != nil { 19 | return "", errors.Wrap(err, "must provide a valid Bech32 address") 20 | } 21 | ethAddr := common.BytesToAddress(toAddr.Bytes()) 22 | return ethAddr.Hex(), nil 23 | } 24 | 25 | if !strings.HasPrefix(addr, "0x") { 26 | addr = "0x" + addr 27 | } 28 | 29 | valid := common.IsHexAddress(addr) 30 | if !valid { 31 | return "", fmt.Errorf("%s is not a valid Ethereum or Cosmos address", addr) 32 | } 33 | 34 | ethAddr := common.HexToAddress(addr) 35 | 36 | return ethAddr.Hex(), nil 37 | } 38 | 39 | func formatKeyToHash(key string) string { 40 | if !strings.HasPrefix(key, "0x") { 41 | key = "0x" + key 42 | } 43 | 44 | ethkey := common.HexToHash(key) 45 | 46 | return ethkey.Hex() 47 | } 48 | -------------------------------------------------------------------------------- /x/evm/handler.go: -------------------------------------------------------------------------------- 1 | package evm 2 | 3 | import ( 4 | "runtime/debug" 5 | 6 | log "github.com/xlab/suplog" 7 | 8 | sdk "github.com/cosmos/cosmos-sdk/types" 9 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 10 | 11 | "github.com/tharsis/ethermint/x/evm/types" 12 | ) 13 | 14 | // NewHandler returns a handler for Ethermint type messages. 15 | func NewHandler(server types.MsgServer) sdk.Handler { 16 | return func(ctx sdk.Context, msg sdk.Msg) (result *sdk.Result, err error) { 17 | defer Recover(&err) 18 | 19 | ctx = ctx.WithEventManager(sdk.NewEventManager()) 20 | 21 | switch msg := msg.(type) { 22 | case *types.MsgEthereumTx: 23 | // execute state transition 24 | res, err := server.EthereumTx(sdk.WrapSDKContext(ctx), msg) 25 | return sdk.WrapServiceResult(ctx, res, err) 26 | 27 | default: 28 | err := sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", types.ModuleName, msg) 29 | return nil, err 30 | } 31 | } 32 | } 33 | 34 | func Recover(err *error) { 35 | if r := recover(); r != nil { 36 | *err = sdkerrors.Wrapf(sdkerrors.ErrPanic, "%v", r) 37 | 38 | if e, ok := r.(error); ok { 39 | log.WithError(e).Errorln("evm msg handler panicked with an error") 40 | log.Debugln(string(debug.Stack())) 41 | } else { 42 | log.Errorln(r) 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /x/evm/keeper/abci.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "time" 5 | 6 | abci "github.com/tendermint/tendermint/abci/types" 7 | 8 | "github.com/cosmos/cosmos-sdk/telemetry" 9 | sdk "github.com/cosmos/cosmos-sdk/types" 10 | 11 | ethtypes "github.com/ethereum/go-ethereum/core/types" 12 | "github.com/tharsis/ethermint/x/evm/types" 13 | ) 14 | 15 | // BeginBlock sets the sdk Context and EIP155 chain id to the Keeper. 16 | func (k *Keeper) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { 17 | defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyBeginBlocker) 18 | k.WithContext(ctx) 19 | k.WithChainID(ctx) 20 | } 21 | 22 | // EndBlock also retrieves the bloom filter value from the transient store and commits it to the 23 | // KVStore. The EVM end block logic doesn't update the validator set, thus it returns 24 | // an empty slice. 25 | func (k *Keeper) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.ValidatorUpdate { 26 | defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyEndBlocker) 27 | 28 | // Gas costs are handled within msg handler so costs should be ignored 29 | infCtx := ctx.WithGasMeter(sdk.NewInfiniteGasMeter()) 30 | k.WithContext(infCtx) 31 | 32 | k.SetBlockBloom(infCtx, req.Height, ethtypes.BytesToBloom(k.GetBlockBloomTransient().Bytes())) 33 | k.WithContext(ctx) 34 | 35 | return []abci.ValidatorUpdate{} 36 | } 37 | -------------------------------------------------------------------------------- /x/evm/keeper/params.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | "github.com/tharsis/ethermint/x/evm/types" 7 | ) 8 | 9 | // GetParams returns the total set of evm parameters. 10 | func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) { 11 | k.paramSpace.GetParamSet(ctx, ¶ms) 12 | return params 13 | } 14 | 15 | // SetParams sets the evm parameters to the param space. 16 | func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { 17 | k.paramSpace.SetParamSet(ctx, ¶ms) 18 | } 19 | -------------------------------------------------------------------------------- /x/evm/keeper/params_test.go: -------------------------------------------------------------------------------- 1 | package keeper_test 2 | 3 | import ( 4 | "github.com/tharsis/ethermint/x/evm/types" 5 | ) 6 | 7 | func (suite *KeeperTestSuite) TestParams() { 8 | params := suite.app.EvmKeeper.GetParams(suite.ctx) 9 | suite.Require().Equal(types.DefaultParams(), params) 10 | params.EvmDenom = "inj" 11 | suite.app.EvmKeeper.SetParams(suite.ctx, params) 12 | newParams := suite.app.EvmKeeper.GetParams(suite.ctx) 13 | suite.Require().Equal(newParams, params) 14 | } 15 | -------------------------------------------------------------------------------- /x/evm/spec/03_state_transitions.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # State Transitions 6 | 7 | -------------------------------------------------------------------------------- /x/evm/spec/04_messages.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Messages 6 | 7 | ## MsgEthereumTx 8 | 9 | An EVM state transition can be achieved by using the `MsgEthereumTx`. This message encapsulates an 10 | Ethereum transaction as an SDK message and contains the necessary transaction data fields. 11 | 12 | One remark about the `MsgEthereumTx` is that it implements both the [`sdk.Msg`](https://github.com/cosmos/cosmos-sdk/blob/v0.39.2/types/tx_msg.go#L7-L29) and [`sdk.Tx`](https://github.com/cosmos/cosmos-sdk/blob/v0.39.2/types/tx_msg.go#L33-L41) 13 | interfaces (generally SDK messages only implement the former, while the latter is a group of 14 | messages bundled together). The reason of this, is because the `MsgEthereumTx` must not be included in a [`auth.StdTx`](https://github.com/cosmos/cosmos-sdk/blob/v0.39.2/x/auth/types/stdtx.go#L23-L30) (SDK's standard transaction type) as it performs gas and fee checks using the Ethereum logic from Geth instead of the Cosmos SDK checks done on the `auth` module `AnteHandler`. 15 | 16 | +++ https://github.com/tharsis/ethermint/blob/v0.3.1/x/evm/types/msg.go#L117-L124 17 | 18 | +++ https://github.com/tharsis/ethermint/blob/v0.3.1/x/evm/types/tx_data.go#L12-L29 19 | 20 | This message validation is expected to fail if: 21 | 22 | - `Data.Price` (i.e gas price) is ≤ 0. 23 | - `Data.Amount` is negative 24 | 25 | The transaction execution is expected to fail if: 26 | 27 | - Any of the custom `AnteHandler` Ethereum decorators checks fail: 28 | - Minimum gas amount requirements for transaction 29 | - Tx sender account doesn't exist or hasn't enough balance for fees 30 | - Account sequence doesn't match the transaction `Data.AccountNonce` 31 | - Message signature verification fails 32 | - EVM contract creation (i.e `evm.Create`) fails, or `evm.Call` fails 33 | -------------------------------------------------------------------------------- /x/evm/spec/06_events.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Events 6 | 7 | The EVM module emits the Cosmos SDK [events](./../../../docs/quickstart/events.md#sdk-and-tendermint-events) after a state execution. It can be expected that the type `message`, with an 8 | attribute key of `action` will represent the first event for each message being processed as emitted 9 | by the Cosmos SDK's `Baseapp` (i.e the the basic application that implements Tendermint Core's ABCI 10 | interface). 11 | 12 | ## MsgEthereumTx 13 | 14 | | Type | Attribute Key | Attribute Value | 15 | |-------------|--------------------|-------------------------| 16 | | ethereum_tx | `"amount"` | `{amount}` | 17 | | ethereum_tx | `"recipient"` | `{hex_address}` | 18 | | ethereum_tx | `"contract"` | `{hex_address}` | 19 | | ethereum_tx | `"txHash"` | `{tendermint_hex_hash}` | 20 | | ethereum_tx | `"ethereumTxHash"` | `{hex_hash}` | 21 | | message | `"sender"` | `{eth_address}` | 22 | | message | `"action"` | `"ethereum"` | 23 | | message | `"module"` | `"evm"` | 24 | -------------------------------------------------------------------------------- /x/evm/types/access_list.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | ethcmn "github.com/ethereum/go-ethereum/common" 5 | ethtypes "github.com/ethereum/go-ethereum/core/types" 6 | ) 7 | 8 | // AccessList is an EIP-2930 access list that represents the slice of 9 | // the protobuf AccessTuples. 10 | type AccessList []AccessTuple 11 | 12 | // NewAccessList creates a new protobuf-compatible AccessList from an ethereum 13 | // core AccessList type 14 | func NewAccessList(ethAccessList *ethtypes.AccessList) AccessList { 15 | if ethAccessList == nil { 16 | return nil 17 | } 18 | 19 | al := AccessList{} 20 | for _, tuple := range *ethAccessList { 21 | storageKeys := make([]string, len(tuple.StorageKeys)) 22 | 23 | for i := range tuple.StorageKeys { 24 | storageKeys[i] = tuple.StorageKeys[i].String() 25 | } 26 | 27 | al = append(al, AccessTuple{ 28 | Address: tuple.Address.String(), 29 | StorageKeys: storageKeys, 30 | }) 31 | } 32 | 33 | return al 34 | } 35 | 36 | // ToEthAccessList is an utility function to convert the protobuf compatible 37 | // AccessList to eth core AccessList from go-ethereum 38 | func (al AccessList) ToEthAccessList() *ethtypes.AccessList { 39 | var ethAccessList ethtypes.AccessList 40 | 41 | for _, tuple := range al { 42 | storageKeys := make([]ethcmn.Hash, len(tuple.StorageKeys)) 43 | 44 | for i := range tuple.StorageKeys { 45 | storageKeys[i] = ethcmn.HexToHash(tuple.StorageKeys[i]) 46 | } 47 | 48 | ethAccessList = append(ethAccessList, ethtypes.AccessTuple{ 49 | Address: ethcmn.HexToAddress(tuple.Address), 50 | StorageKeys: storageKeys, 51 | }) 52 | } 53 | 54 | return ðAccessList 55 | } 56 | -------------------------------------------------------------------------------- /x/evm/types/codec_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "testing" 5 | 6 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | type caseAny struct { 11 | name string 12 | any *codectypes.Any 13 | expPass bool 14 | } 15 | 16 | func TestPackTxData(t *testing.T) { 17 | 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/evm/types/errors_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/ethereum/go-ethereum/crypto" 5 | "github.com/status-im/keycard-go/hexutils" 6 | "github.com/stretchr/testify/require" 7 | "testing" 8 | ) 9 | 10 | var revertSelector = crypto.Keccak256([]byte("Error(string)"))[:4] 11 | 12 | func TestNewExecErrorWithReason(t *testing.T) { 13 | 14 | testCases := []struct { 15 | name string 16 | errorMessage string 17 | revertReason []byte 18 | data string 19 | }{ 20 | { 21 | "Empty reason", 22 | "execution reverted", 23 | nil, 24 | "0x", 25 | }, 26 | { 27 | "With unpackable reason", 28 | "execution reverted", 29 | []byte("a"), 30 | "0x61", 31 | }, 32 | { 33 | "With packable reason but empty reason", 34 | "execution reverted", 35 | revertSelector, 36 | "0x08c379a0", 37 | }, 38 | { 39 | "With packable reason with reason", 40 | "execution reverted: COUNTER_TOO_LOW", 41 | hexutils.HexToBytes("08C379A00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000F434F554E5445525F544F4F5F4C4F570000000000000000000000000000000000"), 42 | "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000f434f554e5445525f544f4f5f4c4f570000000000000000000000000000000000", 43 | }, 44 | } 45 | 46 | for _, tc := range testCases { 47 | tc := tc 48 | errWithReason := NewExecErrorWithReason(tc.revertReason) 49 | require.Equal(t, tc.errorMessage, errWithReason.Error()) 50 | require.Equal(t, tc.data, errWithReason.ErrorData()) 51 | require.Equal(t, 3, errWithReason.ErrorCode()) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /x/evm/types/events.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // Evm module events 4 | const ( 5 | EventTypeEthereumTx = TypeMsgEthereumTx 6 | 7 | AttributeKeyContractAddress = "contract" 8 | AttributeKeyRecipient = "recipient" 9 | AttributeKeyTxHash = "txHash" 10 | AttributeKeyEthereumTxHash = "ethereumTxHash" 11 | AttributeKeyTxType = "txType" 12 | // tx failed in eth vm execution 13 | AttributeKeyEthereumTxFailed = "ethereumTxFailed" 14 | AttributeValueCategory = ModuleName 15 | 16 | MetricKeyTransitionDB = "transition_db" 17 | MetricKeyStaticCall = "static_call" 18 | ) 19 | -------------------------------------------------------------------------------- /x/evm/types/params_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | ) 8 | 9 | func TestParamsValidate(t *testing.T) { 10 | testCases := []struct { 11 | name string 12 | params Params 13 | expError bool 14 | }{ 15 | {"default", DefaultParams(), false}, 16 | { 17 | "valid", 18 | NewParams("ara", true, true, DefaultChainConfig(), 2929, 1884, 1344), 19 | false, 20 | }, 21 | { 22 | "empty", 23 | Params{}, 24 | true, 25 | }, 26 | { 27 | "invalid evm denom", 28 | Params{ 29 | EvmDenom: "@!#!@$!@5^32", 30 | }, 31 | true, 32 | }, 33 | { 34 | "invalid eip", 35 | Params{ 36 | EvmDenom: "stake", 37 | ExtraEIPs: []int64{1}, 38 | }, 39 | true, 40 | }, 41 | { 42 | "invalid chain config", 43 | NewParams("ara", true, true, ChainConfig{}, 2929, 1884, 1344), 44 | false, 45 | }, 46 | } 47 | 48 | for _, tc := range testCases { 49 | err := tc.params.Validate() 50 | 51 | if tc.expError { 52 | require.Error(t, err, tc.name) 53 | } else { 54 | require.NoError(t, err, tc.name) 55 | } 56 | } 57 | } 58 | 59 | func TestParamsValidatePriv(t *testing.T) { 60 | require.Error(t, validateEVMDenom(false)) 61 | require.NoError(t, validateEVMDenom("inj")) 62 | require.Error(t, validateBool("")) 63 | require.NoError(t, validateBool(true)) 64 | require.Error(t, validateEIPs("")) 65 | require.NoError(t, validateEIPs([]int64{1884})) 66 | } 67 | -------------------------------------------------------------------------------- /x/evm/types/tx.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // Failed returns if the contract execution failed in vm errors 4 | func (m *MsgEthereumTxResponse) Failed() bool { 5 | return len(m.VmError) > 0 6 | } 7 | --------------------------------------------------------------------------------