├── examples ├── anvil │ ├── README.md │ ├── Cargo.toml │ └── examples │ │ └── anvil_fork.rs ├── events │ ├── README.md │ ├── examples │ │ └── placeholder.rs │ └── Cargo.toml ├── providers │ ├── README.md │ ├── examples │ │ ├── rw.rs │ │ ├── ws.rs │ │ ├── http_jwt.rs │ │ ├── quorum.rs │ │ ├── retry.rs │ │ └── ipc.rs │ └── Cargo.toml ├── queries │ ├── README.md │ ├── Cargo.toml │ └── examples │ │ ├── uniswapv2_pair.rs │ │ └── paginated_logs.rs ├── wallets │ ├── README.md │ ├── Cargo.toml │ └── examples │ │ ├── sign_message.rs │ │ ├── ledger.rs │ │ ├── permit_hash.rs │ │ ├── trezor.rs │ │ ├── yubi.rs │ │ ├── mnemonic.rs │ │ └── local_signer.rs ├── middleware │ ├── README.md │ ├── examples │ │ ├── timelag.rs │ │ ├── transformer.rs │ │ ├── policy.rs │ │ └── signer.rs │ └── Cargo.toml ├── subscriptions │ ├── README.md │ ├── Cargo.toml │ └── examples │ │ ├── subscribe_blocks.rs │ │ └── subscribe_logs.rs ├── transactions │ ├── README.md │ ├── examples │ │ ├── contracts │ │ │ └── erc20_example │ │ │ │ ├── ERC20Example.sol │ │ │ │ └── @openzeppelin │ │ │ │ └── contracts │ │ │ │ ├── README.md │ │ │ │ ├── token │ │ │ │ └── ERC20 │ │ │ │ │ └── extensions │ │ │ │ │ └── IERC20Metadata.sol │ │ │ │ └── utils │ │ │ │ └── Context.sol │ │ ├── ens.rs │ │ ├── transfer_eth.rs │ │ ├── decode_input.rs │ │ └── trace_call.rs │ └── Cargo.toml ├── wasm │ ├── LICENSE-MIT │ ├── LICENSE-APACHE │ ├── .gitignore │ ├── index.js │ ├── index.html │ ├── README.md │ ├── package.json │ ├── src │ │ └── utils.rs │ ├── webpack.config.js │ ├── Cargo.toml │ └── tests │ │ └── contract_with_abi.rs ├── contracts │ ├── examples │ │ ├── instances.rs │ │ ├── methods.rs │ │ ├── contracts │ │ │ └── contract.sol │ │ ├── abi │ │ │ └── contract_abi.json │ │ ├── compile.rs │ │ ├── methods_abi_and_structs.rs │ │ ├── events_with_meta.rs │ │ └── deploy_from_abi_and_bytecode.rs │ └── Cargo.toml ├── big-numbers │ ├── Cargo.toml │ ├── examples │ │ ├── comparison_equivalence.rs │ │ ├── conversion.rs │ │ └── create_instances.rs │ └── README.md └── geth │ ├── Cargo.toml │ └── examples │ └── clique.rs ├── .clippy.toml ├── ethers-solc ├── test-data │ ├── bytes.sol │ ├── 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-warnings │ │ └── LicenseWarning.sol │ ├── model-checker-sample │ │ └── Assert.sol │ ├── test-contract-versions │ │ ├── caret-0.4.14.sol │ │ ├── pinned-0.4.14.sol │ │ ├── simple-0.4.14.sol │ │ ├── greater-equal-0.5.0.sol │ │ └── range-0.5.0.sol │ ├── test-versioned-linkrefs │ │ ├── lib │ │ │ └── Lib.sol │ │ └── src │ │ │ ├── FooV1.sol │ │ │ └── FooV2.sol │ ├── dapp-sample │ │ └── src │ │ │ ├── Dapp.sol │ │ │ └── Dapp.t.sol │ ├── test-flatten-duplicates │ │ └── contracts │ │ │ ├── Bar.sol │ │ │ ├── Foo.sol │ │ │ └── FooBar.sol │ ├── test-flatten-solang-failure │ │ └── contracts │ │ │ ├── Lib.sol │ │ │ └── Contract.sol │ ├── cache-sample │ │ ├── NewContract.sol │ │ └── Dapp.sol │ ├── yul-sample │ │ ├── Dapp.sol │ │ └── SimpleStore.yul │ ├── in │ │ ├── compiler-in-16.json │ │ ├── compiler-in-18.json │ │ ├── compiler-in-13.json │ │ ├── compiler-in-14.json │ │ ├── compiler-in-15.json │ │ ├── compiler-in-17.json │ │ ├── compiler-in-1.json │ │ ├── compiler-in-7.json │ │ ├── compiler-in-22.json │ │ ├── compiler-in-21.json │ │ └── compiler-in-23.json │ ├── ast │ │ ├── global_enum.json │ │ ├── smoke.json │ │ ├── license.json │ │ ├── documentation_1.json │ │ ├── documentation_2.json │ │ ├── event_definition.json │ │ ├── enum_value.json │ │ ├── global_struct.json │ │ ├── placeholder_statement.json │ │ ├── fallback.json │ │ ├── constructor.json │ │ ├── receive_ether.json │ │ ├── fallback_payable.json │ │ ├── abstract_contract.json │ │ ├── inheritance_specifier.json │ │ ├── array_type_name.json │ │ ├── empty_block.json │ │ ├── leave.json │ │ ├── stringlit.json │ │ ├── fallback_and_reveice_ether.json │ │ ├── switch_default.json │ │ ├── short_type_name.json │ │ ├── function.json │ │ ├── yul_hex_literal.json │ │ ├── string.json │ │ ├── unicode.json │ │ ├── loop.json │ │ ├── short_type_name_ref.json │ │ └── var_access.json │ ├── hardhat-sample │ │ └── contracts │ │ │ └── Greeter.sol │ ├── foundryissue2462.json │ ├── library-remapping-in.json │ ├── library-remapping-in-2.json │ └── out │ │ ├── compiler-out-1.json │ │ └── compiler-out-14.json ├── src │ ├── artifacts │ │ └── ast │ │ │ ├── util.rs │ │ │ └── visitor.rs │ └── compile │ │ └── many.rs ├── README.md └── benches │ └── compile_many.rs ├── ethers-core └── src │ ├── types │ ├── trace │ │ ├── parity.rs │ │ ├── geth │ │ │ ├── test_data │ │ │ │ ├── call_tracer │ │ │ │ │ ├── only_top_call.json │ │ │ │ │ ├── legacy.json │ │ │ │ │ ├── default.json │ │ │ │ │ └── with_log.json │ │ │ │ └── pre_state_tracer │ │ │ │ │ └── default.json │ │ │ ├── noop.rs │ │ │ └── four_byte.rs │ │ └── example-traces-str.rs │ ├── address_or_bytes.rs │ ├── fee.rs │ ├── proof.rs │ ├── withdrawal.rs │ └── path_or_string.rs │ ├── macros │ └── mod.rs │ ├── lib.rs │ └── abi │ └── error.rs ├── book ├── middleware │ ├── time-lag.md │ ├── transformer.md │ ├── signer.md │ ├── gas-oracle.md │ ├── policy.md │ ├── builder.md │ ├── gas-escalator.md │ ├── nonce-manager.md │ └── custom.md ├── big-numbers │ ├── intro.md │ ├── utilities.md │ ├── conversion.md │ ├── creating_instances.md │ ├── math-operations.md │ └── comparison-and-equivalence.md ├── contracts │ ├── abigen.md │ ├── events.md │ ├── compile.md │ ├── methods.md │ ├── deploy-anvil.md │ ├── creating-instances.md │ ├── doploy-moonbeam.md │ ├── events-with-meta.md │ └── deploy-from-abi-and-bytecode.md ├── providers │ ├── rw.md │ ├── mock.md │ ├── retry.md │ ├── quorum.md │ ├── custom.md │ └── ipc.md ├── events │ └── logs-and-filtering.md ├── subscriptions │ ├── events-by-type.md │ ├── watch-blocks.md │ └── logs.md ├── mermaid-style.txt ├── README.md └── getting-started │ ├── intro.md │ └── connect_to_an_ethereum_node.md ├── .gitattributes ├── ethers-providers ├── src │ ├── stream │ │ └── mod.rs │ ├── rpc │ │ ├── mod.rs │ │ ├── transports │ │ │ └── mod.rs │ │ └── connections.rs │ ├── toolbox │ │ └── mod.rs │ ├── ext │ │ └── mod.rs │ └── utils.rs └── tests │ └── it │ ├── main.rs │ └── txpool.rs ├── release.toml ├── ethers-contract ├── src │ ├── multicall │ │ └── contract.rs │ └── call_core.rs ├── tests │ ├── solidity-contracts │ │ ├── large-array.json │ │ ├── StructContract.sol │ │ ├── EventWithStruct.json │ │ ├── Abiencoderv2Test.sol │ │ ├── LargeStruct.json │ │ ├── MultiInputOutput.sol │ │ ├── MultiInputOutput.json │ │ ├── NotSoSimpleStorage.sol │ │ ├── large_tuple.json │ │ ├── sale.json │ │ ├── SimpleStorage.sol │ │ ├── Abiencoderv2Test.json │ │ ├── SlotStorage.sol │ │ ├── SimpleRevertingStorage.sol │ │ └── OverloadedFuncs.json │ └── it │ │ ├── main.rs │ │ └── contract_call.rs ├── ethers-contract-derive │ ├── README.md │ ├── Cargo.toml │ └── src │ │ └── spanned.rs ├── ethers-contract-abigen │ ├── README.md │ └── src │ │ └── test │ │ └── macros.rs └── README.md ├── .gitignore ├── .github ├── dependabot.yml ├── ISSUE_TEMPLATE │ ├── question.md │ ├── feature_request.md │ └── bug_report.md ├── workflows │ └── deps.yml ├── PULL_REQUEST_TEMPLATE.md └── scripts │ └── release-tag-from.js ├── rustfmt.toml ├── ethers-addressbook ├── README.md └── Cargo.toml ├── book.toml ├── .git-blame-ignore-revs ├── testdata ├── uniswap │ └── IERC20.sol └── SimpleStorage.json ├── ethers-middleware ├── src │ ├── transformer │ │ ├── ds_proxy │ │ │ └── factory.rs │ │ └── mod.rs │ └── gas_oracle │ │ └── provider_oracle.rs └── tests │ └── it │ ├── nonce_manager.rs │ └── gas_escalator.rs ├── ethers-etherscan ├── README.md ├── tests │ └── it │ │ ├── version.rs │ │ ├── blocks.rs │ │ └── gas.rs └── Cargo.toml ├── LICENSE-MIT └── bin └── run_all_examples /examples/anvil/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/events/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/providers/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/queries/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/wallets/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.clippy.toml: -------------------------------------------------------------------------------- 1 | msrv = "1.65" 2 | -------------------------------------------------------------------------------- /ethers-solc/test-data/bytes.sol: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/middleware/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/subscriptions/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/transactions/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ethers-core/src/types/trace/parity.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ethers-solc/src/artifacts/ast/util.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/wasm/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../../LICENSE-MIT -------------------------------------------------------------------------------- /ethers-solc/src/artifacts/ast/visitor.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/wasm/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../../LICENSE-APACHE -------------------------------------------------------------------------------- /book/middleware/time-lag.md: -------------------------------------------------------------------------------- 1 | # Time lag 2 | 3 | TODO -------------------------------------------------------------------------------- /book/middleware/transformer.md: -------------------------------------------------------------------------------- 1 | # Transformer 2 | 3 | TODO -------------------------------------------------------------------------------- /book/big-numbers/intro.md: -------------------------------------------------------------------------------- 1 | {{#include ../../examples/big-numbers/README.md}} 2 | -------------------------------------------------------------------------------- /ethers-core/src/macros/mod.rs: -------------------------------------------------------------------------------- 1 | mod ethers_crate; 2 | pub use ethers_crate::*; 3 | -------------------------------------------------------------------------------- /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/events/examples/placeholder.rs: -------------------------------------------------------------------------------- 1 | #[tokio::main] 2 | async fn main() {} 3 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | Cargo.lock linguist-generated=true 2 | flake.lock linguist-generated=true 3 | -------------------------------------------------------------------------------- /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-remappings/lib/bar/src/Bar.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.6; 2 | 3 | contract Bar {} 4 | -------------------------------------------------------------------------------- /book/contracts/abigen.md: -------------------------------------------------------------------------------- 1 | # Abigen 2 | 3 | ```rust 4 | {{#include ../../examples/contracts/examples/abigen.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /book/contracts/events.md: -------------------------------------------------------------------------------- 1 | # Events 2 | 3 | ```rust 4 | {{#include ../../examples/contracts/examples/events.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /book/middleware/signer.md: -------------------------------------------------------------------------------- 1 | # Signer 2 | 3 | ```rust 4 | {{#include ../../examples/middleware/examples/signer.rs}} 5 | ``` -------------------------------------------------------------------------------- /book/providers/rw.md: -------------------------------------------------------------------------------- 1 | # RW provider 2 | 3 | ```rust 4 | {{#include ../../examples/providers/examples/rw.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /book/contracts/compile.md: -------------------------------------------------------------------------------- 1 | # Compile 2 | 3 | ```rust 4 | {{#include ../../examples/contracts/examples/compile.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /book/contracts/methods.md: -------------------------------------------------------------------------------- 1 | # Methods 2 | 3 | ```rust 4 | {{#include ../../examples/contracts/examples/methods.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /book/providers/mock.md: -------------------------------------------------------------------------------- 1 | # Mock provider 2 | 3 | ```rust 4 | {{#include ../../examples/providers/examples/mock.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /book/providers/retry.md: -------------------------------------------------------------------------------- 1 | # Retry client 2 | 3 | ```rust 4 | {{#include ../../examples/providers/examples/retry.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /ethers-solc/test-data/test-contract-warnings/LicenseWarning.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.6; 2 | 3 | contract LicenseWarning {} 4 | -------------------------------------------------------------------------------- /book/big-numbers/utilities.md: -------------------------------------------------------------------------------- 1 | # Utilities 2 | 3 | ```rust 4 | {{#include ../../examples/big-numbers/examples/utilities.rs}} 5 | ``` -------------------------------------------------------------------------------- /book/middleware/gas-oracle.md: -------------------------------------------------------------------------------- 1 | # Gas oracle 2 | 3 | ```rust 4 | {{#include ../../examples/middleware/examples/gas_oracle.rs}} 5 | ``` -------------------------------------------------------------------------------- /book/middleware/policy.md: -------------------------------------------------------------------------------- 1 | # Policy middleware 2 | 3 | ```rust 4 | {{#include ../../examples/middleware/examples/policy.rs}} 5 | ``` -------------------------------------------------------------------------------- /book/providers/quorum.md: -------------------------------------------------------------------------------- 1 | # Quorum provider 2 | 3 | ```rust 4 | {{#include ../../examples/providers/examples/quorum.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /ethers-providers/src/stream/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod tx_stream; 2 | pub use tx_stream::*; 3 | 4 | pub mod watcher; 5 | pub use watcher::*; 6 | -------------------------------------------------------------------------------- /book/big-numbers/conversion.md: -------------------------------------------------------------------------------- 1 | # Conversion 2 | 3 | ```rust 4 | {{#include ../../examples/big-numbers/examples/conversion.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/middleware/builder.md: -------------------------------------------------------------------------------- 1 | # Middleware builder 2 | 3 | ```rust 4 | {{#include ../../examples/middleware/examples/builder.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/nonce-manager.md: -------------------------------------------------------------------------------- 1 | # Nonce manager 2 | 3 | ```rust 4 | {{#include ../../examples/middleware/examples/nonce_manager.rs}} 5 | ``` -------------------------------------------------------------------------------- /book/events/logs-and-filtering.md: -------------------------------------------------------------------------------- 1 | # Logs and filtering 2 | 3 | ```rust 4 | {{#include ../../examples/events/examples/filtering.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /book/contracts/creating-instances.md: -------------------------------------------------------------------------------- 1 | # Creating Instances 2 | 3 | ```rust 4 | {{#include ../../examples/contracts/examples/instances.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 | -------------------------------------------------------------------------------- /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/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/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-versioned-linkrefs/lib/Lib.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity >0.4.0; 3 | 4 | contract Lib {} 5 | -------------------------------------------------------------------------------- /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/math-operations.md: -------------------------------------------------------------------------------- 1 | # Math operations 2 | 3 | ```rust 4 | {{#include ../../examples/big-numbers/examples/math_operations.rs}} 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/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/range-0.5.0.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.0 <0.5.0; 2 | 3 | contract E { 4 | function foo() public {} 5 | } 6 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /release.toml: -------------------------------------------------------------------------------- 1 | allow-branch = ["master"] 2 | pre-release-commit-message = "chore: release" 3 | tag-message = "chore: release {{crate_name}} v{{version}}" 4 | -------------------------------------------------------------------------------- /book/middleware/custom.md: -------------------------------------------------------------------------------- 1 | # Create custom middleware 2 | 3 | ```rust 4 | {{#include ../../examples/middleware/examples/create_custom_middleware.rs}} 5 | ``` 6 | -------------------------------------------------------------------------------- /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-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/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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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-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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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::{PubsubClient, SubscriptionStream}; 12 | -------------------------------------------------------------------------------- /examples/wasm/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ethers WASM example 6 | 7 | 8 | 9 |

