├── .clippy.toml ├── .git-blame-ignore-revs ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── question.md ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yml ├── scripts │ ├── install_test_binaries.sh │ └── release-tag-from.js └── workflows │ ├── book.yml │ ├── ci.yml │ └── deps.yml ├── .gitignore ├── CHANGELOG-OLD.md ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── bin ├── release └── run_all_examples ├── book.toml ├── book ├── README.md ├── SUMMARY.md ├── big-numbers │ ├── comparison-and-equivalence.md │ ├── conversion.md │ ├── creating_instances.md │ ├── intro.md │ ├── math-operations.md │ └── utilities.md ├── contracts │ ├── abigen.md │ ├── compile.md │ ├── contracts.md │ ├── creating-instances.md │ ├── deploy-anvil.md │ ├── deploy-from-abi-and-bytecode.md │ ├── doploy-moonbeam.md │ ├── events-with-meta.md │ ├── events.md │ └── methods.md ├── events │ ├── events.md │ └── logs-and-filtering.md ├── getting-started │ ├── connect_to_an_ethereum_node.md │ ├── intro.md │ └── start_a_new_project.md ├── mermaid-style.txt ├── middleware │ ├── builder.md │ ├── custom.md │ ├── gas-escalator.md │ ├── gas-oracle.md │ ├── middleware.md │ ├── nonce-manager.md │ ├── policy.md │ ├── signer.md │ ├── time-lag.md │ └── transformer.md ├── providers │ ├── advanced_usage.md │ ├── custom.md │ ├── http.md │ ├── ipc.md │ ├── mock.md │ ├── providers.md │ ├── quorum.md │ ├── retry.md │ ├── rw.md │ └── ws.md └── subscriptions │ ├── events-by-type.md │ ├── logs.md │ ├── multiple-subscriptions.md │ ├── subscriptions.md │ └── watch-blocks.md ├── cliff.toml ├── deny.toml ├── ethers-addressbook ├── Cargo.toml ├── README.md └── src │ ├── contracts │ └── contracts.json │ └── lib.rs ├── ethers-contract ├── Cargo.toml ├── README.md ├── ethers-contract-abigen │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── contract.rs │ │ ├── contract │ │ ├── errors.rs │ │ ├── events.rs │ │ ├── methods.rs │ │ ├── structs.rs │ │ └── types.rs │ │ ├── filter.rs │ │ ├── lib.rs │ │ ├── multi.rs │ │ ├── source │ │ ├── mod.rs │ │ └── online.rs │ │ ├── test │ │ └── macros.rs │ │ ├── util.rs │ │ └── verbatim.rs ├── ethers-contract-derive │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── abi_ty.rs │ │ ├── abigen.rs │ │ ├── call.rs │ │ ├── calllike.rs │ │ ├── codec.rs │ │ ├── display.rs │ │ ├── eip712.rs │ │ ├── error.rs │ │ ├── event.rs │ │ ├── lib.rs │ │ ├── spanned.rs │ │ └── utils.rs ├── src │ ├── base.rs │ ├── call.rs │ ├── call_core.rs │ ├── contract.rs │ ├── error.rs │ ├── event.rs │ ├── event_core.rs │ ├── factory.rs │ ├── lib.rs │ ├── log.rs │ ├── multicall │ │ ├── constants.rs │ │ ├── contract.rs │ │ ├── error.rs │ │ ├── middleware.rs │ │ ├── mod.rs │ │ └── multicall_abi.json │ └── stream.rs └── tests │ ├── it │ ├── abigen.rs │ ├── common.rs │ ├── contract.rs │ ├── contract_call.rs │ ├── derive.rs │ ├── eip712.rs │ └── main.rs │ └── solidity-contracts │ ├── Abiencoderv2Test.json │ ├── Abiencoderv2Test.sol │ ├── BeefyV1.json │ ├── DeriveEip712Test.json │ ├── DeriveEip712Test.sol │ ├── EventWithStruct.json │ ├── LargeStruct.json │ ├── LargeStructs.json │ ├── MultiInputOutput.json │ ├── MultiInputOutput.sol │ ├── Multicall.json │ ├── Multicall.sol │ ├── NotSoSimpleStorage.json │ ├── NotSoSimpleStorage.sol │ ├── OverloadedFuncs.json │ ├── ReservedWords │ ├── Enum.json │ └── Mod.json │ ├── SimpleRevertingStorage.json │ ├── SimpleRevertingStorage.sol │ ├── SimpleStorage.json │ ├── SimpleStorage.sol │ ├── SlotStorage.json │ ├── SlotStorage.sol │ ├── StructConstructor.json │ ├── StructConstructor.sol │ ├── StructContract.json │ ├── StructContract.sol │ ├── console.json │ ├── draft-IERCPermit.json │ ├── greeter.json │ ├── greeter │ ├── Greeter1.json │ └── Greeter2.json │ ├── greeter_with_struct.json │ ├── large-array.json │ ├── large_tuple.json │ ├── sale.json │ ├── seaport_1_0.json │ ├── seaport_1_1.json │ ├── seaport_1_2.json │ ├── seaport_1_3.json │ ├── verifier_abi.json │ └── verifier_abi_hardhat.json ├── ethers-core ├── Cargo.toml ├── README.md ├── src │ ├── abi │ │ ├── codec.rs │ │ ├── error.rs │ │ ├── human_readable │ │ │ ├── lexer.rs │ │ │ └── mod.rs │ │ ├── mod.rs │ │ ├── packed.rs │ │ ├── raw.rs │ │ ├── struct_def.rs │ │ └── tokens.rs │ ├── lib.rs │ ├── macros │ │ ├── ethers_crate.rs │ │ └── mod.rs │ ├── types │ │ ├── address_or_bytes.rs │ │ ├── block.rs │ │ ├── bytes.rs │ │ ├── chain.rs │ │ ├── ens.rs │ │ ├── fee.rs │ │ ├── filter.rs │ │ ├── i256.rs │ │ ├── log.rs │ │ ├── mod.rs │ │ ├── opcode.rs │ │ ├── other.rs │ │ ├── path_or_string.rs │ │ ├── proof.rs │ │ ├── serde_helpers.rs │ │ ├── signature.rs │ │ ├── syncing.rs │ │ ├── trace │ │ │ ├── example-trace-str.rs │ │ │ ├── example-traces-str.rs │ │ │ ├── filter.rs │ │ │ ├── geth.rs │ │ │ ├── geth │ │ │ │ ├── call.rs │ │ │ │ ├── four_byte.rs │ │ │ │ ├── noop.rs │ │ │ │ ├── pre_state.rs │ │ │ │ └── test_data │ │ │ │ │ ├── call_tracer │ │ │ │ │ ├── default.json │ │ │ │ │ ├── legacy.json │ │ │ │ │ ├── only_top_call.json │ │ │ │ │ └── with_log.json │ │ │ │ │ └── pre_state_tracer │ │ │ │ │ ├── default.json │ │ │ │ │ ├── diff_mode.json │ │ │ │ │ └── legacy.json │ │ │ ├── mod.rs │ │ │ └── parity.rs │ │ ├── transaction │ │ │ ├── eip1559.rs │ │ │ ├── eip2718.rs │ │ │ ├── eip2930.rs │ │ │ ├── eip712.rs │ │ │ ├── mod.rs │ │ │ ├── optimism.rs │ │ │ ├── request.rs │ │ │ └── response.rs │ │ ├── txpool.rs │ │ ├── u256.rs │ │ ├── uint8.rs │ │ └── withdrawal.rs │ └── utils │ │ ├── anvil.rs │ │ ├── ganache.rs │ │ ├── genesis.rs │ │ ├── geth.rs │ │ ├── hash.rs │ │ ├── mod.rs │ │ ├── moonbeam.rs │ │ └── units.rs └── testdata │ ├── proof.json │ ├── proof_empty_key.json │ ├── proof_uint_key.json │ └── solc-obj.json ├── ethers-etherscan ├── Cargo.toml ├── README.md ├── src │ ├── account.rs │ ├── blocks.rs │ ├── contract.rs │ ├── errors.rs │ ├── gas.rs │ ├── lib.rs │ ├── source_tree.rs │ ├── stats.rs │ ├── transaction.rs │ ├── utils.rs │ └── verify.rs └── tests │ └── it │ ├── account.rs │ ├── blocks.rs │ ├── contract.rs │ ├── gas.rs │ ├── main.rs │ ├── stats.rs │ ├── transaction.rs │ ├── verify.rs │ └── version.rs ├── ethers-middleware ├── Cargo.toml ├── README.md ├── contracts │ └── DSProxyFactory.json ├── src │ ├── builder.rs │ ├── gas_escalator │ │ ├── geometric.rs │ │ ├── linear.rs │ │ └── mod.rs │ ├── gas_oracle │ │ ├── blocknative.rs │ │ ├── cache.rs │ │ ├── eth_gas_station.rs │ │ ├── etherchain.rs │ │ ├── etherscan.rs │ │ ├── gas_now.rs │ │ ├── median.rs │ │ ├── middleware.rs │ │ ├── mod.rs │ │ ├── polygon.rs │ │ └── provider_oracle.rs │ ├── lib.rs │ ├── nonce_manager.rs │ ├── policy.rs │ ├── signer.rs │ ├── timelag │ │ └── mod.rs │ └── transformer │ │ ├── ds_proxy │ │ ├── factory.rs │ │ └── mod.rs │ │ ├── middleware.rs │ │ └── mod.rs └── tests │ └── it │ ├── builder.rs │ ├── gas_escalator.rs │ ├── gas_oracle.rs │ ├── main.rs │ ├── nonce_manager.rs │ ├── signer.rs │ ├── stack.rs │ └── transformer.rs ├── ethers-providers ├── Cargo.toml ├── README.md ├── src │ ├── errors.rs │ ├── ext │ │ ├── admin.rs │ │ ├── dev_rpc.rs │ │ ├── ens.rs │ │ ├── erc.rs │ │ └── mod.rs │ ├── lib.rs │ ├── middleware.rs │ ├── rpc │ │ ├── connections.rs │ │ ├── mod.rs │ │ ├── provider.rs │ │ ├── pubsub.rs │ │ └── transports │ │ │ ├── common.rs │ │ │ ├── http.rs │ │ │ ├── ipc.rs │ │ │ ├── legacy_ws.rs │ │ │ ├── mock.rs │ │ │ ├── mod.rs │ │ │ ├── quorum.rs │ │ │ ├── retry.rs │ │ │ ├── rw.rs │ │ │ └── ws │ │ │ ├── backend.rs │ │ │ ├── error.rs │ │ │ ├── manager.rs │ │ │ ├── mod.rs │ │ │ └── types.rs │ ├── stream │ │ ├── mod.rs │ │ ├── tx_stream.rs │ │ └── watcher.rs │ ├── toolbox │ │ ├── call_raw.rs │ │ ├── log_query.rs │ │ ├── mod.rs │ │ ├── pending_escalator.rs │ │ └── pending_transaction.rs │ └── utils.rs └── tests │ └── it │ ├── main.rs │ ├── provider.rs │ ├── txpool.rs │ └── ws_errors.rs ├── ethers-signers ├── Cargo.toml ├── README.md └── src │ ├── aws │ ├── mod.rs │ └── utils.rs │ ├── ledger │ ├── app.rs │ ├── mod.rs │ └── types.rs │ ├── lib.rs │ ├── trezor │ ├── app.rs │ ├── mod.rs │ └── types.rs │ └── wallet │ ├── mnemonic.rs │ ├── mod.rs │ ├── private_key.rs │ └── yubi.rs ├── ethers-solc ├── Cargo.toml ├── README.md ├── benches │ ├── compile_many.rs │ └── read_all.rs ├── src │ ├── artifact_output │ │ ├── configurable.rs │ │ ├── files.rs │ │ └── mod.rs │ ├── artifacts │ │ ├── ast │ │ │ ├── lowfidelity.rs │ │ │ ├── macros.rs │ │ │ ├── misc.rs │ │ │ ├── mod.rs │ │ │ ├── util.rs │ │ │ ├── visitor.rs │ │ │ └── yul.rs │ │ ├── bytecode.rs │ │ ├── contract.rs │ │ ├── mod.rs │ │ ├── output_selection.rs │ │ └── serde_helpers.rs │ ├── buildinfo.rs │ ├── cache.rs │ ├── compile │ │ ├── many.rs │ │ ├── mod.rs │ │ ├── output │ │ │ ├── contracts.rs │ │ │ ├── info.rs │ │ │ ├── mod.rs │ │ │ └── sources.rs │ │ └── project.rs │ ├── config.rs │ ├── error.rs │ ├── filter.rs │ ├── hh.rs │ ├── lib.rs │ ├── project_util │ │ ├── mock.rs │ │ └── mod.rs │ ├── remappings.rs │ ├── report │ │ ├── compiler.rs │ │ └── mod.rs │ ├── resolver │ │ ├── mod.rs │ │ ├── parse.rs │ │ └── tree.rs │ ├── sourcemap.rs │ └── utils.rs ├── test-data │ ├── 0.6.12-with-libs.json │ ├── ast │ │ ├── abstract_contract.json │ │ ├── address_payable.json │ │ ├── array_type_name.json │ │ ├── ast-erc4626.json │ │ ├── base_constructor_call.json │ │ ├── bit_not.json │ │ ├── call.json │ │ ├── constructor.json │ │ ├── contract_dep_order.json │ │ ├── documentation_1.json │ │ ├── documentation_2.json │ │ ├── documentation_3.json │ │ ├── documentation_local_variable.json │ │ ├── documentation_on_statements.json │ │ ├── documentation_triple.json │ │ ├── empty_block.json │ │ ├── enum_value.json │ │ ├── enum_value_declaration.json │ │ ├── event_definition.json │ │ ├── fallback.json │ │ ├── fallback_and_reveice_ether.json │ │ ├── fallback_payable.json │ │ ├── function.json │ │ ├── function_type.json │ │ ├── global_enum.json │ │ ├── global_struct.json │ │ ├── inheritance_specifier.json │ │ ├── leave.json │ │ ├── license.json │ │ ├── long_type_name_binary_operation.json │ │ ├── long_type_name_identifier.json │ │ ├── loop.json │ │ ├── mappings.json │ │ ├── modifier_definition.json │ │ ├── modifier_invocation.json │ │ ├── mutability.json │ │ ├── nested_functions.json │ │ ├── non_utf8.json │ │ ├── override.json │ │ ├── placeholder_statement.json │ │ ├── receive_ether.json │ │ ├── short_type_name.json │ │ ├── short_type_name_ref.json │ │ ├── slot_offset.json │ │ ├── smoke.json │ │ ├── source_location.json │ │ ├── string.json │ │ ├── stringlit.json │ │ ├── switch.json │ │ ├── switch_default.json │ │ ├── two_base_functions.json │ │ ├── unicode.json │ │ ├── used_errors.json │ │ ├── userDefinedValueType.json │ │ ├── using_for_directive.json │ │ ├── var_access.json │ │ └── yul_hex_literal.json │ ├── bytes.sol │ ├── cache-sample │ │ ├── Dapp.sol │ │ └── NewContract.sol │ ├── cheatcodes.sol-sourcemap.txt │ ├── dapp-sample │ │ ├── lib │ │ │ └── ds-test │ │ │ │ ├── demo │ │ │ │ └── demo.sol │ │ │ │ └── src │ │ │ │ └── test.sol │ │ └── src │ │ │ ├── Dapp.sol │ │ │ └── Dapp.t.sol │ ├── foundryissue2462.json │ ├── hardhat-sample │ │ ├── contracts │ │ │ └── Greeter.sol │ │ └── node_modules │ │ │ └── hardhat │ │ │ └── console.sol │ ├── hh-greeter-artifact.json │ ├── in │ │ ├── compiler-in-1.json │ │ ├── compiler-in-10.json │ │ ├── compiler-in-11.json │ │ ├── compiler-in-12.json │ │ ├── compiler-in-13.json │ │ ├── compiler-in-14.json │ │ ├── compiler-in-15.json │ │ ├── compiler-in-16.json │ │ ├── compiler-in-17.json │ │ ├── compiler-in-18.json │ │ ├── compiler-in-19.json │ │ ├── compiler-in-2.json │ │ ├── compiler-in-20.json │ │ ├── compiler-in-21.json │ │ ├── compiler-in-22.json │ │ ├── compiler-in-23.json │ │ ├── compiler-in-3.json │ │ ├── compiler-in-4.json │ │ ├── compiler-in-5.json │ │ ├── compiler-in-6.json │ │ ├── compiler-in-7.json │ │ ├── compiler-in-8.json │ │ └── compiler-in-9.json │ ├── library-remapping-in-2.json │ ├── library-remapping-in.json │ ├── model-checker-sample │ │ └── Assert.sol │ ├── out-source-maps.txt │ ├── out │ │ ├── compiler-out-1.json │ │ ├── compiler-out-10.json │ │ ├── compiler-out-11.json │ │ ├── compiler-out-12.json │ │ ├── compiler-out-13.json │ │ ├── compiler-out-14.json │ │ ├── compiler-out-15.json │ │ ├── compiler-out-16.json │ │ ├── compiler-out-17.json │ │ ├── compiler-out-2.json │ │ ├── compiler-out-3.json │ │ ├── compiler-out-4.json │ │ ├── compiler-out-5.json │ │ ├── compiler-out-6.json │ │ ├── compiler-out-7.json │ │ ├── compiler-out-8.json │ │ └── compiler-out-9.json │ ├── solidity-files-cache.json │ ├── test-contract-libs │ │ ├── lib1 │ │ │ └── bar │ │ │ │ └── src │ │ │ │ └── Bar.sol │ │ ├── lib2 │ │ │ └── baz │ │ │ │ └── src │ │ │ │ └── Baz.sol │ │ └── src │ │ │ └── Foo.sol │ ├── test-contract-remappings │ │ ├── lib │ │ │ └── bar │ │ │ │ └── src │ │ │ │ └── Bar.sol │ │ └── src │ │ │ └── Foo.sol │ ├── test-contract-versions │ │ ├── caret-0.4.14.sol │ │ ├── greater-equal-0.5.0.sol │ │ ├── pinned-0.4.14.sol │ │ ├── range-0.5.0.sol │ │ └── simple-0.4.14.sol │ ├── test-contract-warnings │ │ └── LicenseWarning.sol │ ├── test-flatten-duplicates │ │ └── contracts │ │ │ ├── Bar.sol │ │ │ ├── Foo.sol │ │ │ └── FooBar.sol │ ├── test-flatten-solang-failure │ │ └── contracts │ │ │ ├── Contract.sol │ │ │ └── Lib.sol │ ├── test-versioned-linkrefs │ │ ├── lib │ │ │ └── Lib.sol │ │ └── src │ │ │ ├── FooV1.sol │ │ │ └── FooV2.sol │ └── yul-sample │ │ ├── Dapp.sol │ │ └── SimpleStore.yul └── tests │ ├── mocked.rs │ └── project.rs ├── ethers ├── Cargo.toml └── src │ └── lib.rs ├── examples ├── README.md ├── anvil │ ├── Cargo.toml │ ├── README.md │ └── examples │ │ └── anvil_fork.rs ├── big-numbers │ ├── Cargo.toml │ ├── README.md │ └── examples │ │ ├── comparison_equivalence.rs │ │ ├── conversion.rs │ │ ├── create_instances.rs │ │ ├── math_operations.rs │ │ └── utilities.rs ├── contracts │ ├── Cargo.toml │ ├── README.md │ └── examples │ │ ├── abi │ │ ├── IERC20.json │ │ └── contract_abi.json │ │ ├── abigen.rs │ │ ├── compile.rs │ │ ├── contracts │ │ └── contract.sol │ │ ├── deploy_anvil.rs │ │ ├── deploy_from_abi_and_bytecode.rs │ │ ├── deploy_from_solidity.rs │ │ ├── deploy_moonbeam.rs │ │ ├── events.rs │ │ ├── events_with_meta.rs │ │ ├── instances.rs │ │ ├── methods.rs │ │ └── methods_abi_and_structs.rs ├── events │ ├── Cargo.toml │ ├── README.md │ └── examples │ │ ├── filtering.rs │ │ ├── placeholder.rs │ │ └── subscribe.rs ├── geth │ ├── Cargo.toml │ └── examples │ │ └── clique.rs ├── middleware │ ├── Cargo.toml │ ├── README.md │ └── examples │ │ ├── builder.rs │ │ ├── create_custom_middleware.rs │ │ ├── gas_escalator.rs │ │ ├── gas_oracle.rs │ │ ├── nonce_manager.rs │ │ ├── policy.rs │ │ ├── signer.rs │ │ ├── timelag.rs │ │ └── transformer.rs ├── providers │ ├── Cargo.toml │ ├── README.md │ └── examples │ │ ├── custom.rs │ │ ├── http.rs │ │ ├── http_jwt.rs │ │ ├── ipc.rs │ │ ├── mock.rs │ │ ├── quorum.rs │ │ ├── retry.rs │ │ ├── rw.rs │ │ └── ws.rs ├── queries │ ├── Cargo.toml │ ├── README.md │ └── examples │ │ ├── paginated_logs.rs │ │ └── uniswapv2_pair.rs ├── subscriptions │ ├── Cargo.toml │ ├── README.md │ └── examples │ │ ├── subscribe_blocks.rs │ │ ├── subscribe_events_by_type.rs │ │ └── subscribe_logs.rs ├── transactions │ ├── Cargo.toml │ ├── README.md │ └── examples │ │ ├── call_override.rs │ │ ├── contracts │ │ └── erc20_example │ │ │ ├── @openzeppelin │ │ │ └── contracts │ │ │ │ ├── README.md │ │ │ │ ├── token │ │ │ │ └── ERC20 │ │ │ │ │ ├── ERC20.sol │ │ │ │ │ ├── IERC20.sol │ │ │ │ │ └── extensions │ │ │ │ │ └── IERC20Metadata.sol │ │ │ │ └── utils │ │ │ │ └── Context.sol │ │ │ └── ERC20Example.sol │ │ ├── decode_input.rs │ │ ├── ens.rs │ │ ├── gas_price_usd.rs │ │ ├── remove_liquidity.rs │ │ ├── trace_call.rs │ │ ├── trace_transaction.rs │ │ ├── transfer_erc20.rs │ │ └── transfer_eth.rs ├── wallets │ ├── Cargo.toml │ ├── README.md │ └── examples │ │ ├── ledger.rs │ │ ├── local_signer.rs │ │ ├── mnemonic.rs │ │ ├── permit_hash.rs │ │ ├── sign_message.rs │ │ ├── trezor.rs │ │ └── yubi.rs └── wasm │ ├── .gitignore │ ├── Cargo.toml │ ├── LICENSE-APACHE │ ├── LICENSE-MIT │ ├── README.md │ ├── abi │ └── contract.json │ ├── index.html │ ├── index.js │ ├── package.json │ ├── src │ ├── lib.rs │ └── utils.rs │ ├── tests │ └── contract_with_abi.rs │ ├── webpack.config.js │ └── yarn.lock ├── flake.lock ├── flake.nix ├── release.toml ├── rustfmt.toml └── testdata ├── SimpleStorage.json ├── the_dao_abi.expr └── uniswap ├── IERC20.sol └── UniswapExchange.sol /.clippy.toml: -------------------------------------------------------------------------------- 1 | msrv = "1.65" 2 | -------------------------------------------------------------------------------- /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # Since version 2.23 (released in August 2019), git-blame has a feature 2 | # to ignore or bypass certain commits. 3 | # 4 | # This file contains a list of commits that are not likely what you 5 | # are looking for in a blame, such as mass reformatting or renaming. 6 | # You can set this file as a default ignore file for blame by running 7 | # the following command. 8 | # 9 | # $ git config blame.ignoreRevsFile .git-blame-ignore-revs 10 | 11 | # chore: add rustfmt.toml (#537) 12 | dcf20022c66921779059bbfc58f5d378d20b84be 13 | 14 | # fmt: all (#1751) 15 | 5c762c44d760ed9dad3900be079062174ada0245 16 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | Cargo.lock linguist-generated=true 2 | flake.lock linguist-generated=true 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "" 5 | labels: bug 6 | assignees: "" 7 | --- 8 | 9 | **Version** 10 | List the versions of all `ethers-rs` crates you are using. The easiest way to get 11 | this information is using `cargo-tree`. 12 | 13 | `cargo install cargo-tree` 14 | (see install here: https://github.com/sfackler/cargo-tree) 15 | 16 | Then: 17 | 18 | `cargo tree | grep ethers` 19 | 20 | **Platform** 21 | The output of `uname -a` (UNIX), or version and 32 or 64-bit (Windows) 22 | 23 | **Description** 24 | Enter your issue details here. 25 | One way to structure the description: 26 | 27 | [short summary of the bug] 28 | 29 | I tried this code: 30 | 31 | [code sample that causes the bug] 32 | 33 | I expected to see this happen: [explanation] 34 | 35 | Instead, this happened: [explanation] 36 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "" 5 | labels: feature-request 6 | assignees: "" 7 | --- 8 | 9 | **Is your feature request related to a problem? Please describe.** 10 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 11 | 12 | **Describe the solution you'd like** 13 | A clear and concise description of what you want to happen. 14 | 15 | **Describe alternatives you've considered** 16 | A clear and concise description of any alternative solutions or features you've considered. 17 | 18 | **Additional context** 19 | Add any other context or screenshots about the feature request here. 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: Please use the Telegram group for questions 4 | title: "" 5 | labels: "" 6 | assignees: "" 7 | --- 8 | 9 | Please post your question as a discussion in Telegram: https://t.me/ethers_rs 10 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 12 | 13 | ## Motivation 14 | 15 | 20 | 21 | ## Solution 22 | 23 | 27 | 28 | ## PR Checklist 29 | 30 | - [ ] Added Tests 31 | - [ ] Added Documentation 32 | - [ ] Breaking changes 33 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: cargo 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "03:00" 8 | open-pull-requests-limit: 10 9 | -------------------------------------------------------------------------------- /.github/scripts/release-tag-from.js: -------------------------------------------------------------------------------- 1 | const semver = require("semver"); 2 | 3 | const previousVersion = (currentVersion, releaseType) => { 4 | const parsedVersion = semver.parse(currentVersion); 5 | 6 | switch (releaseType) { 7 | case "major": { 8 | return `v${parsedVersion.major - 1}.0.0`; 9 | } 10 | case "minor": { 11 | return `v${parsedVersion.major}.${parsedVersion.minor - 1}.0`; 12 | } 13 | case "patch": { 14 | return `v${parsedVersion.major}.${parsedVersion.minor}.${parsedVersion.patch - 1}`; 15 | } 16 | case "alpha": { 17 | return `v${parsedVersion.major}.${parsedVersion.minor}.${parsedVersion.patch}-alpha.${ 18 | parsedVersion.prerelease[1] - 1 19 | }`; 20 | } 21 | case "beta": { 22 | return `v${parsedVersion.major}.${parsedVersion.minor}.${parsedVersion.patch}-beta.${ 23 | parsedVersion.prerelease[1] - 1 24 | }`; 25 | } 26 | case "rc": { 27 | return `v${parsedVersion.major}.${parsedVersion.minor}.${parsedVersion.patch}-rc.${ 28 | parsedVersion.prerelease[1] - 1 29 | }`; 30 | } 31 | } 32 | }; 33 | 34 | const [currentVersion, releaseType] = process.argv.slice(-2); 35 | console.log(previousVersion(currentVersion, releaseType)); 36 | -------------------------------------------------------------------------------- /.github/workflows/deps.yml: -------------------------------------------------------------------------------- 1 | name: deps 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | branches: [master] 8 | schedule: [cron: "00 00 * * *"] 9 | 10 | jobs: 11 | cargo-deny: 12 | name: cargo deny check 13 | runs-on: ubuntu-latest 14 | timeout-minutes: 30 15 | steps: 16 | - uses: actions/checkout@v3 17 | - uses: EmbarkStudios/cargo-deny-action@v1 18 | with: 19 | command: check all 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | 4 | .vscode 5 | /.envrc 6 | .idea 7 | .nlsp-settings 8 | .devenv* 9 | devenv.local.nix 10 | .direnv 11 | .pre-commit-config.yaml 12 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 Georgios Konstantopoulos 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /bin/run_all_examples: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e; # Fail fast 4 | # shellcheck shell=bash 5 | 6 | # examples that we can't run because they require some additional infra, docker or ledger for example 7 | ignored=( 8 | "examples-contracts:deploy_moonbeam" 9 | "examples-providers:ipc" 10 | "examples-wallets:ledger" 11 | "examples-wallets:trezor" 12 | "examples-wallets:yubi" 13 | "examples-transactions:remove_liquidity" 14 | ) 15 | 16 | example_crates=$(cargo metadata --format-version 1 | 17 | jq -c '.workspace_members' | 18 | jq -r 'map(select(startswith("examples")) | 19 | sub("\\s.*$";"")) | .[]') 20 | 21 | # First build all examples, then run them individually 22 | for crate in $example_crates; do 23 | echo "building $crate" 24 | cargo build -p "$crate" --examples 25 | done 26 | 27 | for crate in $example_crates; do 28 | # Remove "examples-" prefix from crate name (e.g. examples-contracts => contracts) 29 | cratedir="${crate#examples-}" 30 | srcdir="examples/$cratedir/examples" 31 | # Retrieve all example files in crate: 32 | # Transform the absolute path into the filename (e.g. some-path/deploy_anvil.rs => deploy_anvil) 33 | example_files=$(find "$srcdir" -type f -name '*.rs' -exec basename {} \; | sed 's/\.[^.]*$//') 34 | 35 | for file in $example_files; do 36 | # Run the example 37 | if [[ "${ignored[*]}" =~ $(basename "$crate:$file") ]]; then 38 | echo "skipping: $crate:$file" 39 | continue 40 | fi 41 | echo "running $crate:$file" 42 | cargo run -p "$crate" --example "$file" 43 | done 44 | done 45 | -------------------------------------------------------------------------------- /book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | authors = ["The ethers-rs contributors"] 3 | language = "en" 4 | multilingual = false 5 | src = "book" 6 | title = "Ethers.rs: The Ethereum Library for Rust" 7 | description = "A book on all things ethers-rs" 8 | 9 | [output.html] 10 | git-repository-url = "https://github.com/gakonst/ethers-rs" 11 | default-theme = "ayu" 12 | no-section-label = true 13 | 14 | [output.html.fold] 15 | enable = true 16 | level = 1 17 | 18 | [build] 19 | build-dir = "target/book" 20 | 21 | [preprocessor.template] 22 | before = [ "links" ] 23 | 24 | [preprocessor.index] 25 | 26 | [preprocessor.links] 27 | 28 | -------------------------------------------------------------------------------- /book/README.md: -------------------------------------------------------------------------------- 1 | # The ethers-rs book 2 | 3 | Everything about `ethers-rs`. Work-in-progress. View online here: 4 | 5 | ## Contributing 6 | 7 | The book is built with [mdbook](https://github.com/rust-lang/mdBook), which you can install by running `cargo install mdbook`. 8 | 9 | To view changes live, run: 10 | 11 | ```sh 12 | mdbook serve 13 | ``` 14 | 15 | Or with docker: 16 | 17 | ```sh 18 | docker run -p 3000:3000 -v `pwd`:/book peaceiris/mdbook serve 19 | ``` 20 | 21 | To add a new section (file) to the book, add it to [`SUMMARY.md`](./SUMMARY.md). 22 | -------------------------------------------------------------------------------- /book/big-numbers/comparison-and-equivalence.md: -------------------------------------------------------------------------------- 1 | 2 | # Comparison and equivalence 3 | 4 | ```rust 5 | {{#include ../../examples/big-numbers/examples/comparison_equivalence.rs}} 6 | ``` 7 | -------------------------------------------------------------------------------- /book/big-numbers/conversion.md: -------------------------------------------------------------------------------- 1 | # Conversion 2 | 3 | ```rust 4 | {{#include ../../examples/big-numbers/examples/conversion.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /book/big-numbers/creating_instances.md: -------------------------------------------------------------------------------- 1 | # Creating instances 2 | 3 | ```rust 4 | {{#include ../../examples/big-numbers/examples/create_instances.rs}} 5 | ``` -------------------------------------------------------------------------------- /book/big-numbers/intro.md: -------------------------------------------------------------------------------- 1 | {{#include ../../examples/big-numbers/README.md}} 2 | -------------------------------------------------------------------------------- /book/big-numbers/math-operations.md: -------------------------------------------------------------------------------- 1 | # Math operations 2 | 3 | ```rust 4 | {{#include ../../examples/big-numbers/examples/math_operations.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /book/big-numbers/utilities.md: -------------------------------------------------------------------------------- 1 | # Utilities 2 | 3 | ```rust 4 | {{#include ../../examples/big-numbers/examples/utilities.rs}} 5 | ``` -------------------------------------------------------------------------------- /book/contracts/abigen.md: -------------------------------------------------------------------------------- 1 | # Abigen 2 | 3 | ```rust 4 | {{#include ../../examples/contracts/examples/abigen.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /book/contracts/compile.md: -------------------------------------------------------------------------------- 1 | # Compile 2 | 3 | ```rust 4 | {{#include ../../examples/contracts/examples/compile.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /book/contracts/creating-instances.md: -------------------------------------------------------------------------------- 1 | # Creating Instances 2 | 3 | ```rust 4 | {{#include ../../examples/contracts/examples/instances.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /book/contracts/deploy-anvil.md: -------------------------------------------------------------------------------- 1 | # Deploy Anvil 2 | 3 | ```rust 4 | {{#include ../../examples/contracts/examples/deploy_anvil.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /book/contracts/deploy-from-abi-and-bytecode.md: -------------------------------------------------------------------------------- 1 | # Deploying a Contract from ABI and Bytecode 2 | 3 | ```rust 4 | {{#include ../../examples/contracts/examples/deploy_from_abi_and_bytecode.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /book/contracts/doploy-moonbeam.md: -------------------------------------------------------------------------------- 1 | # Deploy Moonbeam 2 | 3 | ```rust 4 | {{#include ../../examples/contracts/examples/deploy_moonbeam.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /book/contracts/events-with-meta.md: -------------------------------------------------------------------------------- 1 | # Events with meta 2 | 3 | ```rust 4 | {{#include ../../examples/contracts/examples/events_with_meta.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /book/contracts/events.md: -------------------------------------------------------------------------------- 1 | # Events 2 | 3 | ```rust 4 | {{#include ../../examples/contracts/examples/events.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /book/contracts/methods.md: -------------------------------------------------------------------------------- 1 | # Methods 2 | 3 | ```rust 4 | {{#include ../../examples/contracts/examples/methods.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /book/events/logs-and-filtering.md: -------------------------------------------------------------------------------- 1 | # Logs and filtering 2 | 3 | ```rust 4 | {{#include ../../examples/events/examples/filtering.rs}} 5 | {{#include ../../examples/events/examples/subscribe.rs}} 6 | ``` 7 | -------------------------------------------------------------------------------- /book/getting-started/connect_to_an_ethereum_node.md: -------------------------------------------------------------------------------- 1 | # Connect to an Ethereum node 2 | 3 | Ethers-rs allows application to connect the blockchain using web3 providers. Providers act as an interface between applications and an Ethereum node, allowing you to send requests and receive responses via JSON-RPC messages. 4 | 5 | Some common actions you can perform using a provider include: 6 | 7 | - Getting the current block number 8 | - Getting the balance of an Ethereum address 9 | - Sending a transaction to the blockchain 10 | - Calling a smart contract function 11 | - Subscribe logs and smart contract events 12 | - Getting the transaction history of an address 13 | 14 | Providers are an important part of web3 libraries because they allow you to easily interact with the Ethereum blockchain without having to manage the underlying connection to the node yourself. 15 | 16 | Code below shows a basic setup to connect a provider to a node: 17 | 18 | ```rust 19 | // The `prelude` module provides a convenient way to import a number 20 | // of common dependencies at once. This can be useful if you are working 21 | // with multiple parts of the library and want to avoid having 22 | // to import each dependency individually. 23 | use ethers::prelude::*; 24 | 25 | const RPC_URL: &str = "https://eth.llamarpc.com"; 26 | 27 | #[tokio::main] 28 | async fn main() -> Result<(), Box> { 29 | let provider = Provider::::try_from(RPC_URL)?; 30 | let block_number: U64 = provider.get_block_number().await?; 31 | println!("{block_number}"); 32 | 33 | Ok(()) 34 | } 35 | ``` 36 | -------------------------------------------------------------------------------- /book/getting-started/intro.md: -------------------------------------------------------------------------------- 1 | # Intro 2 | 3 | Welcome to the hands-on guide for the ethers-rs library! 4 | 5 | This documentation contains a collection of examples demonstrating how to use the library to build Ethereum-based applications in Rust. The examples cover a range of topics, from basic smart contract interactions to more advanced usage of ethers-rs. 6 | 7 | ```admonish info 8 | You can find the official ethers-rs documentation on docs.rs - [here](https://docs.rs/ethers/0.5.0/ethers/). 9 | ``` 10 | 11 | Each example includes a detailed description of the functionality being demonstrated, as well as complete code snippets that you can use as a starting point for your own projects. 12 | 13 | We hope that these docs will help you get started with ethers-rs and give you a better understanding of how to use the library to build your own web3 applications in Rust. If you have any questions or need further assistance, please don't hesitate to reach out to the ethers-rs community. 14 | 15 | The following is a brief overview diagram of the topics covered in this guide. 16 | 17 | ```mermaid 18 | {{#include ../mermaid-style.txt}} 19 | 20 | graph LR 21 | A[Ethers-rs
Manual] --> A1[Providers] 22 | A --> A2[Middleware] 23 | A --> A3[Contracts] 24 | A --> A4[Events] 25 | A --> A5[Subscriptions] 26 | A --> A6[Queries] 27 | A --> A7[Transactions] 28 | A --> A8[Wallets] 29 | A --> A9[Big numbers] 30 | A --> A10[Anvil] 31 | ``` 32 | 33 | ```admonish bug 34 | This diagram is incomplete and will undergo continuous changes. 35 | ``` 36 | -------------------------------------------------------------------------------- /book/mermaid-style.txt: -------------------------------------------------------------------------------- 1 | %%{ 2 | init: { 3 | 'theme':'dark', 4 | 'themeVariables': { 5 | 'textColor':' #ffffff', 6 | 'nodeBorder':'#ff2d00', 7 | 'edgeLabelBackground':'#00000', 8 | 'lineColor':'#87ff00', 9 | 'fontSize':'14px', 10 | 'curve':'linear' 11 | } 12 | } 13 | }%% -------------------------------------------------------------------------------- /book/middleware/builder.md: -------------------------------------------------------------------------------- 1 | # Middleware builder 2 | 3 | ```rust 4 | {{#include ../../examples/middleware/examples/builder.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /book/middleware/custom.md: -------------------------------------------------------------------------------- 1 | # Create custom middleware 2 | 3 | ```rust 4 | {{#include ../../examples/middleware/examples/create_custom_middleware.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /book/middleware/gas-escalator.md: -------------------------------------------------------------------------------- 1 | # Gas escalator 2 | 3 | ```rust 4 | {{#include ../../examples/middleware/examples/gas_escalator.rs}} 5 | ``` -------------------------------------------------------------------------------- /book/middleware/gas-oracle.md: -------------------------------------------------------------------------------- 1 | # Gas oracle 2 | 3 | ```rust 4 | {{#include ../../examples/middleware/examples/gas_oracle.rs}} 5 | ``` -------------------------------------------------------------------------------- /book/middleware/nonce-manager.md: -------------------------------------------------------------------------------- 1 | # Nonce manager 2 | 3 | ```rust 4 | {{#include ../../examples/middleware/examples/nonce_manager.rs}} 5 | ``` -------------------------------------------------------------------------------- /book/middleware/policy.md: -------------------------------------------------------------------------------- 1 | # Policy middleware 2 | 3 | ```rust 4 | {{#include ../../examples/middleware/examples/policy.rs}} 5 | ``` -------------------------------------------------------------------------------- /book/middleware/signer.md: -------------------------------------------------------------------------------- 1 | # Signer 2 | 3 | ```rust 4 | {{#include ../../examples/middleware/examples/signer.rs}} 5 | ``` -------------------------------------------------------------------------------- /book/middleware/time-lag.md: -------------------------------------------------------------------------------- 1 | # Time lag 2 | 3 | TODO -------------------------------------------------------------------------------- /book/middleware/transformer.md: -------------------------------------------------------------------------------- 1 | # Transformer 2 | 3 | TODO -------------------------------------------------------------------------------- /book/providers/custom.md: -------------------------------------------------------------------------------- 1 | # Custom data transport 2 | 3 | As [we've previously seen](./providers.md#data-transports), a transport must implement [`JsonRpcClient`](https://docs.rs/ethers/latest/ethers/providers/trait.JsonRpcClient.html), and can also optionally implement [`PubsubClient`](https://docs.rs/ethers/latest/ethers/providers/trait.PubsubClient.html). 4 | 5 | Let's see how we can create a custom data transport by implementing one that stores either a `Ws` or an `Ipc` transport: 6 | 7 | ```rust 8 | {{#include ../../examples/providers/examples/custom.rs}} 9 | ``` 10 | -------------------------------------------------------------------------------- /book/providers/ipc.md: -------------------------------------------------------------------------------- 1 | # IPC provider 2 | 3 | The [IPC (Inter-Process Communication)](https://en.wikipedia.org/wiki/Inter-process_communication) transport allows our program to communicate with a node over a local [Unix domain socket](https://en.wikipedia.org/wiki/Unix_domain_socket) or [Windows named pipe](https://learn.microsoft.com/en-us/windows/win32/ipc/named-pipes). 4 | 5 | Using the IPC transport allows the ethers library to send JSON-RPC requests to the Ethereum client and receive responses, without the need for a network connection or HTTP server. This can be useful for interacting with a local Ethereum node that is running on the same network. Using IPC [is faster than RPC](https://github.com/0xKitsune/geth-ipc-rpc-bench), however you will need to have a local node that you can connect to. 6 | 7 | ## Initializing an Ipc Provider 8 | 9 | Below is an example of how to initialize a new Ipc provider. 10 | 11 | ```rust 12 | use ethers::providers::Provider; 13 | 14 | #[tokio::main] 15 | async fn main() -> eyre::Result<()> { 16 | // Using a UNIX domain socket: `/path/to/ipc` 17 | #[cfg(unix)] 18 | let provider = Provider::connect_ipc("~/.ethereum/geth.ipc").await?; 19 | 20 | // Using a Windows named pipe: `\\\pipe\` 21 | #[cfg(windows)] 22 | let provider = Provider::connect_ipc(r"\\.\pipe\geth").await?; 23 | 24 | Ok(()) 25 | } 26 | ``` 27 | 28 | ## Usage 29 | 30 | The `Ipc` provider implements both `JsonRpcClient` and `PubsubClient`, just like `Ws`. 31 | 32 | In this example, we monitor the [`WETH/USDC`](https://etherscan.io/address/0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc) [UniswapV2](https://docs.uniswap.org/) pair reserves and print when they have changed. 33 | 34 | ```rust 35 | {{#include ../../examples/providers/examples/ipc.rs}} 36 | ``` 37 | -------------------------------------------------------------------------------- /book/providers/mock.md: -------------------------------------------------------------------------------- 1 | # Mock provider 2 | 3 | ```rust 4 | {{#include ../../examples/providers/examples/mock.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /book/providers/quorum.md: -------------------------------------------------------------------------------- 1 | # Quorum provider 2 | 3 | ```rust 4 | {{#include ../../examples/providers/examples/quorum.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /book/providers/retry.md: -------------------------------------------------------------------------------- 1 | # Retry client 2 | 3 | ```rust 4 | {{#include ../../examples/providers/examples/retry.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /book/providers/rw.md: -------------------------------------------------------------------------------- 1 | # RW provider 2 | 3 | ```rust 4 | {{#include ../../examples/providers/examples/rw.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /book/subscriptions/events-by-type.md: -------------------------------------------------------------------------------- 1 | # Subscribe events by type 2 | 3 | ```rust 4 | {{#include ../../examples/subscriptions/examples/subscribe_events_by_type.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /book/subscriptions/logs.md: -------------------------------------------------------------------------------- 1 | # Subscribing to Logs 2 | 3 | To subscribe to logs, create a Filter object that specifies the criteria for the logs you want to listen to. Then, pass the filter to the Provider's subscribe_logs method: 4 | 5 | ```rust 6 | async fn main() -> Result<(), Box> { 7 | let provider = Provider::::try_from("http://localhost:8545")?; 8 | 9 | let filter = Filter::new().address("0xcontract_address_here".parse()?); 10 | 11 | let mut stream = provider.subscribe_logs(filter).await?; 12 | 13 | // Your code to handle logs goes here. 14 | 15 | Ok(()) 16 | 17 | } 18 | ``` 19 | 20 | You can now listen to logs that match your filter criteria: 21 | 22 | ```rust 23 | while let Some(log) = stream.next().await { 24 | match log { 25 | Ok(log) => { 26 | println!("New log: {:?}", log); 27 | } 28 | Err(e) => { 29 | eprintln!("Error: {:?}", e); 30 | } 31 | } 32 | } 33 | ``` 34 | 35 | Here is another example of subscribing to logs: 36 | 37 | ```rust 38 | {{#include ../../examples/subscriptions/examples/subscribe_logs.rs}} 39 | ``` 40 | -------------------------------------------------------------------------------- /book/subscriptions/watch-blocks.md: -------------------------------------------------------------------------------- 1 | # Subscribing to New Blocks 2 | 3 | To subscribe to new blocks, create a Provider instance and call the subscribe_blocks method: 4 | 5 | ```rust 6 | async fn main() -> Result<(), Box> { 7 | let provider = Provider::::try_from("http://localhost:8545")?; 8 | 9 | let mut stream = provider.subscribe_blocks().await?; 10 | 11 | // Your code to handle new blocks goes here. 12 | 13 | Ok(()) 14 | 15 | } 16 | ``` 17 | 18 | You can now listen to new blocks as they are mined: 19 | 20 | ```rust 21 | while let Some(block) = stream.next().await { 22 | match block { 23 | Ok(block) => { 24 | println!("New block: {:?}", block); 25 | } 26 | Err(e) => { 27 | eprintln!("Error: {:?}", e); 28 | } 29 | } 30 | } 31 | ``` 32 | 33 | Here is another example of subscribing to new blocks: 34 | 35 | ```rust 36 | {{#include ../../examples/subscriptions/examples/subscribe_blocks.rs}} 37 | ``` 38 | -------------------------------------------------------------------------------- /ethers-addressbook/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ethers-addressbook" 3 | authors = ["Rohit Narurkar "] 4 | readme = "README.md" 5 | description = "Common Ethereum name to address mappings" 6 | 7 | version.workspace = true 8 | edition.workspace = true 9 | rust-version.workspace = true 10 | license.workspace = true 11 | documentation.workspace = true 12 | repository.workspace = true 13 | homepage.workspace = true 14 | categories.workspace = true 15 | keywords.workspace = true 16 | exclude.workspace = true 17 | 18 | [package.metadata.docs.rs] 19 | all-features = true 20 | rustdoc-args = ["--cfg", "docsrs"] 21 | 22 | [package.metadata.playground] 23 | all-features = true 24 | 25 | [dependencies] 26 | ethers-core.workspace = true 27 | 28 | once_cell.workspace = true 29 | serde.workspace = true 30 | serde_json.workspace = true 31 | -------------------------------------------------------------------------------- /ethers-addressbook/README.md: -------------------------------------------------------------------------------- 1 | # ethers-addressbook 2 | 3 | A collection of commonly used smart contract addresses. 4 | 5 | For more information, please refer to the [book](https://gakonst.com/ethers-rs). 6 | 7 | > **Warning** 8 | > 9 | > This library is in the process of being deprecated. See [#2667](https://github.com/gakonst/ethers-rs/issues/2667) for more information. 10 | 11 | ## Examples 12 | 13 | ```rust 14 | use ethers_addressbook::{contract, Chain}; 15 | 16 | let weth = contract("weth").unwrap(); 17 | let mainnet_address = weth.address(Chain::Mainnet).unwrap(); 18 | assert_eq!(mainnet_address, "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2".parse().unwrap()); 19 | ``` 20 | -------------------------------------------------------------------------------- /ethers-contract/README.md: -------------------------------------------------------------------------------- 1 | # ethers-contract 2 | 3 | Type-safe abstractions for interacting with Ethereum smart contracts. 4 | 5 | > **Warning** 6 | > 7 | > This library is in the process of being deprecated. See [#2667](https://github.com/gakonst/ethers-rs/issues/2667) for more information. 8 | 9 | Interacting with a smart contract requires broadcasting carefully crafted 10 | [transactions](ethers_core::types::TransactionRequest) where the `data` field 11 | contains the 12 | [function's selector](https://ethereum.stackexchange.com/questions/72363/what-is-a-function-selector) 13 | along with the arguments of the called function. 14 | 15 | This module provides the [`Contract`] and [`ContractFactory`] abstractions so 16 | that you do not have to worry about that. It also provides typesafe bindings via 17 | the [`abigen`] macro and the [`Abigen` builder]. 18 | 19 | For more information, please refer to the [book](https://gakonst.com/ethers-rs). 20 | 21 | [`contractfactory`]: ./struct.ContractFactory.html 22 | [`contract`]: ./struct.Contract.html 23 | [`abigen`]: ./macro.abigen.html 24 | [`abigen` builder]: ./struct.Abigen.html 25 | -------------------------------------------------------------------------------- /ethers-contract/ethers-contract-abigen/README.md: -------------------------------------------------------------------------------- 1 | # ethers-contract-abigen 2 | 3 | Code generation for type-safe bindings to Ethereum smart contracts. 4 | 5 | This code generator was adapted from the original [ethcontract-rs repository by Gnosis](https://github.com/gnosis/ethcontract-rs/tree/master/generate). 6 | 7 | For more information, please refer to the [book](https://gakonst.com/ethers-rs). 8 | -------------------------------------------------------------------------------- /ethers-contract/ethers-contract-abigen/src/test/macros.rs: -------------------------------------------------------------------------------- 1 | /// Asserts the result of an expansion matches source output. 2 | /// 3 | /// # Panics 4 | /// 5 | /// If the expanded source does not match the quoted source. 6 | macro_rules! assert_quote { 7 | ($ex:expr, { $($t:tt)* } $(,)?) => { 8 | assert_eq!( 9 | $ex.to_string(), 10 | quote::quote! { $($t)* }.to_string(), 11 | ) 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /ethers-contract/ethers-contract-derive/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ethers-contract-derive" 3 | authors = [ 4 | "Nicholas Rodrigues Lordello ", 5 | "Georgios Konstantopoulos ", 6 | ] 7 | readme = "README.md" 8 | description = "Proc macros for type-safe bindings generation to Ethereum smart contracts" 9 | 10 | version.workspace = true 11 | edition.workspace = true 12 | rust-version.workspace = true 13 | license.workspace = true 14 | documentation.workspace = true 15 | repository.workspace = true 16 | homepage.workspace = true 17 | categories.workspace = true 18 | keywords.workspace = true 19 | 20 | [lib] 21 | proc-macro = true 22 | 23 | [dependencies] 24 | ethers-core.workspace = true 25 | ethers-contract-abigen.workspace = true 26 | 27 | proc-macro2.workspace = true 28 | quote.workspace = true 29 | syn.workspace = true 30 | 31 | Inflector.workspace = true 32 | hex.workspace = true 33 | serde_json.workspace = true 34 | 35 | [features] 36 | default = ["providers"] 37 | 38 | providers = ["ethers-contract-abigen/providers"] 39 | -------------------------------------------------------------------------------- /ethers-contract/ethers-contract-derive/README.md: -------------------------------------------------------------------------------- 1 | # ethers-contract-derive 2 | 3 | Proc macros for type-safe bindings generation to Ethereum smart contracts. 4 | 5 | Adapted from the original [ethcontract-rs repository by Gnosis](https://github.com/gnosis/ethcontract-rs/tree/master/derive). 6 | 7 | For more information, please refer to the [book](https://gakonst.com/ethers-rs). 8 | -------------------------------------------------------------------------------- /ethers-contract/ethers-contract-derive/src/spanned.rs: -------------------------------------------------------------------------------- 1 | //! Provides implementation for helpers used in parsing `TokenStream`s where the 2 | //! data ultimately does not care about its `Span` information, but it is useful 3 | //! during intermediate processing. 4 | 5 | use proc_macro2::Span; 6 | use std::ops::Deref; 7 | use syn::parse::{Parse, ParseStream, Result as ParseResult}; 8 | 9 | /// Trait that abstracts functionality for inner data that can be parsed and 10 | /// wrapped with a specific `Span`. 11 | pub trait ParseInner: Sized { 12 | fn spanned_parse(input: ParseStream) -> ParseResult<(Span, Self)>; 13 | } 14 | 15 | impl ParseInner for T { 16 | fn spanned_parse(input: ParseStream) -> ParseResult<(Span, Self)> { 17 | Ok((input.span(), T::parse(input)?)) 18 | } 19 | } 20 | 21 | impl Parse for Spanned { 22 | fn parse(input: ParseStream) -> ParseResult { 23 | let (span, value) = T::spanned_parse(input)?; 24 | Ok(Spanned(span, value)) 25 | } 26 | } 27 | 28 | /// A struct that captures `Span` information for inner parsable data. 29 | #[cfg_attr(test, derive(Clone, Debug))] 30 | pub struct Spanned(Span, T); 31 | 32 | impl Spanned { 33 | /// Retrieves the captured `Span` information for the parsed data. 34 | pub fn span(&self) -> Span { 35 | self.0 36 | } 37 | 38 | /// Retrieves the inner data. 39 | pub fn into_inner(self) -> T { 40 | self.1 41 | } 42 | } 43 | 44 | impl Deref for Spanned { 45 | type Target = T; 46 | 47 | fn deref(&self) -> &Self::Target { 48 | &self.1 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /ethers-contract/src/call_core.rs: -------------------------------------------------------------------------------- 1 | use ethers_core::{ 2 | abi::{AbiDecode, AbiEncode, Tokenizable}, 3 | types::Selector, 4 | utils::id, 5 | }; 6 | use std::borrow::Cow; 7 | 8 | /// A helper trait for types that represent all call input parameters of a specific function 9 | pub trait EthCall: Tokenizable + AbiDecode + AbiEncode + Send + Sync { 10 | /// The name of the function 11 | fn function_name() -> Cow<'static, str>; 12 | 13 | /// Retrieves the ABI signature for the call 14 | fn abi_signature() -> Cow<'static, str>; 15 | 16 | /// The selector of the function 17 | fn selector() -> Selector { 18 | id(Self::abi_signature()) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ethers-contract/src/multicall/contract.rs: -------------------------------------------------------------------------------- 1 | #![allow(missing_docs)] 2 | use ethers_contract_derive::abigen; 3 | 4 | abigen!(Multicall3, "src/multicall/multicall_abi.json"); 5 | -------------------------------------------------------------------------------- /ethers-contract/tests/it/contract_call.rs: -------------------------------------------------------------------------------- 1 | use ethers_contract_derive::abigen; 2 | use ethers_core::abi::Address; 3 | use ethers_providers::Provider; 4 | use std::{ 5 | future::{Future, IntoFuture}, 6 | sync::Arc, 7 | }; 8 | 9 | fn _contract_call_into_future_is_send() { 10 | abigen!(DsProxyFactory, "./../ethers-middleware/contracts/DSProxyFactory.json"); 11 | let (provider, _) = Provider::mocked(); 12 | let client = Arc::new(provider); 13 | let contract = DsProxyFactory::new(Address::zero(), client); 14 | 15 | fn is_send(future: T) -> T { 16 | future 17 | } 18 | 19 | drop(is_send(contract.cache().into_future())); 20 | } 21 | -------------------------------------------------------------------------------- /ethers-contract/tests/it/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::extra_unused_type_parameters)] 2 | #![cfg(feature = "abigen")] 3 | 4 | mod abigen; 5 | 6 | mod derive; 7 | 8 | #[cfg(feature = "providers")] 9 | mod contract_call; 10 | 11 | mod eip712; 12 | 13 | #[cfg(all(not(target_arch = "wasm32"), not(feature = "celo")))] 14 | mod common; 15 | 16 | #[cfg(all(feature = "providers", not(target_arch = "wasm32"), not(feature = "celo")))] 17 | mod contract; 18 | -------------------------------------------------------------------------------- /ethers-contract/tests/solidity-contracts/Abiencoderv2Test.json: -------------------------------------------------------------------------------- 1 | {"abi":[{"inputs":[],"name":"defaultPerson","outputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"age","type":"uint256"}],"internalType":"struct Hello.Person","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"}],"bytecode":"0x608060405234801561001057600080fd5b506101fe806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063ca8b722c14610030575b600080fd5b61003861004e565b60405161004591906101a6565b60405180910390f35b6100566100a6565b60405180604001604052806040518060400160405280600581526020017f416c69636500000000000000000000000000000000000000000000000000000081525081526020016014815250905090565b604051806040016040528060608152602001600081525090565b600081519050919050565b600082825260208201905092915050565b60005b838110156100fa5780820151818401526020810190506100df565b60008484015250505050565b6000601f19601f8301169050919050565b6000610122826100c0565b61012c81856100cb565b935061013c8185602086016100dc565b61014581610106565b840191505092915050565b6000819050919050565b61016381610150565b82525050565b600060408301600083015184820360008601526101868282610117565b915050602083015161019b602086018261015a565b508091505092915050565b600060208201905081810360008301526101c08184610169565b90509291505056fea2646970667358221220b4b2e7e5d170378b15eba0a22e58c197891d2bace43f60ff0dcc8e9b9be5878b64736f6c63430008140033"} 2 | -------------------------------------------------------------------------------- /ethers-contract/tests/solidity-contracts/Abiencoderv2Test.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.6.0; 2 | pragma experimental ABIEncoderV2; 3 | 4 | // note that this file is not synced with Abiencoderv2Test.json 5 | contract AbiencoderV2Test { 6 | struct Person { 7 | string name; 8 | uint age; 9 | } 10 | function defaultPerson() public pure returns (Person memory) { 11 | return Person("Alice", 20); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ethers-contract/tests/solidity-contracts/EventWithStruct.json: -------------------------------------------------------------------------------- 1 | [{"anonymous":false,"inputs":[{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256","name":"b","type":"uint256"}],"indexed":false,"internalType":"struct MyContract.MyStruct","name":"","type":"tuple"},{"indexed":false,"internalType":"uint256","name":"c","type":"uint256"}],"name":"MyEvent","type":"event"}] 2 | -------------------------------------------------------------------------------- /ethers-contract/tests/solidity-contracts/LargeStruct.json: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"getById","outputs":[{"components":[{"internalType":"uint128","name":"x","type":"uint128"},{"internalType":"int24","name":"y","type":"int24"},{"internalType":"int24","name":"z","type":"int24"},{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"int256","name":"b","type":"int256"},{"internalType":"int256","name":"c","type":"int256"},{"internalType":"int256","name":"d","type":"int256"},{"internalType":"uint256","name":"e","type":"uint256"},{"internalType":"uint256","name":"f","type":"uint256"}],"internalType":"struct Many.Info","name":"","type":"tuple"}],"stateMutability":"view","type":"function"}] 2 | -------------------------------------------------------------------------------- /ethers-contract/tests/solidity-contracts/MultiInputOutput.json: -------------------------------------------------------------------------------- 1 | {"abi":[{"inputs":[{"internalType":"uint256[]","name":"inputs","type":"uint256[]"}],"name":"arrayRelayer","outputs":[{"internalType":"uint256[]","name":"outputs","type":"uint256[]"},{"internalType":"uint256","name":"someNumber","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"input","type":"uint256"}],"name":"callWithoutReturnData","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"input","type":"uint256"}],"name":"dupeInt","outputs":[{"internalType":"uint256","name":"outOne","type":"uint256"},{"internalType":"uint256","name":"outTwo","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"singleUnnamed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"}]} 2 | -------------------------------------------------------------------------------- /ethers-contract/tests/solidity-contracts/MultiInputOutput.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.6.0; 2 | pragma experimental ABIEncoderV2; 3 | 4 | contract MultiInputOutput { 5 | function dupeInt(uint256 input) public pure returns (uint256 outOne, uint256 outTwo) { 6 | return (input, input); 7 | } 8 | function arrayRelayer(uint256[] memory inputs) public pure returns (uint256[] memory outputs, uint someNumber) { 9 | outputs = new uint[](inputs.length); 10 | for(uint256 i = 0; i < inputs.length; i++) { 11 | outputs[i] = inputs[i]; 12 | } 13 | someNumber = 42; 14 | } 15 | function singleUnnamed() public pure returns (uint) { 16 | return 0x45; 17 | } 18 | function callWithoutReturnData(uint256 input) public pure { 19 | // silence unused errors 20 | uint nothing = input; 21 | input = nothing; 22 | return; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ethers-contract/tests/solidity-contracts/NotSoSimpleStorage.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | // note that this file is not synced with NotSoSimpleStorage.json 4 | contract NotSoSimpleStorage { 5 | event ValueChanged(address indexed author, address indexed oldAuthor, string oldValue, string newValue); 6 | 7 | address public lastSender; 8 | string _value; 9 | 10 | constructor(string memory value) public { 11 | emit ValueChanged(msg.sender, address(0), _value, value); 12 | _value = value; 13 | } 14 | 15 | function getValue() view public returns (string memory) { 16 | return _value; 17 | } 18 | 19 | function getValues() view public returns (string memory, address) { 20 | return (_value, lastSender); 21 | } 22 | 23 | function setValue(string memory value) public { 24 | emit ValueChanged(msg.sender, lastSender, _value, value); 25 | _value = value; 26 | lastSender = msg.sender; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ethers-contract/tests/solidity-contracts/OverloadedFuncs.json: -------------------------------------------------------------------------------- 1 | { 2 | "abi": [ 3 | { 4 | "inputs": [ 5 | { 6 | "internalType": "bytes", 7 | "name": "", 8 | "type": "bytes" 9 | }, 10 | { 11 | "internalType": "bytes[]", 12 | "name": "", 13 | "type": "bytes[]" 14 | } 15 | ], 16 | "name": "execute", 17 | "outputs": [], 18 | "stateMutability": "nonpayable", 19 | "type": "function" 20 | }, 21 | { 22 | "inputs": [ 23 | { 24 | "internalType": "bytes", 25 | "name": "", 26 | "type": "bytes" 27 | }, 28 | { 29 | "internalType": "bytes[]", 30 | "name": "", 31 | "type": "bytes[]" 32 | }, 33 | { 34 | "internalType": "uint256", 35 | "name": "", 36 | "type": "uint256" 37 | } 38 | ], 39 | "name": "execute", 40 | "outputs": [], 41 | "stateMutability": "nonpayable", 42 | "type": "function" 43 | }, 44 | { 45 | "inputs": [ 46 | { 47 | "internalType": "bytes", 48 | "name": "", 49 | "type": "bytes" 50 | }, 51 | { 52 | "internalType": "bytes[3]", 53 | "name": "", 54 | "type": "bytes[3]" 55 | }, 56 | { 57 | "internalType": "uint256", 58 | "name": "", 59 | "type": "uint256" 60 | }, 61 | { 62 | "internalType": "bytes[]", 63 | "name": "", 64 | "type": "bytes[]" 65 | } 66 | ], 67 | "name": "execute", 68 | "outputs": [], 69 | "stateMutability": "nonpayable", 70 | "type": "function" 71 | } 72 | ] 73 | } 74 | -------------------------------------------------------------------------------- /ethers-contract/tests/solidity-contracts/SimpleRevertingStorage.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.8.4; 2 | 3 | // note that this file is not synced with SimpleRevertingStorage.json 4 | contract SimpleRevertingStorage { 5 | event ValueChanged( 6 | address indexed author, 7 | address indexed oldAuthor, 8 | string oldValue, 9 | string newValue 10 | ); 11 | 12 | address public lastSender; 13 | string _value; 14 | string _otherValue; 15 | 16 | constructor(string memory value) { 17 | emit ValueChanged(msg.sender, address(0), _value, value); 18 | _value = value; 19 | } 20 | 21 | function getValue(bool rev) external view returns (string memory) { 22 | require(!rev, "getValue revert"); 23 | return _value; 24 | } 25 | 26 | function setValue(string memory value, bool rev) external { 27 | require(!rev, "setValue revert"); 28 | emit ValueChanged(msg.sender, lastSender, _value, value); 29 | _value = value; 30 | lastSender = msg.sender; 31 | } 32 | 33 | event Deposit(uint256 value); 34 | 35 | function deposit() external payable { 36 | emit Deposit(msg.value); 37 | } 38 | 39 | function emptyRevert() external pure { 40 | revert(); 41 | } 42 | 43 | function stringRevert(string calldata data) external pure { 44 | revert(data); 45 | } 46 | 47 | error CustomError(); 48 | 49 | function customError() external pure { 50 | revert CustomError(); 51 | } 52 | 53 | error CustomErrorWithData(string); 54 | 55 | function customErrorWithData(string calldata data) external pure { 56 | revert CustomErrorWithData(data); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /ethers-contract/tests/solidity-contracts/SimpleStorage.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | // note that this file is not synced with SimpleStorage.json 4 | contract SimpleStorage { 5 | event ValueChanged(address indexed author, address indexed oldAuthor, string oldValue, string newValue); 6 | 7 | address public lastSender; 8 | string _value; 9 | string _otherValue; 10 | 11 | constructor(string memory value) public { 12 | emit ValueChanged(msg.sender, address(0), _value, value); 13 | _value = value; 14 | } 15 | 16 | function getValue() view public returns (string memory) { 17 | return _value; 18 | } 19 | 20 | function setValue(string memory value) public { 21 | emit ValueChanged(msg.sender, lastSender, _value, value); 22 | _value = value; 23 | lastSender = msg.sender; 24 | } 25 | 26 | function setValues(string memory value, string memory value2) public { 27 | _value = value; 28 | _otherValue = value2; 29 | lastSender = msg.sender; 30 | } 31 | 32 | function _hashPuzzle() public view returns (uint256) { 33 | return 100; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ethers-contract/tests/solidity-contracts/SlotStorage.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.24; 2 | 3 | contract SlotStorage { 4 | event ValueChanged( 5 | address indexed author, 6 | address indexed oldAuthor, 7 | bytes32 oldValue, 8 | bytes32 newValue 9 | ); 10 | 11 | bytes32 private constant KEY = 12 | bytes32( 13 | 0xa35a6bd95953594c6d23a75dc715af91915e970ba4d87f1141e13b915e0201a3 14 | ); 15 | 16 | address public lastSender; 17 | 18 | constructor(bytes32 value) { 19 | bytes32 _value = getValue(); 20 | emit ValueChanged(msg.sender, address(0), _value, value); 21 | setValue(value); 22 | } 23 | 24 | function getValue() public view returns (bytes32 val) { 25 | val = readBytes32(KEY); 26 | } 27 | 28 | function setValue(bytes32 value) public returns (bytes32 val) { 29 | bytes32 _value = getValue(); 30 | emit ValueChanged(msg.sender, lastSender, _value, value); 31 | writeBytes32(KEY, value); 32 | lastSender = msg.sender; 33 | val = _value; 34 | } 35 | 36 | function writeBytes32(bytes32 _key, bytes32 _val) internal { 37 | assembly { 38 | sstore(_key, _val) 39 | } 40 | } 41 | 42 | function readBytes32(bytes32 _key) internal view returns (bytes32 val) { 43 | assembly { 44 | val := sload(_key) 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /ethers-contract/tests/solidity-contracts/StructConstructor.json: -------------------------------------------------------------------------------- 1 | {"abi": [{"inputs":[{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"internalType":"struct MyContract.ConstructorParams","name":"params","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"}], "bin": "608060405234801561001057600080fd5b506040516101df3803806101df833981810160405281019061003291906100b2565b8060008082015181600001556020820151816001015590505050610192565b60006040828403121561006357600080fd5b61006d60406100db565b9050600061007d8482850161009d565b60008301525060206100918482850161009d565b60208301525092915050565b6000815190506100ac8161017b565b92915050565b6000604082840312156100c457600080fd5b60006100d284828501610051565b91505092915050565b60006100e56100f6565b90506100f1828261010a565b919050565b6000604051905090565b6000819050919050565b6101138261016a565b810181811067ffffffffffffffff821117156101325761013161013b565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b61018481610100565b811461018f57600080fd5b50565b603f806101a06000396000f3fe6080604052600080fdfea2646970667358221220bbd84df82374c1aa309661efb1096e8b1edc2b6fd57eaa1d43c53908b04321b864736f6c63430008020033"} 2 | -------------------------------------------------------------------------------- /ethers-contract/tests/solidity-contracts/StructConstructor.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity >=0.8; 3 | 4 | // To sync with StructContractor.json run: 5 | 6 | // CONTRACT=ethers-contract/tests/solidity-contracts/StructConstructor 7 | // BIN=$(solc --bin $CONTRACT.sol | sed '4q;d' | tr -d '\n') 8 | // ABI=$(solc --abi $CONTRACT.sol | tail -n 1) 9 | // echo "{\"abi\": $ABI, \"bin\": \"$BIN\"}" > $CONTRACT.json 10 | 11 | contract MyContract { 12 | struct ConstructorParams { 13 | uint256 x; 14 | uint256 y; 15 | } 16 | 17 | ConstructorParams _params; 18 | 19 | constructor(ConstructorParams memory params) { 20 | _params = params; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ethers-contract/tests/solidity-contracts/StructContract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity >=0.8.10; 3 | 4 | contract MyContract { 5 | struct Point { 6 | uint256 x; 7 | uint256 y; 8 | } 9 | 10 | event NewPoint(Point x); 11 | 12 | function submitPoint(Point memory _point) public { 13 | emit NewPoint(_point); 14 | } 15 | } -------------------------------------------------------------------------------- /ethers-contract/tests/solidity-contracts/draft-IERCPermit.json: -------------------------------------------------------------------------------- 1 | { 2 | "abi": [], 3 | "bytecode": { 4 | "object": "0x", 5 | "linkReferences": {} 6 | }, 7 | "deployedBytecode": { 8 | "object": "0x", 9 | "linkReferences": {} 10 | }, 11 | "id": 217 12 | } -------------------------------------------------------------------------------- /ethers-contract/tests/solidity-contracts/large-array.json: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"uint64[128]","name":"longArray","type":"uint64[128]"}],"name":"callWithLongArray","outputs":[],"stateMutability":"view","type":"function"}] 2 | -------------------------------------------------------------------------------- /ethers-contract/tests/solidity-contracts/large_tuple.json: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"uint160","name":"input","type":"uint160"}],"name":"doSomething","outputs":[{"components":[{"internalType":"bytes","name":"output1","type":"bytes"},{"internalType":"bytes","name":"output2","type":"bytes"},{"internalType":"bytes","name":"output3","type":"bytes"},{"internalType":"bytes","name":"output4","type":"bytes"},{"internalType":"bytes","name":"output5","type":"bytes"},{"internalType":"bytes","name":"output6","type":"bytes"},{"internalType":"bytes","name":"output7","type":"bytes"},{"internalType":"bytes","name":"output8","type":"bytes"},{"internalType":"bytes","name":"output9","type":"bytes"},{"internalType":"bytes","name":"output10","type":"bytes"},{"internalType":"bytes","name":"output11","type":"bytes"},{"internalType":"bytes","name":"output12","type":"bytes"},{"internalType":"bytes","name":"output13","type":"bytes"}],"internalType":"struct Contract.Response","name":"","type":"tuple"}],"stateMutability":"view","type":"function"}] 2 | -------------------------------------------------------------------------------- /ethers-contract/tests/solidity-contracts/sale.json: -------------------------------------------------------------------------------- 1 | [{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"marketplaceId","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"nfts","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"amountBatches","type":"uint256[]"},{"indexed":false,"internalType":"uint128","name":"price","type":"uint128"},{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isAuction","type":"bool"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isNSFW","type":"bool"},{"indexed":false,"internalType":"string","name":"marketplaceURI","type":"string"},{"indexed":false,"internalType":"string","name":"searchKeywords","type":"string"},{"indexed":false,"internalType":"address[]","name":"addresses","type":"address[]"}],"name":"NewSale","type":"event"}] 2 | -------------------------------------------------------------------------------- /ethers-core/src/abi/error.rs: -------------------------------------------------------------------------------- 1 | //! Boilerplate error definitions. 2 | use crate::abi::{human_readable, InvalidOutputType}; 3 | use thiserror::Error; 4 | 5 | /// A type alias for std's Result with the Error as our error type. 6 | pub type Result = std::result::Result; 7 | 8 | /// Error that can occur during human readable parsing 9 | #[derive(Error, Debug)] 10 | pub enum ParseError { 11 | #[error("{0}")] 12 | Message(String), 13 | // ethabi parser error 14 | #[error(transparent)] 15 | ParseError(#[from] ethabi::Error), 16 | // errors from human readable lexer 17 | #[error(transparent)] 18 | LexerError(#[from] human_readable::lexer::LexerError), 19 | } 20 | 21 | macro_rules! _format_err { 22 | ($($tt:tt)*) => { 23 | $crate::abi::ParseError::Message(format!($($tt)*)) 24 | }; 25 | } 26 | pub(crate) use _format_err as format_err; 27 | 28 | macro_rules! _bail { 29 | ($($tt:tt)*) => { return Err($crate::abi::error::format_err!($($tt)*)) }; 30 | } 31 | use crate::types::ParseBytesError; 32 | pub(crate) use _bail as bail; 33 | 34 | /// ABI codec related errors 35 | #[derive(Error, Debug)] 36 | pub enum AbiError { 37 | /// Thrown when the ABI decoding fails 38 | #[error(transparent)] 39 | DecodingError(#[from] ethabi::Error), 40 | 41 | /// Thrown when detokenizing an argument 42 | #[error(transparent)] 43 | DetokenizationError(#[from] InvalidOutputType), 44 | 45 | #[error("missing or wrong function selector")] 46 | WrongSelector, 47 | 48 | #[error(transparent)] 49 | ParseBytesError(#[from] ParseBytesError), 50 | } 51 | -------------------------------------------------------------------------------- /ethers-core/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![doc = include_str!("../README.md")] 2 | #![deny(rustdoc::broken_intra_doc_links)] 3 | #![cfg_attr(not(target_arch = "wasm32"), deny(unused_crate_dependencies))] 4 | #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] 5 | 6 | pub mod types; 7 | 8 | pub mod abi; 9 | 10 | /// Various utilities 11 | pub mod utils; 12 | 13 | #[cfg(feature = "macros")] 14 | pub mod macros; 15 | 16 | // re-export rand to avoid potential confusion when there's rand version mismatches 17 | pub use rand; 18 | 19 | // re-export k256 20 | pub use k256; 21 | -------------------------------------------------------------------------------- /ethers-core/src/macros/mod.rs: -------------------------------------------------------------------------------- 1 | mod ethers_crate; 2 | pub use ethers_crate::*; 3 | -------------------------------------------------------------------------------- /ethers-core/src/types/address_or_bytes.rs: -------------------------------------------------------------------------------- 1 | use crate::types::{Address, Bytes}; 2 | 3 | #[derive(Clone, Debug, PartialEq, Eq)] 4 | /// A type that can either be an `Address` or `Bytes`. 5 | pub enum AddressOrBytes { 6 | /// An address type 7 | Address(Address), 8 | /// A bytes type 9 | Bytes(Bytes), 10 | } 11 | 12 | impl From
for AddressOrBytes { 13 | fn from(s: Address) -> Self { 14 | Self::Address(s) 15 | } 16 | } 17 | 18 | impl From for AddressOrBytes { 19 | fn from(s: Bytes) -> Self { 20 | Self::Bytes(s) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ethers-core/src/types/fee.rs: -------------------------------------------------------------------------------- 1 | use crate::types::{serde_helpers::deserialize_stringified_numeric, U256}; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | #[derive(Deserialize, Serialize, Debug, Clone)] 5 | #[serde(rename_all = "camelCase")] 6 | pub struct FeeHistory { 7 | #[serde(default, skip_serializing_if = "Vec::is_empty")] 8 | pub base_fee_per_gas: Vec, 9 | pub gas_used_ratio: Vec, 10 | #[serde(deserialize_with = "deserialize_stringified_numeric")] 11 | /// oldestBlock is returned as an unsigned integer up to geth v1.10.6. From 12 | /// geth v1.10.7, this has been updated to return in the hex encoded form. 13 | /// The custom deserializer allows backward compatibility for those clients 14 | /// not running v1.10.7 yet. 15 | pub oldest_block: U256, 16 | /// An (optional) array of effective priority fee per gas data points from a single block. All 17 | /// zeroes are returned if the block is empty. 18 | #[serde(default, skip_serializing_if = "Vec::is_empty")] 19 | pub reward: Vec>, 20 | } 21 | -------------------------------------------------------------------------------- /ethers-core/src/types/path_or_string.rs: -------------------------------------------------------------------------------- 1 | use std::path::{Path, PathBuf}; 2 | 3 | /// A type that can either be a `Path` or a `String` 4 | #[derive(Clone, Debug, PartialEq, Eq)] 5 | pub enum PathOrString { 6 | /// A path type 7 | Path(PathBuf), 8 | /// A string type 9 | String(String), 10 | } 11 | 12 | impl From for PathOrString { 13 | fn from(p: PathBuf) -> Self { 14 | PathOrString::Path(p) 15 | } 16 | } 17 | 18 | impl From<&str> for PathOrString { 19 | fn from(s: &str) -> Self { 20 | let path = Path::new(s); 21 | if path.exists() { 22 | PathOrString::Path(path.to_owned()) 23 | } else { 24 | PathOrString::String(s.to_owned()) 25 | } 26 | } 27 | } 28 | 29 | impl PathOrString { 30 | /// Reads the contents at path, or simply returns the string. 31 | pub fn read(&self) -> Result { 32 | match self { 33 | PathOrString::Path(pathbuf) => std::fs::read_to_string(pathbuf), 34 | PathOrString::String(s) => Ok(s.to_string()), 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /ethers-core/src/types/proof.rs: -------------------------------------------------------------------------------- 1 | use crate::types::{ 2 | serde_helpers::deserialize_stringified_numeric, Address, Bytes, H256, U256, U64, 3 | }; 4 | use serde::{Deserialize, Serialize}; 5 | 6 | #[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize, Serialize)] 7 | pub struct StorageProof { 8 | #[serde(deserialize_with = "deserialize_stringified_numeric")] 9 | pub key: U256, 10 | pub proof: Vec, 11 | pub value: U256, 12 | } 13 | 14 | #[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize, Serialize)] 15 | #[serde(rename_all = "camelCase")] 16 | pub struct EIP1186ProofResponse { 17 | pub address: Address, 18 | pub balance: U256, 19 | pub code_hash: H256, 20 | pub nonce: U64, 21 | pub storage_hash: H256, 22 | pub account_proof: Vec, 23 | pub storage_proof: Vec, 24 | } 25 | 26 | #[cfg(test)] 27 | mod tests { 28 | use super::*; 29 | 30 | #[test] 31 | fn can_deserialize_proof() { 32 | serde_json::from_str::(include_str!("../../testdata/proof.json")) 33 | .unwrap(); 34 | } 35 | 36 | #[test] 37 | fn can_deserialize_proof_uint_key() { 38 | serde_json::from_str::(include_str!( 39 | "../../testdata/proof_uint_key.json" 40 | )) 41 | .unwrap(); 42 | } 43 | 44 | #[test] 45 | fn can_deserialize_proof_empty_key() { 46 | serde_json::from_str::(include_str!( 47 | "../../testdata/proof_empty_key.json" 48 | )) 49 | .unwrap(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ethers-core/src/types/trace/example-traces-str.rs: -------------------------------------------------------------------------------- 1 | r#"[{ 2 | "output": "0x", 3 | "stateDiff": { 4 | "0x5df9b87991262f6ba471f09758cde1c0fc1de734": { 5 | "balance": { 6 | "+": "0x7a69" 7 | }, 8 | "code": { 9 | "+": "0x" 10 | }, 11 | "nonce": { 12 | "+": "0x0" 13 | }, 14 | "storage": {} 15 | }, 16 | "0xa1e4380a3b1f749673e270229993ee55f35663b4": { 17 | "balance": { 18 | "*": { 19 | "from": "0x6c6b935b8bbd400000", 20 | "to": "0x6c5d01021be7168597" 21 | } 22 | }, 23 | "code": "=", 24 | "nonce": { 25 | "*": { 26 | "from": "0x0", 27 | "to": "0x1" 28 | } 29 | }, 30 | "storage": {} 31 | }, 32 | "0xe6a7a1d47ff21b6321162aea7c6cb457d5476bca": { 33 | "balance": { 34 | "*": { 35 | "from": "0xf3426785a8ab466000", 36 | "to": "0xf350f9df18816f6000" 37 | } 38 | }, 39 | "code": "=", 40 | "nonce": "=", 41 | "storage": {} 42 | } 43 | }, 44 | "trace": [ 45 | { 46 | "action": { 47 | "callType": "call", 48 | "from": "0xa1e4380a3b1f749673e270229993ee55f35663b4", 49 | "gas": "0x0", 50 | "input": "0x", 51 | "to": "0x5df9b87991262f6ba471f09758cde1c0fc1de734", 52 | "value": "0x7a69" 53 | }, 54 | "result": { 55 | "gasUsed": "0x0", 56 | "output": "0x" 57 | }, 58 | "subtraces": 0, 59 | "traceAddress": [], 60 | "type": "call" 61 | } 62 | ], 63 | "transactionHash": "0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060", 64 | "vmTrace": { 65 | "code": "0x", 66 | "ops": [] 67 | } 68 | }]"# 69 | -------------------------------------------------------------------------------- /ethers-core/src/types/trace/geth/four_byte.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use std::collections::BTreeMap; 3 | 4 | // https://github.com/ethereum/go-ethereum/blob/91cb6f863a965481e51d5d9c0e5ccd54796fd967/eth/tracers/native/4byte.go#L48 5 | #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] 6 | pub struct FourByteFrame(pub BTreeMap); 7 | 8 | #[cfg(test)] 9 | mod tests { 10 | use super::*; 11 | use crate::types::*; 12 | 13 | const DEFAULT: &str = r#"{ 14 | "0x27dc297e-128": 1, 15 | "0x38cc4831-0": 2, 16 | "0x524f3889-96": 1, 17 | "0xadf59f99-288": 1, 18 | "0xc281d19e-0": 1 19 | }"#; 20 | 21 | #[test] 22 | fn test_serialize_four_byte_trace() { 23 | let mut opts = GethDebugTracingCallOptions::default(); 24 | opts.tracing_options.tracer = 25 | Some(GethDebugTracerType::BuiltInTracer(GethDebugBuiltInTracerType::FourByteTracer)); 26 | 27 | assert_eq!(serde_json::to_string(&opts).unwrap(), r#"{"tracer":"4byteTracer"}"#); 28 | } 29 | 30 | #[test] 31 | fn test_deserialize_four_byte_trace() { 32 | let _trace: FourByteFrame = serde_json::from_str(DEFAULT).unwrap(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ethers-core/src/types/trace/geth/noop.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use std::collections::BTreeMap; 3 | 4 | // https://github.com/ethereum/go-ethereum/blob/91cb6f863a965481e51d5d9c0e5ccd54796fd967/eth/tracers/native/noop.go#L34 5 | #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] 6 | pub struct NoopFrame(BTreeMap); 7 | #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)] 8 | struct Null; 9 | 10 | #[cfg(test)] 11 | mod tests { 12 | use super::*; 13 | use crate::types::*; 14 | 15 | const DEFAULT: &str = r"{}"; 16 | 17 | #[test] 18 | fn test_serialize_noop_trace() { 19 | let mut opts = GethDebugTracingCallOptions::default(); 20 | opts.tracing_options.tracer = 21 | Some(GethDebugTracerType::BuiltInTracer(GethDebugBuiltInTracerType::NoopTracer)); 22 | 23 | assert_eq!(serde_json::to_string(&opts).unwrap(), r#"{"tracer":"noopTracer"}"#); 24 | } 25 | 26 | #[test] 27 | fn test_deserialize_noop_trace() { 28 | let _trace: NoopFrame = serde_json::from_str(DEFAULT).unwrap(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ethers-core/src/types/trace/geth/test_data/call_tracer/default.json: -------------------------------------------------------------------------------- 1 | {"calls":[{"from":"0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe","gas":"0x6d05","gasUsed":"0x0","input":"0x","to":"0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5","type":"CALL","value":"0x6f05b59d3b20000"}],"from":"0xb436ba50d378d4bbc8660d312a13df6af6e89dfb","gas":"0x10738","gasUsed":"0x9751","input":"0x63e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c5","output":"0x0000000000000000000000000000000000000000000000000000000000000001","to":"0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe","type":"CALL","value":"0x0"} 2 | -------------------------------------------------------------------------------- /ethers-core/src/types/trace/geth/test_data/call_tracer/legacy.json: -------------------------------------------------------------------------------- 1 | {"calls":[{"from":"0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe","input":"0x","to":"0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5","type":"CALL","value":"0x6f05b59d3b20000"}],"from":"0xb436ba50d378d4bbc8660d312a13df6af6e89dfb","gas":"0x10738","gasUsed":"0x9751","input":"0x63e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c5","output":"0x0000000000000000000000000000000000000000000000000000000000000001","to":"0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe","type":"CALL","value":"0x0"} 2 | -------------------------------------------------------------------------------- /ethers-core/src/types/trace/geth/test_data/call_tracer/only_top_call.json: -------------------------------------------------------------------------------- 1 | {"from":"0x4f5777744b500616697cb655dcb02ee6cd51deb5","gas":"0x2dced","gasUsed":"0x1a9e5","to":"0x200edd17f30485a8735878661960cd7a9a95733f","input":"0xba51a6df0000000000000000000000000000000000000000000000000000000000000000","output":"0xba51a6df00000000000000000000000000000000000000000000000000000000","value":"0x8ac7230489e80000","type":"CALL"} 2 | -------------------------------------------------------------------------------- /ethers-core/src/types/trace/geth/test_data/call_tracer/with_log.json: -------------------------------------------------------------------------------- 1 | {"from":"0xd1220a0cf47c7b9be7a2e6ba89f429762e7b9adb","gas":"0x1f36d","gasUsed":"0xc6a5","to":"0xf4eced2f682ce333f96f2d8966c613ded8fc95dd","input":"0xa9059cbb000000000000000000000000dbf03b407c01e7cd3cbea99509d93f8dddc8c6fb0000000000000000000000000000000000000000000000000000000000989680","logs":[{"address":"0xf4eced2f682ce333f96f2d8966c613ded8fc95dd","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000d1220a0cf47c7b9be7a2e6ba89f429762e7b9adb","0x000000000000000000000000dbf03b407c01e7cd3cbea99509d93f8dddc8c6fb"],"data":"0x0000000000000000000000000000000000000000000000000000000000989680"}],"value":"0x0","type":"CALL"} 2 | -------------------------------------------------------------------------------- /ethers-core/src/types/trace/geth/test_data/pre_state_tracer/default.json: -------------------------------------------------------------------------------- 1 | {"0x082d4cdf07f386ffa9258f52a5c49db4ac321ec6":{"balance":"0xc820f93200f4000","nonce":94},"0x332b656504f4eabb44c8617a42af37461a34e9dc":{"balance":"0x11faea4f35e5af80000","storage":{"0x0000000000000000000000000000000000000000000000000000000000000000":"0x0000000000000000000000000000000000000000000000000000000000000000"}},"0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5":{"balance":"0xbf681825be002ac452","nonce":28922},"0x82effbaaaf28614e55b2ba440fb198e0e5789b0f":{"balance":"0xb3d0ac5cb94df6f6b0","nonce":1}} 2 | -------------------------------------------------------------------------------- /ethers-core/src/types/trace/parity.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ethers-core/src/types/withdrawal.rs: -------------------------------------------------------------------------------- 1 | use crate::types::{Address, U256, U64}; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | /// A validator withdrawal from the consensus layer. 5 | /// See EIP-4895: Beacon chain push withdrawals as operations. 6 | #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] 7 | pub struct Withdrawal { 8 | /// Monotonically increasing identifier issued by consensus layer 9 | pub index: U64, 10 | 11 | /// Index of validator associated with withdrawal 12 | #[serde(rename = "validatorIndex")] 13 | pub validator_index: U64, 14 | 15 | /// Target address for withdrawn ether 16 | pub address: Address, 17 | 18 | /// Value of withdrawal (in wei) 19 | pub amount: U256, 20 | } 21 | 22 | impl rlp::Encodable for Withdrawal { 23 | fn rlp_append(&self, s: &mut rlp::RlpStream) { 24 | s.begin_list(4); 25 | s.append(&self.index); 26 | s.append(&self.validator_index); 27 | s.append(&self.address); 28 | s.append(&self.amount); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ethers-etherscan/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ethers-etherscan" 3 | authors = [ 4 | "Matthias Seitz ", 5 | "Georgios Konstantopoulos ", 6 | ] 7 | readme = "README.md" 8 | description = "Bindings for the etherscan.io web API" 9 | keywords = ["crypto", "ethers", "ethereum", "web3", "etherscan"] 10 | 11 | version.workspace = true 12 | edition.workspace = true 13 | rust-version.workspace = true 14 | license.workspace = true 15 | documentation.workspace = true 16 | repository.workspace = true 17 | homepage.workspace = true 18 | categories.workspace = true 19 | exclude.workspace = true 20 | 21 | [package.metadata.docs.rs] 22 | all-features = true 23 | rustdoc-args = ["--cfg", "docsrs"] 24 | 25 | [package.metadata.playground] 26 | all-features = true 27 | 28 | [dependencies] 29 | ethers-core.workspace = true 30 | 31 | ethers-solc = { workspace = true, optional = true } 32 | 33 | reqwest = { workspace = true, features = ["json"] } 34 | serde = { workspace = true, features = ["derive"] } 35 | serde_json.workspace = true 36 | thiserror.workspace = true 37 | tracing.workspace = true 38 | semver.workspace = true 39 | chrono.workspace = true 40 | 41 | [dev-dependencies] 42 | ethers-solc.workspace = true 43 | 44 | tempfile.workspace = true 45 | tokio = { workspace = true, features = ["macros", "rt-multi-thread", "time"] } 46 | serial_test = "3.0.0" 47 | tracing-subscriber = { workspace = true, features = ["env-filter", "fmt"] } 48 | 49 | [features] 50 | default = ["rustls"] 51 | rustls = ["reqwest/rustls-tls"] 52 | openssl = ["reqwest/native-tls"] 53 | 54 | ethers-solc = ["dep:ethers-solc"] 55 | solc-full = ["ethers-solc?/full"] 56 | solc-tests = ["ethers-solc?/tests"] 57 | -------------------------------------------------------------------------------- /ethers-etherscan/README.md: -------------------------------------------------------------------------------- 1 | # ethers-etherscan 2 | 3 | Bindings for the [etherscan.io web API](https://docs.etherscan.io). 4 | 5 | For more information, please refer to the [book](https://gakonst.com/ethers-rs). 6 | 7 | > **Warning** 8 | > 9 | > This crate is deprecated in favor of [`foundry-block-explorers`](https://crates.io/foundry-block-explorers) ([foundry-rs/block-explorers](https://github.com/foundry-rs/block-explorers)). See [#2667](https://github.com/gakonst/ethers-rs/issues/2667) for more information. 10 | 11 | ## Examples 12 | 13 | ```rust,no_run 14 | # use ethers_core::types::Chain; 15 | # use ethers_etherscan::Client; 16 | # async fn foo() -> Result<(), Box> { 17 | let client = Client::new(Chain::Mainnet, "")?; 18 | // Or using environment variables 19 | let client = Client::new_from_env(Chain::Mainnet)?; 20 | 21 | let address = "0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413".parse()?; 22 | let metadata = client.contract_source_code(address).await?; 23 | assert_eq!(metadata.items[0].contract_name, "DAO"); 24 | # Ok(()) 25 | # } 26 | ``` 27 | -------------------------------------------------------------------------------- /ethers-etherscan/tests/it/blocks.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use ethers_core::types::BlockNumber; 3 | use serial_test::serial; 4 | 5 | #[tokio::test] 6 | #[serial] 7 | async fn check_get_block_by_timestamp_before() { 8 | run_with_client(Chain::Mainnet, |client| async move { 9 | let block_no = client.get_block_by_timestamp(1577836800, "before").await; 10 | assert!(block_no.is_ok()); 11 | 12 | let block_no = block_no.unwrap().block_number; 13 | assert_eq!(block_no, "9193265".parse::().unwrap()); 14 | }) 15 | .await 16 | } 17 | 18 | #[tokio::test] 19 | #[serial] 20 | async fn check_get_block_by_timestamp_after() { 21 | run_with_client(Chain::Mainnet, |client| async move { 22 | let block_no = client.get_block_by_timestamp(1577836800, "after").await; 23 | 24 | let block_no = block_no.unwrap().block_number; 25 | assert_eq!(block_no, "9193266".parse::().unwrap()); 26 | }) 27 | .await 28 | } 29 | -------------------------------------------------------------------------------- /ethers-etherscan/tests/it/gas.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use ethers_core::types::U256; 3 | use serial_test::serial; 4 | 5 | #[tokio::test] 6 | #[serial] 7 | async fn gas_estimate_success() { 8 | run_with_client(Chain::Mainnet, |client| async move { 9 | let result = client.gas_estimate(2000000000u32.into()).await; 10 | 11 | result.unwrap(); 12 | }) 13 | .await 14 | } 15 | 16 | #[tokio::test] 17 | #[serial] 18 | async fn gas_estimate_error() { 19 | run_with_client(Chain::Mainnet, |client| async move { 20 | let err = client.gas_estimate(7123189371829732819379218u128.into()).await.unwrap_err(); 21 | 22 | assert!(matches!(err, EtherscanError::GasEstimationFailed)); 23 | }) 24 | .await 25 | } 26 | 27 | #[tokio::test] 28 | #[serial] 29 | async fn gas_oracle_success() { 30 | run_with_client(Chain::Mainnet, |client| async move { 31 | let result = client.gas_oracle().await; 32 | 33 | assert!(result.is_ok()); 34 | 35 | let oracle = result.unwrap(); 36 | 37 | assert!(oracle.safe_gas_price > U256::zero()); 38 | assert!(oracle.propose_gas_price > U256::zero()); 39 | assert!(oracle.fast_gas_price > U256::zero()); 40 | assert!(oracle.last_block > 0); 41 | assert!(oracle.suggested_base_fee > U256::zero()); 42 | assert!(!oracle.gas_used_ratio.is_empty()); 43 | }) 44 | .await 45 | } 46 | -------------------------------------------------------------------------------- /ethers-etherscan/tests/it/stats.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use serial_test::serial; 3 | 4 | #[tokio::test] 5 | #[serial] 6 | async fn eth_supply_success() { 7 | run_with_client(Chain::Mainnet, |client| async move { 8 | let result = client.eth_supply().await; 9 | 10 | result.unwrap(); 11 | }) 12 | .await 13 | } 14 | 15 | #[tokio::test] 16 | #[serial] 17 | async fn eth_supply2_success() { 18 | run_with_client(Chain::Mainnet, |client| async move { 19 | let result = client.eth_supply2().await; 20 | 21 | result.unwrap(); 22 | }) 23 | .await 24 | } 25 | 26 | #[tokio::test] 27 | #[serial] 28 | async fn eth_price_success() { 29 | run_with_client(Chain::Mainnet, |client| async move { 30 | let result = client.eth_price().await; 31 | 32 | result.unwrap(); 33 | }) 34 | .await 35 | } 36 | 37 | #[tokio::test] 38 | #[serial] 39 | async fn node_count_success() { 40 | run_with_client(Chain::Mainnet, |client| async move { 41 | let result = client.node_count().await; 42 | 43 | result.unwrap(); 44 | }) 45 | .await 46 | } 47 | -------------------------------------------------------------------------------- /ethers-etherscan/tests/it/version.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use ethers_etherscan::utils::lookup_compiler_version; 3 | use semver::{BuildMetadata, Prerelease, Version}; 4 | 5 | #[tokio::test] 6 | async fn can_lookup_compiler_version_build_metadata() { 7 | let v = Version::new(0, 8, 13); 8 | let version = lookup_compiler_version(&v).await.unwrap(); 9 | assert_eq!(v.major, version.major); 10 | assert_eq!(v.minor, version.minor); 11 | assert_eq!(v.patch, version.patch); 12 | assert_ne!(version.build, BuildMetadata::EMPTY); 13 | assert_eq!(version.pre, Prerelease::EMPTY); 14 | } 15 | 16 | #[tokio::test] 17 | async fn errors_on_invalid_solc() { 18 | let v = Version::new(100, 0, 0); 19 | let err = lookup_compiler_version(&v).await.unwrap_err(); 20 | assert!(matches!(err, EtherscanError::MissingSolcVersion(_))); 21 | } 22 | -------------------------------------------------------------------------------- /ethers-middleware/src/gas_oracle/provider_oracle.rs: -------------------------------------------------------------------------------- 1 | use super::{GasOracle, GasOracleError, Result}; 2 | use async_trait::async_trait; 3 | use ethers_core::types::U256; 4 | use ethers_providers::Middleware; 5 | use std::fmt::Debug; 6 | 7 | /// Gas oracle from a [`Middleware`] implementation such as an 8 | /// Ethereum RPC provider. 9 | #[derive(Clone, Debug)] 10 | #[must_use] 11 | pub struct ProviderOracle { 12 | provider: M, 13 | } 14 | 15 | impl ProviderOracle { 16 | pub fn new(provider: M) -> Self { 17 | Self { provider } 18 | } 19 | } 20 | 21 | #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] 22 | #[cfg_attr(not(target_arch = "wasm32"), async_trait)] 23 | impl GasOracle for ProviderOracle 24 | where 25 | M::Error: 'static, 26 | { 27 | async fn fetch(&self) -> Result { 28 | self.provider 29 | .get_gas_price() 30 | .await 31 | .map_err(|err| GasOracleError::ProviderError(Box::new(err))) 32 | } 33 | 34 | async fn estimate_eip1559_fees(&self) -> Result<(U256, U256)> { 35 | // TODO: Allow configuring different estimation functions. 36 | self.provider 37 | .estimate_eip1559_fees(None) 38 | .await 39 | .map_err(|err| GasOracleError::ProviderError(Box::new(err))) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ethers-middleware/src/transformer/ds_proxy/factory.rs: -------------------------------------------------------------------------------- 1 | use ethers_contract::{abigen, Lazy}; 2 | use ethers_core::types::{Address, U256}; 3 | use std::collections::HashMap; 4 | 5 | /// A lazily computed hash map with the Ethereum network IDs as keys and the corresponding 6 | /// DsProxyFactory contract addresses as values 7 | pub static ADDRESS_BOOK: Lazy> = Lazy::new(|| { 8 | HashMap::from([ 9 | // Mainnet 10 | (U256::from(1_u64), "eefba1e63905ef1d7acba5a8513c70307c1ce441".parse().unwrap()), 11 | ]) 12 | }); 13 | 14 | abigen!( 15 | DsProxyFactory, 16 | "./contracts/DSProxyFactory.json", 17 | methods { 18 | build() as build_with_sender; 19 | } 20 | ); 21 | -------------------------------------------------------------------------------- /ethers-middleware/src/transformer/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod ds_proxy; 2 | pub use ds_proxy::DsProxy; 3 | 4 | mod middleware; 5 | pub use middleware::TransformerMiddleware; 6 | 7 | use ethers_contract::AbiError; 8 | use ethers_core::{abi::ParseError, types::transaction::eip2718::TypedTransaction}; 9 | use thiserror::Error; 10 | 11 | #[derive(Error, Debug)] 12 | /// Errors thrown from the types that implement the `Transformer` trait. 13 | pub enum TransformerError { 14 | #[error("The field `{0}` is missing")] 15 | MissingField(String), 16 | 17 | #[error(transparent)] 18 | AbiParseError(#[from] ParseError), 19 | 20 | #[error(transparent)] 21 | AbiError(#[from] AbiError), 22 | } 23 | 24 | /// `Transformer` is a trait to be implemented by a proxy wallet, eg. [`DsProxy`], that intends to 25 | /// intercept a transaction request and transform it into one that is instead sent via the proxy 26 | /// contract. 27 | pub trait Transformer: Send + Sync + std::fmt::Debug { 28 | /// Transforms a [`transaction request`] into one that can be broadcasted and execute via the 29 | /// proxy contract. 30 | /// 31 | /// [`transaction request`]: struct@ethers_core::types::TransactionRequest 32 | fn transform(&self, tx: &mut TypedTransaction) -> Result<(), TransformerError>; 33 | } 34 | -------------------------------------------------------------------------------- /ethers-middleware/tests/it/gas_escalator.rs: -------------------------------------------------------------------------------- 1 | use ethers_core::{types::*, utils::Anvil}; 2 | use ethers_middleware::{ 3 | gas_escalator::{Frequency, GasEscalatorMiddleware, GeometricGasPrice}, 4 | MiddlewareBuilder, 5 | }; 6 | use ethers_providers::{Http, Middleware, Provider}; 7 | use ethers_signers::{LocalWallet, Signer}; 8 | 9 | #[tokio::test] 10 | #[ignore] 11 | async fn gas_escalator() { 12 | let anvil = Anvil::new().block_time(2u64).spawn(); 13 | let chain_id = anvil.chain_id(); 14 | let provider = Provider::::try_from(anvil.endpoint()).unwrap(); 15 | 16 | // wrap with signer 17 | let wallet: LocalWallet = anvil.keys().first().unwrap().clone().into(); 18 | let wallet = wallet.with_chain_id(chain_id); 19 | let address = wallet.address(); 20 | let provider = provider.with_signer(wallet); 21 | 22 | // wrap with escalator 23 | let escalator = GeometricGasPrice::new(5.0, 10u64, Some(2_000_000_000_000u64)); 24 | let provider = GasEscalatorMiddleware::new(provider, escalator, Frequency::Duration(300)); 25 | 26 | let nonce = provider.get_transaction_count(address, None).await.unwrap(); 27 | // 1 gwei default base fee 28 | let gas_price = U256::from(1_000_000_000_u64); 29 | let tx = TransactionRequest::pay(Address::zero(), 1u64) 30 | .gas_price(gas_price) 31 | .nonce(nonce) 32 | .chain_id(chain_id); 33 | 34 | eprintln!("sending"); 35 | let pending = provider.send_transaction(tx, None).await.expect("could not send"); 36 | eprintln!("waiting"); 37 | let receipt = pending.await.expect("reverted").expect("dropped"); 38 | assert_eq!(receipt.from, address); 39 | assert_eq!(receipt.to, Some(Address::zero())); 40 | assert!(receipt.effective_gas_price.unwrap() > gas_price * 2, "{receipt:?}"); 41 | } 42 | -------------------------------------------------------------------------------- /ethers-middleware/tests/it/nonce_manager.rs: -------------------------------------------------------------------------------- 1 | use crate::spawn_anvil; 2 | use ethers_core::types::*; 3 | use ethers_middleware::MiddlewareBuilder; 4 | use ethers_providers::Middleware; 5 | 6 | #[tokio::test] 7 | async fn nonce_manager() { 8 | let (provider, anvil) = spawn_anvil(); 9 | let address = anvil.addresses()[0]; 10 | let to = anvil.addresses()[1]; 11 | 12 | // the nonce manager must be over the Client so that it overrides the nonce 13 | // before the client gets it 14 | let provider = provider.nonce_manager(address); 15 | 16 | let nonce = provider 17 | .get_transaction_count(address, Some(BlockNumber::Pending.into())) 18 | .await 19 | .unwrap() 20 | .as_u64(); 21 | 22 | let num_tx = 3; 23 | let mut tx_hashes = Vec::with_capacity(num_tx); 24 | for _ in 0..num_tx { 25 | let tx = provider 26 | .send_transaction(TransactionRequest::new().from(address).to(to).value(100u64), None) 27 | .await 28 | .unwrap(); 29 | tx_hashes.push(*tx); 30 | } 31 | 32 | let mut nonces = Vec::with_capacity(num_tx); 33 | for tx_hash in tx_hashes { 34 | nonces.push(provider.get_transaction(tx_hash).await.unwrap().unwrap().nonce.as_u64()); 35 | } 36 | 37 | assert_eq!(nonces, (nonce..nonce + num_tx as u64).collect::>()); 38 | } 39 | -------------------------------------------------------------------------------- /ethers-providers/src/ext/mod.rs: -------------------------------------------------------------------------------- 1 | /// Types for the admin api 2 | pub mod admin; 3 | pub use admin::{NodeInfo, PeerInfo}; 4 | 5 | pub mod ens; 6 | pub use ens::*; 7 | 8 | pub mod erc; 9 | 10 | #[cfg(feature = "dev-rpc")] 11 | pub mod dev_rpc; 12 | #[cfg(feature = "dev-rpc")] 13 | pub use dev_rpc::{DevRpcMiddleware, DevRpcMiddlewareError}; 14 | -------------------------------------------------------------------------------- /ethers-providers/src/rpc/connections.rs: -------------------------------------------------------------------------------- 1 | use crate::{ProviderError, RpcError}; 2 | use async_trait::async_trait; 3 | use auto_impl::auto_impl; 4 | use serde::{de::DeserializeOwned, Serialize}; 5 | use std::fmt::Debug; 6 | 7 | #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] 8 | #[cfg_attr(not(target_arch = "wasm32"), async_trait)] 9 | #[auto_impl(&, Box, Arc)] 10 | /// Trait which must be implemented by data transports to be used with the Ethereum 11 | /// JSON-RPC provider. 12 | pub trait JsonRpcClient: Debug + Send + Sync { 13 | /// A JSON-RPC Error 14 | type Error: Into + RpcError; 15 | 16 | /// Sends a request with the provided JSON-RPC and parameters serialized as JSON 17 | async fn request(&self, method: &str, params: T) -> Result 18 | where 19 | T: Debug + Serialize + Send + Sync, 20 | R: DeserializeOwned + Send; 21 | } 22 | -------------------------------------------------------------------------------- /ethers-providers/src/rpc/mod.rs: -------------------------------------------------------------------------------- 1 | mod provider; 2 | pub use provider::*; 3 | 4 | mod transports; 5 | pub use transports::*; 6 | 7 | mod connections; 8 | pub use connections::*; 9 | 10 | mod pubsub; 11 | pub use pubsub::*; 12 | -------------------------------------------------------------------------------- /ethers-providers/src/rpc/transports/mod.rs: -------------------------------------------------------------------------------- 1 | pub(crate) mod common; 2 | pub use common::{Authorization, JsonRpcError, JwtAuth, JwtKey}; 3 | 4 | mod http; 5 | pub use self::http::{ClientError as HttpClientError, Provider as Http}; 6 | 7 | #[cfg(all(feature = "ipc", any(unix, windows)))] 8 | mod ipc; 9 | #[cfg(all(feature = "ipc", any(unix, windows)))] 10 | pub use ipc::{Ipc, IpcError}; 11 | 12 | mod quorum; 13 | pub use quorum::{JsonRpcClientWrapper, Quorum, QuorumError, QuorumProvider, WeightedProvider}; 14 | 15 | mod rw; 16 | pub use rw::{RwClient, RwClientError}; 17 | 18 | mod retry; 19 | pub use retry::*; 20 | 21 | #[cfg(all(feature = "ws", not(feature = "legacy-ws")))] 22 | mod ws; 23 | #[cfg(all(feature = "ws", not(feature = "legacy-ws")))] 24 | pub use ws::{ConnectionDetails, WsClient as Ws, WsClientError}; 25 | 26 | /// archival websocket 27 | #[cfg(feature = "legacy-ws")] 28 | pub mod legacy_ws; 29 | #[cfg(feature = "legacy-ws")] 30 | pub use legacy_ws::{ClientError as WsClientError, Ws}; 31 | 32 | mod mock; 33 | pub use mock::{MockError, MockProvider, MockResponse}; 34 | -------------------------------------------------------------------------------- /ethers-providers/src/stream/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod tx_stream; 2 | 3 | pub mod watcher; 4 | pub use watcher::*; 5 | -------------------------------------------------------------------------------- /ethers-providers/src/toolbox/mod.rs: -------------------------------------------------------------------------------- 1 | mod pending_transaction; 2 | pub use pending_transaction::PendingTransaction; 3 | 4 | mod pending_escalator; 5 | pub use pending_escalator::EscalatingPending; 6 | 7 | mod log_query; 8 | pub use log_query::{LogQuery, LogQueryError}; 9 | 10 | pub mod call_raw; 11 | pub use call_raw::*; 12 | -------------------------------------------------------------------------------- /ethers-providers/src/utils.rs: -------------------------------------------------------------------------------- 1 | use crate::ProviderError; 2 | use ethers_core::types::U256; 3 | use futures_timer::Delay; 4 | use futures_util::{stream, FutureExt, StreamExt}; 5 | use std::{future::Future, pin::Pin}; 6 | 7 | /// A simple gas escalation policy 8 | pub type EscalationPolicy = Box U256 + Send + Sync>; 9 | 10 | // Helper type alias 11 | #[cfg(target_arch = "wasm32")] 12 | pub(crate) type PinBoxFut<'a, T> = Pin> + 'a>>; 13 | #[cfg(not(target_arch = "wasm32"))] 14 | pub(crate) type PinBoxFut<'a, T> = 15 | Pin> + Send + 'a>>; 16 | 17 | /// Calls the future if `item` is None, otherwise returns a `futures::ok` 18 | pub async fn maybe(item: Option, f: F) -> Result 19 | where 20 | F: Future>, 21 | { 22 | if let Some(item) = item { 23 | futures_util::future::ok(item).await 24 | } else { 25 | f.await 26 | } 27 | } 28 | 29 | // https://github.com/tomusdrw/rust-web3/blob/befcb2fb8f3ca0a43e3081f68886fa327e64c8e6/src/api/eth_filter.rs#L20 30 | /// Create a stream that emits items at a fixed interval. Used for rate control 31 | pub fn interval( 32 | duration: instant::Duration, 33 | ) -> impl futures_core::stream::Stream + Send + Unpin { 34 | stream::unfold((), move |_| Delay::new(duration).map(|_| Some(((), ())))).map(drop) 35 | } 36 | -------------------------------------------------------------------------------- /ethers-providers/tests/it/txpool.rs: -------------------------------------------------------------------------------- 1 | use ethers_core::{ 2 | types::{TransactionRequest, U256}, 3 | utils::Anvil, 4 | }; 5 | use ethers_providers::{Http, Middleware, Provider}; 6 | 7 | #[tokio::test] 8 | async fn txpool() { 9 | let anvil = Anvil::new().block_time(5u64).spawn(); 10 | let provider = Provider::::try_from(anvil.endpoint()).unwrap(); 11 | 12 | let account = provider.get_accounts().await.unwrap()[0]; 13 | let value: u64 = 42; 14 | let gas_price = U256::from_dec_str("221435145689").unwrap(); 15 | let tx = TransactionRequest::new().to(account).from(account).value(value).gas_price(gas_price); 16 | 17 | // send a few transactions 18 | for _ in 0..10 { 19 | drop(provider.send_transaction(tx.clone(), None).await.unwrap()); 20 | } 21 | 22 | // we gave a 5s block time, should be plenty for us to get the txpool's content 23 | let status = provider.txpool_status().await.unwrap(); 24 | assert_eq!(status.pending.as_u64(), 10); 25 | assert_eq!(status.queued.as_u64(), 0); 26 | 27 | let inspect = provider.txpool_inspect().await.unwrap(); 28 | assert!(inspect.queued.is_empty()); 29 | let summary = inspect.pending.get(&account).unwrap(); 30 | for i in 0..10 { 31 | let tx_summary = summary.get(&i.to_string()).unwrap(); 32 | assert_eq!(tx_summary.gas_price, gas_price); 33 | assert_eq!(tx_summary.value, value.into()); 34 | assert_eq!(tx_summary.gas, 21000.into()); 35 | assert_eq!(tx_summary.to.unwrap(), account); 36 | } 37 | 38 | let content = provider.txpool_content().await.unwrap(); 39 | assert!(content.queued.is_empty()); 40 | let content = content.pending.get(&account).unwrap(); 41 | 42 | for nonce in 0..10 { 43 | assert!(content.contains_key(&nonce.to_string())); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /ethers-solc/README.md: -------------------------------------------------------------------------------- 1 | # ethers-solc 2 | 3 | Utilities for working with native `solc` and compiling projects. 4 | 5 | > **Warning** 6 | > 7 | > This crate is deprecated in favor of [`foundry-compilers`](https://crates.io/foundry-compilers) ([foundry-rs/compilers](https://github.com/foundry-rs/compilers)). See [#2667](https://github.com/gakonst/ethers-rs/issues/2667) for more information. 8 | 9 | To also compile contracts during `cargo build` (so that ethers `abigen!` can pull in updated abi automatically) you can configure a `ethers_solc::Project` in your `build.rs` file 10 | 11 | First add `ethers-solc` to your cargo build-dependencies. 12 | 13 | Once you compiled the project, you can configure cargo change detection with `rerun_if_sources_changed`, so that cargo will execute the `build.rs` file if a contract in the sources directory has changed 14 | 15 | ```toml 16 | [build-dependencies] 17 | ethers-solc = { git = "https://github.com/gakonst/ethers-rs" } 18 | ``` 19 | 20 | ```rust 21 | use ethers_solc::{Project, ProjectPathsConfig}; 22 | 23 | fn main() { 24 | // configure the project with all its paths, solc, cache etc. 25 | let project = Project::builder() 26 | .paths(ProjectPathsConfig::hardhat(env!("CARGO_MANIFEST_DIR")).unwrap()) 27 | .build() 28 | .unwrap(); 29 | let output = project.compile().unwrap(); 30 | 31 | // Tell Cargo that if a source file changes, to rerun this build script. 32 | project.rerun_if_sources_changed(); 33 | } 34 | ``` 35 | -------------------------------------------------------------------------------- /ethers-solc/benches/compile_many.rs: -------------------------------------------------------------------------------- 1 | //! compile many benches 2 | #[macro_use] 3 | extern crate criterion; 4 | 5 | use criterion::Criterion; 6 | use ethers_solc::{CompilerInput, Solc}; 7 | use std::path::Path; 8 | 9 | fn compile_many_benchmark(c: &mut Criterion) { 10 | let inputs = load_compiler_inputs(); 11 | let solc = Solc::default(); 12 | 13 | let mut group = c.benchmark_group("compile many"); 14 | group.sample_size(10); 15 | group.bench_function("sequential", |b| { 16 | b.iter(|| { 17 | for i in inputs.iter() { 18 | let _ = solc.compile(i).unwrap(); 19 | } 20 | }); 21 | }); 22 | 23 | #[cfg(feature = "full")] 24 | { 25 | let tasks = inputs.into_iter().map(|input| (Solc::default(), input)).collect::>(); 26 | let num = tasks.len(); 27 | group.bench_function("concurrently", |b| { 28 | b.to_async(tokio::runtime::Runtime::new().unwrap()).iter(|| async { 29 | let _ = Solc::compile_many(tasks.clone(), num).await.flattened().unwrap(); 30 | }); 31 | }); 32 | } 33 | } 34 | 35 | fn load_compiler_inputs() -> Vec { 36 | let mut inputs = Vec::new(); 37 | for file in std::fs::read_dir(Path::new(&env!("CARGO_MANIFEST_DIR")).join("test-data/in")) 38 | .unwrap() 39 | .take(5) 40 | { 41 | let file = file.unwrap(); 42 | let input = std::fs::read_to_string(file.path()).unwrap(); 43 | let input: CompilerInput = serde_json::from_str(&input).unwrap(); 44 | inputs.push(input); 45 | } 46 | inputs 47 | } 48 | 49 | criterion_group!(benches, compile_many_benchmark); 50 | criterion_main!(benches); 51 | -------------------------------------------------------------------------------- /ethers-solc/src/artifacts/ast/util.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ethers-solc/src/artifacts/ast/visitor.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ethers-solc/src/compile/many.rs: -------------------------------------------------------------------------------- 1 | use crate::{error::Result, CompilerInput, CompilerOutput, Solc}; 2 | 3 | /// The result of a `solc` process bundled with its `Solc` and `CompilerInput` 4 | type CompileElement = (Result, Solc, CompilerInput); 5 | 6 | /// The bundled output of multiple `solc` processes. 7 | #[derive(Debug)] 8 | pub struct CompiledMany { 9 | outputs: Vec, 10 | } 11 | 12 | impl CompiledMany { 13 | pub fn new(outputs: Vec) -> Self { 14 | Self { outputs } 15 | } 16 | 17 | /// Returns an iterator over all output elements 18 | pub fn outputs(&self) -> impl Iterator { 19 | self.outputs.iter() 20 | } 21 | 22 | /// Returns an iterator over all output elements 23 | pub fn into_outputs(self) -> impl Iterator { 24 | self.outputs.into_iter() 25 | } 26 | 27 | /// Returns all `CompilerOutput` or the first error that occurred 28 | pub fn flattened(self) -> Result> { 29 | self.into_iter().collect() 30 | } 31 | } 32 | 33 | impl IntoIterator for CompiledMany { 34 | type Item = Result; 35 | type IntoIter = std::vec::IntoIter>; 36 | 37 | fn into_iter(self) -> Self::IntoIter { 38 | self.outputs.into_iter().map(|(res, _, _)| res).collect::>().into_iter() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/abstract_contract.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"C":[5]},"id":6,"nodeType":"SourceUnit","nodes":[{"abstract":true,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":5,"linearizedBaseContracts":[5],"name":"C","nameLocation":"18:1:1","nodeType":"ContractDefinition","nodes":[{"body":{"id":3,"nodeType":"Block","src":"37:4:1","statements":[]},"id":4,"implemented":true,"kind":"constructor","modifiers":[],"name":"","nameLocation":"-1:-1:-1","nodeType":"FunctionDefinition","parameters":{"id":1,"nodeType":"ParameterList","parameters":[],"src":"34:2:1"},"returnParameters":{"id":2,"nodeType":"ParameterList","parameters":[],"src":"37:0:1"},"scope":5,"src":"23:18:1","stateMutability":"nonpayable","virtual":false,"visibility":"internal"}],"scope":6,"src":"0:43:1","usedErrors":[]}],"src":"0:44:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/array_type_name.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"C":[4]},"id":5,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":4,"linearizedBaseContracts":[4],"name":"C","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"constant":false,"id":3,"mutability":"mutable","name":"i","nameLocation":"20:1:1","nodeType":"VariableDeclaration","scope":4,"src":"13:8:1","stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_array$_t_uint256_$dyn_storage","typeString":"uint256[]"},"typeName":{"baseType":{"id":1,"name":"uint","nodeType":"ElementaryTypeName","src":"13:4:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":2,"nodeType":"ArrayTypeName","src":"13:6:1","typeDescriptions":{"typeIdentifier":"t_array$_t_uint256_$dyn_storage_ptr","typeString":"uint256[]"}},"visibility":"internal"}],"scope":5,"src":"0:24:1","usedErrors":[]}],"src":"0:25:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/constructor.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"C":[5]},"id":6,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":5,"linearizedBaseContracts":[5],"name":"C","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"body":{"id":3,"nodeType":"Block","src":"28:4:1","statements":[]},"id":4,"implemented":true,"kind":"constructor","modifiers":[],"name":"","nameLocation":"-1:-1:-1","nodeType":"FunctionDefinition","parameters":{"id":1,"nodeType":"ParameterList","parameters":[],"src":"25:2:1"},"returnParameters":{"id":2,"nodeType":"ParameterList","parameters":[],"src":"28:0:1"},"scope":5,"src":"14:18:1","stateMutability":"nonpayable","virtual":false,"visibility":"public"}],"scope":6,"src":"0:34:1","usedErrors":[]}],"src":"0:35:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/documentation_1.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"C":[2]},"id":3,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","documentation":{"id":1,"nodeType":"StructuredDocumentation","src":"0:27:1","text":"This contract is empty"},"fullyImplemented":true,"id":2,"linearizedBaseContracts":[2],"name":"C","nameLocation":"37:1:1","nodeType":"ContractDefinition","nodes":[],"scope":3,"src":"28:13:1","usedErrors":[]}],"src":"28:14:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/documentation_2.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"b","exportedSymbols":{"C":[5]},"id":6,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","documentation":{"id":4,"nodeType":"StructuredDocumentation","src":"0:61:2","text":"This contract is empty\nand has a line-breaking comment."},"fullyImplemented":true,"id":5,"linearizedBaseContracts":[5],"name":"C","nameLocation":"71:1:2","nodeType":"ContractDefinition","nodes":[],"scope":6,"src":"62:13:2","usedErrors":[]}],"src":"62:14:2"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/empty_block.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"C":[6]},"id":7,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":6,"linearizedBaseContracts":[6],"name":"C","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"body":{"id":4,"nodeType":"Block","src":"42:31:1","statements":[{"AST":{"nodeType":"YulBlock","src":"61:6:1","statements":[{"nodeType":"YulBlock","src":"63:2:1","statements":[]}]},"evmVersion":"london","externalReferences":[],"id":3,"nodeType":"InlineAssembly","src":"52:15:1"}]},"functionSelector":"e2179b8e","id":5,"implemented":true,"kind":"function","modifiers":[],"name":"g","nameLocation":"26:1:1","nodeType":"FunctionDefinition","parameters":{"id":1,"nodeType":"ParameterList","parameters":[],"src":"27:2:1"},"returnParameters":{"id":2,"nodeType":"ParameterList","parameters":[],"src":"42:0:1"},"scope":6,"src":"17:56:1","stateMutability":"view","virtual":false,"visibility":"public"}],"scope":7,"src":"0:75:1","usedErrors":[]}],"src":"0:76:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/enum_value.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"C":[4]},"id":5,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":4,"linearizedBaseContracts":[4],"name":"C","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"canonicalName":"C.E","id":3,"members":[{"id":1,"name":"A","nameLocation":"22:1:1","nodeType":"EnumValue","src":"22:1:1"},{"id":2,"name":"B","nameLocation":"25:1:1","nodeType":"EnumValue","src":"25:1:1"}],"name":"E","nameLocation":"18:1:1","nodeType":"EnumDefinition","src":"13:15:1"}],"scope":5,"src":"0:30:1","usedErrors":[]}],"src":"0:31:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/event_definition.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"C":[3]},"id":4,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":3,"linearizedBaseContracts":[3],"name":"C","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"anonymous":false,"eventSelector":"92bbf6e823a631f3c8e09b1c8df90f378fb56f7fbc9701827e1ff8aad7f6a028","id":2,"name":"E","nameLocation":"19:1:1","nodeType":"EventDefinition","parameters":{"id":1,"nodeType":"ParameterList","parameters":[],"src":"20:2:1"},"src":"13:10:1"}],"scope":4,"src":"0:25:1","usedErrors":[]}],"src":"0:26:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/fallback.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"C":[5]},"id":6,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":5,"linearizedBaseContracts":[5],"name":"C","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"body":{"id":3,"nodeType":"Block","src":"43:5:1","statements":[]},"id":4,"implemented":true,"kind":"fallback","modifiers":[],"name":"","nameLocation":"-1:-1:-1","nodeType":"FunctionDefinition","parameters":{"id":1,"nodeType":"ParameterList","parameters":[],"src":"23:2:1"},"returnParameters":{"id":2,"nodeType":"ParameterList","parameters":[],"src":"43:0:1"},"scope":5,"src":"15:33:1","stateMutability":"payable","virtual":false,"visibility":"external"}],"scope":6,"src":"0:50:1","usedErrors":[]}],"src":"0:51:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/fallback_and_reveice_ether.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"C":[9]},"id":10,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":9,"linearizedBaseContracts":[9],"name":"C","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"body":{"id":3,"nodeType":"Block","src":"42:5:1","statements":[]},"id":4,"implemented":true,"kind":"receive","modifiers":[],"name":"","nameLocation":"-1:-1:-1","nodeType":"FunctionDefinition","parameters":{"id":1,"nodeType":"ParameterList","parameters":[],"src":"22:2:1"},"returnParameters":{"id":2,"nodeType":"ParameterList","parameters":[],"src":"42:0:1"},"scope":9,"src":"15:32:1","stateMutability":"payable","virtual":false,"visibility":"external"},{"body":{"id":7,"nodeType":"Block","src":"78:5:1","statements":[]},"id":8,"implemented":true,"kind":"fallback","modifiers":[],"name":"","nameLocation":"-1:-1:-1","nodeType":"FunctionDefinition","parameters":{"id":5,"nodeType":"ParameterList","parameters":[],"src":"58:2:1"},"returnParameters":{"id":6,"nodeType":"ParameterList","parameters":[],"src":"78:0:1"},"scope":9,"src":"50:33:1","stateMutability":"payable","virtual":false,"visibility":"external"}],"scope":10,"src":"0:85:1","usedErrors":[]}],"src":"0:86:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/fallback_payable.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"C":[5]},"id":6,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":5,"linearizedBaseContracts":[5],"name":"C","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"body":{"id":3,"nodeType":"Block","src":"34:2:1","statements":[]},"id":4,"implemented":true,"kind":"fallback","modifiers":[],"name":"","nameLocation":"-1:-1:-1","nodeType":"FunctionDefinition","parameters":{"id":1,"nodeType":"ParameterList","parameters":[],"src":"22:2:1"},"returnParameters":{"id":2,"nodeType":"ParameterList","parameters":[],"src":"34:0:1"},"scope":5,"src":"14:22:1","stateMutability":"nonpayable","virtual":false,"visibility":"external"}],"scope":6,"src":"0:38:1","usedErrors":[]}],"src":"0:39:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/function.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"C":[6]},"id":7,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":6,"linearizedBaseContracts":[6],"name":"C","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"body":{"id":4,"nodeType":"Block","src":"42:68:1","statements":[{"AST":{"nodeType":"YulBlock","src":"61:43:1","statements":[{"body":{"nodeType":"YulBlock","src":"76:22:1","statements":[{"expression":{"arguments":[{"arguments":[{"kind":"number","nodeType":"YulLiteral","src":"92:2:1","type":"","value":"20"}],"functionName":{"name":"blockhash","nodeType":"YulIdentifier","src":"82:9:1"},"nodeType":"YulFunctionCall","src":"82:13:1"}],"functionName":{"name":"pop","nodeType":"YulIdentifier","src":"78:3:1"},"nodeType":"YulFunctionCall","src":"78:18:1"},"nodeType":"YulExpressionStatement","src":"78:18:1"}]},"name":"g","nodeType":"YulFunctionDefinition","src":"63:35:1"},{"expression":{"arguments":[],"functionName":{"name":"g","nodeType":"YulIdentifier","src":"99:1:1"},"nodeType":"YulFunctionCall","src":"99:3:1"},"nodeType":"YulExpressionStatement","src":"99:3:1"}]},"evmVersion":"london","externalReferences":[],"id":3,"nodeType":"InlineAssembly","src":"52:52:1"}]},"functionSelector":"b8c9d365","id":5,"implemented":true,"kind":"function","modifiers":[],"name":"h","nameLocation":"26:1:1","nodeType":"FunctionDefinition","parameters":{"id":1,"nodeType":"ParameterList","parameters":[],"src":"27:2:1"},"returnParameters":{"id":2,"nodeType":"ParameterList","parameters":[],"src":"42:0:1"},"scope":6,"src":"17:93:1","stateMutability":"view","virtual":false,"visibility":"public"}],"scope":7,"src":"0:112:1","usedErrors":[]}],"src":"0:113:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/global_enum.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"E":[2]},"id":3,"nodeType":"SourceUnit","nodes":[{"canonicalName":"E","id":2,"members":[{"id":1,"name":"A","nameLocation":"9:1:1","nodeType":"EnumValue","src":"9:1:1"}],"name":"E","nameLocation":"5:1:1","nodeType":"EnumDefinition","src":"0:12:1"}],"src":"0:13:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/global_struct.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"S":[3]},"id":4,"nodeType":"SourceUnit","nodes":[{"canonicalName":"S","id":3,"members":[{"constant":false,"id":2,"mutability":"mutable","name":"a","nameLocation":"19:1:1","nodeType":"VariableDeclaration","scope":3,"src":"11:9:1","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":1,"name":"uint256","nodeType":"ElementaryTypeName","src":"11:7:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"name":"S","nameLocation":"7:1:1","nodeType":"StructDefinition","scope":4,"src":"0:23:1","visibility":"public"}],"src":"0:24:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/inheritance_specifier.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"C1":[1],"C2":[4]},"id":5,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C1","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":1,"linearizedBaseContracts":[1],"name":"C1","nameLocation":"9:2:1","nodeType":"ContractDefinition","nodes":[],"scope":5,"src":"0:14:1","usedErrors":[]},{"abstract":false,"baseContracts":[{"baseName":{"id":2,"name":"C1","nameLocations":["30:2:1"],"nodeType":"IdentifierPath","referencedDeclaration":1,"src":"30:2:1"},"id":3,"nodeType":"InheritanceSpecifier","src":"30:2:1"}],"canonicalName":"C2","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":4,"linearizedBaseContracts":[4,1],"name":"C2","nameLocation":"24:2:1","nodeType":"ContractDefinition","nodes":[],"scope":5,"src":"15:20:1","usedErrors":[]}],"src":"0:36:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/leave.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"C":[6]},"id":7,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":6,"linearizedBaseContracts":[6],"name":"C","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"body":{"id":4,"nodeType":"Block","src":"37:51:1","statements":[{"AST":{"nodeType":"YulBlock","src":"56:26:1","statements":[{"body":{"nodeType":"YulBlock","src":"71:9:1","statements":[{"nodeType":"YulLeave","src":"73:5:1"}]},"name":"f","nodeType":"YulFunctionDefinition","src":"58:22:1"}]},"evmVersion":"london","externalReferences":[],"id":3,"nodeType":"InlineAssembly","src":"47:35:1"}]},"functionSelector":"ece866b9","id":5,"implemented":true,"kind":"function","modifiers":[],"name":"l","nameLocation":"26:1:1","nodeType":"FunctionDefinition","parameters":{"id":1,"nodeType":"ParameterList","parameters":[],"src":"27:2:1"},"returnParameters":{"id":2,"nodeType":"ParameterList","parameters":[],"src":"37:0:1"},"scope":6,"src":"17:71:1","stateMutability":"nonpayable","virtual":false,"visibility":"public"}],"scope":7,"src":"0:90:1","usedErrors":[]}],"src":"0:91:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/license.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"C":[1]},"id":2,"license":"GPL-3.0","nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":1,"linearizedBaseContracts":[1],"name":"C","nameLocation":"45:1:1","nodeType":"ContractDefinition","nodes":[],"scope":2,"src":"36:13:1","usedErrors":[]}],"src":"36:14:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/loop.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"C":[6]},"id":7,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":6,"linearizedBaseContracts":[6],"name":"C","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"body":{"id":4,"nodeType":"Block","src":"42:74:1","statements":[{"AST":{"nodeType":"YulBlock","src":"61:49:1","statements":[{"body":{"nodeType":"YulBlock","src":"90:18:1","statements":[{"nodeType":"YulBreak","src":"92:5:1"},{"nodeType":"YulContinue","src":"98:8:1"}]},"condition":{"kind":"number","nodeType":"YulLiteral","src":"70:1:1","type":"","value":"1"},"nodeType":"YulForLoop","post":{"nodeType":"YulBlock","src":"72:17:1","statements":[{"expression":{"arguments":[{"arguments":[{"kind":"number","nodeType":"YulLiteral","src":"84:1:1","type":"","value":"0"}],"functionName":{"name":"sload","nodeType":"YulIdentifier","src":"78:5:1"},"nodeType":"YulFunctionCall","src":"78:8:1"}],"functionName":{"name":"pop","nodeType":"YulIdentifier","src":"74:3:1"},"nodeType":"YulFunctionCall","src":"74:13:1"},"nodeType":"YulExpressionStatement","src":"74:13:1"}]},"pre":{"nodeType":"YulBlock","src":"67:2:1","statements":[]},"src":"63:45:1"}]},"evmVersion":"london","externalReferences":[],"id":3,"nodeType":"InlineAssembly","src":"52:58:1"}]},"functionSelector":"e2179b8e","id":5,"implemented":true,"kind":"function","modifiers":[],"name":"g","nameLocation":"26:1:1","nodeType":"FunctionDefinition","parameters":{"id":1,"nodeType":"ParameterList","parameters":[],"src":"27:2:1"},"returnParameters":{"id":2,"nodeType":"ParameterList","parameters":[],"src":"42:0:1"},"scope":6,"src":"17:99:1","stateMutability":"view","virtual":false,"visibility":"public"}],"scope":7,"src":"0:118:1","usedErrors":[]}],"src":"0:119:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/placeholder_statement.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"C":[5]},"id":6,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":5,"linearizedBaseContracts":[5],"name":"C","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"body":{"id":3,"nodeType":"Block","src":"24:6:1","statements":[{"id":2,"nodeType":"PlaceholderStatement","src":"26:1:1"}]},"id":4,"name":"M","nameLocation":"22:1:1","nodeType":"ModifierDefinition","parameters":{"id":1,"nodeType":"ParameterList","parameters":[],"src":"24:0:1"},"src":"13:17:1","virtual":false,"visibility":"internal"}],"scope":6,"src":"0:32:1","usedErrors":[]}],"src":"0:33:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/receive_ether.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"C":[5]},"id":6,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":5,"linearizedBaseContracts":[5],"name":"C","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"body":{"id":3,"nodeType":"Block","src":"42:5:1","statements":[]},"id":4,"implemented":true,"kind":"receive","modifiers":[],"name":"","nameLocation":"-1:-1:-1","nodeType":"FunctionDefinition","parameters":{"id":1,"nodeType":"ParameterList","parameters":[],"src":"22:2:1"},"returnParameters":{"id":2,"nodeType":"ParameterList","parameters":[],"src":"42:0:1"},"scope":5,"src":"15:32:1","stateMutability":"payable","virtual":false,"visibility":"external"}],"scope":6,"src":"0:49:1","usedErrors":[]}],"src":"0:50:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/short_type_name.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"c":[11]},"id":12,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"c","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":11,"linearizedBaseContracts":[11],"name":"c","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"body":{"id":9,"nodeType":"Block","src":"33:20:1","statements":[{"assignments":[7],"declarations":[{"constant":false,"id":7,"mutability":"mutable","name":"x","nameLocation":"49:1:1","nodeType":"VariableDeclaration","scope":9,"src":"35:15:1","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_uint256_$dyn_memory_ptr","typeString":"uint256[]"},"typeName":{"baseType":{"id":5,"name":"uint","nodeType":"ElementaryTypeName","src":"35:4:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":6,"nodeType":"ArrayTypeName","src":"35:6:1","typeDescriptions":{"typeIdentifier":"t_array$_t_uint256_$dyn_storage_ptr","typeString":"uint256[]"}},"visibility":"internal"}],"id":8,"nodeType":"VariableDeclarationStatement","src":"35:15:1"}]},"functionSelector":"26121ff0","id":10,"implemented":true,"kind":"function","modifiers":[],"name":"f","nameLocation":"22:1:1","nodeType":"FunctionDefinition","parameters":{"id":1,"nodeType":"ParameterList","parameters":[],"src":"23:2:1"},"returnParameters":{"id":2,"nodeType":"ParameterList","parameters":[],"src":"33:0:1"},"scope":11,"src":"13:40:1","stateMutability":"nonpayable","virtual":false,"visibility":"public"}],"scope":12,"src":"0:55:1","usedErrors":[]}],"src":"0:56:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/smoke.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"C":[1]},"id":2,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":1,"linearizedBaseContracts":[1],"name":"C","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[],"scope":2,"src":"0:13:1","usedErrors":[]}],"src":"0:14:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/string.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"C":[9]},"id":10,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":9,"linearizedBaseContracts":[9],"name":"C","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"body":{"id":7,"nodeType":"Block","src":"33:36:1","statements":[{"assignments":[4],"declarations":[{"constant":false,"id":4,"mutability":"mutable","name":"x","nameLocation":"49:1:1","nodeType":"VariableDeclaration","scope":7,"src":"35:15:1","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":3,"name":"string","nodeType":"ElementaryTypeName","src":"35:6:1","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"id":6,"initialValue":{"hexValue":"48656c6c6f20576f726c64","id":5,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"53:13:1","typeDescriptions":{"typeIdentifier":"t_stringliteral_592fa743889fc7f92ac2a37bb1f5ba1daf2a5c84741ca0e0061d243a2e6707ba","typeString":"literal_string \"Hello World\""},"value":"Hello World"},"nodeType":"VariableDeclarationStatement","src":"35:31:1"}]},"functionSelector":"26121ff0","id":8,"implemented":true,"kind":"function","modifiers":[],"name":"f","nameLocation":"22:1:1","nodeType":"FunctionDefinition","parameters":{"id":1,"nodeType":"ParameterList","parameters":[],"src":"23:2:1"},"returnParameters":{"id":2,"nodeType":"ParameterList","parameters":[],"src":"33:0:1"},"scope":9,"src":"13:56:1","stateMutability":"nonpayable","virtual":false,"visibility":"public"}],"scope":10,"src":"0:71:1","usedErrors":[]}],"src":"0:72:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/stringlit.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"C":[6]},"id":7,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":6,"linearizedBaseContracts":[6],"name":"C","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"body":{"id":4,"nodeType":"Block","src":"37:43:1","statements":[{"AST":{"nodeType":"YulBlock","src":"56:18:1","statements":[{"nodeType":"YulVariableDeclaration","src":"58:14:1","value":{"hexValue":"616263","kind":"string","nodeType":"YulLiteral","src":"67:5:1","type":"","value":"abc"},"variables":[{"name":"x","nodeType":"YulTypedName","src":"62:1:1","type":""}]}]},"evmVersion":"london","externalReferences":[],"id":3,"nodeType":"InlineAssembly","src":"47:27:1"}]},"functionSelector":"5a2ee019","id":5,"implemented":true,"kind":"function","modifiers":[],"name":"m","nameLocation":"26:1:1","nodeType":"FunctionDefinition","parameters":{"id":1,"nodeType":"ParameterList","parameters":[],"src":"27:2:1"},"returnParameters":{"id":2,"nodeType":"ParameterList","parameters":[],"src":"37:0:1"},"scope":6,"src":"17:63:1","stateMutability":"nonpayable","virtual":false,"visibility":"public"}],"scope":7,"src":"0:82:1","usedErrors":[]}],"src":"0:83:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/switch_default.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"C":[6]},"id":7,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":6,"linearizedBaseContracts":[6],"name":"C","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"body":{"id":4,"nodeType":"Block","src":"42:58:1","statements":[{"AST":{"nodeType":"YulBlock","src":"61:33:1","statements":[{"cases":[{"body":{"nodeType":"YulBlock","src":"79:2:1","statements":[]},"nodeType":"YulCase","src":"72:9:1","value":{"kind":"number","nodeType":"YulLiteral","src":"77:1:1","type":"","value":"0"}},{"body":{"nodeType":"YulBlock","src":"90:2:1","statements":[]},"nodeType":"YulCase","src":"82:10:1","value":"default"}],"expression":{"kind":"number","nodeType":"YulLiteral","src":"70:1:1","type":"","value":"0"},"nodeType":"YulSwitch","src":"63:29:1"}]},"evmVersion":"london","externalReferences":[],"id":3,"nodeType":"InlineAssembly","src":"52:42:1"}]},"functionSelector":"e2179b8e","id":5,"implemented":true,"kind":"function","modifiers":[],"name":"g","nameLocation":"26:1:1","nodeType":"FunctionDefinition","parameters":{"id":1,"nodeType":"ParameterList","parameters":[],"src":"27:2:1"},"returnParameters":{"id":2,"nodeType":"ParameterList","parameters":[],"src":"42:0:1"},"scope":6,"src":"17:83:1","stateMutability":"view","virtual":false,"visibility":"public"}],"scope":7,"src":"0:102:1","usedErrors":[]}],"src":"0:103:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/unicode.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"C":[9]},"id":10,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":9,"linearizedBaseContracts":[9],"name":"C","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"body":{"id":7,"nodeType":"Block","src":"33:42:1","statements":[{"assignments":[4],"declarations":[{"constant":false,"id":4,"mutability":"mutable","name":"x","nameLocation":"49:1:1","nodeType":"VariableDeclaration","scope":7,"src":"35:15:1","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":3,"name":"string","nodeType":"ElementaryTypeName","src":"35:6:1","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"id":6,"initialValue":{"hexValue":"48656c6c6f20f09f9883","id":5,"isConstant":false,"isLValue":false,"isPure":true,"kind":"unicodeString","lValueRequested":false,"nodeType":"Literal","src":"53:19:1","typeDescriptions":{"typeIdentifier":"t_stringliteral_cd7a99177cebb3d14b8cc54e313dbf76867c71cd6fbb9a33ce3870dc80e9992b","typeString":"literal_string hex\"48656c6c6f20f09f9883\""},"value":"Hello 😃"},"nodeType":"VariableDeclarationStatement","src":"35:37:1"}]},"functionSelector":"26121ff0","id":8,"implemented":true,"kind":"function","modifiers":[],"name":"f","nameLocation":"22:1:1","nodeType":"FunctionDefinition","parameters":{"id":1,"nodeType":"ParameterList","parameters":[],"src":"23:2:1"},"returnParameters":{"id":2,"nodeType":"ParameterList","parameters":[],"src":"33:0:1"},"scope":9,"src":"13:62:1","stateMutability":"nonpayable","virtual":false,"visibility":"public"}],"scope":10,"src":"0:77:1","usedErrors":[]}],"src":"0:78:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/yul_hex_literal.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"Sample":[6]},"id":7,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"Sample","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":6,"linearizedBaseContracts":[6],"name":"Sample","nameLocation":"9:6:1","nodeType":"ContractDefinition","nodes":[{"body":{"id":4,"nodeType":"Block","src":"47:167:1","statements":[{"AST":{"nodeType":"YulBlock","src":"66:142:1","statements":[{"nodeType":"YulVariableDeclaration","src":"80:15:1","value":{"hexValue":"74657374","kind":"string","nodeType":"YulLiteral","src":"89:6:1","type":"","value":"test"},"variables":[{"name":"a","nodeType":"YulTypedName","src":"84:1:1","type":""}]},{"nodeType":"YulVariableDeclaration","src":"108:54:1","value":{"hexValue":"112233445566778899aabbccddeeff6677889900","kind":"string","nodeType":"YulLiteral","src":"117:45:1","type":""},"variables":[{"name":"b","nodeType":"YulTypedName","src":"112:1:1","type":""}]},{"nodeType":"YulVariableDeclaration","src":"175:23:1","value":{"hexValue":"1234abcd","kind":"string","nodeType":"YulLiteral","src":"184:14:1","type":""},"variables":[{"name":"c","nodeType":"YulTypedName","src":"179:1:1","type":""}]}]},"evmVersion":"loop","externalReferences":[],"id":3,"nodeType":"InlineAssembly","src":"57:151:1"}]},"functionSelector":"26121ff0","id":5,"implemented":true,"kind":"function","modifiers":[],"name":"f","nameLocation":"31:1:1","nodeType":"FunctionDefinition","parameters":{"id":1,"nodeType":"ParameterList","parameters":[],"src":"32:2:1"},"returnParameters":{"id":2,"nodeType":"ParameterList","parameters":[],"src":"47:0:1"},"scope":6,"src":"22:192:1","stateMutability":"pure","virtual":false,"visibility":"public"}],"scope":7,"src":"0:216:1","usedErrors":[]}],"src":"0:217:1"} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/bytes.sol: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gakonst/ethers-rs/6e2ff0ef8af8c0ee3c21b7e1960f8c025bcd5588/ethers-solc/test-data/bytes.sol -------------------------------------------------------------------------------- /ethers-solc/test-data/cache-sample/Dapp.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity >=0.6.6; 3 | 4 | contract Dapp { 5 | 6 | function modified() public {} 7 | } 8 | -------------------------------------------------------------------------------- /ethers-solc/test-data/cache-sample/NewContract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity >=0.6.6; 3 | 4 | contract NewContract { 5 | } 6 | -------------------------------------------------------------------------------- /ethers-solc/test-data/dapp-sample/src/Dapp.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity >=0.6.6; 3 | 4 | contract Dapp { 5 | } 6 | -------------------------------------------------------------------------------- /ethers-solc/test-data/dapp-sample/src/Dapp.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity >=0.6.6; 3 | 4 | import "ds-test/test.sol"; 5 | 6 | import "./Dapp.sol"; 7 | 8 | contract DappTest is DSTest { 9 | Dapp dapp; 10 | 11 | function setUp() public { 12 | dapp = new Dapp(); 13 | } 14 | 15 | function testFail_basic_sanity() public { 16 | assertTrue(false); 17 | } 18 | 19 | function test_basic_sanity() public { 20 | assertTrue(true); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ethers-solc/test-data/foundryissue2462.json: -------------------------------------------------------------------------------- 1 | {"storage":[{"astId":3,"contract":"test-data/foundryissue2462.sol:Token","label":"x","offset":0,"slot":"0","type":"t_uint256"},{"astId":7,"contract":"test-data/foundryissue2462.sol:Token","label":"balances","offset":0,"slot":"1","type":"t_mapping(t_address,t_uint256)"},{"astId":13,"contract":"test-data/foundryissue2462.sol:Token","label":"allowances","offset":0,"slot":"2","type":"t_mapping(t_address,t_mapping(t_address,t_uint256))"}],"types":{"t_address":{"encoding":"inplace","label":"address","numberOfBytes":"20"},"t_mapping(t_address,t_mapping(t_address,t_uint256))":{"encoding":"mapping","key":"t_address","label":"mapping(address => mapping(address => uint256))","numberOfBytes":"32","value":"t_mapping(t_address,t_uint256)"},"t_mapping(t_address,t_uint256)":{"encoding":"mapping","key":"t_address","label":"mapping(address => uint256)","numberOfBytes":"32","value":"t_uint256"},"t_uint256":{"encoding":"inplace","label":"uint256","numberOfBytes":"32"}}} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/hardhat-sample/contracts/Greeter.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: Unlicense 2 | pragma solidity >=0.6.0; 3 | 4 | import "hardhat/console.sol"; 5 | 6 | contract Greeter { 7 | string private greeting; 8 | 9 | constructor(string memory _greeting) public { 10 | console.log("Deploying a Greeter with greeting:", _greeting); 11 | greeting = _greeting; 12 | } 13 | 14 | function greet() public view returns (string memory) { 15 | return greeting; 16 | } 17 | 18 | function setGreeting(string memory _greeting) public { 19 | console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); 20 | greeting = _greeting; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ethers-solc/test-data/in/compiler-in-1.json: -------------------------------------------------------------------------------- 1 | {"language":"Solidity","sources":{"contracts/Contract.sol":{"content":"pragma solidity >0.7.0;\n\ncontract Contract {\n}\n"}},"settings":{"optimizer":{"enabled":false,"runs":200},"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers"],"":["ast"]}}}} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/in/compiler-in-13.json: -------------------------------------------------------------------------------- 1 | {"language":"Solidity","sources":{"contracts/A.sol":{"content":"pragma solidity >0.5.1;\n\ncontract A {}\n"}},"settings":{"optimizer":{"enabled":false,"runs":200},"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers"],"":["ast"]}}}} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/in/compiler-in-14.json: -------------------------------------------------------------------------------- 1 | {"language":"Solidity","sources":{"contracts/A.sol":{"content":"pragma solidity >0.5.1;\n\ncontract A {}\n"}},"settings":{"optimizer":{"enabled":false,"runs":200},"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers"],"":["ast"]}}}} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/in/compiler-in-15.json: -------------------------------------------------------------------------------- 1 | {"language":"Solidity","sources":{"contracts/B.sol":{"content":"pragma solidity >0.6.1;\n\ncontract B {}\n"}},"settings":{"optimizer":{"enabled":false,"runs":200},"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers"],"":["ast"]}}}} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/in/compiler-in-16.json: -------------------------------------------------------------------------------- 1 | {"language":"Solidity","sources":{"contracts/a.sol":{"content":"contract A {}\n\n"}},"settings":{"optimizer":{"enabled":false,"runs":200},"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers"],"":["ast"]}}}} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/in/compiler-in-17.json: -------------------------------------------------------------------------------- 1 | {"language":"Solidity","sources":{"A.sol":{"content":"\npragma solidity >0.6.6;\ncontract A {}\n"}},"settings":{"evmVersion":"byzantium","metadata":{"useLiteralContent":true},"optimizer":{"runs":200,"enabled":false},"outputSelection":{"*":{"*":["evm.bytecode.object","abi"],"":["ast"]}}}} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/in/compiler-in-18.json: -------------------------------------------------------------------------------- 1 | {"language":"Solidity","sources":{"A.sol":{"content":"pragma sol"}},"settings":{"evmVersion":"byzantium","metadata":{"useLiteralContent":true},"optimizer":{"runs":200,"enabled":false},"outputSelection":{"*":{"*":["evm.bytecode.object","abi"],"":["ast"]}}}} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/in/compiler-in-21.json: -------------------------------------------------------------------------------- 1 | {"language":"Solidity","sources":{"contracts/Greeter.sol":{"content":"pragma solidity >0.5.1;\n\ncontract Greeter {\n\n string greeting;\n\n constructor() public {\n greeting = \"Hi\";\n }\n\n function setGreeting(string memory _greeting) public {\n greeting = _greeting;\n }\n\n function greet() public view returns (string memory) {\n return greeting;\n }\n\n}\n"}},"settings":{"optimizer":{"enabled":false,"runs":200},"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers"],"":["ast"]}}}} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/in/compiler-in-22.json: -------------------------------------------------------------------------------- 1 | {"language":"Solidity","sources":{"contracts/EVMInspector.sol":{"content":"pragma solidity >0.7.4;\n\ncontract EVMConsumer {\n\n uint256 theChainID;\n\n constructor() public {\n uint256 id;\n assembly {\n id := chainid()\n }\n theChainID = id;\n }\n\n}\n"}},"settings":{"optimizer":{"enabled":false,"runs":200},"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers"],"":["ast"]}}}} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/in/compiler-in-23.json: -------------------------------------------------------------------------------- 1 | {"language":"Solidity","sources":{"contracts/Greeter.sol":{"content":"pragma solidity >0.5.1;\n\n\ncontract Greeter {\n\n string greeting;\n string bad;\n constructor(string memory _greeting) public {\n greeting = _greeting;\n bad = \"baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaad\";\n }\n\n function greet() public view returns (string memory) {\n return greeting;\n }\n\n}\n"}},"settings":{"optimizer":{"enabled":false,"runs":200},"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers"],"":["ast"]}}}} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/in/compiler-in-7.json: -------------------------------------------------------------------------------- 1 | {"language":"Solidity","sources":{"contracts/Contract.sol":{"content":"pragma solidity >0.7.0;\n\ncontract Contract {\n}\n"}},"settings":{"optimizer":{"enabled":false,"runs":200},"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers"],"":["ast"]}}}} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/library-remapping-in-2.json: -------------------------------------------------------------------------------- 1 | {"language":"Solidity","sources":{"/private/var/folders/l5/lprhf87s6xv8djgd017f0b2h0000gn/T/can_create_on_goerli-0vd5EOs/lib/remapping/MyLib.sol":{"content":"\n// SPDX-License-Identifier: MIT\nlibrary MyLib {\n function foobar(uint256 a) public view returns (uint256) {\n \treturn a * 100;\n }\n}\n"},"/private/var/folders/l5/lprhf87s6xv8djgd017f0b2h0000gn/T/can_create_on_goerli-0vd5EOs/src/LinkTest.sol":{"content":"\n// SPDX-License-Identifier: MIT\nimport \"remapping/MyLib.sol\";\ncontract LinkTest {\n function foo() public returns (uint256) {\n return MyLib.foobar(1);\n }\n}\n"}},"settings":{"remappings":["remapping/=/private/var/folders/l5/lprhf87s6xv8djgd017f0b2h0000gn/T/can_create_on_goerli-0vd5EOs/lib/remapping/","src/=/private/var/folders/l5/lprhf87s6xv8djgd017f0b2h0000gn/T/can_create_on_goerli-0vd5EOs/src/"],"optimizer":{"enabled":true,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"outputSelection":{"*":{"":["ast"],"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers"]}},"evmVersion":"london","libraries":{"/private/var/folders/l5/lprhf87s6xv8djgd017f0b2h0000gn/T/can_create_on_goerli-0vd5EOs/lib/remapping/MyLib.sol":{"MyLib":"0x0000000000000000000000000000000000000000"}}}} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/library-remapping-in.json: -------------------------------------------------------------------------------- 1 | {"language":"Solidity","sources":{"/private/var/folders/l5/lprhf87s6xv8djgd017f0b2h0000gn/T/tmp_dappPyXsdD/lib/remapping/MyLib.sol":{"content":"\n// SPDX-License-Identifier: MIT\nlibrary MyLib {\n function foobar(uint256 a) public view returns (uint256) {\n \treturn a * 100;\n }\n}\n"},"/private/var/folders/l5/lprhf87s6xv8djgd017f0b2h0000gn/T/tmp_dappPyXsdD/src/LinkTest.sol":{"content":"\n// SPDX-License-Identifier: MIT\nimport \"remapping/MyLib.sol\";\ncontract LinkTest {\n function foo() public returns (uint256) {\n return MyLib.foobar(1);\n }\n}\n"}},"settings":{"remappings":["remapping/=/private/var/folders/l5/lprhf87s6xv8djgd017f0b2h0000gn/T/tmp_dappPyXsdD/lib/remapping/"],"optimizer":{"enabled":false,"runs":200},"outputSelection":{"*":{"":["ast"],"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers"]}},"evmVersion":"london","libraries":{"/private/var/folders/l5/lprhf87s6xv8djgd017f0b2h0000gn/T/tmp_dappPyXsdD/lib/remapping/MyLib.sol":{"MyLib":"0x0000000000000000000000000000000000000000"}}}} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/model-checker-sample/Assert.sol: -------------------------------------------------------------------------------- 1 | contract Assert { 2 | function f(uint x) public pure { 3 | assert(x > 0); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /ethers-solc/test-data/out/compiler-out-1.json: -------------------------------------------------------------------------------- 1 | {"errors":[{"sourceLocation":{"file":"sourceFile.sol","start":0,"end":100},"secondarySourceLocations":[{"file":"sourceFile.sol","start":64,"end":92,"message":"Other declaration is here:"}],"type":"TypeError","component":"general","severity":"error","errorCode":"3141","message":"Invalid keyword","formattedMessage":"sourceFile.sol:100: Invalid keyword"}],"sources":{"sourceFile.sol":{"id":1,"ast":{}}},"contracts":{"sourceFile.sol":{"ContractName":{"abi":[],"userdoc":{},"devdoc":{},"ir":"","storageLayout":{"storage":[],"types":{}},"evm":{"assembly":"","legacyAssembly":{},"bytecode":{"functionDebugData":{"@mint_13":{"entryPoint":128,"id":13,"parameterSlots":2,"returnSlots":1}},"object":"00fe","opcodes":"","sourceMap":"","generatedSources":[{"ast":{},"contents":"{ function abi_decode(start, end) -> data { data := calldataload(start) } }","id":2,"language":"Yul","name":"#utility.yul"}],"linkReferences":{"libraryFile.sol":{"Library1":[{"start":0,"length":20},{"start":200,"length":20}]}}},"deployedBytecode":{"immutableReferences":{"3":[{"start":42,"length":32},{"start":80,"length":32}]}},"methodIdentifiers":{"delegate(address)":"5c19a95c"},"gasEstimates":{"creation":{"codeDepositCost":"420000","executionCost":"infinite","totalCost":"infinite"},"external":{"delegate(address)":"25000"},"internal":{"heavyLifting()":"infinite"}}},"ewasm":{"wast":"","wasm":""}}}}} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/out/compiler-out-14.json: -------------------------------------------------------------------------------- 1 | {"contracts":{"contracts/A.sol":{"A":{"abi":[],"evm":{"bytecode":{"linkReferences":{},"object":"6080604052348015600f57600080fd5b50603e80601d6000396000f3fe6080604052600080fdfea265627a7a7231582049e7b4338422a1959c58d9c89a45d1229f35b0430073411a41b0e3bd6cd5fcd364736f6c634300050f0032","opcodes":"PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH1 0xF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x3E DUP1 PUSH1 0x1D PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x0 DUP1 REVERT INVALID LOG2 PUSH6 0x627A7A723158 KECCAK256 0x49 0xE7 0xB4 CALLER DUP5 0x22 LOG1 SWAP6 SWAP13 PC 0xD9 0xC8 SWAP11 GASLIMIT 0xD1 0x22 SWAP16 CALLDATALOAD 0xB0 NUMBER STOP PUSH20 0x411A41B0E3BD6CD5FCD364736F6C634300050F00 ORIGIN ","sourceMap":"25:13:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;25:13:0;;;;;;;"},"deployedBytecode":{"linkReferences":{},"object":"6080604052600080fdfea265627a7a7231582049e7b4338422a1959c58d9c89a45d1229f35b0430073411a41b0e3bd6cd5fcd364736f6c634300050f0032","opcodes":"PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x0 DUP1 REVERT INVALID LOG2 PUSH6 0x627A7A723158 KECCAK256 0x49 0xE7 0xB4 CALLER DUP5 0x22 LOG1 SWAP6 SWAP13 PC 0xD9 0xC8 SWAP11 GASLIMIT 0xD1 0x22 SWAP16 CALLDATALOAD 0xB0 NUMBER STOP PUSH20 0x411A41B0E3BD6CD5FCD364736F6C634300050F00 ORIGIN ","sourceMap":"25:13:0:-;;;;;"},"methodIdentifiers":{}}}}},"sources":{"contracts/A.sol":{"ast":{"absolutePath":"contracts/A.sol","exportedSymbols":{"A":[2]},"id":3,"nodeType":"SourceUnit","nodes":[{"id":1,"literals":["solidity","^","0.5",".1"],"nodeType":"PragmaDirective","src":"0:23:0"},{"baseContracts":[],"contractDependencies":[],"contractKind":"contract","documentation":null,"fullyImplemented":true,"id":2,"linearizedBaseContracts":[2],"name":"A","nodeType":"ContractDefinition","nodes":[],"scope":3,"src":"25:13:0"}],"src":"0:39:0"},"id":0}}} 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/test-contract-libs/lib1/bar/src/Bar.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.6; 2 | 3 | contract Bar {} 4 | -------------------------------------------------------------------------------- /ethers-solc/test-data/test-contract-libs/lib2/baz/src/Baz.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.6; 2 | 3 | contract Baz {} 4 | -------------------------------------------------------------------------------- /ethers-solc/test-data/test-contract-libs/src/Foo.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.6; 2 | 3 | import "bar/Bar.sol"; 4 | import "baz/Baz.sol"; 5 | 6 | contract Foo is Bar, Baz {} 7 | -------------------------------------------------------------------------------- /ethers-solc/test-data/test-contract-remappings/lib/bar/src/Bar.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.6; 2 | 3 | contract Bar {} 4 | -------------------------------------------------------------------------------- /ethers-solc/test-data/test-contract-remappings/src/Foo.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.6; 2 | 3 | import "bar/Bar.sol"; 4 | 5 | contract Foo is Bar {} 6 | -------------------------------------------------------------------------------- /ethers-solc/test-data/test-contract-versions/caret-0.4.14.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.14; 2 | 3 | contract B { 4 | function foo() public {} 5 | } 6 | -------------------------------------------------------------------------------- /ethers-solc/test-data/test-contract-versions/greater-equal-0.5.0.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | contract C { 4 | function foo() public {} 5 | } 6 | -------------------------------------------------------------------------------- /ethers-solc/test-data/test-contract-versions/pinned-0.4.14.sol: -------------------------------------------------------------------------------- 1 | pragma solidity =0.4.14; 2 | 3 | contract D { 4 | function foo() public {} 5 | } 6 | -------------------------------------------------------------------------------- /ethers-solc/test-data/test-contract-versions/range-0.5.0.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.0 <0.5.0; 2 | 3 | contract E { 4 | function foo() public {} 5 | } 6 | -------------------------------------------------------------------------------- /ethers-solc/test-data/test-contract-versions/simple-0.4.14.sol: -------------------------------------------------------------------------------- 1 | pragma solidity =0.4.14; 2 | 3 | contract F { 4 | function foo() public {} 5 | } 6 | -------------------------------------------------------------------------------- /ethers-solc/test-data/test-contract-warnings/LicenseWarning.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.6; 2 | 3 | contract LicenseWarning {} 4 | -------------------------------------------------------------------------------- /ethers-solc/test-data/test-flatten-duplicates/contracts/Bar.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: UNLICENSED 2 | pragma solidity >=0.6.0; 3 | 4 | contract Bar {} 5 | -------------------------------------------------------------------------------- /ethers-solc/test-data/test-flatten-duplicates/contracts/Foo.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: UNLICENSED 2 | pragma solidity >=0.6.0; 3 | 4 | import { Bar } from './Bar.sol'; 5 | 6 | contract Foo {} 7 | -------------------------------------------------------------------------------- /ethers-solc/test-data/test-flatten-duplicates/contracts/FooBar.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: UNLICENSED 2 | pragma solidity >=0.6.0; 3 | 4 | import { Bar } from './Bar.sol'; 5 | import { Foo } from './Foo.sol'; 6 | 7 | contract FooBar {} 8 | -------------------------------------------------------------------------------- /ethers-solc/test-data/test-flatten-solang-failure/contracts/Contract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.10; 3 | 4 | import { Lib } from "./Lib.sol"; 5 | 6 | // Intentionally erroneous code 7 | contract Contract { 8 | failure(); 9 | } 10 | -------------------------------------------------------------------------------- /ethers-solc/test-data/test-flatten-solang-failure/contracts/Lib.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.10; 3 | 4 | library Lib {} 5 | -------------------------------------------------------------------------------- /ethers-solc/test-data/test-versioned-linkrefs/lib/Lib.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity >0.4.0; 3 | 4 | contract Lib {} 5 | -------------------------------------------------------------------------------- /ethers-solc/test-data/test-versioned-linkrefs/src/FooV1.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity <=0.8.10; 3 | 4 | import "../lib/Lib.sol"; 5 | 6 | contract FooV1 {} 7 | -------------------------------------------------------------------------------- /ethers-solc/test-data/test-versioned-linkrefs/src/FooV2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity 0.8.11; 3 | 4 | import "../lib/Lib.sol"; 5 | 6 | contract FooV2 {} 7 | -------------------------------------------------------------------------------- /ethers-solc/test-data/yul-sample/Dapp.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity >=0.6.6; 3 | 4 | contract Dapp { 5 | 6 | function modified() public {} 7 | } 8 | -------------------------------------------------------------------------------- /ethers-solc/test-data/yul-sample/SimpleStore.yul: -------------------------------------------------------------------------------- 1 | object "SimpleStore" { 2 | code { 3 | datacopy(0, dataoffset("Runtime"), datasize("Runtime")) 4 | return(0, datasize("Runtime")) 5 | } 6 | object "Runtime" { 7 | code { 8 | calldatacopy(0, 0, 36) // write calldata to memory 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/anvil/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "examples-anvil" 3 | version = "0.0.0" 4 | publish = false 5 | authors = ["Andrea Simeoni "] 6 | 7 | license.workspace = true 8 | rust-version.workspace = true 9 | edition.workspace = true 10 | 11 | [dev-dependencies] 12 | ethers.workspace = true 13 | tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } 14 | eyre.workspace = true 15 | -------------------------------------------------------------------------------- /examples/anvil/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gakonst/ethers-rs/6e2ff0ef8af8c0ee3c21b7e1960f8c025bcd5588/examples/anvil/README.md -------------------------------------------------------------------------------- /examples/anvil/examples/anvil_fork.rs: -------------------------------------------------------------------------------- 1 | //! Spawn an [anvil](https://github.com/foundry-rs/foundry/tree/master/anvil) instance in forking mode 2 | 3 | use ethers::utils::Anvil; 4 | use eyre::Result; 5 | 6 | #[tokio::main] 7 | async fn main() -> Result<()> { 8 | // ensure `anvil` is available in $PATH 9 | let anvil = Anvil::new().fork("https://eth.llamarpc.com").spawn(); 10 | 11 | println!("Anvil running at `{}`", anvil.endpoint()); 12 | 13 | Ok(()) 14 | } 15 | -------------------------------------------------------------------------------- /examples/big-numbers/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "examples-big-numbers" 3 | version = "0.0.0" 4 | publish = false 5 | authors = ["Andrea Simeoni "] 6 | 7 | license.workspace = true 8 | rust-version.workspace = true 9 | edition.workspace = true 10 | 11 | [dev-dependencies] 12 | ethers.workspace = true 13 | -------------------------------------------------------------------------------- /examples/big-numbers/README.md: -------------------------------------------------------------------------------- 1 | # Big numbers 2 | Ethereum uses big numbers (also known as "bignums" or "arbitrary-precision integers") to represent certain values in its codebase and in blockchain transactions. This is necessary because [the EVM](https://ethereum.org/en/developers/docs/evm) operates on a 256-bit word size, which is different from the usual 32-bit or 64-bit of modern machines. This was chosen for the ease of use with 256-bit cryptography (such as Keccak-256 hashes or secp256k1 signatures). 3 | 4 | It is worth noting that Ethereum is not the only blockchain or cryptocurrency that uses big numbers. Many other blockchains and cryptocurrencies also use big numbers to represent values in their respective systems. 5 | 6 | ## Utilities 7 | In order to create an application, it is often necessary to convert between the representation of values that is easily understood by humans (such as ether) and the machine-readable form that is used by contracts and math functions (such as wei). This is particularly important when working with Ethereum, as certain values, such as balances and gas prices, must be expressed in wei when sending transactions, even if they are displayed to the user in a different format, such as ether or gwei. To help with this conversion, ethers-rs provides two functions, `parse_units` and `format_units`, which allow you to easily convert between human-readable and machine-readable forms of values. `parse_units` can be used to convert a string representing a value in ether, such as "1.1", into a big number in wei, which can be used in contracts and math functions. `format_units` can be used to convert a big number value into a human-readable string, which is useful for displaying values to users. 8 | -------------------------------------------------------------------------------- /examples/big-numbers/examples/comparison_equivalence.rs: -------------------------------------------------------------------------------- 1 | use ethers::types::U256; 2 | 3 | /// `U256` implements traits in `std::cmp`, that means `U256` instances 4 | /// can be easily compared using standard Rust operators. 5 | fn main() { 6 | // a == b 7 | let a = U256::from(100_u32); 8 | let b = U256::from(100_u32); 9 | assert!(a == b); 10 | 11 | // a < b 12 | let a = U256::from(1_u32); 13 | let b = U256::from(100_u32); 14 | assert!(a < b); 15 | 16 | // a <= b 17 | let a = U256::from(100_u32); 18 | let b = U256::from(100_u32); 19 | assert!(a <= b); 20 | 21 | // a > b 22 | let a = U256::from(100_u32); 23 | let b = U256::from(1_u32); 24 | assert!(a > b); 25 | 26 | // a >= b 27 | let a = U256::from(100_u32); 28 | let b = U256::from(100_u32); 29 | assert!(a >= b); 30 | 31 | // a == 0 32 | let a = U256::zero(); 33 | assert!(a.is_zero()); 34 | } 35 | -------------------------------------------------------------------------------- /examples/big-numbers/examples/conversion.rs: -------------------------------------------------------------------------------- 1 | use ethers::{types::U256, utils::format_units}; 2 | 3 | /// `U256` provides useful conversion functions to enable transformation into native Rust types. 4 | /// 5 | /// It is important to note that converting a big-number to a floating point type (such as a `f32` 6 | /// or `f64`) can result in a loss of precision, since you cannot fit 256 bits of information into 7 | /// 64 bits. 8 | /// 9 | /// However, there may be cases where you want to perform conversions for presentation purposes. 10 | /// For example, you may want to display a large number to the user in a more readable format. 11 | fn main() { 12 | let num = U256::from(42_u8); 13 | 14 | let a: u128 = num.as_u128(); 15 | assert_eq!(a, 42); 16 | 17 | let b: u64 = num.as_u64(); 18 | assert_eq!(b, 42); 19 | 20 | let c: u32 = num.as_u32(); 21 | assert_eq!(c, 42); 22 | 23 | let d: usize = num.as_usize(); 24 | assert_eq!(d, 42); 25 | 26 | let e: String = num.to_string(); 27 | assert_eq!(e, "42"); 28 | 29 | let f: String = format_units(num, 4).unwrap(); 30 | assert_eq!(f, "0.0042"); 31 | } 32 | -------------------------------------------------------------------------------- /examples/big-numbers/examples/create_instances.rs: -------------------------------------------------------------------------------- 1 | use ethers::{ 2 | types::{serde_helpers::Numeric, U256}, 3 | utils::{parse_units, ParseUnits}, 4 | }; 5 | 6 | fn main() { 7 | // From strings 8 | let a = U256::from_dec_str("42").unwrap(); 9 | assert_eq!(format!("{a:?}"), "42"); 10 | 11 | let amount = "42"; 12 | let units = 4; 13 | let pu: ParseUnits = parse_units(amount, units).unwrap(); 14 | let b = U256::from(pu); 15 | assert_eq!(format!("{b:?}"), "420000"); 16 | 17 | // From numbers 18 | let c = U256::from(42_u8); 19 | assert_eq!(format!("{c:?}"), "42"); 20 | 21 | let d = U256::from(42_u16); 22 | assert_eq!(format!("{d:?}"), "42"); 23 | 24 | let e = U256::from(42_u32); 25 | assert_eq!(format!("{e:?}"), "42"); 26 | 27 | let f = U256::from(42_u64); 28 | assert_eq!(format!("{f:?}"), "42"); 29 | 30 | let g = U256::from(42_u128); 31 | assert_eq!(format!("{g:?}"), "42"); 32 | 33 | let h = U256::from(0x2a); 34 | assert_eq!(format!("{h:?}"), "42"); 35 | 36 | let i: U256 = 42.into(); 37 | assert_eq!(format!("{i:?}"), "42"); 38 | 39 | // From `Numeric` 40 | let num: Numeric = Numeric::U256(U256::one()); 41 | let l = U256::from(num); 42 | assert_eq!(format!("{l:?}"), "1"); 43 | 44 | let num: Numeric = Numeric::Num(42); 45 | let m = U256::from(num); 46 | assert_eq!(format!("{m:?}"), "42"); 47 | } 48 | -------------------------------------------------------------------------------- /examples/contracts/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "examples-contracts" 3 | version = "0.0.0" 4 | publish = false 5 | authors = ["Andrea Simeoni "] 6 | 7 | license.workspace = true 8 | rust-version.workspace = true 9 | edition.workspace = true 10 | 11 | [dev-dependencies] 12 | ethers = { workspace = true, features = ["abigen", "rustls", "ws", "ethers-solc"] } 13 | 14 | tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } 15 | 16 | serde.workspace = true 17 | serde_json.workspace = true 18 | 19 | eyre.workspace = true 20 | -------------------------------------------------------------------------------- /examples/contracts/examples/abi/contract_abi.json: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"string","name":"value","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"author","type":"address"},{"indexed":false,"internalType":"string","name":"oldValue","type":"string"},{"indexed":false,"internalType":"string","name":"newValue","type":"string"}],"name":"ValueChanged","type":"event"},{"inputs":[],"name":"getValue","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"value","type":"string"}],"name":"setValue","outputs":[],"stateMutability":"nonpayable","type":"function"}] 2 | -------------------------------------------------------------------------------- /examples/contracts/examples/compile.rs: -------------------------------------------------------------------------------- 1 | use ethers::{prelude::Abigen, solc::Solc}; 2 | use eyre::Result; 3 | 4 | fn main() -> Result<()> { 5 | let mut args = std::env::args(); 6 | args.next().unwrap(); // skip program name 7 | 8 | let contract_name = args.next().unwrap_or_else(|| "SimpleStorage".to_owned()); 9 | let contract: String = args 10 | .next() 11 | .unwrap_or_else(|| "examples/contracts/examples/contracts/contract.sol".to_owned()); 12 | 13 | println!("Generating bindings for {contract}\n"); 14 | 15 | // compile it 16 | let abi = if contract.ends_with(".sol") { 17 | let contracts = Solc::default().compile_source(&contract)?; 18 | let abi = contracts.get(&contract, &contract_name).unwrap().abi.unwrap(); 19 | serde_json::to_string(abi).unwrap() 20 | } else { 21 | contract 22 | }; 23 | 24 | let bindings = Abigen::new(&contract_name, abi)?.generate()?; 25 | 26 | // print to stdout if no output arg is given 27 | if let Some(output_path) = args.next() { 28 | bindings.write_to_file(output_path)?; 29 | } else { 30 | bindings.write(&mut std::io::stdout())?; 31 | } 32 | 33 | Ok(()) 34 | } 35 | -------------------------------------------------------------------------------- /examples/contracts/examples/contracts/contract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Unlicense 2 | pragma solidity >=0.4.24; 3 | 4 | contract SimpleStorage { 5 | 6 | event ValueChanged(address indexed author, string oldValue, string newValue); 7 | 8 | string _value; 9 | 10 | constructor(string memory value) public { 11 | emit ValueChanged(msg.sender, _value, value); 12 | _value = value; 13 | } 14 | 15 | function getValue() view public returns (string memory) { 16 | return _value; 17 | } 18 | 19 | function setValue(string memory value) public { 20 | emit ValueChanged(msg.sender, _value, value); 21 | _value = value; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/contracts/examples/deploy_from_abi_and_bytecode.rs: -------------------------------------------------------------------------------- 1 | use ethers::{ 2 | contract::abigen, 3 | core::utils::Anvil, 4 | middleware::SignerMiddleware, 5 | providers::{Http, Provider}, 6 | signers::{LocalWallet, Signer}, 7 | }; 8 | use eyre::Result; 9 | use std::{sync::Arc, time::Duration}; 10 | 11 | // Generate the type-safe contract bindings by providing the json artifact 12 | // *Note*: this requires a `bytecode` and `abi` object in the `greeter.json` artifact: 13 | // `{"abi": [..], "bin": "..."}` , `{"abi": [..], "bytecode": {"object": "..."}}` or 14 | // `{"abi": [..], "bytecode": "..."}` this will embedd the bytecode in a variable `GREETER_BYTECODE` 15 | abigen!(Greeter, "ethers-contract/tests/solidity-contracts/greeter.json",); 16 | 17 | #[tokio::main] 18 | async fn main() -> Result<()> { 19 | // 1. compile the contract (note this requires that you are inside the `examples` directory) and 20 | // launch anvil 21 | let anvil = Anvil::new().spawn(); 22 | 23 | // 2. instantiate our wallet 24 | let wallet: LocalWallet = anvil.keys()[0].clone().into(); 25 | 26 | // 3. connect to the network 27 | let provider = 28 | Provider::::try_from(anvil.endpoint())?.interval(Duration::from_millis(10u64)); 29 | 30 | // 4. instantiate the client with the wallet 31 | let client = Arc::new(SignerMiddleware::new(provider, wallet.with_chain_id(anvil.chain_id()))); 32 | 33 | // 5. deploy contract 34 | let greeter_contract = 35 | Greeter::deploy(client, "Hello World!".to_string()).unwrap().send().await.unwrap(); 36 | 37 | // 6. call contract function 38 | let greeting = greeter_contract.greet().call().await.unwrap(); 39 | assert_eq!("Hello World!", greeting); 40 | 41 | Ok(()) 42 | } 43 | -------------------------------------------------------------------------------- /examples/contracts/examples/events_with_meta.rs: -------------------------------------------------------------------------------- 1 | use ethers::{ 2 | contract::abigen, 3 | core::types::Address, 4 | providers::{Provider, StreamExt, Ws}, 5 | }; 6 | use eyre::Result; 7 | use std::sync::Arc; 8 | 9 | // Generate the type-safe contract bindings by providing the ABI 10 | // definition in human readable format 11 | abigen!( 12 | ERC20, 13 | r#"[ 14 | event Transfer(address indexed src, address indexed dst, uint wad) 15 | ]"#, 16 | ); 17 | 18 | #[tokio::main] 19 | async fn main() -> Result<()> { 20 | let client = 21 | Provider::::connect("wss://mainnet.infura.io/ws/v3/c60b0bb42f8a4c6481ecd229eddaca27") 22 | .await?; 23 | 24 | let client = Arc::new(client); 25 | 26 | // WETH Token 27 | let address = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2".parse::
()?; 28 | let weth = ERC20::new(address, Arc::clone(&client)); 29 | 30 | // Subscribe Transfer events 31 | let events = weth.events().from_block(16232698); 32 | let mut stream = events.stream().await?.with_meta().take(1); 33 | while let Some(Ok((event, meta))) = stream.next().await { 34 | println!("src: {:?}, dst: {:?}, wad: {:?}", event.src, event.dst, event.wad); 35 | 36 | println!( 37 | r#"address: {:?}, 38 | block_number: {:?}, 39 | block_hash: {:?}, 40 | transaction_hash: {:?}, 41 | transaction_index: {:?}, 42 | log_index: {:?} 43 | "#, 44 | meta.address, 45 | meta.block_number, 46 | meta.block_hash, 47 | meta.transaction_hash, 48 | meta.transaction_index, 49 | meta.log_index 50 | ); 51 | } 52 | 53 | Ok(()) 54 | } 55 | -------------------------------------------------------------------------------- /examples/contracts/examples/instances.rs: -------------------------------------------------------------------------------- 1 | #[tokio::main] 2 | async fn main() {} 3 | -------------------------------------------------------------------------------- /examples/contracts/examples/methods.rs: -------------------------------------------------------------------------------- 1 | #[tokio::main] 2 | async fn main() {} 3 | -------------------------------------------------------------------------------- /examples/contracts/examples/methods_abi_and_structs.rs: -------------------------------------------------------------------------------- 1 | //! Main entry point for ContractMonitor 2 | 3 | use std::{sync::Arc, time::Duration}; 4 | 5 | use ethers::{ 6 | contract::abigen, 7 | core::{ 8 | types::{Address, U256}, 9 | utils::Anvil, 10 | }, 11 | middleware::SignerMiddleware, 12 | providers::{Http, Provider}, 13 | signers::LocalWallet, 14 | }; 15 | 16 | abigen!(VerifierContract, "ethers-contract/tests/solidity-contracts/verifier_abi.json"); 17 | 18 | /// This example only demonstrates how to use generated structs for solidity functions that 19 | /// have structs as input. 20 | #[tokio::main] 21 | async fn main() -> Result<(), Box> { 22 | let anvil = Anvil::new().spawn(); 23 | let provider = 24 | Provider::::try_from(anvil.endpoint())?.interval(Duration::from_millis(10u64)); 25 | let wallet: LocalWallet = anvil.keys()[0].clone().into(); 26 | 27 | let client = SignerMiddleware::new(provider, wallet); 28 | let client = Arc::new(client); 29 | 30 | let contract = VerifierContract::new(Address::zero(), client); 31 | 32 | // NOTE: this is all just dummy data 33 | let g1 = G1Point { x: U256::zero(), y: U256::zero() }; 34 | let g2 = G2Point { x: [U256::zero(), U256::zero()], y: [U256::zero(), U256::zero()] }; 35 | let vk = VerifyingKey { 36 | alfa_1: g1.clone(), 37 | beta_2: g2.clone(), 38 | gamma_2: g2.clone(), 39 | delta_2: g2.clone(), 40 | ic: vec![g1.clone()], 41 | }; 42 | let proof = Proof { a: g1.clone(), b: g2, c: g1 }; 43 | 44 | let _ = contract.verify(vec![], proof, vk); 45 | Ok(()) 46 | } 47 | -------------------------------------------------------------------------------- /examples/events/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "examples-events" 3 | version = "0.0.0" 4 | publish = false 5 | authors = ["Andrea Simeoni "] 6 | 7 | license.workspace = true 8 | rust-version.workspace = true 9 | edition.workspace = true 10 | 11 | [dev-dependencies] 12 | ethers = { workspace = true, features = ["rustls", "ws"] } 13 | 14 | tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } 15 | 16 | serde.workspace = true 17 | serde_json.workspace = true 18 | 19 | eyre.workspace = true 20 | -------------------------------------------------------------------------------- /examples/events/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gakonst/ethers-rs/6e2ff0ef8af8c0ee3c21b7e1960f8c025bcd5588/examples/events/README.md -------------------------------------------------------------------------------- /examples/events/examples/placeholder.rs: -------------------------------------------------------------------------------- 1 | #[tokio::main] 2 | async fn main() {} 3 | -------------------------------------------------------------------------------- /examples/events/examples/subscribe.rs: -------------------------------------------------------------------------------- 1 | use ethers::prelude::*; 2 | use eyre::Result; 3 | use serde::{Deserialize, Serialize}; 4 | use std::sync::Arc; 5 | 6 | const WSS_URL: &str = "wss://mainnet.infura.io/ws/v3/c60b0bb42f8a4c6481ecd229eddaca27"; 7 | 8 | #[derive(Clone, Debug, Serialize, Deserialize, EthEvent)] 9 | pub struct Transfer { 10 | #[ethevent(indexed)] 11 | pub from: Address, 12 | #[ethevent(indexed)] 13 | pub to: Address, 14 | pub tokens: U256, 15 | } 16 | 17 | /// This example shows how to subscribe to events using the Ws transport for a specific event 18 | #[tokio::main] 19 | async fn main() -> Result<()> { 20 | let provider = Provider::::connect(WSS_URL).await?; 21 | let provider = Arc::new(provider); 22 | let event = Transfer::new::<_, Provider>(Filter::new(), Arc::clone(&provider)); 23 | let mut transfers = event.subscribe().await?.take(5); 24 | while let Some(log) = transfers.next().await { 25 | println!("Transfer: {:?}", log); 26 | } 27 | 28 | Ok(()) 29 | } 30 | -------------------------------------------------------------------------------- /examples/geth/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "examples-geth" 3 | version = "0.0.0" 4 | publish = false 5 | authors = ["Andrea Simeoni "] 6 | 7 | license.workspace = true 8 | rust-version.workspace = true 9 | edition.workspace = true 10 | 11 | [dev-dependencies] 12 | ethers.workspace = true 13 | 14 | tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } 15 | 16 | serde.workspace = true 17 | serde_json.workspace = true 18 | 19 | eyre.workspace = true 20 | tempfile.workspace = true 21 | -------------------------------------------------------------------------------- /examples/geth/examples/clique.rs: -------------------------------------------------------------------------------- 1 | //! Instantiate `Geth` with Clique enabled. 2 | 3 | use ethers::{ 4 | core::{rand::thread_rng, utils::Geth}, 5 | signers::LocalWallet, 6 | }; 7 | use eyre::Result; 8 | 9 | #[tokio::main] 10 | async fn main() -> Result<()> { 11 | // Generate a random clique signer and set it on Geth. 12 | let data_dir = tempfile::tempdir().expect("should be able to create temp geth datadir"); 13 | let dir_path = data_dir.into_path(); 14 | println!("Using {}", dir_path.display()); 15 | 16 | // Create a random signer 17 | let key = LocalWallet::new(&mut thread_rng()); 18 | 19 | let clique_key = key.signer().clone(); 20 | let _geth = Geth::new() 21 | // set the signer 22 | .set_clique_private_key(clique_key) 23 | // must always set the chain id here 24 | .chain_id(199u64) 25 | // set the datadir to a temp dir 26 | .data_dir(dir_path) 27 | // spawn it 28 | .spawn(); 29 | 30 | Ok(()) 31 | } 32 | -------------------------------------------------------------------------------- /examples/middleware/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "examples-middleware" 3 | version = "0.0.0" 4 | publish = false 5 | authors = ["Andrea Simeoni "] 6 | 7 | license.workspace = true 8 | rust-version.workspace = true 9 | edition.workspace = true 10 | 11 | [dev-dependencies] 12 | ethers = { workspace = true, features = ["rustls", "etherscan"] } 13 | serde.workspace = true 14 | serde_json.workspace = true 15 | tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } 16 | async-trait.workspace = true 17 | thiserror.workspace = true 18 | eyre.workspace = true 19 | -------------------------------------------------------------------------------- /examples/middleware/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gakonst/ethers-rs/6e2ff0ef8af8c0ee3c21b7e1960f8c025bcd5588/examples/middleware/README.md -------------------------------------------------------------------------------- /examples/middleware/examples/policy.rs: -------------------------------------------------------------------------------- 1 | use ethers::{ 2 | core::{types::TransactionRequest, utils::Anvil}, 3 | middleware::{ 4 | policy::{PolicyMiddlewareError, RejectEverything}, 5 | MiddlewareBuilder, PolicyMiddleware, 6 | }, 7 | providers::{Http, Middleware, Provider}, 8 | }; 9 | use eyre::Result; 10 | 11 | /// Policy middleware is a way to inject custom logic into the process of sending transactions and 12 | /// interacting with contracts on the Ethereum blockchain. It allows you to define rules or policies 13 | /// that should be followed when performing these actions, and to customize the behavior of the 14 | /// library based on these policies. 15 | #[tokio::main] 16 | async fn main() -> Result<()> { 17 | let anvil = Anvil::new().spawn(); 18 | let endpoint = anvil.endpoint(); 19 | 20 | let provider = Provider::::try_from(endpoint)?; 21 | 22 | let accounts = provider.get_accounts().await?; 23 | let account = accounts[0]; 24 | let to = accounts[1]; 25 | let tx = TransactionRequest::new().from(account).to(to).value(1000); 26 | 27 | let policy = RejectEverything; 28 | let policy_middleware = provider.wrap_into(|p| PolicyMiddleware::new(p, policy)); 29 | 30 | match policy_middleware.send_transaction(tx, None).await { 31 | Err(e) => { 32 | // Given the RejectEverything policy, we expect to execute this branch 33 | assert!(matches!(e, PolicyMiddlewareError::PolicyError(()))) 34 | } 35 | _ => panic!("We don't expect this to happen!"), 36 | } 37 | 38 | Ok(()) 39 | } 40 | -------------------------------------------------------------------------------- /examples/middleware/examples/signer.rs: -------------------------------------------------------------------------------- 1 | use ethers::{ 2 | core::{types::TransactionRequest, utils::Anvil}, 3 | middleware::SignerMiddleware, 4 | providers::{Http, Middleware, Provider}, 5 | signers::{LocalWallet, Signer}, 6 | }; 7 | use eyre::Result; 8 | 9 | /// In Ethereum, transactions must be signed with a private key before they can be broadcast to the 10 | /// network. Ethers-rs provides a way to customize this process by allowing 11 | /// you to define a signer, called to sign transactions before they are sent. 12 | #[tokio::main] 13 | async fn main() -> Result<()> { 14 | let anvil = Anvil::new().spawn(); 15 | 16 | let wallet: LocalWallet = anvil.keys()[0].clone().into(); 17 | let wallet2: LocalWallet = anvil.keys()[1].clone().into(); 18 | 19 | // connect to the network 20 | let provider = Provider::::try_from(anvil.endpoint())?; 21 | 22 | // connect the wallet to the provider 23 | let client = SignerMiddleware::new(provider, wallet.with_chain_id(anvil.chain_id())); 24 | 25 | // craft the transaction 26 | let tx = TransactionRequest::new().to(wallet2.address()).value(10000); 27 | 28 | // send it! 29 | let pending_tx = client.send_transaction(tx, None).await?; 30 | 31 | // get the mined tx 32 | let receipt = pending_tx.await?.ok_or_else(|| eyre::format_err!("tx dropped from mempool"))?; 33 | let tx = client.get_transaction(receipt.transaction_hash).await?; 34 | 35 | println!("Sent tx: {}\n", serde_json::to_string(&tx)?); 36 | println!("Tx receipt: {}", serde_json::to_string(&receipt)?); 37 | 38 | Ok(()) 39 | } 40 | -------------------------------------------------------------------------------- /examples/middleware/examples/timelag.rs: -------------------------------------------------------------------------------- 1 | #[tokio::main] 2 | async fn main() {} 3 | -------------------------------------------------------------------------------- /examples/middleware/examples/transformer.rs: -------------------------------------------------------------------------------- 1 | #[tokio::main] 2 | async fn main() {} 3 | -------------------------------------------------------------------------------- /examples/providers/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "examples-providers" 3 | version = "0.0.0" 4 | publish = false 5 | authors = ["Andrea Simeoni "] 6 | 7 | license.workspace = true 8 | rust-version.workspace = true 9 | edition.workspace = true 10 | 11 | [dev-dependencies] 12 | ethers = { workspace = true, features = ["abigen", "ipc", "rustls", "ws"] } 13 | 14 | tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } 15 | async-trait.workspace = true 16 | reqwest.workspace = true 17 | url.workspace = true 18 | 19 | serde.workspace = true 20 | serde_json.workspace = true 21 | 22 | thiserror.workspace = true 23 | eyre.workspace = true 24 | -------------------------------------------------------------------------------- /examples/providers/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gakonst/ethers-rs/6e2ff0ef8af8c0ee3c21b7e1960f8c025bcd5588/examples/providers/README.md -------------------------------------------------------------------------------- /examples/providers/examples/http_jwt.rs: -------------------------------------------------------------------------------- 1 | use ethers::prelude::*; 2 | 3 | const RPC_URL: &str = "http://localhost:8551"; 4 | 5 | #[tokio::main] 6 | async fn main() -> eyre::Result<()> { 7 | connect_jwt().await?; 8 | Ok(()) 9 | } 10 | 11 | async fn connect_jwt() -> eyre::Result<()> { 12 | // An Http provider can be created from an http(s) URI. 13 | // In case of https you must add the "rustls" or "openssl" feature 14 | // to the ethers library dependency in `Cargo.toml`. 15 | let _provider = Provider::::try_from(RPC_URL)?; 16 | 17 | // Instantiate with auth to append basic authorization headers across requests 18 | let url = reqwest::Url::parse(RPC_URL)?; 19 | 20 | // Use a JWT signing key to generate a bearer token 21 | let jwt_secret = &[42; 32]; 22 | let secret = JwtKey::from_slice(jwt_secret).map_err(|err| eyre::eyre!("Invalid key: {err}"))?; 23 | let jwt_auth = JwtAuth::new(secret, None, None); 24 | let token = jwt_auth.generate_token()?; 25 | 26 | let auth = Authorization::bearer(token); 27 | let _provider = Http::new_with_auth(url, auth)?; 28 | 29 | Ok(()) 30 | } 31 | -------------------------------------------------------------------------------- /examples/providers/examples/ipc.rs: -------------------------------------------------------------------------------- 1 | //! The IPC (Inter-Process Communication) transport allows our program to communicate 2 | //! with a node over a local [Unix domain socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 3 | //! or [Windows named pipe](https://learn.microsoft.com/en-us/windows/win32/ipc/named-pipes). 4 | //! 5 | //! It functions much the same as a Ws connection. 6 | 7 | use ethers::prelude::*; 8 | use std::sync::Arc; 9 | 10 | abigen!( 11 | IUniswapV2Pair, 12 | "[function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast)]" 13 | ); 14 | 15 | #[tokio::main] 16 | async fn main() -> eyre::Result<()> { 17 | let provider = Provider::connect_ipc("~/.ethereum/geth.ipc").await?; 18 | let provider = Arc::new(provider); 19 | 20 | let pair_address: Address = "0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc".parse()?; 21 | let weth_usdc = IUniswapV2Pair::new(pair_address, provider.clone()); 22 | 23 | let block = provider.get_block_number().await?; 24 | println!("Current block: {block}"); 25 | 26 | let mut initial_reserves = weth_usdc.get_reserves().call().await?; 27 | println!("Initial reserves: {initial_reserves:?}"); 28 | 29 | let mut stream = provider.subscribe_blocks().await?; 30 | while let Some(block) = stream.next().await { 31 | println!("New block: {:?}", block.number); 32 | 33 | let reserves = weth_usdc.get_reserves().call().await?; 34 | if reserves != initial_reserves { 35 | println!("Reserves changed: old {initial_reserves:?} - new {reserves:?}"); 36 | initial_reserves = reserves; 37 | } 38 | } 39 | 40 | Ok(()) 41 | } 42 | -------------------------------------------------------------------------------- /examples/providers/examples/quorum.rs: -------------------------------------------------------------------------------- 1 | //! The `QuorumProvider` sends a request to multiple backends and only returns a value 2 | //! if the configured `Quorum` was reached. 3 | 4 | use ethers::{ 5 | core::utils::Anvil, 6 | providers::{Http, Middleware, Provider, Quorum, QuorumProvider, WeightedProvider, Ws}, 7 | }; 8 | use eyre::Result; 9 | use std::{str::FromStr, time::Duration}; 10 | 11 | #[tokio::main] 12 | async fn main() -> Result<()> { 13 | let anvil = Anvil::new().spawn(); 14 | 15 | // create a quorum provider with some providers 16 | let quorum = QuorumProvider::dyn_rpc() 17 | .add_provider(WeightedProvider::new(Box::new(Http::from_str(&anvil.endpoint())?))) 18 | .add_provider(WeightedProvider::with_weight( 19 | Box::new(Ws::connect(anvil.ws_endpoint()).await?), 20 | 2, 21 | )) 22 | .add_provider(WeightedProvider::with_weight( 23 | Box::new(Ws::connect(anvil.ws_endpoint()).await?), 24 | 2, 25 | )) 26 | // the quorum provider will yield the response if >50% of the weighted inner provider 27 | // returned the same value 28 | .quorum(Quorum::Majority) 29 | .build(); 30 | 31 | let provider = Provider::quorum(quorum).interval(Duration::from_millis(10u64)); 32 | 33 | let _ = provider.get_accounts().await?; 34 | 35 | Ok(()) 36 | } 37 | -------------------------------------------------------------------------------- /examples/providers/examples/retry.rs: -------------------------------------------------------------------------------- 1 | //! The RetryClient is a type that wraps around a JsonRpcClient and automatically retries failed 2 | //! requests using an exponential backoff and filtering based on a RetryPolicy. It presents as a 3 | //! JsonRpcClient, but with additional functionality for retrying requests. 4 | //! 5 | //! The RetryPolicy can be customized for specific applications and endpoints, mainly to handle 6 | //! rate-limiting errors. In addition to the RetryPolicy, errors caused by connectivity issues such 7 | //! as timed out connections or responses in the 5xx range can also be retried separately. 8 | 9 | use ethers::prelude::*; 10 | use reqwest::Url; 11 | use std::time::Duration; 12 | 13 | const RPC_URL: &str = "https://eth.llamarpc.com"; 14 | 15 | #[tokio::main] 16 | async fn main() -> eyre::Result<()> { 17 | let provider = Http::new(Url::parse(RPC_URL)?); 18 | 19 | let client = RetryClientBuilder::default() 20 | .rate_limit_retries(10) 21 | .timeout_retries(3) 22 | .initial_backoff(Duration::from_millis(500)) 23 | .build(provider, Box::::default()); 24 | 25 | // Send a JSON-RPC request for the latest block 26 | let block_num = "latest".to_string(); 27 | let txn_details = false; 28 | let params = (block_num, txn_details); 29 | 30 | let block: Block = 31 | JsonRpcClient::request(&client, "eth_getBlockByNumber", params).await?; 32 | 33 | println!("{block:?}"); 34 | 35 | Ok(()) 36 | } 37 | -------------------------------------------------------------------------------- /examples/providers/examples/rw.rs: -------------------------------------------------------------------------------- 1 | //! The RwClient wraps two data transports: the first is used for read operations, and the second 2 | //! one is used for write operations, that consume gas like sending transactions. 3 | 4 | use ethers::{prelude::*, utils::Anvil}; 5 | use url::Url; 6 | 7 | #[tokio::main] 8 | async fn main() -> eyre::Result<()> { 9 | let anvil = Anvil::new().spawn(); 10 | 11 | let http_url = Url::parse(&anvil.endpoint())?; 12 | let http = Http::new(http_url); 13 | 14 | let ws = Ws::connect(anvil.ws_endpoint()).await?; 15 | 16 | let _provider = Provider::rw(http, ws); 17 | 18 | Ok(()) 19 | } 20 | -------------------------------------------------------------------------------- /examples/providers/examples/ws.rs: -------------------------------------------------------------------------------- 1 | //! The Ws transport allows you to send JSON-RPC requests and receive responses over 2 | //! [WebSocket](https://en.wikipedia.org/wiki/WebSocket). 3 | //! 4 | //! This allows to interact with the network in real-time without the need for HTTP 5 | //! polling. 6 | 7 | use ethers::prelude::*; 8 | 9 | const WSS_URL: &str = "wss://mainnet.infura.io/ws/v3/c60b0bb42f8a4c6481ecd229eddaca27"; 10 | 11 | #[tokio::main] 12 | async fn main() -> eyre::Result<()> { 13 | // A Ws provider can be created from a ws(s) URI. 14 | // In case of wss you must add the "rustls" or "openssl" feature 15 | // to the ethers library dependency in `Cargo.toml`. 16 | let provider = Provider::::connect(WSS_URL).await?; 17 | 18 | let mut stream = provider.subscribe_blocks().await?.take(1); 19 | while let Some(block) = stream.next().await { 20 | println!("{:?}", block.hash); 21 | } 22 | 23 | Ok(()) 24 | } 25 | -------------------------------------------------------------------------------- /examples/queries/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "examples-queries" 3 | version = "0.0.0" 4 | publish = false 5 | authors = ["Andrea Simeoni "] 6 | 7 | license.workspace = true 8 | rust-version.workspace = true 9 | edition.workspace = true 10 | 11 | [dev-dependencies] 12 | ethers = { workspace = true, features = ["abigen", "ws", "rustls"] } 13 | 14 | tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } 15 | 16 | serde.workspace = true 17 | serde_json.workspace = true 18 | 19 | eyre.workspace = true 20 | -------------------------------------------------------------------------------- /examples/queries/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gakonst/ethers-rs/6e2ff0ef8af8c0ee3c21b7e1960f8c025bcd5588/examples/queries/README.md -------------------------------------------------------------------------------- /examples/queries/examples/paginated_logs.rs: -------------------------------------------------------------------------------- 1 | use ethers::{ 2 | core::{ 3 | abi::AbiDecode, 4 | types::{BlockNumber, Filter, U256}, 5 | }, 6 | providers::{Middleware, Provider, StreamExt, Ws}, 7 | }; 8 | use eyre::Result; 9 | use std::sync::Arc; 10 | 11 | #[tokio::main] 12 | async fn main() -> Result<()> { 13 | let client: Provider = 14 | Provider::::connect("wss://mainnet.infura.io/ws/v3/c60b0bb42f8a4c6481ecd229eddaca27") 15 | .await?; 16 | let client = Arc::new(client); 17 | 18 | let last_block = client.get_block(BlockNumber::Latest).await?.unwrap().number.unwrap(); 19 | println!("last_block: {last_block}"); 20 | 21 | let erc20_transfer_filter = 22 | Filter::new().from_block(last_block - 10000).event("Transfer(address,address,uint256)"); 23 | 24 | let mut stream = client.get_logs_paginated(&erc20_transfer_filter, 10).take(5); 25 | 26 | while let Some(res) = stream.next().await { 27 | let log = res?; 28 | println!( 29 | "block: {:?}, tx: {:?}, token: {:?}, from: {:?}, to: {:?}, amount: {:?}", 30 | log.block_number, 31 | log.transaction_hash, 32 | log.address, 33 | log.topics.get(1), 34 | log.topics.get(2), 35 | U256::decode(log.data) 36 | ); 37 | } 38 | 39 | Ok(()) 40 | } 41 | -------------------------------------------------------------------------------- /examples/queries/examples/uniswapv2_pair.rs: -------------------------------------------------------------------------------- 1 | use ethers::{ 2 | contract::abigen, 3 | core::types::Address, 4 | providers::{Http, Provider}, 5 | }; 6 | use eyre::Result; 7 | use std::sync::Arc; 8 | 9 | // Generate the type-safe contract bindings by providing the ABI 10 | // definition in human readable format 11 | abigen!( 12 | IUniswapV2Pair, 13 | r#"[ 14 | function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast) 15 | ]"#, 16 | ); 17 | 18 | #[tokio::main] 19 | async fn main() -> Result<()> { 20 | let client = Provider::::try_from("https://eth.llamarpc.com")?; 21 | let client = Arc::new(client); 22 | 23 | // ETH/USDT pair on Uniswap V2 24 | let address = "0x0d4a11d5EEaaC28EC3F61d100daF4d40471f1852".parse::
()?; 25 | let pair = IUniswapV2Pair::new(address, Arc::clone(&client)); 26 | 27 | // getReserves -> get_reserves 28 | let (reserve0, reserve1, _timestamp) = pair.get_reserves().call().await?; 29 | println!("Reserves (ETH, USDT): ({reserve0}, {reserve1})"); 30 | 31 | let mid_price = f64::powi(10.0, 18 - 6) * reserve1 as f64 / reserve0 as f64; 32 | println!("ETH/USDT price: {mid_price:.2}"); 33 | Ok(()) 34 | } 35 | -------------------------------------------------------------------------------- /examples/subscriptions/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "examples-subscriptions" 3 | version = "0.0.0" 4 | publish = false 5 | authors = ["Andrea Simeoni "] 6 | 7 | license.workspace = true 8 | rust-version.workspace = true 9 | edition.workspace = true 10 | 11 | [dev-dependencies] 12 | ethers = { workspace = true, features = ["abigen", "ws", "rustls"] } 13 | 14 | tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } 15 | 16 | serde.workspace = true 17 | serde_json.workspace = true 18 | 19 | eyre.workspace = true 20 | -------------------------------------------------------------------------------- /examples/subscriptions/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gakonst/ethers-rs/6e2ff0ef8af8c0ee3c21b7e1960f8c025bcd5588/examples/subscriptions/README.md -------------------------------------------------------------------------------- /examples/subscriptions/examples/subscribe_blocks.rs: -------------------------------------------------------------------------------- 1 | use ethers::providers::{Middleware, Provider, StreamExt, Ws}; 2 | use eyre::Result; 3 | 4 | #[tokio::main] 5 | async fn main() -> Result<()> { 6 | let provider = 7 | Provider::::connect("wss://mainnet.infura.io/ws/v3/c60b0bb42f8a4c6481ecd229eddaca27") 8 | .await?; 9 | let mut stream = provider.subscribe_blocks().await?.take(1); 10 | while let Some(block) = stream.next().await { 11 | println!( 12 | "Ts: {:?}, block number: {} -> {:?}", 13 | block.timestamp, 14 | block.number.unwrap(), 15 | block.hash.unwrap() 16 | ); 17 | } 18 | 19 | Ok(()) 20 | } 21 | -------------------------------------------------------------------------------- /examples/subscriptions/examples/subscribe_logs.rs: -------------------------------------------------------------------------------- 1 | use ethers::{ 2 | core::{ 3 | abi::AbiDecode, 4 | types::{Address, BlockNumber, Filter, U256}, 5 | }, 6 | providers::{Middleware, Provider, StreamExt, Ws}, 7 | }; 8 | use eyre::Result; 9 | use std::sync::Arc; 10 | 11 | #[tokio::main] 12 | async fn main() -> Result<()> { 13 | let client = 14 | Provider::::connect("wss://mainnet.infura.io/ws/v3/c60b0bb42f8a4c6481ecd229eddaca27") 15 | .await?; 16 | let client = Arc::new(client); 17 | 18 | let last_block = client.get_block(BlockNumber::Latest).await?.unwrap().number.unwrap(); 19 | println!("last_block: {last_block}"); 20 | 21 | let erc20_transfer_filter = 22 | Filter::new().from_block(last_block - 25).event("Transfer(address,address,uint256)"); 23 | 24 | let mut stream = client.subscribe_logs(&erc20_transfer_filter).await?.take(2); 25 | 26 | while let Some(log) = stream.next().await { 27 | println!( 28 | "block: {:?}, tx: {:?}, token: {:?}, from: {:?}, to: {:?}, amount: {:?}", 29 | log.block_number, 30 | log.transaction_hash, 31 | log.address, 32 | Address::from(log.topics[1]), 33 | Address::from(log.topics[2]), 34 | U256::decode(log.data) 35 | ); 36 | } 37 | 38 | Ok(()) 39 | } 40 | -------------------------------------------------------------------------------- /examples/transactions/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "examples-transactions" 3 | version = "0.0.0" 4 | publish = false 5 | authors = ["Andrea Simeoni "] 6 | 7 | license.workspace = true 8 | rust-version.workspace = true 9 | edition.workspace = true 10 | 11 | [dev-dependencies] 12 | ethers = { workspace = true, features = ["abigen", "ws", "rustls", "ethers-solc"] } 13 | 14 | tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } 15 | 16 | serde.workspace = true 17 | serde_json.workspace = true 18 | 19 | eyre.workspace = true 20 | -------------------------------------------------------------------------------- /examples/transactions/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gakonst/ethers-rs/6e2ff0ef8af8c0ee3c21b7e1960f8c025bcd5588/examples/transactions/README.md -------------------------------------------------------------------------------- /examples/transactions/examples/contracts/erc20_example/@openzeppelin/contracts/README.md: -------------------------------------------------------------------------------- 1 | # OpenZeppelin Contracts 2 | 3 | The files in this directory were sourced unmodified from OpenZeppelin Contracts v4.7.3. 4 | 5 | They are not meant to be edited. 6 | 7 | The originals can be found on [GitHub] and [npm]. 8 | 9 | [GitHub]: https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v4.7.3 10 | [npm]: https://www.npmjs.com/package/@openzeppelin/contracts/v/4.7.3 11 | 12 | Generated with OpenZeppelin Contracts Wizard (https://zpl.in/wizard). 13 | -------------------------------------------------------------------------------- /examples/transactions/examples/contracts/erc20_example/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | import "../IERC20.sol"; 7 | 8 | /** 9 | * @dev Interface for the optional metadata functions from the ERC20 standard. 10 | * 11 | * _Available since v4.1._ 12 | */ 13 | interface IERC20Metadata is IERC20 { 14 | /** 15 | * @dev Returns the name of the token. 16 | */ 17 | function name() external view returns (string memory); 18 | 19 | /** 20 | * @dev Returns the symbol of the token. 21 | */ 22 | function symbol() external view returns (string memory); 23 | 24 | /** 25 | * @dev Returns the decimals places of the token. 26 | */ 27 | function decimals() external view returns (uint8); 28 | } 29 | -------------------------------------------------------------------------------- /examples/transactions/examples/contracts/erc20_example/@openzeppelin/contracts/utils/Context.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | /** 7 | * @dev Provides information about the current execution context, including the 8 | * sender of the transaction and its data. While these are generally available 9 | * via msg.sender and msg.data, they should not be accessed in such a direct 10 | * manner, since when dealing with meta-transactions the account sending and 11 | * paying for execution may not be the actual sender (as far as an application 12 | * is concerned). 13 | * 14 | * This contract is only required for intermediate, library-like contracts. 15 | */ 16 | abstract contract Context { 17 | function _msgSender() internal view virtual returns (address) { 18 | return msg.sender; 19 | } 20 | 21 | function _msgData() internal view virtual returns (bytes calldata) { 22 | return msg.data; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/transactions/examples/contracts/erc20_example/ERC20Example.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | import "./@openzeppelin/contracts/token/ERC20/ERC20.sol"; 5 | 6 | contract ERC20Example is ERC20 { 7 | constructor() ERC20("ERC20Example", "XYZ") { 8 | _mint(msg.sender, 1000 * 10 ** decimals()); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/transactions/examples/decode_input.rs: -------------------------------------------------------------------------------- 1 | use ethers::{ 2 | contract::abigen, 3 | core::{abi::AbiDecode, types::Bytes}, 4 | }; 5 | use eyre::Result; 6 | 7 | // Abigen creates a SwapExactTokensForTokensCall struct that can be used to decode 8 | // the call data for the swapExactTokensForTokens function in the IUniswapV2Router02 contract 9 | abigen!( 10 | IUniswapV2Router02, 11 | r#"[ 12 | swapExactTokensForTokens(uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline) 13 | ]"#, 14 | ); 15 | fn main() -> Result<()> { 16 | println!("Decoding https://etherscan.io/tx/0xd1b449d8b1552156957309bffb988924569de34fbf21b51e7af31070cc80fe9a"); 17 | let tx_input = "0x38ed173900000000000000000000000000000000000000000001a717cc0a3e4f84c00000000000000000000000000000000000000000000000000000000000000283568400000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000201f129111c60401630932d9f9811bd5b5fff34e000000000000000000000000000000000000000000000000000000006227723d000000000000000000000000000000000000000000000000000000000000000200000000000000000000000095ad61b0a150d79219dcf64e1e6cc01f0b64c4ce000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7"; 18 | let calldata: Bytes = tx_input.parse().unwrap(); 19 | let decoded = SwapExactTokensForTokensCall::decode(&calldata)?; 20 | let mut path = decoded.path.into_iter(); 21 | let from = path.next().unwrap(); 22 | let to = path.next().unwrap(); 23 | println!( 24 | "Swapped {} of token {from} for {} of token {to}", 25 | decoded.amount_in, decoded.amount_out_min 26 | ); 27 | 28 | Ok(()) 29 | } 30 | -------------------------------------------------------------------------------- /examples/transactions/examples/ens.rs: -------------------------------------------------------------------------------- 1 | use ethers::{ 2 | core::{types::TransactionRequest, utils::Anvil}, 3 | providers::{Http, Middleware, Provider}, 4 | }; 5 | use eyre::Result; 6 | 7 | #[tokio::main] 8 | async fn main() -> Result<()> { 9 | // fork mainnet 10 | let anvil = Anvil::new().fork("https://eth.llamarpc.com").spawn(); 11 | let from = anvil.addresses()[0]; 12 | // connect to the network 13 | let provider = Provider::::try_from(anvil.endpoint()).unwrap().with_sender(from); 14 | 15 | // craft the transaction 16 | let tx = TransactionRequest::new().to("vitalik.eth").value(100_000); 17 | 18 | // send it! 19 | let receipt = provider 20 | .send_transaction(tx, None) 21 | .await? 22 | .await? 23 | .ok_or_else(|| eyre::format_err!("tx dropped from mempool"))?; 24 | let tx = provider.get_transaction(receipt.transaction_hash).await?; 25 | 26 | println!("{}", serde_json::to_string(&tx)?); 27 | println!("{}", serde_json::to_string(&receipt)?); 28 | 29 | Ok(()) 30 | } 31 | -------------------------------------------------------------------------------- /examples/transactions/examples/trace_call.rs: -------------------------------------------------------------------------------- 1 | use ethers::{ 2 | core::types::GethDebugTracingOptions, 3 | providers::{Http, Middleware, Provider}, 4 | types::{ 5 | Address, BlockId, Bytes, GethDebugBuiltInTracerType, GethDebugTracerType, 6 | GethDebugTracingCallOptions, TransactionRequest, 7 | }, 8 | }; 9 | use eyre::Result; 10 | use std::str::FromStr; 11 | 12 | /// use `debug_traceCall` to fetch traces 13 | /// requires, a valid endpoint in `RPC_URL` env var that supports `debug_traceCall` 14 | #[tokio::main] 15 | async fn main() -> Result<()> { 16 | if let Ok(url) = std::env::var("RPC_URL") { 17 | let client = Provider::::try_from(url)?; 18 | let tx = TransactionRequest::new().from(Address::from_str("0xdeadbeef29292929192939494959594933929292").unwrap()).to(Address::from_str("0xde929f939d939d393f939393f93939f393929023").unwrap()).gas("0x7a120").data(Bytes::from_str("0xf00d4b5d00000000000000000000000001291230982139282304923482304912923823920000000000000000000000001293123098123928310239129839291010293810").unwrap()); 19 | let block = BlockId::from(16213100); 20 | let options: GethDebugTracingCallOptions = GethDebugTracingCallOptions { 21 | tracing_options: GethDebugTracingOptions { 22 | disable_storage: Some(true), 23 | enable_memory: Some(false), 24 | tracer: Some(GethDebugTracerType::BuiltInTracer( 25 | GethDebugBuiltInTracerType::CallTracer, 26 | )), 27 | ..Default::default() 28 | }, 29 | state_overrides: None, 30 | block_overrides: None, 31 | }; 32 | let traces = client.debug_trace_call(tx, Some(block), options).await?; 33 | println!("{traces:?}"); 34 | } 35 | 36 | Ok(()) 37 | } 38 | -------------------------------------------------------------------------------- /examples/transactions/examples/transfer_eth.rs: -------------------------------------------------------------------------------- 1 | use ethers::{ 2 | core::{types::TransactionRequest, utils::Anvil}, 3 | providers::{Http, Middleware, Provider}, 4 | }; 5 | use eyre::Result; 6 | 7 | #[tokio::main] 8 | async fn main() -> Result<()> { 9 | let anvil = Anvil::new().spawn(); 10 | 11 | // connect to the network 12 | let provider = Provider::::try_from(anvil.endpoint())?; 13 | let accounts = provider.get_accounts().await?; 14 | let from = accounts[0]; 15 | let to = accounts[1]; 16 | 17 | // craft the tx 18 | let tx = TransactionRequest::new().to(to).value(1000).from(from); // specify the `from` field so that the client knows which account to use 19 | 20 | let balance_before = provider.get_balance(from, None).await?; 21 | let nonce1 = provider.get_transaction_count(from, None).await?; 22 | 23 | // broadcast it via the eth_sendTransaction API 24 | let tx = provider.send_transaction(tx, None).await?.await?; 25 | 26 | println!("{}", serde_json::to_string(&tx)?); 27 | 28 | let nonce2 = provider.get_transaction_count(from, None).await?; 29 | 30 | assert!(nonce1 < nonce2); 31 | 32 | let balance_after = provider.get_balance(from, None).await?; 33 | assert!(balance_after < balance_before); 34 | 35 | println!("Balance before {balance_before}"); 36 | println!("Balance after {balance_after}"); 37 | 38 | Ok(()) 39 | } 40 | -------------------------------------------------------------------------------- /examples/wallets/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "examples-wallets" 3 | version = "0.0.0" 4 | publish = false 5 | authors = ["Andrea Simeoni "] 6 | 7 | license.workspace = true 8 | rust-version.workspace = true 9 | edition.workspace = true 10 | 11 | [dev-dependencies] 12 | ethers = { workspace = true, features = ["abigen", "ws", "rustls", "ledger", "trezor", "yubi"] } 13 | 14 | tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } 15 | 16 | serde.workspace = true 17 | serde_json.workspace = true 18 | 19 | eyre.workspace = true 20 | -------------------------------------------------------------------------------- /examples/wallets/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gakonst/ethers-rs/6e2ff0ef8af8c0ee3c21b7e1960f8c025bcd5588/examples/wallets/README.md -------------------------------------------------------------------------------- /examples/wallets/examples/ledger.rs: -------------------------------------------------------------------------------- 1 | #[tokio::main] 2 | async fn main() -> Result<(), Box> { 3 | use ethers::{prelude::*, utils::parse_ether}; 4 | 5 | // Connect over websockets 6 | let provider = Provider::new(Ws::connect("ws://localhost:8545").await?); 7 | // Instantiate the connection to ledger with Ledger Live derivation path and 8 | // the wallet's index. Alternatively, you may use Legacy with the wallet's 9 | // index or supply the full HD path string. You may also provide the chain_id 10 | // (here: mainnet) for EIP155 support. 11 | let ledger = Ledger::new(HDPath::LedgerLive(0), 1).await?; 12 | let client = SignerMiddleware::new(provider, ledger); 13 | 14 | // Create and broadcast a transaction (ENS enabled!) 15 | // (this will require confirming the tx on the device) 16 | let tx = TransactionRequest::new().to("vitalik.eth").value(parse_ether(10)?); 17 | let pending_tx = client.send_transaction(tx, None).await?; 18 | 19 | // Get the receipt 20 | let _receipt = pending_tx.confirmations(3).await?; 21 | Ok(()) 22 | } 23 | -------------------------------------------------------------------------------- /examples/wallets/examples/local_signer.rs: -------------------------------------------------------------------------------- 1 | use ethers::{ 2 | core::{types::TransactionRequest, utils::Anvil}, 3 | middleware::SignerMiddleware, 4 | providers::{Http, Middleware, Provider}, 5 | signers::{LocalWallet, Signer}, 6 | }; 7 | use eyre::Result; 8 | 9 | #[tokio::main] 10 | async fn main() -> Result<()> { 11 | let anvil = Anvil::new().spawn(); 12 | 13 | let wallet: LocalWallet = anvil.keys()[0].clone().into(); 14 | let wallet2: LocalWallet = anvil.keys()[1].clone().into(); 15 | 16 | // connect to the network 17 | let provider = Provider::::try_from(anvil.endpoint())?; 18 | 19 | // connect the wallet to the provider 20 | let client = SignerMiddleware::new(provider, wallet.with_chain_id(anvil.chain_id())); 21 | 22 | // craft the transaction 23 | let tx = TransactionRequest::new().to(wallet2.address()).value(10000); 24 | 25 | // send it! 26 | let pending_tx = client.send_transaction(tx, None).await?; 27 | 28 | // get the mined tx 29 | let receipt = pending_tx.await?.ok_or_else(|| eyre::format_err!("tx dropped from mempool"))?; 30 | let tx = client.get_transaction(receipt.transaction_hash).await?; 31 | 32 | println!("Sent tx: {}\n", serde_json::to_string(&tx)?); 33 | println!("Tx receipt: {}", serde_json::to_string(&receipt)?); 34 | 35 | Ok(()) 36 | } 37 | -------------------------------------------------------------------------------- /examples/wallets/examples/mnemonic.rs: -------------------------------------------------------------------------------- 1 | use ethers::{ 2 | core::rand, 3 | signers::{coins_bip39::English, MnemonicBuilder}, 4 | }; 5 | use eyre::Result; 6 | 7 | fn main() -> Result<()> { 8 | let phrase = "work man father plunge mystery proud hollow address reunion sauce theory bonus"; 9 | let index = 0u32; 10 | let password = "TREZOR123"; 11 | 12 | // Access mnemonic phrase with password 13 | // Child key at derivation path: m/44'/60'/0'/0/{index} 14 | let wallet = MnemonicBuilder::::default() 15 | .phrase(phrase) 16 | .index(index)? 17 | // Use this if your mnemonic is encrypted 18 | .password(password) 19 | .build()?; 20 | 21 | eprintln!("Wallet: {wallet:?}"); 22 | 23 | // Generate a random wallet (24 word phrase) at custom derivation path 24 | let mut rng = rand::thread_rng(); 25 | let wallet = MnemonicBuilder::::default() 26 | .word_count(24) 27 | .derivation_path("m/44'/60'/0'/2/1")? 28 | // Optionally add this if you want the generated mnemonic to be written 29 | // to a file 30 | // .write_to(path) 31 | .build_random(&mut rng)?; 32 | 33 | eprintln!("Random wallet: {wallet:?}"); 34 | 35 | Ok(()) 36 | } 37 | -------------------------------------------------------------------------------- /examples/wallets/examples/permit_hash.rs: -------------------------------------------------------------------------------- 1 | use ethers::{ 2 | contract::{Eip712, EthAbiType}, 3 | core::{ 4 | types::{transaction::eip712::Eip712, Address, U256}, 5 | utils::hex, 6 | }, 7 | }; 8 | 9 | // Generate the EIP712 permit hash to sign for a Uniswap V2 pair. 10 | // 11 | // 12 | #[derive(Eip712, EthAbiType, Clone)] 13 | #[eip712( 14 | name = "Uniswap V2", 15 | version = "1", 16 | chain_id = 1, 17 | verifying_contract = "0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc" 18 | )] 19 | struct Permit { 20 | owner: Address, 21 | spender: Address, 22 | value: U256, 23 | nonce: U256, 24 | deadline: U256, 25 | } 26 | 27 | fn main() { 28 | let permit = Permit { 29 | owner: Address::random(), 30 | spender: Address::random(), 31 | value: 100.into(), 32 | nonce: 0.into(), 33 | deadline: U256::MAX, 34 | }; 35 | let permit_hash = permit.encode_eip712().unwrap(); 36 | println!("Permit hash: 0x{}", hex::encode(permit_hash)); 37 | } 38 | -------------------------------------------------------------------------------- /examples/wallets/examples/sign_message.rs: -------------------------------------------------------------------------------- 1 | // use the eyre crate for easy idiomatic error handling 2 | use eyre::Result; 3 | // use the ethers_core rand for rng 4 | use ethers::core::rand::thread_rng; 5 | // use the ethers_signers crate to manage LocalWallet and Signer 6 | use ethers::signers::{LocalWallet, Signer}; 7 | 8 | // Use the `tokio::main` macro for using async on the main function 9 | #[tokio::main] 10 | async fn main() -> Result<()> { 11 | // Generate a random wallet 12 | let wallet = LocalWallet::new(&mut thread_rng()); 13 | 14 | // Declare the message you want to sign. 15 | let message = "Some data"; 16 | 17 | // sign message from your wallet and print out signature produced. 18 | let signature = wallet.sign_message(message).await?; 19 | println!("Produced signature {signature}"); 20 | 21 | // verify the signature produced from your wallet. 22 | signature.verify(message, wallet.address()).unwrap(); 23 | println!("Verified signature produced by {:?}!", wallet.address()); 24 | 25 | Ok(()) 26 | } 27 | -------------------------------------------------------------------------------- /examples/wallets/examples/trezor.rs: -------------------------------------------------------------------------------- 1 | #[tokio::main] 2 | async fn main() -> Result<(), Box> { 3 | use ethers::{prelude::*, utils::parse_ether}; 4 | 5 | // Connect over websockets 6 | let provider = Provider::new(Ws::connect("ws://localhost:8545").await?); 7 | // Instantiate the connection to trezor with Trezor Live derivation path and 8 | // the wallet's index. You may also provide the chain_id. 9 | // (here: mainnet) for EIP155 support. 10 | // EIP1559 support 11 | // No EIP712 support yet. 12 | let trezor = Trezor::new(TrezorHDPath::TrezorLive(0), 1, None).await?; 13 | let client = SignerMiddleware::new(provider, trezor); 14 | 15 | // Create and broadcast a transaction (ENS disabled!) 16 | // (this will require confirming the tx on the device) 17 | let tx = TransactionRequest::new() 18 | .to("0x99E2B13A8Ea8b00C68FA017ee250E98e870D8241") 19 | .value(parse_ether(10)?); 20 | let pending_tx = client.send_transaction(tx, None).await?; 21 | 22 | // Get the receipt 23 | let _receipt = pending_tx.confirmations(3).await?; 24 | Ok(()) 25 | } 26 | -------------------------------------------------------------------------------- /examples/wallets/examples/yubi.rs: -------------------------------------------------------------------------------- 1 | #[tokio::main] 2 | async fn main() -> Result<(), Box> { 3 | use ethers::{prelude::*, utils::parse_ether}; 4 | use yubihsm::{Connector, Credentials, UsbConfig}; 5 | 6 | // Connect over websockets 7 | let provider = Provider::new(Ws::connect("ws://localhost:8545").await?); 8 | 9 | // We use USB for the example, but you can connect over HTTP as well. Refer 10 | // to the [YubiHSM](https://docs.rs/yubihsm/0.34.0/yubihsm/) docs for more info 11 | let connector = Connector::usb(&UsbConfig::default()); 12 | // Instantiate the connection to the YubiKey. Alternatively, use the 13 | // `from_key` method to upload a key you already have, or the `new` method 14 | // to generate a new keypair. 15 | let wallet = YubiWallet::connect(connector, Credentials::default(), 0); 16 | let client = SignerMiddleware::new(provider, wallet); 17 | 18 | // Create and broadcast a transaction (ENS enabled!) 19 | let tx = TransactionRequest::new().to("vitalik.eth").value(parse_ether(10)?); 20 | let pending_tx = client.send_transaction(tx, None).await?; 21 | 22 | // Get the receipt 23 | let _receipt = pending_tx.confirmations(3).await?; 24 | Ok(()) 25 | } 26 | -------------------------------------------------------------------------------- /examples/wasm/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | bin/ 5 | pkg/ 6 | wasm-pack.log 7 | node_modules/ 8 | yarn-error.log 9 | dist 10 | -------------------------------------------------------------------------------- /examples/wasm/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "examples-wasm" 3 | version = "0.0.0" 4 | authors = ["Matthias Seitz "] 5 | license = "MIT OR Apache-2.0" 6 | publish = false 7 | 8 | rust-version.workspace = true 9 | edition.workspace = true 10 | 11 | [lib] 12 | crate-type = ["cdylib", "rlib"] 13 | 14 | [features] 15 | default = ["console_error_panic_hook"] 16 | 17 | [dependencies] 18 | ethers = { workspace = true, features = ["abigen", "ws"] } 19 | 20 | serde.workspace = true 21 | serde_json.workspace = true 22 | serde-wasm-bindgen = "0.6.0" 23 | hex.workspace = true 24 | 25 | wasm-bindgen-futures = "0.4.36" 26 | wasm-bindgen = { version = "0.2.86", features = ["serde-serialize"] } 27 | 28 | # The `console_error_panic_hook` crate provides better debugging of panics by 29 | # logging them with `console.error`. This is great for development, but requires 30 | # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for 31 | # code size when deploying. 32 | console_error_panic_hook = { version = "0.1.7", optional = true } 33 | 34 | web-sys = { version = "0.3.63", features = ["console"] } 35 | 36 | # needed to enable the "js" feature for compatibility with wasm, 37 | # see https://docs.rs/getrandom/#webassembly-support 38 | getrandom = { version = "0.2", features = ["js"] } 39 | 40 | [dev-dependencies] 41 | wasm-bindgen-test = "0.3.36" 42 | -------------------------------------------------------------------------------- /examples/wasm/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../../LICENSE-APACHE -------------------------------------------------------------------------------- /examples/wasm/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../../LICENSE-MIT -------------------------------------------------------------------------------- /examples/wasm/README.md: -------------------------------------------------------------------------------- 1 | # ethers-wasm 2 | 3 | ## Example 4 | 5 | Install wasm-pack with 6 | 7 | yarn install 8 | 9 | Start a local Anvil or Ganache instance 10 | 11 | yarn anvil 12 | or 13 | yarn ganache 14 | 15 | Build the example locally with: 16 | 17 | yarn serve 18 | 19 | Visit http://localhost:8080 in a browser to run the example! 20 | -------------------------------------------------------------------------------- /examples/wasm/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ethers WASM example 6 | 7 | 8 | 9 |

ethers WASM

10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/wasm/index.js: -------------------------------------------------------------------------------- 1 | const ethers = import("./pkg"); 2 | 3 | ethers 4 | .then(m => { 5 | m.deploy().catch(console.error); 6 | }) 7 | .catch(console.error); 8 | -------------------------------------------------------------------------------- /examples/wasm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "examples-wasm", 3 | "license": "MIT OR Apache-2.0", 4 | "private": "true", 5 | "scripts": { 6 | "build": "webpack", 7 | "serve": "webpack-dev-server", 8 | "anvil": "anvil -m 'stuff inherit faith park genre spread huge knee ecology private marble supreme'", 9 | "ganache": "ganache-cli -m 'stuff inherit faith park genre spread huge knee ecology private marble supreme'" 10 | }, 11 | "devDependencies": { 12 | "@wasm-tool/wasm-pack-plugin": "^1.6", 13 | "ganache-cli": "^6.12", 14 | "html-webpack-plugin": "^5.5", 15 | "text-encoding": "^0.7", 16 | "webpack": "^5.75", 17 | "webpack-cli": "^5.0", 18 | "webpack-dev-server": "^4.11" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/wasm/src/utils.rs: -------------------------------------------------------------------------------- 1 | use ethers::{ 2 | prelude::{LocalWallet, MnemonicBuilder}, 3 | signers::coins_bip39::English, 4 | }; 5 | 6 | pub fn set_panic_hook() { 7 | // When the `console_error_panic_hook` feature is enabled, we can call the 8 | // `set_panic_hook` function at least once during initialization, and then 9 | // we will get better error messages if our code ever panics. 10 | // 11 | // For more details see 12 | // https://github.com/rustwasm/console_error_panic_hook#readme 13 | #[cfg(feature = "console_error_panic_hook")] 14 | console_error_panic_hook::set_once(); 15 | } 16 | 17 | /// The mnemonic phrase used by ganache 18 | pub const PHRASE: &str = 19 | "stuff inherit faith park genre spread huge knee ecology private marble supreme"; 20 | 21 | pub fn key(index: u32) -> LocalWallet { 22 | MnemonicBuilder::::default().phrase(PHRASE).index(index).unwrap().build().unwrap() 23 | } 24 | -------------------------------------------------------------------------------- /examples/wasm/tests/contract_with_abi.rs: -------------------------------------------------------------------------------- 1 | #![cfg(target_arch = "wasm32")] 2 | 3 | use ethers::{ 4 | prelude::{Http, JsonRpcClient, LocalWallet, Provider, SignerMiddleware, Ws}, 5 | signers::Signer, 6 | types::Chain, 7 | }; 8 | use examples_wasm::{utils, SimpleContract}; 9 | use std::sync::Arc; 10 | use wasm_bindgen_test::*; 11 | 12 | wasm_bindgen_test_configure!(run_in_browser); 13 | 14 | #[wasm_bindgen_test] 15 | async fn http_connect_and_deploy() { 16 | console_log!("connecting http..."); 17 | let provider = Provider::::try_from("http://localhost:8545").unwrap(); 18 | deploy(provider, utils::key(0).with_chain_id(Chain::AnvilHardhat)).await; 19 | } 20 | 21 | #[wasm_bindgen_test] 22 | async fn ws_connect_and_deploy() { 23 | console_log!("connecting ws..."); 24 | let provider = Provider::new(Ws::connect("ws://localhost:8545").await.unwrap()); 25 | deploy(provider, utils::key(1).with_chain_id(Chain::AnvilHardhat)).await; 26 | } 27 | 28 | async fn deploy(provider: Provider, wallet: LocalWallet) { 29 | let client = Arc::new(SignerMiddleware::new(provider, wallet)); 30 | 31 | let expected = "Hello from Contract!"; 32 | let deploy_tx = SimpleContract::deploy(client, expected.to_string()).unwrap(); 33 | let contract: SimpleContract<_> = deploy_tx.send().await.unwrap(); 34 | let addr = contract.address(); 35 | console_log!("deployed to {addr}"); 36 | 37 | let value = contract.get_value().call().await.unwrap(); 38 | 39 | console_log!("value: {value:?}"); 40 | 41 | assert_eq!(value, expected); 42 | } 43 | -------------------------------------------------------------------------------- /examples/wasm/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const HtmlWebpackPlugin = require("html-webpack-plugin"); 3 | const webpack = require("webpack"); 4 | const WasmPackPlugin = require("@wasm-tool/wasm-pack-plugin"); 5 | 6 | module.exports = { 7 | entry: "./index.js", 8 | output: { 9 | path: path.resolve(__dirname, "dist"), 10 | filename: "index.js", 11 | }, 12 | plugins: [ 13 | new HtmlWebpackPlugin({ 14 | template: "./index.html", 15 | inject: false, 16 | }), 17 | new WasmPackPlugin({ 18 | crateDirectory: path.resolve(__dirname, "."), 19 | }), 20 | // Have this example work in Edge which doesn't ship `TextEncoder` or 21 | // `TextDecoder` at this time. 22 | new webpack.ProvidePlugin({ 23 | TextDecoder: ["text-encoding", "TextDecoder"], 24 | TextEncoder: ["text-encoding", "TextEncoder"], 25 | }), 26 | ], 27 | experiments: { 28 | asyncWebAssembly: true, 29 | }, 30 | mode: "development", 31 | }; 32 | -------------------------------------------------------------------------------- /release.toml: -------------------------------------------------------------------------------- 1 | allow-branch = ["master"] 2 | pre-release-commit-message = "chore: release" 3 | tag-message = "chore: release {{crate_name}} v{{version}}" 4 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | reorder_imports = true 2 | imports_granularity = "Crate" 3 | use_small_heuristics = "Max" 4 | comment_width = 100 5 | wrap_comments = true 6 | binop_separator = "Back" 7 | trailing_comma = "Vertical" 8 | trailing_semicolon = false 9 | use_field_init_shorthand = true 10 | -------------------------------------------------------------------------------- /testdata/SimpleStorage.json: -------------------------------------------------------------------------------- 1 | {"abi":[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"author","type":"address"},{"indexed":true,"internalType":"address","name":"oldAuthor","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"ValueChanged","type":"event"},{"inputs":[],"name":"lastSender","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"setValue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"value","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}],"bytecode":"608060405234801561001057600080fd5b50610155806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063256fec88146100465780633fa4f24514610076578063552410771461008d575b600080fd5b600054610059906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61007f60015481565b60405190815260200161006d565b6100a061009b366004610106565b6100a2565b005b60005460015460408051918252602082018490526001600160a01b039092169133917f43a35cb4f6bbf56c64a97aba2d057d75ae7c2b008cfbbcf77c9bd7f2a525d969910160405180910390a3600155600080546001600160a01b03191633179055565b60006020828403121561011857600080fd5b503591905056fea26469706673582212202aa583b44008e0a0ecde172d743bed0508a31118ec816f86cd3551d73480e13d64736f6c63430008130033"} 2 | -------------------------------------------------------------------------------- /testdata/uniswap/IERC20.sol: -------------------------------------------------------------------------------- 1 | interface IERC20 { 2 | function totalSupply() external view returns(uint); 3 | 4 | function balanceOf(address account) external view returns(uint); 5 | 6 | function transfer(address recipient, uint amount) external returns(bool); 7 | 8 | function allowance(address owner, address spender) external view returns(uint); 9 | 10 | function approve(address spender, uint amount) external returns(bool); 11 | 12 | function transferFrom(address sender, address recipient, uint amount) external returns(bool); 13 | event Transfer(address indexed from, address indexed to, uint value); 14 | event Approval(address indexed owner, address indexed spender, uint value); 15 | } 16 | --------------------------------------------------------------------------------