ethers WASM

10 | 11 | 12 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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-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-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-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-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/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 | -------------------------------------------------------------------------------- /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-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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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-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 | -------------------------------------------------------------------------------- /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 | }%% -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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-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/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/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-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-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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/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-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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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-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 | ## Examples 8 | 9 | ```rust 10 | use ethers_addressbook::{contract, Chain}; 11 | 12 | let weth = contract("weth").unwrap(); 13 | let mainnet_address = weth.address(Chain::Mainnet).unwrap(); 14 | assert_eq!(mainnet_address, "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2".parse().unwrap()); 15 | ``` 16 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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"] } 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 | -------------------------------------------------------------------------------- /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-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))] 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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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"] } 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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 | is_send(contract.cache().into_future()); 20 | } 21 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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-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-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-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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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-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 | ## Examples 8 | 9 | ```rust,no_run 10 | # use ethers_core::types::Chain; 11 | # use ethers_etherscan::Client; 12 | # async fn foo() -> Result<(), Box> { 13 | let client = Client::new(Chain::Mainnet, "")?; 14 | // Or using environment variables 15 | let client = Client::new_from_env(Chain::Mainnet)?; 16 | 17 | let address = "0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413".parse()?; 18 | let metadata = client.contract_source_code(address).await?; 19 | assert_eq!(metadata.items[0].contract_name, "DAO"); 20 | # Ok(()) 21 | # } 22 | ``` 23 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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-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-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-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/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/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/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/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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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-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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /ethers-contract/README.md: -------------------------------------------------------------------------------- 1 | # ethers-contract 2 | 3 | Type-safe abstractions for interacting with Ethereum smart contracts. 4 | 5 | Interacting with a smart contract requires broadcasting carefully crafted 6 | [transactions](ethers_core::types::TransactionRequest) where the `data` field 7 | contains the 8 | [function's selector](https://ethereum.stackexchange.com/questions/72363/what-is-a-function-selector) 9 | along with the arguments of the called function. 10 | 11 | This module provides the [`Contract`] and [`ContractFactory`] abstractions so 12 | that you do not have to worry about that. It also provides typesafe bindings via 13 | the [`abigen`] macro and the [`Abigen` builder]. 14 | 15 | For more information, please refer to the [book](https://gakonst.com/ethers-rs). 16 | 17 | [`contractfactory`]: ./struct.ContractFactory.html 18 | [`contract`]: ./struct.Contract.html 19 | [`abigen`]: ./macro.abigen.html 20 | [`abigen` builder]: ./struct.Abigen.html 21 | -------------------------------------------------------------------------------- /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 | pub base_fee_per_gas: Vec, 8 | pub gas_used_ratio: Vec, 9 | #[serde(deserialize_with = "deserialize_stringified_numeric")] 10 | /// oldestBlock is returned as an unsigned integer up to geth v1.10.6. From 11 | /// geth v1.10.7, this has been updated to return in the hex encoded form. 12 | /// The custom deserializer allows backward compatibility for those clients 13 | /// not running v1.10.7 yet. 14 | pub oldest_block: U256, 15 | /// An (optional) array of effective priority fee per gas data points from a single block. All 16 | /// zeroes are returned if the block is empty. 17 | #[serde(default)] 18 | pub reward: Vec>, 19 | } 20 | -------------------------------------------------------------------------------- /ethers-core/src/types/proof.rs: -------------------------------------------------------------------------------- 1 | use crate::types::{Address, Bytes, H256, U256, U64}; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | #[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize, Serialize)] 5 | pub struct StorageProof { 6 | pub key: H256, 7 | pub proof: Vec, 8 | pub value: U256, 9 | } 10 | 11 | #[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize, Serialize)] 12 | #[serde(rename_all = "camelCase")] 13 | pub struct EIP1186ProofResponse { 14 | pub address: Address, 15 | pub balance: U256, 16 | pub code_hash: H256, 17 | pub nonce: U64, 18 | pub storage_hash: H256, 19 | pub account_proof: Vec, 20 | pub storage_proof: Vec, 21 | } 22 | 23 | #[cfg(test)] 24 | mod tests { 25 | use super::*; 26 | 27 | #[test] 28 | fn can_deserialize_proof() { 29 | serde_json::from_str::(include_str!("../../testdata/proof.json")) 30 | .unwrap(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /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-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-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 | -------------------------------------------------------------------------------- /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-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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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-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-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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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-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-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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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-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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /ethers-solc/README.md: -------------------------------------------------------------------------------- 1 | # ethers-solc 2 | 3 | Utilities for working with native `solc` and compiling projects. 4 | 5 | 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 6 | 7 | First add `ethers-solc` to your cargo build-dependencies. 8 | 9 | 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 10 | 11 | ```toml 12 | [build-dependencies] 13 | ethers-solc = { git = "https://github.com/gakonst/ethers-rs" } 14 | ``` 15 | 16 | ```rust 17 | use ethers_solc::{Project, ProjectPathsConfig}; 18 | 19 | fn main() { 20 | // configure the project with all its paths, solc, cache etc. 21 | let project = Project::builder() 22 | .paths(ProjectPathsConfig::hardhat(env!("CARGO_MANIFEST_DIR")).unwrap()) 23 | .build() 24 | .unwrap(); 25 | let output = project.compile().unwrap(); 26 | 27 | // Tell Cargo that if a source file changes, to rerun this build script. 28 | project.rerun_if_sources_changed(); 29 | } 30 | ``` 31 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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-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-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-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-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 | -------------------------------------------------------------------------------- /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/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/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 | use std::convert::TryFrom; 9 | 10 | #[tokio::main] 11 | async fn main() -> Result<()> { 12 | let anvil = Anvil::new().spawn(); 13 | 14 | let wallet: LocalWallet = anvil.keys()[0].clone().into(); 15 | let wallet2: LocalWallet = anvil.keys()[1].clone().into(); 16 | 17 | // connect to the network 18 | let provider = Provider::::try_from(anvil.endpoint())?; 19 | 20 | // connect the wallet to the provider 21 | let client = SignerMiddleware::new(provider, wallet.with_chain_id(anvil.chain_id())); 22 | 23 | // craft the transaction 24 | let tx = TransactionRequest::new().to(wallet2.address()).value(10000); 25 | 26 | // send it! 27 | let pending_tx = client.send_transaction(tx, None).await?; 28 | 29 | // get the mined tx 30 | let receipt = pending_tx.await?.ok_or_else(|| eyre::format_err!("tx dropped from mempool"))?; 31 | let tx = client.get_transaction(receipt.transaction_hash).await?; 32 | 33 | println!("Sent tx: {}\n", serde_json::to_string(&tx)?); 34 | println!("Tx receipt: {}", serde_json::to_string(&receipt)?); 35 | 36 | Ok(()) 37 | } 38 | -------------------------------------------------------------------------------- /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.5.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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /ethers-etherscan/tests/it/gas.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use ethers_core::types::{Chain, 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-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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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-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-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 | -------------------------------------------------------------------------------- /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 | use std::convert::TryFrom; 7 | 8 | #[tokio::main] 9 | async fn main() -> Result<()> { 10 | let anvil = Anvil::new().spawn(); 11 | 12 | // connect to the network 13 | let provider = Provider::::try_from(anvil.endpoint())?; 14 | let accounts = provider.get_accounts().await?; 15 | let from = accounts[0]; 16 | let to = accounts[1]; 17 | 18 | // craft the tx 19 | let tx = TransactionRequest::new().to(to).value(1000).from(from); // specify the `from` field so that the client knows which account to use 20 | 21 | let balance_before = provider.get_balance(from, None).await?; 22 | let nonce1 = provider.get_transaction_count(from, None).await?; 23 | 24 | // broadcast it via the eth_sendTransaction API 25 | let tx = provider.send_transaction(tx, None).await?.await?; 26 | 27 | println!("{}", serde_json::to_string(&tx)?); 28 | 29 | let nonce2 = provider.get_transaction_count(from, None).await?; 30 | 31 | assert!(nonce1 < nonce2); 32 | 33 | let balance_after = provider.get_balance(from, None).await?; 34 | assert!(balance_after < balance_before); 35 | 36 | println!("Balance before {balance_before}"); 37 | println!("Balance after {balance_after}"); 38 | 39 | Ok(()) 40 | } 41 | -------------------------------------------------------------------------------- /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-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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /ethers-providers/src/rpc/connections.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Debug; 2 | 3 | use async_trait::async_trait; 4 | use auto_impl::auto_impl; 5 | use ethers_core::types::U256; 6 | use serde::{de::DeserializeOwned, Serialize}; 7 | use serde_json::value::RawValue; 8 | 9 | use crate::{ProviderError, RpcError}; 10 | 11 | #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] 12 | #[cfg_attr(not(target_arch = "wasm32"), async_trait)] 13 | #[auto_impl(&, Box, Arc)] 14 | /// Trait which must be implemented by data transports to be used with the Ethereum 15 | /// JSON-RPC provider. 16 | pub trait JsonRpcClient: Debug + Send + Sync { 17 | /// A JSON-RPC Error 18 | type Error: Into + RpcError; 19 | 20 | /// Sends a request with the provided JSON-RPC and parameters serialized as JSON 21 | async fn request(&self, method: &str, params: T) -> Result 22 | where 23 | T: Debug + Serialize + Send + Sync, 24 | R: DeserializeOwned + Send; 25 | } 26 | 27 | /// A transport implementation supporting pub sub subscriptions. 28 | pub trait PubsubClient: JsonRpcClient { 29 | /// The type of stream this transport returns 30 | type NotificationStream: futures_core::Stream> + Send + Unpin; 31 | 32 | /// Add a subscription to this transport 33 | fn subscribe>(&self, id: T) -> Result; 34 | 35 | /// Remove a subscription from this transport 36 | fn unsubscribe>(&self, id: T) -> Result<(), Self::Error>; 37 | } 38 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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-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-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 | -------------------------------------------------------------------------------- /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 | use std::convert::TryFrom; 9 | 10 | /// In Ethereum, transactions must be signed with a private key before they can be broadcast to the 11 | /// network. Ethers-rs provides a way to customize this process by allowing 12 | /// you to define a signer, called to sign transactions before they are sent. 13 | #[tokio::main] 14 | async fn main() -> Result<()> { 15 | let anvil = Anvil::new().spawn(); 16 | 17 | let wallet: LocalWallet = anvil.keys()[0].clone().into(); 18 | let wallet2: LocalWallet = anvil.keys()[1].clone().into(); 19 | 20 | // connect to the network 21 | let provider = Provider::::try_from(anvil.endpoint())?; 22 | 23 | // connect the wallet to the provider 24 | let client = SignerMiddleware::new(provider, wallet.with_chain_id(anvil.chain_id())); 25 | 26 | // craft the transaction 27 | let tx = TransactionRequest::new().to(wallet2.address()).value(10000); 28 | 29 | // send it! 30 | let pending_tx = client.send_transaction(tx, None).await?; 31 | 32 | // get the mined tx 33 | let receipt = pending_tx.await?.ok_or_else(|| eyre::format_err!("tx dropped from mempool"))?; 34 | let tx = client.get_transaction(receipt.transaction_hash).await?; 35 | 36 | println!("Sent tx: {}\n", serde_json::to_string(&tx)?); 37 | println!("Tx receipt: {}", serde_json::to_string(&receipt)?); 38 | 39 | Ok(()) 40 | } 41 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | 40 | [dev-dependencies] 41 | ethers-solc.workspace = true 42 | 43 | tempfile.workspace = true 44 | tokio = { workspace = true, features = ["macros", "rt-multi-thread", "time"] } 45 | serial_test = "2.0.0" 46 | tracing-subscriber = { workspace = true, features = ["env-filter", "fmt"] } 47 | 48 | [features] 49 | default = ["rustls"] 50 | rustls = ["reqwest/rustls-tls"] 51 | openssl = ["reqwest/native-tls"] 52 | 53 | ethers-solc = ["dep:ethers-solc"] 54 | solc-full = ["ethers-solc?/full"] 55 | solc-tests = ["ethers-solc?/tests"] 56 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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-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/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 | -------------------------------------------------------------------------------- /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/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::{convert::TryFrom, 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/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 | }; 31 | let traces = client.debug_trace_call(tx, Some(block), options).await?; 32 | println!("{traces:?}"); 33 | } 34 | 35 | Ok(()) 36 | } 37 | -------------------------------------------------------------------------------- /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-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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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-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/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/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/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/ast/short_type_name_ref.json: -------------------------------------------------------------------------------- 1 | {"absolutePath":"a","exportedSymbols":{"c":[12]},"id":13,"nodeType":"SourceUnit","nodes":[{"abstract":false,"baseContracts":[],"canonicalName":"c","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":12,"linearizedBaseContracts":[12],"name":"c","nameLocation":"9:1:1","nodeType":"ContractDefinition","nodes":[{"body":{"id":10,"nodeType":"Block","src":"33:25:1","statements":[{"assignments":[8],"declarations":[{"constant":false,"id":8,"mutability":"mutable","name":"rows","nameLocation":"51:4:1","nodeType":"VariableDeclaration","scope":10,"src":"35:20:1","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_array$_t_uint256_$dyn_memory_ptr_$dyn_memory_ptr","typeString":"uint256[][]"},"typeName":{"baseType":{"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[]"}},"id":7,"nodeType":"ArrayTypeName","src":"35:8:1","typeDescriptions":{"typeIdentifier":"t_array$_t_array$_t_uint256_$dyn_storage_$dyn_storage_ptr","typeString":"uint256[][]"}},"visibility":"internal"}],"id":9,"nodeType":"VariableDeclarationStatement","src":"35:20:1"}]},"functionSelector":"26121ff0","id":11,"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":12,"src":"13:45:1","stateMutability":"nonpayable","virtual":false,"visibility":"public"}],"scope":13,"src":"0:60:1","usedErrors":[]}],"src":"0:61:1"} 2 | -------------------------------------------------------------------------------- /ethers-providers/tests/it/main.rs: -------------------------------------------------------------------------------- 1 | #![cfg(not(target_arch = "wasm32"))] 2 | 3 | use ethers_core::utils::{Anvil, AnvilInstance}; 4 | use ethers_providers::{Http, Provider}; 5 | use std::time::Duration; 6 | 7 | #[cfg(feature = "ipc")] 8 | use ethers_providers::Ipc; 9 | #[cfg(feature = "ipc")] 10 | use tempfile::NamedTempFile; 11 | 12 | #[cfg(feature = "ws")] 13 | use ethers_providers::Ws; 14 | 15 | mod provider; 16 | 17 | mod txpool; 18 | 19 | #[cfg(all(feature = "ws", not(feature = "legacy-ws"), not(feature = "celo")))] 20 | mod ws_errors; 21 | 22 | /// Spawns Anvil and instantiates an Http provider. 23 | pub fn spawn_anvil() -> (Provider, AnvilInstance) { 24 | let anvil = Anvil::new().block_time(1u64).spawn(); 25 | let provider = Provider::::try_from(anvil.endpoint()) 26 | .unwrap() 27 | .interval(Duration::from_millis(50u64)); 28 | (provider, anvil) 29 | } 30 | 31 | /// Spawns Anvil and instantiates a Ws provider. 32 | #[cfg(feature = "ws")] 33 | pub async fn spawn_anvil_ws() -> (Provider, AnvilInstance) { 34 | let anvil = Anvil::new().block_time(1u64).spawn(); 35 | let provider = Provider::::connect(anvil.ws_endpoint()) 36 | .await 37 | .unwrap() 38 | .interval(Duration::from_millis(50u64)); 39 | (provider, anvil) 40 | } 41 | 42 | /// Spawns Anvil and instantiates a Ipc provider. 43 | #[cfg(feature = "ipc")] 44 | pub async fn spawn_anvil_ipc() -> (Provider, AnvilInstance, NamedTempFile) { 45 | let ipc = NamedTempFile::new().unwrap(); 46 | let anvil = 47 | Anvil::new().block_time(1u64).arg("--ipc").arg(ipc.path().display().to_string()).spawn(); 48 | let provider = Provider::::connect_ipc(ipc.path()) 49 | .await 50 | .unwrap() 51 | .interval(Duration::from_millis(50u64)); 52 | (provider, anvil, ipc) 53 | } 54 | -------------------------------------------------------------------------------- /ethers-solc/test-data/ast/var_access.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":"42:51:1","statements":[{"assignments":[4],"declarations":[{"constant":false,"id":4,"mutability":"mutable","name":"x","nameLocation":"57:1:1","nodeType":"VariableDeclaration","scope":7,"src":"52:6:1","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":3,"name":"uint","nodeType":"ElementaryTypeName","src":"52:4:1","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"id":5,"nodeType":"VariableDeclarationStatement","src":"52:6:1"},{"AST":{"nodeType":"YulBlock","src":"77:10:1","statements":[{"nodeType":"YulAssignment","src":"79:6:1","value":{"kind":"number","nodeType":"YulLiteral","src":"84:1:1","type":"","value":"7"},"variableNames":[{"name":"x","nodeType":"YulIdentifier","src":"79:1:1"}]}]},"evmVersion":"london","externalReferences":[{"declaration":4,"isOffset":false,"isSlot":false,"src":"79:1:1","valueSize":1}],"id":6,"nodeType":"InlineAssembly","src":"68:19:1"}]},"functionSelector":"26121ff0","id":8,"implemented":true,"kind":"function","modifiers":[],"name":"f","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":9,"src":"17:76:1","stateMutability":"pure","virtual":false,"visibility":"public"}],"scope":10,"src":"0:95:1","usedErrors":[]}],"src":"0:96:1"} 2 | -------------------------------------------------------------------------------- /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 | use std::convert::TryFrom; 7 | 8 | #[tokio::test] 9 | async fn txpool() { 10 | let anvil = Anvil::new().block_time(5u64).spawn(); 11 | let provider = Provider::::try_from(anvil.endpoint()).unwrap(); 12 | 13 | let account = provider.get_accounts().await.unwrap()[0]; 14 | let value: u64 = 42; 15 | let gas_price = U256::from_dec_str("221435145689").unwrap(); 16 | let tx = TransactionRequest::new().to(account).from(account).value(value).gas_price(gas_price); 17 | 18 | // send a few transactions 19 | for _ in 0..10 { 20 | drop(provider.send_transaction(tx.clone(), None).await.unwrap()); 21 | } 22 | 23 | // we gave a 5s block time, should be plenty for us to get the txpool's content 24 | let status = provider.txpool_status().await.unwrap(); 25 | assert_eq!(status.pending.as_u64(), 10); 26 | assert_eq!(status.queued.as_u64(), 0); 27 | 28 | let inspect = provider.txpool_inspect().await.unwrap(); 29 | assert!(inspect.queued.is_empty()); 30 | let summary = inspect.pending.get(&account).unwrap(); 31 | for i in 0..10 { 32 | let tx_summary = summary.get(&i.to_string()).unwrap(); 33 | assert_eq!(tx_summary.gas_price, gas_price); 34 | assert_eq!(tx_summary.value, value.into()); 35 | assert_eq!(tx_summary.gas, 21000.into()); 36 | assert_eq!(tx_summary.to.unwrap(), account); 37 | } 38 | 39 | let content = provider.txpool_content().await.unwrap(); 40 | assert!(content.queued.is_empty()); 41 | let content = content.pending.get(&account).unwrap(); 42 | 43 | for nonce in 0..10 { 44 | assert!(content.contains_key(&nonce.to_string())); 45 | } 46 | } 47 | --------------------------------------------------------------------------------