Merge branch 'master' into feat/syn-2
This commit is contained in:
commit
0ff8d6942c
|
@ -29,5 +29,4 @@ the code change.
|
|||
|
||||
- [ ] Added Tests
|
||||
- [ ] Added Documentation
|
||||
- [ ] Updated the changelog
|
||||
- [ ] Breaking changes
|
||||
|
|
|
@ -63,11 +63,11 @@ jobs:
|
|||
- uses: Swatinem/rust-cache@v2
|
||||
- name: test ${{ matrix.flags.flags }}
|
||||
shell: bash
|
||||
# skip `ethers_etherscan::it` and `ethers::live`
|
||||
# skip `ethers_etherscan::it`
|
||||
run: |
|
||||
cargo nextest run \
|
||||
${{ matrix.flags.flags }} \
|
||||
-E "!binary(~live) & !(deps(ethers-etherscan) & kind(test))"
|
||||
-E "!(deps(ethers-etherscan) & kind(test))"
|
||||
|
||||
etherscan-tests:
|
||||
name: etherscan tests
|
||||
|
@ -94,7 +94,7 @@ jobs:
|
|||
- uses: dtolnay/rust-toolchain@stable
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- name: live tests
|
||||
run: cargo test -p ethers --test live --all-features
|
||||
run: cargo test -p ethers --all-features
|
||||
|
||||
# TODO: [#2191](https://github.com/gakonst/ethers-rs/issues/2191)
|
||||
# feature-checks:
|
||||
|
@ -172,7 +172,7 @@ jobs:
|
|||
with:
|
||||
node-version: 16
|
||||
- name: Run wasm example
|
||||
working-directory: examples/ethers-wasm
|
||||
working-directory: examples/wasm
|
||||
run: |
|
||||
yarn
|
||||
yarn anvil &
|
||||
|
@ -194,4 +194,4 @@ jobs:
|
|||
run: ./.github/scripts/install_test_binaries.sh
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- name: Build and run all examples
|
||||
run: ./scripts/examples.sh
|
||||
run: ./bin/run_all_examples
|
||||
|
|
|
@ -1,99 +0,0 @@
|
|||
name: release
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * 0"
|
||||
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release_type:
|
||||
type: choice
|
||||
description: Release type
|
||||
options:
|
||||
- major
|
||||
- minor
|
||||
- patch
|
||||
- rc
|
||||
- beta
|
||||
- alpha
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CARGO_TOKEN: ${{ secrets.CARGO_TOKEN }}
|
||||
RELEASE_TYPE: ${{ github.event.inputs.release_type }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Configure git
|
||||
run: |
|
||||
git config user.name github-actions
|
||||
git config user.email github-actions@github.com
|
||||
- name: Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
with:
|
||||
cache-on-failure: true
|
||||
- name: Install cargo-release
|
||||
uses: actions-rs/install@v0.1
|
||||
with:
|
||||
crate: cargo-release
|
||||
version: latest
|
||||
- name: Cargo login
|
||||
run: |
|
||||
cargo login $CARGO_TOKEN
|
||||
- name: Dry-run cargo release
|
||||
run: |
|
||||
cargo release --workspace ${RELEASE_TYPE:-alpha} --exclude ethers-wasm
|
||||
- name: Publish release
|
||||
run: |
|
||||
cargo release --workspace ${RELEASE_TYPE:-alpha} --exclude ethers-wasm --execute --no-confirm
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 14
|
||||
- run: |
|
||||
npm i semver
|
||||
- name: Install git-cliff
|
||||
uses: actions-rs/install@v0.1
|
||||
with:
|
||||
crate: git-cliff
|
||||
version: latest
|
||||
- name: Publish changelog
|
||||
id: changelog
|
||||
run: |
|
||||
current_version=$(git tag --contains HEAD -l "v*" | head -1)
|
||||
from_version=$(node .github/scripts/release-tag-from.js $current_version $RELEASE_TYPE)
|
||||
echo from $from_version to $current_version
|
||||
|
||||
echo "::set-output name=release_version::$(echo $current_version)"
|
||||
|
||||
if git rev-parse "$from_version" >/dev/null 2>&1; then
|
||||
echo "tag exists, can generate changelog";
|
||||
else
|
||||
echo "tag does not exist, cannot generate changelog, publish github release manually"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
git cliff $from_version..$current_version > GENERATED_CHANGELOG.md
|
||||
cat GENERATED_CHANGELOG.md
|
||||
- name: Create GitHub release
|
||||
id: release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
RELEASE_VERSION: ${{ steps.changelog.outputs.release_version }}
|
||||
with:
|
||||
tag_name: ${{ env.RELEASE_VERSION }}
|
||||
release_name: ${{ env.RELEASE_VERSION }}
|
||||
body_path: GENERATED_CHANGELOG.md
|
||||
prerelease: ${{ env.RELEASE_TYPE == 'alpha' }}
|
|
@ -0,0 +1,406 @@
|
|||
# Changelog
|
||||
|
||||
The old `ethers-rs` changelog, that has been discontinued.
|
||||
|
||||
The new one is located [here](./CHANGELOG.md), which is automatically generated by [git-cliff](https://github.com/orhun/git-cliff).
|
||||
|
||||
## ethers-core
|
||||
|
||||
### Unreleased
|
||||
|
||||
- Add support for `ethlive` as a chain name [#2268](https://github.com/gakonst/ethers-rs/pull/2268)
|
||||
- Make `Chain` more round-trip friendly [#2270](https://github.com/gakonst/ethers-rs/pull/2270)
|
||||
- Add `other: OtherFields` to `TransactionReceipt` [#2209](https://github.com/gakonst/ethers-rs/pull/2209)
|
||||
- Add `Signature::recover_typed_data` [#2120](https://github.com/gakonst/ethers-rs/pull/2120)
|
||||
- Add `abi::encode_packed` [#2104](https://github.com/gakonst/ethers-rs/pull/2104)
|
||||
- Add support for custom JavaScript tracer to `debug_traceCall` and `debug_traceTransaction` [#2064](https://github.com/gakonst/ethers-rs/pull/2064)
|
||||
- Add a `Send` bound to the `IntoFuture` implementation of `ContractCall` [#2083](https://github.com/gakonst/ethers-rs/pull/2083)
|
||||
- Bump [`svm-rs`](https://github.com/roynalnaruto/svm-rs) dependency to fix conflicts with Rust Crytpo packages [#2051](https://github.com/gakonst/ethers-rs/pull/2051)
|
||||
- Avoid unnecessary allocations in `utils` [#2046](https://github.com/gakonst/ethers-rs/pull/2046)
|
||||
- Add abigen support for hardhat generated bytecode json format [#2012](https://github.com/gakonst/ethers-rs/pull/2012)
|
||||
- Fix typo in `RwClient` docs for `write_client` method.
|
||||
- Add support for Geth `debug_traceCall` [#1949](https://github.com/gakonst/ethers-rs/pull/1949)
|
||||
- Add support for Geth built-in tracer and config [#2121](https://github.com/gakonst/ethers-rs/pull/2121)
|
||||
- Graceful handling of WebSocket transport errors [#1889](https://github.com/gakonst/ethers-rs/issues/1889) [#1815](https://github.com/gakonst/ethers-rs/issues/1815)
|
||||
- `MiddlewareBuilder` trait to instantiate a `Provider` as `Middleware` layers.
|
||||
- An `Event` builder can be instantiated specifying the event filter type, without the need to instantiate a contract.
|
||||
- Add 'ethers_core::types::OpCode' and use in 'ethers_core::types::VMOperation' [#1857](https://github.com/gakonst/ethers-rs/issues/1857)
|
||||
- Remove rust_decimals dependency for ethers-core
|
||||
- Add support for numbers greater than 2^96 for `ethers_core::utils::parse_units` [#1822](https://github.com/gakonst/ethers-rs/issues/1822)
|
||||
- Add comment about safety of u8 -> u64 cast in `ethers_core::types::Signature`
|
||||
- Stop defaulting to the `"latest"` block in `eth_estimateGas` params [#1657](https://github.com/gakonst/ethers-rs/pull/1657)
|
||||
- Fix geth trace types for debug_traceTransaction rpc
|
||||
- Fix RLP decoding of legacy `Transaction`
|
||||
- Fix RLP encoding of `TransactionReceipt` [#1661](https://github.com/gakonst/ethers-rs/pull/1661)
|
||||
- Add `Unit8` helper type [#1639](https://github.com/gakonst/ethers-rs/pull/1639)
|
||||
- Add `evm.deployedBytecode.immutableReferences` output selector [#1523](https://github.com/gakonst/ethers-rs/pull/1523)
|
||||
- Added `get_erc1155_token_transfer_events` function for etherscan client [#1503](https://github.com/gakonst/ethers-rs/pull/1503)
|
||||
- Add support for Geth `debug_traceTransaction` [#1469](https://github.com/gakonst/ethers-rs/pull/1469)
|
||||
- Use correct, new transaction type for `typool_content` RPC endpoint [#1501](https://github.com/gakonst/ethers-rs/pull/1501)
|
||||
- Fix the default config for generated `BuildInfo` [#1458](https://github.com/gakonst/ethers-rs/pull/1458)
|
||||
- Allow configuration of the output directory of the generated `BuildInfo` [#1433](https://github.com/gakonst/ethers-rs/pull/1433)
|
||||
- capture unknown fields in `Block` and `Transaction` type via new `OtherFields` type [#1423](https://github.com/gakonst/ethers-rs/pull/1423)
|
||||
- Methods like `set_to()` from `TypedTransaction` can be chained
|
||||
- Use H64 for Block Nonce [#1396](https://github.com/gakonst/ethers-rs/pull/1396)
|
||||
- Add `as_*_mut` methods on `TypedTransaction`
|
||||
[#1310](https://github.com/gakonst/ethers-rs/pull/1310)
|
||||
- AWS EIP712 data signing no longer signs with EIP155
|
||||
- Added Cronos testnet to etherscan options [#1276](https://github.com/gakonst/ethers-rs/pull/1276)
|
||||
- Fix parsing of a pending block
|
||||
[#1272](https://github.com/gakonst/ethers-rs/pull/1272)
|
||||
- Removed Cronos mainnet beta from `is_legacy` [1246](https://github.com/gakonst/ethers-rs/pull/1246)
|
||||
- Fix RLP decoding of `from` field for `Eip1559TransactionRequest` and
|
||||
`Eip2930TransactionRequest`, remove `Eip1559TransactionRequest` `sighash`
|
||||
method [#1180](https://github.com/gakonst/ethers-rs/pull/1180)
|
||||
- Fix RLP encoding of absent access list in `Transaction` [1137](https://github.com/gakonst/ethers-rs/pull/1137)
|
||||
- Pass compilation time as additional argument to `Reporter::on_solc_success` [#1098](https://github.com/gakonst/ethers-rs/pull/1098)
|
||||
- Fix aws signer bug which maps un-normalized signature to error if no normalization occurs (in `aws::utils::decode_signature`)
|
||||
- Implement signed transaction RLP decoding [#1096](https://github.com/gakonst/ethers-rs/pull/1096)
|
||||
- `Transaction::from` will default to `Address::zero()`. Add `recover_from` and
|
||||
`recover_from_mut` methods for recovering the sender from signature, and also
|
||||
setting the same on tx [#1075](https://github.com/gakonst/ethers-rs/pull/1075).
|
||||
- Add Etherscan account API endpoints [#939](https://github.com/gakonst/ethers-rs/pull/939)
|
||||
- Add FTM Mainet and testnet to parse method "try_from" from Chain.rs and add cronos mainet and testnet to "from_str"
|
||||
- Add FTM mainnet and testnet Multicall addresses [#927](https://github.com/gakonst/ethers-rs/pull/927)
|
||||
- Add Cronos mainnet beta and testnet to the list of known chains
|
||||
[#926](https://github.com/gakonst/ethers-rs/pull/926)
|
||||
- `Chain::to_string` will return the same chain name as `Chain::from_str`
|
||||
- Add `eth_syncing` [#848](https://github.com/gakonst/ethers-rs/pull/848)
|
||||
- Fix overflow and possible divide-by-zero in `estimate_priority_fee`
|
||||
- Add BSC mainnet and testnet to the list of known chains
|
||||
[#831](https://github.com/gakonst/ethers-rs/pull/831)
|
||||
- Returns error on invalid type conversion instead of panicking
|
||||
[#691](https://github.com/gakonst/ethers-rs/pull/691/files)
|
||||
- Change types mapping for solidity `bytes` to rust `ethers::core::Bytes` and
|
||||
solidity `uint8[]` to rust `Vec<u8>`.
|
||||
[#613](https://github.com/gakonst/ethers-rs/pull/613)
|
||||
- Fix `format_units` to return a `String` of representing a decimal point float
|
||||
such that the decimal places don't get truncated.
|
||||
[#597](https://github.com/gakonst/ethers-rs/pull/597)
|
||||
- Implement hex display format for `ethers::core::Bytes`
|
||||
[#624](https://github.com/gakonst/ethers-rs/pull/624).
|
||||
- Fix `fee_history` to first try with `block_count` encoded as a hex `QUANTITY`.
|
||||
[#668](https://github.com/gakonst/ethers-rs/pull/668)
|
||||
- Fix `fill_transaction` to set nonces in transactions, if the sender is known
|
||||
and no nonce is specified
|
||||
- Move `fill_transaction` implementation to the provider, to allow middleware
|
||||
to properly override its behavior.
|
||||
- Add informational messages to solc installation and compilation.
|
||||
- Significantly refactor `MultiAbigen` module generation. Now allows for lib
|
||||
generation, and does not make unnecessary disk writes.
|
||||
[#854](https://github.com/gakonst/ethers-rs/pull/852)
|
||||
- Refactor `ethers-contract-abigen` to use `eyre` instead of `anyhow` via
|
||||
[#858](https://github.com/gakonst/ethers-rs/pull/858)
|
||||
- Add `Deployer.send_with_receipt -> Result<(Contract, Receipt), Error>`
|
||||
so that the receipt can be returned to the called when deploying
|
||||
a contract [#865](https://github.com/gakonst/ethers-rs/pull/865)
|
||||
- Add Arbitrum mainnet and testnet to the list of known chains
|
||||
- Add ENS avatar and TXT records resolution
|
||||
[#889](https://github.com/gakonst/ethers-rs/pull/889)
|
||||
- Do not override gas limits provided by an outer middleware when including an EIP-2930 access list
|
||||
[#901](https://github.com/gakonst/ethers-rs/pull/901)
|
||||
- Add a getter to `ProjectCompileOutput` that returns a mapping of compiler
|
||||
versions to a vector of name + contract struct tuples
|
||||
[#908](https://github.com/gakonst/ethers-rs/pull/908)
|
||||
- Add Yul compilation [#994](https://github.com/gakonst/ethers-rs/pull/994)
|
||||
- Enforce commutativity of ENS reverse resolution
|
||||
[#996](https://github.com/gakonst/ethers-rs/pull/996)
|
||||
- Add `TransactionReceipt::to` and `TransactionReceipt::from`
|
||||
[#1184](https://github.com/gakonst/ethers-rs/pull/1184)
|
||||
- Add `From<H160>` and From<Vec<H160>> traits to `ValueOrArray<H160>` [#1199](https://github.com/gakonst/ethers-rs/pull/1200)
|
||||
- Fix handling of Websocket connection errors [#1287](https://github.com/gakonst/ethers-rs/pull/1287)
|
||||
- Add Arithmetic Shift Right operation for I256 [#1323](https://github.com/gakonst/ethers-rs/issues/1323)
|
||||
- [#1535](https://github.com/gakonst/ethers-rs/pull/1535) Add support to Aurora and Aurora testnet networks.
|
||||
- [#1632](https://github.com/gakonst/ethers-rs/pull/1632) Re-export `H32` from `ethabi`.
|
||||
- [#1634](https://github.com/gakonst/ethers-rs/pull/1634) Derive missing `Clone`, `Copy` and `Debug` impls in ethers-etherscan.
|
||||
- Bytes debug format now displays hex literals [#1658](https://github.com/gakonst/ethers-rs/pull/1658)
|
||||
- [#1451](https://github.com/gakonst/ethers-rs/issues/1451) Add Arithmetic Shift Left operation for I256
|
||||
- [#1860](https://github.com/gakonst/ethers-rs/pull/1860) Update I256 type documentation calling out the inconsistency
|
||||
between its right shift operator and standard library numeric types.
|
||||
- [#842](https://github.com/gakonst/ethers-rs/issues/842) Add support for I256 types in `parse_units` and `format_units`.
|
||||
Added `twos_complement` function for I256.
|
||||
- [#1934](https://github.com/gakonst/ethers-rs/pull/1934) Allow 16 calls in multicall.
|
||||
- [#1941](https://github.com/gakonst/ethers-rs/pull/1941) Add `add_calls` and `call_array` for `Multicall`.
|
||||
- Added basic event log filtering example.
|
||||
|
||||
## ethers-contract-abigen
|
||||
|
||||
### Unreleased
|
||||
|
||||
- Abigen now generates events with new `<B, M>` generic pattern [#2103](https://github.com/gakonst/ethers-rs/pull/2103)
|
||||
- Fix Cargo.toml generation issue that could cause dependency conflicts [#1852](https://github.com/gakonst/ethers-rs/pull/1852)
|
||||
- Use corresponding rust structs for event fields if they're solidity structs [#1674](https://github.com/gakonst/ethers-rs/pull/1674)
|
||||
- Add `ContractFilter` to filter contracts in `MultiAbigen` [#1564](https://github.com/gakonst/ethers-rs/pull/1564)
|
||||
- generate error bindings for custom errors [#1549](https://github.com/gakonst/ethers-rs/pull/1549)
|
||||
- Support overloaded events
|
||||
[#1233](https://github.com/gakonst/ethers-rs/pull/1233)
|
||||
- Relax Clone requirements when Arc<Middleware> is used
|
||||
[#1183](https://github.com/gakonst/ethers-rs/pull/1183)
|
||||
- Generate a deploy function if bytecode is provided in the abigen! input (json artifact)
|
||||
[#1030](https://github.com/gakonst/ethers-rs/pull/1030).
|
||||
- Generate correct bindings of struct's field names that are reserved words
|
||||
[#989](https://github.com/gakonst/ethers-rs/pull/989).
|
||||
- Generate correct binding module names that are reserved words
|
||||
[#1498](https://github.com/gakonst/ethers-rs/pull/1498). Note: this changes
|
||||
generated module names to snake case. For example, `MyContract` is now
|
||||
`my_contract` rather than `mycontract_mod`.
|
||||
- The `Cargo.toml` generated by bindings now includes the `abigen` feature on
|
||||
ethers. [#1508](https://github.com/gakonst/ethers-rs/pull/1508)
|
||||
- More descriptive contract deserialization errors.
|
||||
[#1633](https://github.com/gakonst/ethers-rs/pull/1633)
|
||||
|
||||
### 0.6.0
|
||||
|
||||
- Add `MultiAbigen` to generate a series of contract bindings that can be kept in the repo
|
||||
[#724](https://github.com/gakonst/ethers-rs/pull/724).
|
||||
- Add provided `event_derives` to call and event enums as well
|
||||
[#721](https://github.com/gakonst/ethers-rs/pull/721).
|
||||
- Implement snowtrace and polygonscan on par with the etherscan integration
|
||||
[#666](https://github.com/gakonst/ethers-rs/pull/666).
|
||||
|
||||
## ethers-solc
|
||||
|
||||
### Unreleased
|
||||
|
||||
- Add `OutputContext` to `ArtifactOutput` trait
|
||||
[#1621](https://github.com/gakonst/ethers-rs/pull/1621)
|
||||
- On windows all paths in the `ProjectCompilerOutput` are now slashed by default
|
||||
[#1540](https://github.com/gakonst/ethers-rs/pull/1540)
|
||||
- `ArtifactOutput::write_extras` now takes the `Artifacts` directly
|
||||
[#1491](https://github.com/gakonst/ethers-rs/pull/1491)
|
||||
- Make `ethers-solc` optional dependency of `ethers`, needs `ethers-solc` feature to activate
|
||||
[#1463](https://github.com/gakonst/ethers-rs/pull/1463)
|
||||
- Add `rawMetadata:String` field to configurable contract output
|
||||
[#1365](https://github.com/gakonst/ethers-rs/pull/1365)
|
||||
- Use relative source paths and `solc --base-path`
|
||||
[#1317](https://github.com/gakonst/ethers-rs/pull/1317)
|
||||
- Save cache entry objects with relative paths
|
||||
[#1307](https://github.com/gakonst/ethers-rs/pull/1307)
|
||||
- Bundle svm, svm-builds and sha2 dependencies in new `svm-solc` feature
|
||||
[#1071](https://github.com/gakonst/ethers-rs/pull/1071)
|
||||
- Emit artifact files for source files without any ContractDefinition
|
||||
[#1296](https://github.com/gakonst/ethers-rs/pull/1296)
|
||||
- Wrap `ethabi::Contract` into new type `LosslessAbi` and `abi: Option<Abi>` with `abi: Option<LosslessAbi>` in `ConfigurableContractArtifact`
|
||||
[#952](https://github.com/gakonst/ethers-rs/pull/952)
|
||||
- Let `Project` take ownership of `ArtifactOutput` and change trait interface
|
||||
[#907](https://github.com/gakonst/ethers-rs/pull/907)
|
||||
- Total revamp of the `Project::compile` pipeline
|
||||
[#802](https://github.com/gakonst/ethers-rs/pull/802)
|
||||
- Support multiple versions of compiled contracts
|
||||
- Breaking: deprecate hardhat cache file compatibility, cache file now tracks artifact paths and their versions
|
||||
- Fix flatten replacement target location
|
||||
[#846](https://github.com/gakonst/ethers-rs/pull/846)
|
||||
- Fix duplicate files during flattening
|
||||
[#813](https://github.com/gakonst/ethers-rs/pull/813)
|
||||
- Add ability to flatten file imports
|
||||
[#774](https://github.com/gakonst/ethers-rs/pull/774)
|
||||
- Add dependency graph and resolve all imported libraryfiles
|
||||
[#750](https://github.com/gakonst/ethers-rs/pull/750)
|
||||
- `Remapping::find_many` does not return a `Result` anymore
|
||||
[#707](https://github.com/gakonst/ethers-rs/pull/707)
|
||||
- Add support for hardhat artifacts
|
||||
[#677](https://github.com/gakonst/ethers-rs/pull/677)
|
||||
- Add more utility functions to the `Artifact` trait
|
||||
[#673](https://github.com/gakonst/ethers-rs/pull/673)
|
||||
- Return cached artifacts from project `compile` when the cache only contains
|
||||
some files
|
||||
- Add support for library linking and make `Bytecode`'s `object` filed an
|
||||
`enum BytecodeObject` [#656](https://github.com/gakonst/ethers-rs/pull/656).
|
||||
- Nit: remove accidentally doubled double-quotes in an error message
|
||||
- Fix when compiler-out metadata is empty and there's no internalType [#1182](https://github.com/gakonst/ethers-rs/pull/1182)
|
||||
- Add basic `solc` model checker options.
|
||||
[#1258](https://github.com/gakonst/ethers-rs/pull/1258)
|
||||
|
||||
### 0.6.0
|
||||
|
||||
- add `EthAbiCodec` proc macro to derive `AbiEncode` `AbiDecode` implementation
|
||||
[#704](https://github.com/gakonst/ethers-rs/pull/704)
|
||||
- move `AbiEncode` `AbiDecode` trait to ethers-core and implement for core types
|
||||
[#531](https://github.com/gakonst/ethers-rs/pull/531)
|
||||
- Add EIP-712 `sign_typed_data` signer method; add ethers-core type `Eip712`
|
||||
trait and derive macro in ethers-derive-eip712
|
||||
[#481](https://github.com/gakonst/ethers-rs/pull/481)
|
||||
|
||||
### 0.5.3
|
||||
|
||||
- Allow configuring the optimizer & passing arbitrary arguments to solc
|
||||
[#427](https://github.com/gakonst/ethers-rs/pull/427)
|
||||
- Decimal support for `ethers_core::utils::parse_units`
|
||||
[#463](https://github.com/gakonst/ethers-rs/pull/463)
|
||||
- Fixed Wei unit calculation in `Units`
|
||||
[#460](https://github.com/gakonst/ethers-rs/pull/460)
|
||||
- Add `ethers_core::utils::get_create2_address_from_hash`
|
||||
[#444](https://github.com/gakonst/ethers-rs/pull/444)
|
||||
- Bumped ethabi to 0.15.0 and fixing breaking changes
|
||||
[#469](https://github.com/gakonst/ethers-rs/pull/469),
|
||||
[#448](https://github.com/gakonst/ethers-rs/pull/448),
|
||||
[#445](https://github.com/gakonst/ethers-rs/pull/445)
|
||||
|
||||
### 0.5.2
|
||||
|
||||
- Correctly RLP Encode transactions as received from the mempool
|
||||
([#415](https://github.com/gakonst/ethers-rs/pull/415))
|
||||
|
||||
## ethers-providers
|
||||
|
||||
### Unreleased
|
||||
|
||||
- Breaking: WS now includes reconnection logic and a changed `connect`
|
||||
interface. Old behavior can be accessed via the `legacy_ws` feature
|
||||
[#2181](https://github.com/gakonst/ethers-rs/pull/2181)
|
||||
- Re-organize the crate. #[2150](https://github.com/gakonst/ethers-rs/pull/2159)
|
||||
- Convert provider errors to arbitrary middleware errors
|
||||
[#1920](https://github.com/gakonst/ethers-rs/pull/1920)
|
||||
- Add a subset of the `admin` namespace
|
||||
[1880](https://github.com/gakonst/ethers-rs/pull/1880)
|
||||
- Return String for net version
|
||||
[1376](https://github.com/gakonst/ethers-rs/pull/1376)
|
||||
- Stream of paginated logs that load logs in small pages
|
||||
[1285](https://github.com/gakonst/ethers-rs/pull/1285)
|
||||
- Load previous logs before subscribing to new logs in case fromBlock is set
|
||||
[1264](https://github.com/gakonst/ethers-rs/pull/1264)
|
||||
- Add retries to the pending transaction future
|
||||
[1221](https://github.com/gakonst/ethers-rs/pull/1221)
|
||||
- Add support for basic and bearer authentication in http and non-wasm websockets.
|
||||
[829](https://github.com/gakonst/ethers-rs/pull/829)
|
||||
- Export `ethers_providers::IpcError` and `ethers_providers::QuorumError`
|
||||
[1012](https://github.com/gakonst/ethers-rs/pull/1012)
|
||||
|
||||
### 0.6.0
|
||||
|
||||
- re-export error types for `Http` and `Ws` providers in
|
||||
[#570](https://github.com/gakonst/ethers-rs/pull/570)
|
||||
- add a method on the `Middleware` to broadcast a tx with a series of escalating
|
||||
gas prices via [#566](https://github.com/gakonst/ethers-rs/pull/566)
|
||||
- Remove unnecessary `Serialize` constraint to `R` (the Response type) in the
|
||||
`request` method of `JsonRpcClient`.
|
||||
- Fix `http Provider` data race when generating new request `id`s.
|
||||
- Add support for `net_version` RPC method.
|
||||
[595](https://github.com/gakonst/ethers-rs/pull/595)
|
||||
- Add support for `evm_snapshot` and `evm_revert` dev RPC methods.
|
||||
[640](https://github.com/gakonst/ethers-rs/pull/640)
|
||||
|
||||
### 0.5.3
|
||||
|
||||
- Expose `ens` module [#435](https://github.com/gakonst/ethers-rs/pull/435)
|
||||
- Add `eth_getProof` [#459](https://github.com/gakonst/ethers-rs/pull/459)
|
||||
|
||||
### 0.5.2
|
||||
|
||||
- Set resolved ENS name during gas estimation
|
||||
([1e5a9e](https://github.com/gakonst/ethers-rs/commit/1e5a9efb3c678eecd43d5c341b4932da35445831))
|
||||
|
||||
## ethers-signers
|
||||
|
||||
### Unreleased
|
||||
|
||||
- fix: `LedgerSigner` has improved tracing and a ledger app bug mitigation
|
||||
[#2192](https://github.com/gakonst/ethers-rs/pull/2192)
|
||||
- `eth-keystore-rs` crate updated. Allow an optional name for the to-be-generated
|
||||
keystore file [#910](https://github.com/gakonst/ethers-rs/pull/910)
|
||||
- [1983](https://github.com/gakonst/ethers-rs/pull/1983) Added a `from_bytes` function for the `Wallet` type.
|
||||
- Allow parsing of private key that has `0x` prefix
|
||||
[#2037](https://github.com/gakonst/ethers-rs/pull/2037)
|
||||
|
||||
### 0.6.0
|
||||
|
||||
- `LocalWallet::new_keystore` now returns a tuple `(LocalWallet, String)`
|
||||
instead of `LocalWallet`, where the string represents the UUID of the newly
|
||||
created encrypted JSON keystore. The JSON keystore is stored as a file
|
||||
`/dir/uuid`. The issue [#557](https://github.com/gakonst/ethers-rs/issues/557)
|
||||
is addressed [#559](https://github.com/gakonst/ethers-rs/pull/559)
|
||||
|
||||
## ethers-contract
|
||||
|
||||
### Unreleased
|
||||
|
||||
- (Breaking) Add `Revert` to `ContractError`. Add `impl EthError for String`.
|
||||
Modify existing `ContractError` variants to prevent accidental improper
|
||||
usage. Change `MulticallError` to use `ContractError::Revert`. Add
|
||||
convenience methods to decode errors from reverts.
|
||||
[#2172](https://github.com/gakonst/ethers-rs/pull/2172)
|
||||
- (Breaking) Improve Multicall result handling
|
||||
[#2164](https://github.com/gakonst/ethers-rs/pull/2105)
|
||||
- (Breaking) Make `Event` objects generic over borrow & remove lifetime
|
||||
[#2105](https://github.com/gakonst/ethers-rs/pull/2105)
|
||||
- Make `Factory` objects generic over the borrow trait, to allow non-arc mware
|
||||
[#2103](https://github.com/gakonst/ethers-rs/pull/2103)
|
||||
- Make `Contract` objects generic over the borrow trait, to allow non-arc mware
|
||||
[#2082](https://github.com/gakonst/ethers-rs/pull/2082)
|
||||
- Return pending transaction from `Multicall::send`
|
||||
[#2044](https://github.com/gakonst/ethers-rs/pull/2044)
|
||||
- Add abigen to default features
|
||||
[#1684](https://github.com/gakonst/ethers-rs/pull/1684)
|
||||
- Add extra Multicall helper methods
|
||||
[#1666](https://github.com/gakonst/ethers-rs/pull/1666)
|
||||
- Update Multicall to Multicall3
|
||||
[#1584](https://github.com/gakonst/ethers-rs/pull/1584)
|
||||
- Add `Event::stream_with_meta` and `Event::subscribe_with_meta`
|
||||
[#1483](https://github.com/gakonst/ethers-rs/pull/1483)
|
||||
- Added tx builder methods to `ContractFactory`
|
||||
[#1289](https://github.com/gakonst/ethers-rs/pull/1289)
|
||||
- Relax Clone requirements when Arc<Middleware> is used
|
||||
[#1183](https://github.com/gakonst/ethers-rs/pull/1183)
|
||||
- Add `EventStream::select` to combine streams with different event types
|
||||
[#725](https://github.com/gakonst/ethers-rs/pull/725)
|
||||
- Substitute output tuples with rust struct types for function calls
|
||||
[#664](https://github.com/gakonst/ethers-rs/pull/664)
|
||||
- Add AbiType implementation during EthAbiType expansion
|
||||
[#647](https://github.com/gakonst/ethers-rs/pull/647)
|
||||
- fix Etherscan conditional HTTP support
|
||||
[#632](https://github.com/gakonst/ethers-rs/pull/632)
|
||||
- use `CARGO_MANIFEST_DIR` as root for relative paths in abigen
|
||||
[#631](https://github.com/gakonst/ethers-rs/pull/631)
|
||||
|
||||
### 0.6.0
|
||||
|
||||
- Provide a way to opt out of networking support in abigen proc macro with
|
||||
`abigen-offline` feature [#580](https://github.com/gakonst/ethers-rs/pull/580)
|
||||
- Add `.call()` method to `Deployer` for performing dry runs of contract
|
||||
deployments. [#554](https://github.com/gakonst/ethers-rs/pull/554)
|
||||
- Improve error message from failure in `ethers_contract_abigen::Source::parse`
|
||||
[#552](https://github.com/gakonst/ethers-rs/pull/552)
|
||||
- use enumerated aliases for overloaded functions
|
||||
[#545](https://github.com/gakonst/ethers-rs/pull/545)
|
||||
- add `EthCall` trait and derive macro which generates matching structs for
|
||||
contract calls [#517](https://github.com/gakonst/ethers-rs/pull/517)
|
||||
- Use rust types as contract function inputs for human readable abi
|
||||
[#482](https://github.com/gakonst/ethers-rs/pull/482)
|
||||
- `abigen!` now generates `Display` for all events using the new `EthDisplay`
|
||||
macro [#513](https://github.com/gakonst/ethers-rs/pull/513)
|
||||
- `abigen!` now supports overloaded functions natively
|
||||
[#501](https://github.com/gakonst/ethers-rs/pull/501)
|
||||
- `abigen!` now supports multiple contracts
|
||||
[#498](https://github.com/gakonst/ethers-rs/pull/498)
|
||||
|
||||
### Unreleased
|
||||
|
||||
### 0.5.3
|
||||
|
||||
- (De)Tokenize structs and events with only a single field as `Token:Tuple`
|
||||
([#417](https://github.com/gakonst/ethers-rs/pull/417))
|
||||
|
||||
## ethers-middleware
|
||||
|
||||
### Unreleased
|
||||
|
||||
- Added `openssl` and `rustls` feature flags
|
||||
[#1961](https://github.com/gakonst/ethers-rs/pull/1961)
|
||||
- Relax Clone requirements when Arc<Middleware> is used
|
||||
[#1183](https://github.com/gakonst/ethers-rs/pull/1183)
|
||||
- Ensure a consistent chain ID between a Signer and Provider in SignerMiddleware
|
||||
[#1095](https://gakonst/ethers-rs/pull/1095)
|
||||
- Add BlockNative gas oracle [#1175](https://github.com/gakonst/ethers-rs/pull/1175)
|
||||
|
||||
### 0.6.0
|
||||
|
||||
- add the missing constructor for `Timelag` middleware via
|
||||
[#568](https://github.com/gakonst/ethers-rs/pull/568)
|
||||
- Removes GasNow as a gas price oracle
|
||||
[#508](https://github.com/gakonst/ethers-rs/pull/508)
|
||||
- add initialize_nonce public function to initialize NonceMiddleManager
|
||||
|
||||
### 0.5.3
|
||||
|
||||
- Added Time Lagged middleware
|
||||
[#457](https://github.com/gakonst/ethers-rs/pull/457)
|
2372
CHANGELOG.md
2372
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
|
@ -134,14 +134,13 @@ include one or more tests to ensure that ethers-rs does not regress in the futur
|
|||
#### Unit Tests
|
||||
|
||||
Functions which have very specific tasks should be unit tested. We encourage using
|
||||
table tests to cover a large number of cases in a succinct readable manner. A good example
|
||||
is the [create2](https://github.com/gakonst/ethers-rs/blob/1d7bdef0bd792867454da28c4e9c193681295fb2/ethers-core/src/utils/mod.rs#L110-L163) unit tests.
|
||||
table tests to cover a large number of cases in a succinct readable manner. A good
|
||||
example is the [utils](./ethers-core/src/utils/mod.rs#L647) unit tests.
|
||||
|
||||
#### Integration tests
|
||||
|
||||
Integration tests go in the same crate as the code they are testing. Each sub
|
||||
crate should have a `dev-dependency` on `ethers` itself. This makes all
|
||||
utilities available to use in tests, no matter the crate being tested.
|
||||
Integration tests go in the same crate as the code they are testing, in the
|
||||
`tests/it/` directory.
|
||||
|
||||
The best strategy for writing a new integration test is to look at existing
|
||||
integration tests in the crate and follow the style.
|
||||
|
@ -155,27 +154,23 @@ that the example is correct and provides additional test coverage.
|
|||
The trick to documentation tests is striking a balance between being succinct
|
||||
for a reader to understand and actually testing the API.
|
||||
|
||||
Same as with integration tests, when writing a documentation test, the full
|
||||
`ethers` crate is available. This is especially useful for getting access to the
|
||||
runtime to run the example.
|
||||
|
||||
The documentation tests will be visible from both the crate specific
|
||||
documentation **and** the `ethers` facade documentation via the re-export. The
|
||||
example should be written from the point of view of a user that is using the
|
||||
`ethers` crate. As such, the example should use the API via the facade and not by
|
||||
directly referencing the crate.
|
||||
`ethers` crate.
|
||||
|
||||
The type level example for `ethers_providers::Provider` provides a good example of a
|
||||
documentation test:
|
||||
|
||||
````rust
|
||||
/// ```no_run
|
||||
/// use ethers::providers::{JsonRpcClient, Provider, Http};
|
||||
/// use std::convert::TryFrom;
|
||||
/// # async fn foo() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// use ethers_providers::{Middleware, Provider, Http};
|
||||
///
|
||||
/// let provider = Provider::<Http>::try_from("https://eth.llamarpc.com").expect("could not instantiate HTTP Provider");
|
||||
/// let provider = Provider::<Http>::try_from(
|
||||
/// "https://eth.llamarpc.com"
|
||||
/// ).expect("could not instantiate HTTP Provider");
|
||||
///
|
||||
/// # async fn foo<P: JsonRpcClient>(provider: &Provider<P>) -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let block = provider.get_block(100u64).await?;
|
||||
/// println!("Got block: {}", serde_json::to_string(&block)?);
|
||||
/// # Ok(())
|
||||
|
@ -205,52 +200,15 @@ notes about [commit squashing](#commit-squashing)).
|
|||
|
||||
#### Commit message guidelines
|
||||
|
||||
A good commit message should describe what changed and why.
|
||||
Commit messages should follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/)
|
||||
specification.
|
||||
|
||||
1. The first line should:
|
||||
Here's a few examples from the master branch's commit log:
|
||||
|
||||
- contain a short description of the change (preferably 50 characters or less,
|
||||
and no more than 72 characters)
|
||||
- be entirely in lowercase with the exception of proper nouns, acronyms, and
|
||||
the words that refer to code, like function/variable names
|
||||
- be prefixed with the name of the sub crate being changed (without the `ethers-`
|
||||
prefix) and start with an imperative verb. If modifying `ethers` proper,
|
||||
omit the crate prefix.
|
||||
|
||||
Examples:
|
||||
|
||||
- providers: introduce ENS querying for names and addresses
|
||||
- re-export the abi, types and utils modules from `ethers_core`
|
||||
|
||||
2. Keep the second line blank.
|
||||
3. Wrap all other lines at 72 columns (except for long URLs).
|
||||
4. If your patch fixes an open issue, you can add a reference to it at the end
|
||||
of the log. Use the `Fixes: #` prefix and the issue number. For other
|
||||
references use `Refs: #`. `Refs` may include multiple issues, separated by a
|
||||
comma.
|
||||
|
||||
Examples:
|
||||
|
||||
- `Fixes: #1337`
|
||||
- `Refs: #1234`
|
||||
|
||||
Sample complete commit message:
|
||||
|
||||
```txt
|
||||
subcrate: explain the commit in one line
|
||||
|
||||
Body of commit message is a few lines of text, explaining things
|
||||
in more detail, possibly giving some background about the issue
|
||||
being fixed, etc.
|
||||
|
||||
The body of the commit message can be several paragraphs, and
|
||||
please do proper word-wrap and keep columns shorter than about
|
||||
72 characters or so. That way, `git log` will show things
|
||||
nicely even when it is indented.
|
||||
|
||||
Fixes: #1337
|
||||
Refs: #453, #154
|
||||
```
|
||||
- feat(abigen): support empty events
|
||||
- chore: bump crypto deps
|
||||
- test: simplify test cleanup
|
||||
- fmt: run rustfmt
|
||||
|
||||
### Opening the Pull Request
|
||||
|
||||
|
@ -380,17 +338,14 @@ When releasing the workspace:
|
|||
existing APIs. If so, resolve those issues and make a `minor` change
|
||||
release. Otherwise, if it is necessary to make a breaking release, make a
|
||||
`major` change release.
|
||||
2. **Dry run the release** by running `cargo release --workspace <release_type>`
|
||||
3. **Update the changelog for the crate.** Changelog for all crates go in
|
||||
[`CHANGELOG.md`](./CHANGELOG.md). Any unreleased changes changelogs should
|
||||
be moved to respective crates released changelogs. Change descriptions
|
||||
may be taken from the Git history, but should be edited to ensure a consistent
|
||||
format, based on [Keep A Changelog][keep-a-changelog]. Other entries in that
|
||||
crate's changelog may also be used for reference.
|
||||
4. **Release the crate.** Run the following command:
|
||||
|
||||
```bash
|
||||
cargo release --workspace <release_type> --execute
|
||||
```
|
||||
2. **Dry run the release.** Running the `cargo release` command without the
|
||||
`--execute` flag will perform a dry run.
|
||||
3. **Release the crate.**
|
||||
Run the `bin/release` script with the `--execute` flag.
|
||||
This will update the package versions in the relevant manifests, create
|
||||
git tags, automatically generate the [`CHANGELOG.md`](./CHANGELOG.md) file
|
||||
with [git-cliff], and finally publish the crates to `crates.io`.
|
||||
For more information, see the top comment in the script file.
|
||||
|
||||
[keep-a-changelog]: https://github.com/olivierlacan/keep-a-changelog/blob/master/CHANGELOG.md
|
||||
[git-cliff]: https://github.com/orhun/git-cliff
|
||||
|
|
|
@ -77,9 +77,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
|
|||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.69"
|
||||
version = "1.0.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800"
|
||||
checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
|
@ -98,13 +98,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.66"
|
||||
version = "0.1.68"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b84f9ebcc6c1f5b8cb160f6990096a5c127f423fcb6e1ccc46c370cbdfb75dfc"
|
||||
checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"syn 2.0.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -209,9 +209,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.0.1"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5dd14596c0e5b954530d0e6f1fd99b89c03e313aa2086e8da4303701a09e1cf"
|
||||
checksum = "487f1e0fcbe47deb8b0574e646def1c903389d95241dd1bbcc6ce4a715dfc0c1"
|
||||
|
||||
[[package]]
|
||||
name = "bitvec"
|
||||
|
@ -841,9 +841,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cxx"
|
||||
version = "1.0.92"
|
||||
version = "1.0.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a140f260e6f3f79013b8bfc65e7ce630c9ab4388c6a89c71e07226f49487b72"
|
||||
checksum = "a9c00419335c41018365ddf7e4d5f1c12ee3659ddcf3e01974650ba1de73d038"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cxxbridge-flags",
|
||||
|
@ -853,9 +853,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cxx-build"
|
||||
version = "1.0.92"
|
||||
version = "1.0.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da6383f459341ea689374bf0a42979739dc421874f112ff26f829b8040b8e613"
|
||||
checksum = "fb8307ad413a98fff033c8545ecf133e3257747b3bae935e7602aab8aa92d4ca"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"codespan-reporting",
|
||||
|
@ -863,24 +863,24 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
"quote",
|
||||
"scratch",
|
||||
"syn 1.0.109",
|
||||
"syn 2.0.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-flags"
|
||||
version = "1.0.92"
|
||||
version = "1.0.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90201c1a650e95ccff1c8c0bb5a343213bdd317c6e600a93075bca2eff54ec97"
|
||||
checksum = "edc52e2eb08915cb12596d29d55f0b5384f00d697a646dbd269b6ecb0fbd9d31"
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-macro"
|
||||
version = "1.0.92"
|
||||
version = "1.0.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b75aed41bb2e6367cae39e6326ef817a851db13c13e4f3263714ca3cfb8de56"
|
||||
checksum = "631569015d0d8d54e6c241733f944042623ab6df7bc3be7466874b05fcdb1c5f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"syn 2.0.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1054,9 +1054,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ena"
|
||||
version = "0.14.1"
|
||||
version = "0.14.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2e5d13ca2353ab7d0230988629def93914a8c4015f621f9b13ed2955614731d"
|
||||
checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1"
|
||||
dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
@ -1200,7 +1200,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ethers"
|
||||
version = "2.0.0"
|
||||
version = "2.0.1"
|
||||
dependencies = [
|
||||
"ethers-addressbook",
|
||||
"ethers-contract",
|
||||
|
@ -1210,12 +1210,13 @@ dependencies = [
|
|||
"ethers-providers",
|
||||
"ethers-signers",
|
||||
"ethers-solc",
|
||||
"serde",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethers-addressbook"
|
||||
version = "2.0.0"
|
||||
version = "2.0.1"
|
||||
dependencies = [
|
||||
"ethers-core",
|
||||
"once_cell",
|
||||
|
@ -1225,7 +1226,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ethers-contract"
|
||||
version = "2.0.0"
|
||||
version = "2.0.1"
|
||||
dependencies = [
|
||||
"ethers-contract-abigen",
|
||||
"ethers-contract-derive",
|
||||
|
@ -1245,7 +1246,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ethers-contract-abigen"
|
||||
version = "2.0.0"
|
||||
version = "2.0.1"
|
||||
dependencies = [
|
||||
"Inflector",
|
||||
"dunce",
|
||||
|
@ -1272,7 +1273,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ethers-contract-derive"
|
||||
version = "2.0.0"
|
||||
version = "2.0.1"
|
||||
dependencies = [
|
||||
"Inflector",
|
||||
"ethers-contract-abigen",
|
||||
|
@ -1286,7 +1287,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ethers-core"
|
||||
version = "2.0.0"
|
||||
version = "2.0.1"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bincode",
|
||||
|
@ -1317,7 +1318,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ethers-etherscan"
|
||||
version = "2.0.0"
|
||||
version = "2.0.1"
|
||||
dependencies = [
|
||||
"ethers-core",
|
||||
"ethers-solc",
|
||||
|
@ -1336,7 +1337,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ethers-middleware"
|
||||
version = "2.0.0"
|
||||
version = "2.0.1"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"auto_impl",
|
||||
|
@ -1346,6 +1347,7 @@ dependencies = [
|
|||
"ethers-providers",
|
||||
"ethers-signers",
|
||||
"ethers-solc",
|
||||
"futures-channel",
|
||||
"futures-locks",
|
||||
"futures-util",
|
||||
"hex",
|
||||
|
@ -1364,7 +1366,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ethers-providers"
|
||||
version = "2.0.0"
|
||||
version = "2.0.1"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"auto_impl",
|
||||
|
@ -1403,7 +1405,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ethers-signers"
|
||||
version = "2.0.0"
|
||||
version = "2.0.1"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"coins-bip32",
|
||||
|
@ -1435,7 +1437,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ethers-solc"
|
||||
version = "2.0.0"
|
||||
version = "2.0.1"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"criterion",
|
||||
|
@ -1474,25 +1476,9 @@ dependencies = [
|
|||
"yansi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethers-wasm"
|
||||
version = "2.0.0"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"ethers",
|
||||
"hex",
|
||||
"serde",
|
||||
"serde-wasm-bindgen",
|
||||
"serde_json",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-bindgen-test",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "examples-anvil"
|
||||
version = "2.0.0"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"ethers",
|
||||
"eyre",
|
||||
|
@ -1501,14 +1487,14 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "examples-big-numbers"
|
||||
version = "2.0.0"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"ethers",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "examples-contracts"
|
||||
version = "2.0.0"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"ethers",
|
||||
"eyre",
|
||||
|
@ -1519,7 +1505,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "examples-events"
|
||||
version = "2.0.0"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"ethers",
|
||||
"eyre",
|
||||
|
@ -1542,7 +1528,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "examples-middleware"
|
||||
version = "2.0.0"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"ethers",
|
||||
|
@ -1555,7 +1541,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "examples-providers"
|
||||
version = "2.0.0"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"ethers",
|
||||
|
@ -1570,7 +1556,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "examples-queries"
|
||||
version = "2.0.0"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"ethers",
|
||||
"eyre",
|
||||
|
@ -1581,7 +1567,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "examples-subscriptions"
|
||||
version = "2.0.0"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"ethers",
|
||||
"eyre",
|
||||
|
@ -1592,7 +1578,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "examples-transactions"
|
||||
version = "2.0.0"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"ethers",
|
||||
"eyre",
|
||||
|
@ -1603,7 +1589,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "examples-wallets"
|
||||
version = "2.0.0"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"ethers",
|
||||
"eyre",
|
||||
|
@ -1612,6 +1598,22 @@ dependencies = [
|
|||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "examples-wasm"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"ethers",
|
||||
"hex",
|
||||
"serde",
|
||||
"serde-wasm-bindgen",
|
||||
"serde_json",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-bindgen-test",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "eyre"
|
||||
version = "0.6.8"
|
||||
|
@ -2114,16 +2116,16 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.53"
|
||||
version = "0.1.54"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765"
|
||||
checksum = "0c17cc76786e99f8d2f055c11159e7f0091c42474dcc3189fbab96072e873e6d"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"winapi",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2192,9 +2194,9 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
|
|||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.2"
|
||||
version = "1.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
|
||||
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
|
@ -2233,10 +2235,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "io-lifetimes"
|
||||
version = "1.0.6"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfa919a82ea574332e2de6e74b4c36e74d41982b335080fa59d4ef31be20fdf3"
|
||||
checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb"
|
||||
dependencies = [
|
||||
"hermit-abi 0.3.1",
|
||||
"libc",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
@ -2249,9 +2252,9 @@ checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146"
|
|||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857"
|
||||
checksum = "8687c819457e979cc940d09cb16e42a1bf70aa6b60a549de6d3a62a0ee90c69e"
|
||||
dependencies = [
|
||||
"hermit-abi 0.3.1",
|
||||
"io-lifetimes",
|
||||
|
@ -2472,9 +2475,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
version = "0.3.16"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
||||
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
|
@ -2646,9 +2649,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.46"
|
||||
version = "0.10.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd2523381e46256e40930512c7fd25562b9eae4812cb52078f155e87217c9d1e"
|
||||
checksum = "518915b97df115dd36109bfa429a48b8f737bd05508cf9588977b599648926d2"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"cfg-if",
|
||||
|
@ -2678,9 +2681,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
|||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.81"
|
||||
version = "0.9.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "176be2629957c157240f68f61f2d0053ad3a4ecfdd9ebf1e6521d18d9635cf67"
|
||||
checksum = "666416d899cf077260dac8698d60a60b435a46d57e82acb1be3d0dad87284e5b"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cc",
|
||||
|
@ -2691,9 +2694,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "6.4.1"
|
||||
version = "6.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
|
||||
checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267"
|
||||
|
||||
[[package]]
|
||||
name = "output_vt100"
|
||||
|
@ -3090,9 +3093,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.52"
|
||||
version = "1.0.53"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d0e1ae9e836cc3beddd63db0df682593d7e2d3d891ae8c9083d2113e1744224"
|
||||
checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
@ -3198,9 +3201,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.7.1"
|
||||
version = "1.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733"
|
||||
checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
|
@ -3218,15 +3221,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.28"
|
||||
version = "0.6.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
||||
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.11.14"
|
||||
version = "0.11.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9"
|
||||
checksum = "0ba30cc2c0cd02af1222ed216ba659cdb2f879dfe3181852fe7c50b1d0005949"
|
||||
dependencies = [
|
||||
"base64 0.21.0",
|
||||
"bytes",
|
||||
|
@ -3430,9 +3433,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.36.9"
|
||||
version = "0.36.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd5c6ff11fecd55b40746d1995a02f2eb375bf8c00d192d521ee09f42bef37bc"
|
||||
checksum = "db4165c9963ab29e422d6c26fbc1d37f15bace6b2810221f9d925023480fcf0e"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"errno",
|
||||
|
@ -3507,9 +3510,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "scale-info"
|
||||
version = "2.3.1"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "001cf62ece89779fd16105b5f515ad0e5cedcd5440d3dd806bb067978e7c3608"
|
||||
checksum = "61471dff9096de1d8b2319efed7162081e96793f5ebb147e50db10d50d648a4d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"derive_more",
|
||||
|
@ -3519,9 +3522,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "scale-info-derive"
|
||||
version = "2.3.1"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "303959cf613a6f6efd19ed4b4ad5bf79966a13352716299ad532cfb115f4205c"
|
||||
checksum = "219580e803a66b3f05761fd06f1f879a872444e49ce23f73694d26e5a954c7e6"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
|
@ -3638,9 +3641,9 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73"
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.156"
|
||||
version = "1.0.158"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "314b5b092c0ade17c00142951e50ced110ec27cea304b1037c6969246c2469a4"
|
||||
checksum = "771d4d9c4163ee138805e12c710dd365e4f44be8be0503cb1bb9eb989425d9c9"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
@ -3658,13 +3661,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.156"
|
||||
version = "1.0.158"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7e29c4601e36bcec74a223228dce795f4cd3616341a4af93520ca1a837c087d"
|
||||
checksum = "e801c1712f48475582b7696ac71e0ca34ebb30e09338425384269d9717c62cad"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"syn 2.0.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3680,9 +3683,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_path_to_error"
|
||||
version = "0.1.10"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db0969fff533976baadd92e08b1d102c5a3d8a8049eadfd69d4d1e3c5b2ed189"
|
||||
checksum = "f7f05c1d5476066defcdfacce1f52fc3cae3af1d3089727100c02ae92e5abbe0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
@ -4072,22 +4075,22 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
|
|||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.39"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5ab016db510546d856297882807df8da66a16fb8c4101cb8b30054b0d5b2d9c"
|
||||
checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.39"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5420d42e90af0c38c3290abcca25b9b3bdf379fc9f55c528f53a269d9c9a267e"
|
||||
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"syn 2.0.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4267,9 +4270,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.19.7"
|
||||
version = "0.19.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc18466501acd8ac6a3f615dd29a3438f8ca6bb3b19537138b3106e575621274"
|
||||
checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
|
@ -4442,9 +4445,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.11"
|
||||
version = "0.3.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "524b68aca1d05e03fdf03fcdce2c6c94b6daf6d16861ddaa7e4f2b6638a9052c"
|
||||
checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
|
@ -4711,6 +4714,15 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdacb41e6a96a052c6cb63a144f24900236121c6f63f4f8219fef5977ecb0c25"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.42.0"
|
||||
|
@ -4794,9 +4806,9 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
|||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.3.6"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23d020b441f92996c80d94ae9166e8501e59c7bb56121189dc9eab3bd8216966"
|
||||
checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
@ -4857,7 +4869,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "f6a89568917376ff46a3de7bd0abdac47e9cc8ded4e1018e4a36d071d43a54ad"
|
||||
dependencies = [
|
||||
"aes 0.8.2",
|
||||
"bitflags 2.0.1",
|
||||
"bitflags 2.0.2",
|
||||
"cbc",
|
||||
"ccm",
|
||||
"cmac",
|
||||
|
|
24
Cargo.toml
24
Cargo.toml
|
@ -1,5 +1,5 @@
|
|||
[workspace.package]
|
||||
version = "2.0.0"
|
||||
version = "2.0.1"
|
||||
edition = "2021"
|
||||
rust-version = "1.65"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
@ -64,18 +64,18 @@ resolver = "2"
|
|||
|
||||
[workspace.dependencies]
|
||||
# workspace crates
|
||||
ethers = { version = "2.0.0", path = "ethers", default-features = false }
|
||||
ethers-addressbook = { version = "2.0.0", path = "ethers-addressbook", default-features = false }
|
||||
ethers-contract = { version = "2.0.0", path = "ethers-contract", default-features = false }
|
||||
ethers-core = { version = "2.0.0", path = "ethers-core", default-features = false }
|
||||
ethers-etherscan = { version = "2.0.0", path = "ethers-etherscan", default-features = false }
|
||||
ethers-middleware = { version = "2.0.0", path = "ethers-middleware", default-features = false }
|
||||
ethers-providers = { version = "2.0.0", path = "ethers-providers", default-features = false }
|
||||
ethers-signers = { version = "2.0.0", path = "ethers-signers", default-features = false }
|
||||
ethers-solc = { version = "2.0.0", path = "ethers-solc", default-features = false }
|
||||
ethers = { version = "2.0.1", path = "ethers", default-features = false }
|
||||
ethers-addressbook = { version = "2.0.1", path = "ethers-addressbook", default-features = false }
|
||||
ethers-contract = { version = "2.0.1", path = "ethers-contract", default-features = false }
|
||||
ethers-core = { version = "2.0.1", path = "ethers-core", default-features = false }
|
||||
ethers-etherscan = { version = "2.0.1", path = "ethers-etherscan", default-features = false }
|
||||
ethers-middleware = { version = "2.0.1", path = "ethers-middleware", default-features = false }
|
||||
ethers-providers = { version = "2.0.1", path = "ethers-providers", default-features = false }
|
||||
ethers-signers = { version = "2.0.1", path = "ethers-signers", default-features = false }
|
||||
ethers-solc = { version = "2.0.1", path = "ethers-solc", default-features = false }
|
||||
|
||||
ethers-contract-abigen = { version = "2.0.0", path = "ethers-contract/ethers-contract-abigen", default-features = false }
|
||||
ethers-contract-derive = { version = "2.0.0", path = "ethers-contract/ethers-contract-derive", default-features = false }
|
||||
ethers-contract-abigen = { version = "2.0.1", path = "ethers-contract/ethers-contract-abigen", default-features = false }
|
||||
ethers-contract-derive = { version = "2.0.1", path = "ethers-contract/ethers-contract-derive", default-features = false }
|
||||
|
||||
# async / async utils
|
||||
tokio = "1.26"
|
||||
|
|
|
@ -134,7 +134,7 @@ ethers = { version = "1.0.2", features = ["openssl"] }
|
|||
|
||||
## Note on WASM and FFI bindings
|
||||
|
||||
You should be able to build a wasm app that uses ethers-rs (see the [example](./examples/ethers-wasm) for reference). If ethers fails to
|
||||
You should be able to build a wasm app that uses ethers-rs (see the [example](./examples/wasm) for reference). If ethers fails to
|
||||
compile in WASM, please
|
||||
[open an issue](https://github.com/gakonst/ethers-rs/issues/new/choose).
|
||||
There is currently no plan to provide an official JS/TS-accessible library
|
||||
|
|
119
bin/publish
119
bin/publish
|
@ -1,119 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
USAGE="Publish a new release of a ethers-rs crate
|
||||
USAGE:
|
||||
$(basename "$0") [OPTIONS] [CRATE] [VERSION]
|
||||
OPTIONS:
|
||||
-v, --verbose Use verbose Cargo output
|
||||
-d, --dry-run Perform a dry run (do not publish or tag the release)
|
||||
-h, --help Show this help text and exit"
|
||||
|
||||
DRY_RUN=""
|
||||
VERBOSE=""
|
||||
|
||||
err() {
|
||||
echo -e "\e[31m\e[1merror:\e[0m $@" 1>&2;
|
||||
}
|
||||
|
||||
status() {
|
||||
WIDTH=12
|
||||
printf "\e[32m\e[1m%${WIDTH}s\e[0m %s\n" "$1" "$2"
|
||||
}
|
||||
|
||||
verify() {
|
||||
status "Verifying" "if $CRATE v$VERSION can be released"
|
||||
ACTUAL=$(cargo pkgid | sed -n 's/.*#\(.*\)/\1/p')
|
||||
|
||||
if [ "$ACTUAL" != "$VERSION" ]; then
|
||||
err "expected to release version $VERSION, but Cargo.toml contained $ACTUAL"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if git tag -l | grep -Fxq "$TAG" ; then
|
||||
err "git tag \`$TAG\` already exists"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PATH_DEPS=$(grep -F "path = \"" Cargo.toml | sed -e 's/^/ /')
|
||||
if [ -n "$PATH_DEPS" ]; then
|
||||
err "crate \`$CRATE\` contained path dependencies:\n$PATH_DEPS"
|
||||
echo "path dependencies must be removed prior to release"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
release() {
|
||||
status "Releasing" "$CRATE v$VERSION"
|
||||
cargo package $VERBOSE
|
||||
cargo publish $VERBOSE $DRY_RUN
|
||||
|
||||
status "Tagging" "$TAG"
|
||||
if [ -n "$DRY_RUN" ]; then
|
||||
echo "# git tag $TAG && git push --tags"
|
||||
else
|
||||
git tag "$TAG" && git push --tags
|
||||
fi
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]
|
||||
do
|
||||
|
||||
case "$1" in
|
||||
-h|--help)
|
||||
echo "$USAGE"
|
||||
exit 0
|
||||
;;
|
||||
-v|--verbose)
|
||||
VERBOSE="--verbose"
|
||||
set +x
|
||||
shift
|
||||
;;
|
||||
-d|--dry-run)
|
||||
DRY_RUN="--dry-run"
|
||||
shift
|
||||
;;
|
||||
-*)
|
||||
err "unknown flag \"$1\""
|
||||
echo "$USAGE"
|
||||
exit 1
|
||||
;;
|
||||
*) # crate or version
|
||||
if [ -z "$CRATE" ]; then
|
||||
CRATE="$1"
|
||||
elif [ -z "$VERSION" ]; then
|
||||
VERSION="$1"
|
||||
else
|
||||
err "unknown positional argument \"$1\""
|
||||
echo "$USAGE"
|
||||
exit 1
|
||||
fi
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
# set -- "${POSITIONAL[@]}"
|
||||
|
||||
if [ -z "$VERSION" ]; then
|
||||
err "no version specified!"
|
||||
HELP=1
|
||||
fi
|
||||
|
||||
if [ -n "$CRATE" ]; then
|
||||
TAG="$CRATE-$VERSION"
|
||||
else
|
||||
err "no crate specified!"
|
||||
HELP=1
|
||||
fi
|
||||
|
||||
if [ -n "$HELP" ]; then
|
||||
echo "$USAGE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -d "$CRATE" ]; then
|
||||
(cd "$CRATE" && verify && release )
|
||||
else
|
||||
err "no such crate \"$CRATE\""
|
||||
exit 1
|
||||
fi
|
|
@ -0,0 +1,131 @@
|
|||
#!/usr/bin/env bash
|
||||
# Creates a new release of all the ethers crates in the workspace
|
||||
#
|
||||
# Note that this intended be run with the --execute flag, as the dry run will
|
||||
# perform all the checks that a normal `cargo release` command would.
|
||||
# This is because this script will execute only a few of the steps because it
|
||||
# has to run `git-cliff` to create the changelog in between steps, and exclude
|
||||
# all the example crates from the version bump.
|
||||
|
||||
set -e
|
||||
|
||||
info() {
|
||||
printf "\e[34;1minfo\e[0m: %s\n" "$1"
|
||||
}
|
||||
|
||||
throw() {
|
||||
printf "\e[31;1merror\e[0m: %s\n\n%s\n" "$1" "$USAGE" 1>&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
exec_or_print() {
|
||||
if [ "$EXECUTE" ]; then
|
||||
"$@"
|
||||
else
|
||||
echo "Skipping due to dry run. Command:" "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
USAGE="Create a new release of the ethers workspace crates
|
||||
|
||||
Usage:
|
||||
$(basename "$0") [OPTIONS] <VERSION>
|
||||
|
||||
Options:
|
||||
-s, --sign Sign commits and tag
|
||||
-v, --verbose Use verbose Cargo output
|
||||
-e, --execute Actually perform a release. Dry-run mode is the default
|
||||
-h, --help Show this help text and exit
|
||||
|
||||
Arguments:
|
||||
<VERSION> See 'cargo release --help'. Levels are not supported"
|
||||
|
||||
SIGN_COMMIT=""
|
||||
SIGN_TAG=""
|
||||
VERBOSE=""
|
||||
EXECUTE=""
|
||||
VERSION=""
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-s|--sign)
|
||||
SIGN_COMMIT="--sign-commit"
|
||||
SIGN_TAG="--sign-tag"
|
||||
shift
|
||||
;;
|
||||
-v|--verbose)
|
||||
VERBOSE="--verbose"
|
||||
shift
|
||||
;;
|
||||
-x|--execute)
|
||||
EXECUTE="--execute"
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
echo "$USAGE"
|
||||
exit 0
|
||||
;;
|
||||
|
||||
--)
|
||||
VERSION="$2"
|
||||
break
|
||||
;;
|
||||
|
||||
-*)
|
||||
throw "unrecognized option: '$1'"
|
||||
;;
|
||||
|
||||
*)
|
||||
if [ "$VERSION" ]; then
|
||||
throw "only one version can be specified"
|
||||
else
|
||||
VERSION="$1"
|
||||
fi
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ ! "$VERSION" ]; then
|
||||
throw "a version must be set" 1>&2
|
||||
fi
|
||||
|
||||
# check for necessary binaries
|
||||
NECESSARY=(cargo-release git-cliff)
|
||||
MISSING=""
|
||||
for bin in "${NECESSARY[@]}"; do
|
||||
if ! command -v "$bin" &>/dev/null; then
|
||||
MISSING=true
|
||||
echo "'$bin' is required to run this command, but it is not installed" 1>&2
|
||||
fi
|
||||
done
|
||||
[ "$MISSING" ] && throw "missing necessary binaries"
|
||||
|
||||
# exclude examples
|
||||
WORKSPACE_FLAGS=(--workspace)
|
||||
for ex in examples/*; do
|
||||
if [ -d "$ex" ]; then
|
||||
crate=$(echo "$ex" | tr / -)
|
||||
WORKSPACE_FLAGS+=(--exclude "$crate")
|
||||
fi
|
||||
done
|
||||
|
||||
# shellcheck disable=SC2206
|
||||
COMMON_FLAGS=($VERBOSE $EXECUTE)
|
||||
|
||||
info "bumping crate versions"
|
||||
cargo release version "${WORKSPACE_FLAGS[@]}" "${COMMON_FLAGS[@]}" "$VERSION"
|
||||
|
||||
info "creating changelog"
|
||||
exec_or_print git cliff -t "$VERSION" -o CHANGELOG.md
|
||||
|
||||
info "creating git commit"
|
||||
exec_or_print cargo release commit "${COMMON_FLAGS[@]}" $SIGN_COMMIT
|
||||
|
||||
info "publishing crates"
|
||||
exec_or_print cargo release publish "${COMMON_FLAGS[@]}" "${WORKSPACE_FLAGS[@]}"
|
||||
|
||||
info "tagging commits"
|
||||
cargo release tag "${COMMON_FLAGS[@]}" "${WORKSPACE_FLAGS[@]}" $SIGN_TAG
|
||||
|
||||
info "pushing commits and tags to remote"
|
||||
cargo release push "${COMMON_FLAGS[@]}" "${WORKSPACE_FLAGS[@]}"
|
|
@ -1,11 +1,13 @@
|
|||
# Summary
|
||||
|
||||
# Getting started
|
||||
- [Intro](./getting-started/intro.md)
|
||||
- [Start a new project](./getting-started/start_a_new_project.md)
|
||||
- [Connect to an Ethereum node](./getting-started/connect_to_an_ethereum_node.md)
|
||||
|
||||
- [Intro](./getting-started/intro.md)
|
||||
- [Start a new project](./getting-started/start_a_new_project.md)
|
||||
- [Connect to an Ethereum node](./getting-started/connect_to_an_ethereum_node.md)
|
||||
|
||||
# Reference guide
|
||||
|
||||
- [Providers](./providers/providers.md)
|
||||
- [Http](./providers/http.md)
|
||||
- [WebSocket](./providers/ws.md)
|
||||
|
@ -26,16 +28,16 @@
|
|||
- [Signer](./middleware/signer.md)
|
||||
- [Time lag]()
|
||||
- [Transformer]()
|
||||
- [Contracts]()
|
||||
- [Abigen]()
|
||||
- [Compile]()
|
||||
- [Creating Instances]()
|
||||
- [Deploy Anvil]()
|
||||
- [Deploy from ABI and bytecode]()
|
||||
- [Deploy Moonbeam]()
|
||||
- [Events]()
|
||||
- [Events with meta]()
|
||||
- [Methods]()
|
||||
- [Contracts](./contracts/contracts.md)
|
||||
- [Abigen](./contracts/abigen.md)
|
||||
- [Compile](./contracts/compile.md)
|
||||
- [Creating Instances](./contracts/creating-instances.md)
|
||||
- [Deploy Anvil](./contracts/deploy-anvil.md)
|
||||
- [Deploy from ABI and bytecode](./contracts/deploy-from-abi-and-bytecode.md)
|
||||
- [Deploy Moonbeam](./contracts/doploy-moonbeam.md)
|
||||
- [Events](./contracts/events.md)
|
||||
- [Events with meta](./contracts/events-with-meta.md)
|
||||
- [Methods](contracts/methods.md)
|
||||
- [Events]()
|
||||
- [Logs and filtering]()
|
||||
- [Solidity topics]()
|
||||
|
@ -56,7 +58,7 @@
|
|||
- [Create typed transaction]()
|
||||
- [Decode input]()
|
||||
- [EIP-1559]()
|
||||
- [ENS]()
|
||||
- [ENS]()
|
||||
- [Estimate gas]()
|
||||
- [Get gas price]()
|
||||
- [Get gas price USD]()
|
||||
|
@ -78,13 +80,13 @@
|
|||
- [Trezor]()
|
||||
- [Yubi]()
|
||||
- [Big numbers](./big-numbers/intro.md)
|
||||
- [Comparison and equivalence](./big-numbers/comparison-and-equivalence.md)
|
||||
- [Comparison and equivalence](./big-numbers/comparison-and-equivalence.md)
|
||||
- [Conversion](./big-numbers/conversion.md)
|
||||
- [Creating Instances](./big-numbers/creating_instances.md)
|
||||
- [Math operations](./big-numbers/math-operations.md)
|
||||
- [Utilities](./big-numbers/utilities.md)
|
||||
- [Anvil]()
|
||||
- [Boot anvil]()
|
||||
- [Deploy contracts]()
|
||||
- [Fork]()
|
||||
- [Testing]()
|
||||
- [Boot anvil]()
|
||||
- [Deploy contracts]()
|
||||
- [Fork]()
|
||||
- [Testing]()
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
# Abigen
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/contracts/examples/abigen.rs}}
|
||||
```
|
|
@ -0,0 +1,5 @@
|
|||
# Compile
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/contracts/examples/compile.rs}}
|
||||
```
|
|
@ -0,0 +1,29 @@
|
|||
# Contracts
|
||||
|
||||
In ethers-rs, contracts are a way to interact with smart contracts on the Ethereum blockchain through rust bindings, which serve as a robust rust API to these objects.
|
||||
|
||||
The ethers-contracts module includes the following features:
|
||||
|
||||
- [Abigen](): A module for generating Rust code from Solidity contracts.
|
||||
- [Compile](): A module for compiling Solidity contracts into bytecode and ABI files.
|
||||
- [Creating Instances](): A module for creating instances of smart contracts.
|
||||
- [Deploy Anvil](): A module for deploying smart contracts on the Anvil network.
|
||||
- [Deploy from ABI and bytecode](): A module for deploying smart contracts from their ABI and bytecode files.
|
||||
- [Deploy Moonbeam](): A module for deploying smart contracts on the Moonbeam network.
|
||||
- [Events](): A module for listening to smart contract events.
|
||||
- [Events with Meta](): A module for listening to smart contract events with metadata.
|
||||
- [Methods](): A module for calling smart contract methods.
|
||||
|
||||
The ethers-contracts module provides a convenient way to work with Ethereum smart contracts in Rust. With this module, you can easily create instances of smart contracts, deploy them to the network, and interact with their methods and events.
|
||||
|
||||
The Abigen module allows you to generate Rust code from Solidity contracts, which can save you a lot of time and effort when writing Rust code for Ethereum smart contracts.
|
||||
|
||||
The Compile module makes it easy to compile Solidity contracts into bytecode and ABI files, which are required for deploying smart contracts.
|
||||
|
||||
The Deploy Anvil and Deploy Moonbeam modules allow you to deploy smart contracts to specific networks, making it easy to test and deploy your smart contracts on the desired network.
|
||||
|
||||
The Events and Events with Meta modules allow you to listen to smart contract events and retrieve event data, which is essential for building applications that interact with Ethereum smart contracts.
|
||||
|
||||
Finally, the Methods module provides a simple way to call smart contract methods from Rust code, allowing you to interact with smart contracts in a programmatic way.
|
||||
|
||||
Overall, the ethers-contracts module provides a comprehensive set of tools for working with Ethereum smart contracts in Rust, making it an essential tool for Rust developers building decentralized applications on the Ethereum network.
|
|
@ -0,0 +1,5 @@
|
|||
# Creating Instances
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/contracts/examples/instances.rs}}
|
||||
```
|
|
@ -0,0 +1,5 @@
|
|||
# Deploy Anvil
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/contracts/examples/deploy_anvil.rs}}
|
||||
```
|
|
@ -0,0 +1,5 @@
|
|||
# Deploying a Contract from ABI and Bytecode
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/contracts/examples/deploy_from_abi_and_bytecode.rs}}
|
||||
```
|
|
@ -0,0 +1,5 @@
|
|||
# Deploy Moonbeam
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/contracts/examples/deploy_moonbeam.rs}}
|
||||
```
|
|
@ -0,0 +1,5 @@
|
|||
# Events with meta
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/contracts/examples/events_with_meta.rs}}
|
||||
```
|
|
@ -0,0 +1,5 @@
|
|||
# Events
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/contracts/examples/events.rs}}
|
||||
```
|
|
@ -0,0 +1,5 @@
|
|||
# Methods
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/contracts/examples/methods.rs}}
|
||||
```
|
|
@ -0,0 +1,83 @@
|
|||
# configuration file for git-cliff
|
||||
# see https://github.com/orhun/git-cliff#configuration-file
|
||||
|
||||
[changelog]
|
||||
# changelog header
|
||||
header = """
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
This changelog is automatically generated by [git-cliff](https://github.com/orhun/git-cliff),
|
||||
which is configured [here](./cliff.toml).
|
||||
|
||||
Please do not manually edit this file.\n
|
||||
"""
|
||||
# template for the changelog body
|
||||
# https://tera.netlify.app/docs/#introduction
|
||||
body = """
|
||||
{% if version %}\
|
||||
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
|
||||
{% else %}\
|
||||
## [Unreleased]
|
||||
{% endif %}\
|
||||
{% for group, commits in commits | group_by(attribute="group") %}
|
||||
### {{ group | title }}
|
||||
{% for commit in commits %}
|
||||
- {% if commit.breaking %}[**breaking**] {% endif %}{{ commit.message | upper_first | split(pat="\\n") | first }}\
|
||||
{% endfor %}
|
||||
{% endfor %}\n
|
||||
"""
|
||||
# remove the leading and trailing whitespace from the template
|
||||
trim = true
|
||||
# changelog footer
|
||||
footer = """
|
||||
<!-- generated by git-cliff -->
|
||||
"""
|
||||
|
||||
[git]
|
||||
# parse the commits based on https://www.conventionalcommits.org
|
||||
conventional_commits = true
|
||||
# filter out the commits that are not conventional
|
||||
filter_unconventional = false
|
||||
# process each line of a commit as an individual commit
|
||||
split_commits = false
|
||||
# regex for preprocessing the commit messages
|
||||
commit_preprocessors = [
|
||||
# replace issue numbers
|
||||
{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](https://github.com/gakonst/ethers-rs/issues/${2}))" },
|
||||
]
|
||||
# regex for parsing and grouping commits
|
||||
commit_parsers = [
|
||||
{ message = "^feat", group = "Features" },
|
||||
{ message = "^fix", group = "Bug Fixes" },
|
||||
{ message = "^doc", group = "Documentation" },
|
||||
{ message = "(.*deps)|(.*dependencies)|(.*[Bb]ump)", group = "Depedencies" },
|
||||
{ message = "^perf", group = "Performance" },
|
||||
{ message = "^refactor", group = "Refactor" },
|
||||
{ message = "(^style)|(.*fmt)", group = "Styling" },
|
||||
{ message = "^test", group = "Testing" },
|
||||
{ message = ".*release", skip = true },
|
||||
{ message = "^revert", skip = true },
|
||||
{ message = "^chore", group = "Miscellaneous Tasks" },
|
||||
{ message = ".*", group = "Other" },
|
||||
]
|
||||
# protect breaking changes from being skipped due to matching a skipping commit_parser
|
||||
protect_breaking_commits = true
|
||||
# filter out the commits that are not matched by commit parsers
|
||||
filter_commits = false
|
||||
# glob pattern for matching git tags
|
||||
tag_pattern = "*"
|
||||
# regex for skipping tags
|
||||
# skip_tags = "v0.1.0-beta.1"
|
||||
# regex for ignoring tags
|
||||
ignore_tags = "^ethers.*"
|
||||
# sort the tags topologically
|
||||
topo_order = false
|
||||
# sort the commits inside sections by oldest/newest order
|
||||
sort_commits = "newest"
|
||||
# limit the number of commits included in the changelog.
|
||||
# limit_commits = 42
|
|
@ -1,5 +1,6 @@
|
|||
#![doc = include_str!("../README.md")]
|
||||
#![deny(unsafe_code, rustdoc::broken_intra_doc_links)]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
|
||||
pub use ethers_core::types::{Address, Chain};
|
||||
|
||||
|
|
|
@ -40,9 +40,9 @@ ethers-contract-abigen = { workspace = true, optional = true }
|
|||
ethers-contract-derive = { workspace = true, optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
ethers-providers = { workspace = true, features = ["ws"] }
|
||||
ethers-signers.workspace = true
|
||||
ethers-solc.workspace = true
|
||||
ethers-providers = { workspace = true, features = ["ws"] }
|
||||
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
|
||||
tokio = { workspace = true, features = ["macros"] }
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#![deny(rustdoc::broken_intra_doc_links, missing_docs, unsafe_code)]
|
||||
#![warn(unreachable_pub)]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(missing_docs)]
|
||||
|
|
|
@ -263,14 +263,15 @@ fn _derive_builtin_traits_struct(
|
|||
}
|
||||
}
|
||||
|
||||
/// Recurses on the type until it reaches the struct tuple `ParamType`.
|
||||
fn get_struct_params<'a>(s_ty: &StructFieldType, ty: &'a ParamType) -> &'a [ParamType] {
|
||||
match (s_ty, ty) {
|
||||
(StructFieldType::Type(_), ParamType::Tuple(params)) => params,
|
||||
(StructFieldType::Array(s_ty), ParamType::Array(ty)) => get_struct_params(s_ty, ty),
|
||||
(StructFieldType::FixedArray(s_ty, _), ParamType::FixedArray(ty, _)) => {
|
||||
get_struct_params(s_ty, ty)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
(_, ParamType::Tuple(params)) => params,
|
||||
(
|
||||
StructFieldType::Array(s_ty) | StructFieldType::FixedArray(s_ty, _),
|
||||
ParamType::Array(param) | ParamType::FixedArray(param, _),
|
||||
) => get_struct_params(s_ty, param),
|
||||
_ => unreachable!("Unhandled struct field: {s_ty:?} | {ty:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#![deny(missing_docs, unsafe_code, unused_crate_dependencies)]
|
||||
#![deny(rustdoc::broken_intra_doc_links)]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
|
||||
use abigen::Contracts;
|
||||
use proc_macro::TokenStream;
|
||||
|
|
|
@ -75,7 +75,6 @@ pub type Contract<M> = ContractInstance<std::sync::Arc<M>, M>;
|
|||
/// };
|
||||
/// use ethers_contract::Contract;
|
||||
/// use ethers_providers::{Provider, Http};
|
||||
/// use ethers_signers::Wallet;
|
||||
/// use std::{convert::TryFrom, sync::Arc};
|
||||
///
|
||||
/// # async fn foo() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
@ -122,7 +121,6 @@ pub type Contract<M> = ContractInstance<std::sync::Arc<M>, M>;
|
|||
/// use ethers_core::{abi::Abi, types::Address};
|
||||
/// use ethers_contract::{Contract, EthEvent};
|
||||
/// use ethers_providers::{Provider, Http, Middleware};
|
||||
/// use ethers_signers::Wallet;
|
||||
/// use std::{convert::TryFrom, sync::Arc};
|
||||
/// use ethers_core::abi::{Detokenize, Token, InvalidOutputType};
|
||||
/// # // this is a fake address used just for this example
|
||||
|
|
|
@ -323,7 +323,6 @@ where
|
|||
/// use ethers_solc::Solc;
|
||||
/// use ethers_contract::ContractFactory;
|
||||
/// use ethers_providers::{Provider, Http};
|
||||
/// use ethers_signers::Wallet;
|
||||
/// use std::convert::TryFrom;
|
||||
///
|
||||
/// # async fn foo() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#![doc = include_str!("../README.md")]
|
||||
#![deny(unsafe_code)]
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
|
||||
#[path = "contract.rs"]
|
||||
mod _contract;
|
||||
|
|
|
@ -8,7 +8,7 @@ use ethers_core::{
|
|||
};
|
||||
use ethers_providers::{MockProvider, Provider};
|
||||
use ethers_solc::Solc;
|
||||
use std::sync::Arc;
|
||||
use std::{fmt::Debug, hash::Hash, sync::Arc};
|
||||
|
||||
const fn assert_codec<T: AbiDecode + AbiEncode>() {}
|
||||
const fn assert_tokenizeable<T: Tokenizable>() {}
|
||||
|
@ -16,7 +16,12 @@ const fn assert_call<T: AbiEncode + AbiDecode + Default + Tokenizable>() {}
|
|||
const fn assert_event<T: EthEvent>() {}
|
||||
const fn assert_clone<T: Clone>() {}
|
||||
const fn assert_default<T: Default>() {}
|
||||
const fn assert_builtin<T: std::fmt::Debug + PartialEq + Eq + std::hash::Hash>() {}
|
||||
const fn assert_builtin<T: Debug + PartialEq + Eq + Hash>() {}
|
||||
const fn assert_struct<T>()
|
||||
where
|
||||
T: AbiEncode + AbiDecode + Tokenizable + Clone + Default + Debug + PartialEq + Eq + Hash,
|
||||
{
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_generate_human_readable() {
|
||||
|
@ -25,7 +30,7 @@ fn can_generate_human_readable() {
|
|||
r#"[
|
||||
event ValueChanged(address indexed author, string oldValue, string newValue)
|
||||
]"#,
|
||||
event_derives(serde::Deserialize, serde::Serialize)
|
||||
derives(serde::Deserialize, serde::Serialize)
|
||||
);
|
||||
assert_eq!("ValueChanged", ValueChangedFilter::name());
|
||||
assert_eq!("ValueChanged(address,string,string)", ValueChangedFilter::abi_signature());
|
||||
|
@ -43,13 +48,13 @@ fn can_generate_human_readable_multiple() {
|
|||
r#"[
|
||||
event ValueChanged1(address indexed author, string oldValue, string newValue)
|
||||
]"#,
|
||||
event_derives(serde::Deserialize, serde::Serialize);
|
||||
derives(serde::Deserialize, serde::Serialize);
|
||||
|
||||
SimpleContract2,
|
||||
r#"[
|
||||
event ValueChanged2(address indexed author, string oldValue, string newValue)
|
||||
]"#,
|
||||
event_derives(serde::Deserialize, serde::Serialize)
|
||||
derives(serde::Deserialize, serde::Serialize)
|
||||
);
|
||||
assert_eq!("ValueChanged1", ValueChanged1Filter::name());
|
||||
assert_eq!("ValueChanged1(address,string,string)", ValueChanged1Filter::abi_signature());
|
||||
|
@ -66,7 +71,7 @@ fn can_generate_structs_readable() {
|
|||
struct Addresses {address[] addr; string s;}
|
||||
event ValueChanged(Value indexed old, Value newValue, Addresses _a)
|
||||
]"#,
|
||||
event_derives(serde::Deserialize, serde::Serialize)
|
||||
derives(serde::Deserialize, serde::Serialize)
|
||||
);
|
||||
let addr = Addresses {
|
||||
addr: vec!["eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee".parse().unwrap()],
|
||||
|
@ -97,7 +102,7 @@ fn can_generate_structs_with_arrays_readable() {
|
|||
struct Addresses {address[] addr; string s;}
|
||||
event ValueChanged(Value indexed old, Value newValue, Addresses[] _a)
|
||||
]"#,
|
||||
event_derives(serde::Deserialize, serde::Serialize)
|
||||
derives(serde::Deserialize, serde::Serialize)
|
||||
);
|
||||
assert_eq!(
|
||||
"ValueChanged((address,string),(address,string),(address[],string)[])",
|
||||
|
@ -113,15 +118,32 @@ fn can_generate_internal_structs() {
|
|||
abigen!(
|
||||
VerifierContract,
|
||||
"ethers-contract/tests/solidity-contracts/verifier_abi.json",
|
||||
event_derives(serde::Deserialize, serde::Serialize)
|
||||
derives(serde::Deserialize, serde::Serialize)
|
||||
);
|
||||
assert_tokenizeable::<VerifyingKey>();
|
||||
assert_tokenizeable::<G1Point>();
|
||||
assert_tokenizeable::<G2Point>();
|
||||
assert_struct::<VerifyingKey>();
|
||||
assert_struct::<G1Point>();
|
||||
assert_struct::<G2Point>();
|
||||
}
|
||||
|
||||
assert_codec::<VerifyingKey>();
|
||||
assert_codec::<G1Point>();
|
||||
assert_codec::<G2Point>();
|
||||
#[test]
|
||||
fn can_generate_internal_structs_2() {
|
||||
abigen!(Beefy, "./tests/solidity-contracts/BeefyV1.json");
|
||||
assert_struct::<AuthoritySetCommitment>();
|
||||
assert_struct::<BeefyConsensusState>();
|
||||
assert_struct::<ProofNode>();
|
||||
assert_struct::<BeefyConsensusProof>();
|
||||
|
||||
let s =
|
||||
AuthoritySetCommitment { id: U256::from(1), len: U256::from(2), root: Default::default() };
|
||||
let _encoded = AbiEncode::encode(s.clone());
|
||||
|
||||
let s = BeefyConsensusState { current_authority_set: s, ..Default::default() };
|
||||
let _encoded = AbiEncode::encode(s);
|
||||
|
||||
// tuple[][]
|
||||
let node = ProofNode::default();
|
||||
let s = BeefyConsensusProof { authorities_proof: vec![vec![node; 2]; 2], ..Default::default() };
|
||||
let _encoded = AbiEncode::encode(s);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -133,11 +155,11 @@ fn can_generate_internal_structs_multiple() {
|
|||
abigen!(
|
||||
VerifierContract,
|
||||
"ethers-contract/tests/solidity-contracts/verifier_abi.json",
|
||||
event_derives(serde::Deserialize, serde::Serialize);
|
||||
derives(serde::Deserialize, serde::Serialize);
|
||||
|
||||
MyOtherVerifierContract,
|
||||
"ethers-contract/tests/solidity-contracts/verifier_abi.json",
|
||||
event_derives(serde::Deserialize, serde::Serialize);
|
||||
derives(serde::Deserialize, serde::Serialize);
|
||||
);
|
||||
}
|
||||
assert_tokenizeable::<VerifyingKey>();
|
||||
|
@ -207,7 +229,7 @@ fn can_generate_human_readable_with_structs() {
|
|||
function bar(uint256 x, uint256 y, address addr)
|
||||
yeet(uint256,uint256,address)
|
||||
]"#,
|
||||
event_derives(serde::Deserialize, serde::Serialize)
|
||||
derives(serde::Deserialize, serde::Serialize)
|
||||
);
|
||||
assert_tokenizeable::<Foo>();
|
||||
assert_codec::<Foo>();
|
||||
|
|
|
@ -5,10 +5,7 @@ use ethers_contract::{
|
|||
};
|
||||
use ethers_core::{
|
||||
abi::{encode, AbiEncode, Token, Tokenizable},
|
||||
types::{
|
||||
transaction::eip712::Eip712, Address, BlockId, Bytes, Filter, ValueOrArray, H160, H256,
|
||||
I256, U256,
|
||||
},
|
||||
types::{Address, BlockId, Bytes, Filter, ValueOrArray, H160, H256, U256},
|
||||
utils::{keccak256, Anvil},
|
||||
};
|
||||
use ethers_providers::{Http, Middleware, MiddlewareError, Provider, StreamExt, Ws};
|
||||
|
@ -330,7 +327,6 @@ async fn call_past_hash_test() {
|
|||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "abigen")]
|
||||
async fn watch_events() {
|
||||
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
|
||||
let anvil = Anvil::new().spawn();
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
[{"inputs":[{"internalType":"contract ISMPHost","name":"host","type":"address"},{"components":[{"internalType":"uint256","name":"latestHeight","type":"uint256"},{"internalType":"uint256","name":"latestTimestamp","type":"uint256"},{"internalType":"uint256","name":"frozenHeight","type":"uint256"},{"internalType":"bytes32","name":"latestHeadsRoot","type":"bytes32"},{"internalType":"uint256","name":"beefyActivationBlock","type":"uint256"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"len","type":"uint256"},{"internalType":"bytes32","name":"root","type":"bytes32"}],"internalType":"struct AuthoritySetCommitment","name":"currentAuthoritySet","type":"tuple"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"len","type":"uint256"},{"internalType":"bytes32","name":"root","type":"bytes32"}],"internalType":"struct AuthoritySetCommitment","name":"nextAuthoritySet","type":"tuple"}],"internalType":"struct BeefyConsensusState","name":"trustedState","type":"tuple"},{"components":[{"components":[{"components":[{"components":[{"internalType":"bytes2","name":"id","type":"bytes2"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Payload[]","name":"payload","type":"tuple[]"},{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"uint256","name":"validatorSetId","type":"uint256"}],"internalType":"struct Commitment","name":"commitment","type":"tuple"},{"components":[{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"uint256","name":"authorityIndex","type":"uint256"}],"internalType":"struct Signature[]","name":"signatures","type":"tuple[]"}],"internalType":"struct SignedCommitment","name":"signedCommitment","type":"tuple"},{"components":[{"internalType":"uint256","name":"version","type":"uint256"},{"internalType":"uint256","name":"parentNumber","type":"uint256"},{"internalType":"bytes32","name":"parentHash","type":"bytes32"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"len","type":"uint256"},{"internalType":"bytes32","name":"root","type":"bytes32"}],"internalType":"struct AuthoritySetCommitment","name":"nextAuthoritySet","type":"tuple"},{"internalType":"bytes32","name":"extra","type":"bytes32"},{"internalType":"uint256","name":"kIndex","type":"uint256"}],"internalType":"struct BeefyMmrLeaf","name":"latestMmrLeaf","type":"tuple"},{"internalType":"bytes32[]","name":"mmrProof","type":"bytes32[]"},{"components":[{"internalType":"uint256","name":"k_index","type":"uint256"},{"internalType":"bytes32","name":"node","type":"bytes32"}],"internalType":"struct ProofNode[][]","name":"authoritiesProof","type":"tuple[][]"},{"internalType":"bytes","name":"header","type":"bytes"},{"internalType":"uint256","name":"headsIndex","type":"uint256"},{"internalType":"bytes[]","name":"extrinsicProof","type":"bytes[]"},{"internalType":"bytes","name":"timestampExtrinsic","type":"bytes"}],"internalType":"struct BeefyConsensusProof","name":"proof","type":"tuple"}],"name":"VerifyConsensus","outputs":[{"components":[{"internalType":"uint256","name":"latestHeight","type":"uint256"},{"internalType":"uint256","name":"latestTimestamp","type":"uint256"},{"internalType":"uint256","name":"frozenHeight","type":"uint256"},{"internalType":"bytes32","name":"latestHeadsRoot","type":"bytes32"},{"internalType":"uint256","name":"beefyActivationBlock","type":"uint256"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"len","type":"uint256"},{"internalType":"bytes32","name":"root","type":"bytes32"}],"internalType":"struct AuthoritySetCommitment","name":"currentAuthoritySet","type":"tuple"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"len","type":"uint256"},{"internalType":"bytes32","name":"root","type":"bytes32"}],"internalType":"struct AuthoritySetCommitment","name":"nextAuthoritySet","type":"tuple"}],"internalType":"struct BeefyConsensusState","name":"","type":"tuple"},{"components":[{"components":[{"internalType":"uint256","name":"stateMachineId","type":"uint256"},{"internalType":"uint256","name":"height","type":"uint256"}],"internalType":"struct StateMachineHeight","name":"height","type":"tuple"},{"components":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes32","name":"commitment","type":"bytes32"}],"internalType":"struct StateCommitment","name":"commitment","type":"tuple"}],"internalType":"struct IntermediateState","name":"","type":"tuple"}],"stateMutability":"nonpayable","type":"function"}]
|
|
@ -2,6 +2,7 @@
|
|||
#![doc = include_str!("../README.md")]
|
||||
#![deny(rustdoc::broken_intra_doc_links)]
|
||||
#![cfg_attr(not(target_arch = "wasm32"), deny(unused_crate_dependencies))]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
|
||||
pub mod types;
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ mod noop;
|
|||
mod pre_state;
|
||||
|
||||
pub use self::{
|
||||
call::{CallConfig, CallFrame},
|
||||
call::{CallConfig, CallFrame, CallLogFrame},
|
||||
four_byte::FourByteFrame,
|
||||
noop::NoopFrame,
|
||||
pre_state::{PreStateConfig, PreStateFrame},
|
||||
|
|
|
@ -32,11 +32,11 @@ pub struct CallFrame {
|
|||
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct CallLogFrame {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
address: Option<Address>,
|
||||
pub address: Option<Address>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
topics: Option<Vec<H256>>,
|
||||
pub topics: Option<Vec<H256>>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
data: Option<Bytes>,
|
||||
pub data: Option<Bytes>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#![doc = include_str!("../README.md")]
|
||||
#![deny(unsafe_code, rustdoc::broken_intra_doc_links)]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
|
||||
use crate::errors::{is_blocked_by_cloudflare_response, is_cloudflare_security_challenge};
|
||||
use contract::ContractMetadata;
|
||||
|
|
|
@ -36,6 +36,7 @@ serde.workspace = true
|
|||
thiserror.workspace = true
|
||||
futures-util.workspace = true
|
||||
futures-locks.workspace = true
|
||||
futures-channel.workspace = true
|
||||
tracing.workspace = true
|
||||
tracing-futures.workspace = true
|
||||
instant.workspace = true
|
||||
|
|
|
@ -1,21 +1,28 @@
|
|||
mod geometric;
|
||||
use ethers_core::types::transaction::eip2718::TypedTransaction;
|
||||
pub use geometric::GeometricGasPrice;
|
||||
|
||||
mod linear;
|
||||
pub use linear::LinearGasPrice;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use ethers_core::types::{BlockId, TransactionRequest, TxHash, U256};
|
||||
use ethers_providers::{interval, Middleware, MiddlewareError, PendingTransaction, StreamExt};
|
||||
use futures_util::lock::Mutex;
|
||||
|
||||
use futures_channel::oneshot;
|
||||
use futures_util::{lock::Mutex, select_biased};
|
||||
use instant::Instant;
|
||||
use std::{pin::Pin, sync::Arc};
|
||||
use thiserror::Error;
|
||||
use tracing_futures::Instrument;
|
||||
|
||||
use ethers_core::types::{
|
||||
transaction::eip2718::TypedTransaction, BlockId, TransactionRequest, TxHash, U256,
|
||||
};
|
||||
use ethers_providers::{interval, Middleware, MiddlewareError, PendingTransaction, StreamExt};
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use tokio::spawn;
|
||||
|
||||
type ToEscalate = Arc<Mutex<Vec<(TxHash, TransactionRequest, Instant, Option<BlockId>)>>>;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
type WatcherFuture<'a> = Pin<Box<dyn futures_util::stream::Stream<Item = ()> + 'a>>;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
|
@ -29,7 +36,34 @@ pub trait GasEscalator: Send + Sync + std::fmt::Debug {
|
|||
fn get_gas_price(&self, initial_price: U256, time_elapsed: u64) -> U256;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Error, Debug)]
|
||||
/// Error thrown when the GasEscalator interacts with the blockchain
|
||||
pub enum GasEscalatorError<M: Middleware> {
|
||||
#[error("{0}")]
|
||||
/// Thrown when an internal middleware errors
|
||||
MiddlewareError(M::Error),
|
||||
|
||||
#[error("Gas escalation is only supported for EIP2930 or Legacy transactions")]
|
||||
UnsupportedTxType,
|
||||
}
|
||||
|
||||
// Boilerplate
|
||||
impl<M: Middleware> MiddlewareError for GasEscalatorError<M> {
|
||||
type Inner = M::Error;
|
||||
|
||||
fn from_err(src: M::Error) -> GasEscalatorError<M> {
|
||||
GasEscalatorError::MiddlewareError(src)
|
||||
}
|
||||
|
||||
fn as_inner(&self) -> Option<&Self::Inner> {
|
||||
match self {
|
||||
GasEscalatorError::MiddlewareError(e) => Some(e),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
/// The frequency at which transactions will be bumped
|
||||
pub enum Frequency {
|
||||
/// On a per block basis using the eth_newBlock filter
|
||||
|
@ -39,9 +73,49 @@ pub enum Frequency {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct GasEscalatorMiddlewareInternal<M> {
|
||||
pub(crate) inner: Arc<M>,
|
||||
/// The transactions which are currently being monitored for escalation
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub txs: ToEscalate,
|
||||
_background: oneshot::Sender<()>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
/// A Gas escalator allows bumping transactions' gas price to avoid getting them
|
||||
/// stuck in the memory pool.
|
||||
///
|
||||
/// GasEscalator runs a background task which monitors the blockchain for tx
|
||||
/// confirmation, and bumps fees over time if txns do not occur. This task
|
||||
/// periodically loops over a stored history of sent transactions, and checks
|
||||
/// if any require fee bumps. If so, it will resend the same transaction with a
|
||||
/// higher fee.
|
||||
///
|
||||
/// Using [`GasEscalatorMiddleware::new`] will create a new instance of the
|
||||
/// background task. Using [`GasEscalatorMiddleware::clone`] will crate a new
|
||||
/// instance of the middleware, but will not create a new background task. The
|
||||
/// background task is shared among all clones.
|
||||
///
|
||||
/// ## Footgun
|
||||
///
|
||||
/// If you drop the middleware, the background task will be dropped as well,
|
||||
/// and any transactions you have sent will stop escalating. We recommend
|
||||
/// holding an instance of the middleware throughout your application's
|
||||
/// lifecycle, or leaking an `Arc` of it so that it is never dropped.
|
||||
///
|
||||
/// ## Outstanding issue
|
||||
///
|
||||
/// This task is fallible, and will stop if the provider's connection is lost.
|
||||
/// If this happens, the middleware will become unable to properly escalate gas
|
||||
/// prices. Transactions will still be dispatched, but no fee-bumping will
|
||||
/// happen. This will also cause a memory leak, as the middleware will keep
|
||||
/// appending to the list of transactions to escalate (and nothing will ever
|
||||
/// clear that list).
|
||||
///
|
||||
/// We intend to fix this issue in a future release.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// use ethers_providers::{Provider, Http};
|
||||
/// use ethers_middleware::{
|
||||
|
@ -63,39 +137,22 @@ pub enum Frequency {
|
|||
/// let gas_oracle = GasNow::new().category(GasCategory::SafeLow);
|
||||
/// let provider = GasOracleMiddleware::new(provider, gas_oracle);
|
||||
/// ```
|
||||
pub struct GasEscalatorMiddleware<M, E> {
|
||||
pub(crate) inner: Arc<M>,
|
||||
pub(crate) escalator: E,
|
||||
/// The transactions which are currently being monitored for escalation
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub txs: Arc<Mutex<Vec<(TxHash, TransactionRequest, Instant, Option<BlockId>)>>>,
|
||||
frequency: Frequency,
|
||||
}
|
||||
|
||||
impl<M, E: Clone> Clone for GasEscalatorMiddleware<M, E> {
|
||||
fn clone(&self) -> Self {
|
||||
GasEscalatorMiddleware {
|
||||
inner: self.inner.clone(),
|
||||
escalator: self.escalator.clone(),
|
||||
txs: self.txs.clone(),
|
||||
frequency: self.frequency.clone(),
|
||||
}
|
||||
}
|
||||
pub struct GasEscalatorMiddleware<M> {
|
||||
pub(crate) inner: Arc<GasEscalatorMiddlewareInternal<M>>,
|
||||
}
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
impl<M, E> Middleware for GasEscalatorMiddleware<M, E>
|
||||
impl<M> Middleware for GasEscalatorMiddleware<M>
|
||||
where
|
||||
M: Middleware,
|
||||
E: GasEscalator,
|
||||
{
|
||||
type Error = GasEscalatorError<M>;
|
||||
type Provider = M::Provider;
|
||||
type Inner = M;
|
||||
|
||||
fn inner(&self) -> &M {
|
||||
&self.inner
|
||||
fn inner(&self) -> &Self::Inner {
|
||||
&self.inner.inner
|
||||
}
|
||||
|
||||
async fn send_transaction<T: Into<TypedTransaction> + Send + Sync>(
|
||||
|
@ -103,13 +160,26 @@ where
|
|||
tx: T,
|
||||
block: Option<BlockId>,
|
||||
) -> Result<PendingTransaction<'_, Self::Provider>, Self::Error> {
|
||||
self.inner.send_transaction(tx, block).await
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> GasEscalatorMiddlewareInternal<M>
|
||||
where
|
||||
M: Middleware,
|
||||
{
|
||||
async fn send_transaction<T: Into<TypedTransaction> + Send + Sync>(
|
||||
&self,
|
||||
tx: T,
|
||||
block: Option<BlockId>,
|
||||
) -> Result<PendingTransaction<'_, M::Provider>, GasEscalatorError<M>> {
|
||||
let tx = tx.into();
|
||||
|
||||
let pending_tx = self
|
||||
.inner()
|
||||
.inner
|
||||
.send_transaction(tx.clone(), block)
|
||||
.await
|
||||
.map_err(GasEscalatorError::MiddlewareError)?;
|
||||
.map_err(MiddlewareError::from_err)?;
|
||||
|
||||
let tx = match tx {
|
||||
TypedTransaction::Legacy(inner) => inner,
|
||||
|
@ -125,141 +195,164 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<M, E> GasEscalatorMiddleware<M, E>
|
||||
impl<M> GasEscalatorMiddleware<M>
|
||||
where
|
||||
M: Middleware,
|
||||
E: GasEscalator,
|
||||
{
|
||||
/// Initializes the middleware with the provided gas escalator and the chosen
|
||||
/// escalation frequency (per block or per second)
|
||||
#[allow(clippy::let_and_return)]
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub fn new(inner: M, escalator: E, frequency: Frequency) -> Self
|
||||
pub fn new<E>(inner: M, escalator: E, frequency: Frequency) -> Self
|
||||
where
|
||||
E: Clone + 'static,
|
||||
M: Clone + 'static,
|
||||
E: GasEscalator + 'static,
|
||||
M: 'static,
|
||||
{
|
||||
use tracing_futures::Instrument;
|
||||
let (tx, rx) = oneshot::channel();
|
||||
let inner = Arc::new(inner);
|
||||
|
||||
let this = Self {
|
||||
inner: Arc::new(inner),
|
||||
escalator,
|
||||
frequency,
|
||||
txs: Arc::new(Mutex::new(Vec::new())),
|
||||
};
|
||||
let txs: ToEscalate = Default::default();
|
||||
|
||||
let this = Arc::new(GasEscalatorMiddlewareInternal {
|
||||
inner: inner.clone(),
|
||||
txs: txs.clone(),
|
||||
_background: tx,
|
||||
});
|
||||
|
||||
let esc = EscalationTask { inner, escalator, frequency, txs, shutdown: rx };
|
||||
|
||||
{
|
||||
let this2 = this.clone();
|
||||
spawn(async move {
|
||||
this2.escalate().instrument(tracing::trace_span!("gas-escalation")).await.unwrap();
|
||||
});
|
||||
spawn(esc.escalate().instrument(tracing::trace_span!("gas-escalation")));
|
||||
}
|
||||
|
||||
this
|
||||
Self { inner: this }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct EscalationTask<M, E> {
|
||||
inner: M,
|
||||
escalator: E,
|
||||
frequency: Frequency,
|
||||
txs: ToEscalate,
|
||||
shutdown: oneshot::Receiver<()>,
|
||||
}
|
||||
|
||||
impl<M, E> EscalationTask<M, E> {
|
||||
pub fn new(
|
||||
inner: M,
|
||||
escalator: E,
|
||||
frequency: Frequency,
|
||||
txs: ToEscalate,
|
||||
shutdown: oneshot::Receiver<()>,
|
||||
) -> Self {
|
||||
Self { inner, escalator, frequency, txs, shutdown }
|
||||
}
|
||||
|
||||
/// Re-broadcasts pending transactions with a gas price escalator
|
||||
pub async fn escalate(&self) -> Result<(), GasEscalatorError<M>> {
|
||||
async fn escalate(mut self) -> Result<(), GasEscalatorError<M>>
|
||||
where
|
||||
M: Middleware,
|
||||
E: GasEscalator,
|
||||
{
|
||||
// the escalation frequency is either on a per-block basis, or on a duration basis
|
||||
let mut watcher: WatcherFuture = match self.frequency {
|
||||
let watcher: WatcherFuture = match self.frequency {
|
||||
Frequency::PerBlock => Box::pin(
|
||||
self.inner
|
||||
.watch_blocks()
|
||||
.await
|
||||
.map_err(GasEscalatorError::MiddlewareError)?
|
||||
.map(|_| ()),
|
||||
self.inner.watch_blocks().await.map_err(MiddlewareError::from_err)?.map(|_| ()),
|
||||
),
|
||||
Frequency::Duration(ms) => Box::pin(interval(std::time::Duration::from_millis(ms))),
|
||||
};
|
||||
|
||||
while watcher.next().await.is_some() {
|
||||
let now = Instant::now();
|
||||
let mut txs = self.txs.lock().await;
|
||||
let len = txs.len();
|
||||
let mut watcher = watcher.fuse();
|
||||
|
||||
// Pop all transactions and re-insert those that have not been included yet
|
||||
for _ in 0..len {
|
||||
// this must never panic as we're explicitly within bounds
|
||||
let (tx_hash, mut replacement_tx, time, priority) =
|
||||
txs.pop().expect("should have element in vector");
|
||||
loop {
|
||||
select_biased! {
|
||||
_ = &mut self.shutdown => {
|
||||
tracing::debug!("Shutting down escalation task, middleware has gone away");
|
||||
return Ok(())
|
||||
}
|
||||
opt = watcher.next() => {
|
||||
if opt.is_none() {
|
||||
tracing::error!("timing future has gone away");
|
||||
return Ok(());
|
||||
}
|
||||
let now = Instant::now();
|
||||
|
||||
let receipt = self.get_transaction_receipt(tx_hash).await?;
|
||||
tracing::trace!(tx_hash = ?tx_hash, "checking if exists");
|
||||
if receipt.is_none() {
|
||||
let old_gas_price = replacement_tx.gas_price.expect("gas price must be set");
|
||||
// Get the new gas price based on how much time passed since the
|
||||
// tx was last broadcast
|
||||
let new_gas_price = self
|
||||
.escalator
|
||||
.get_gas_price(old_gas_price, now.duration_since(time).as_secs());
|
||||
// We take the contents of the mutex, and then add them back in
|
||||
// later.
|
||||
let mut txs: Vec<_> = {
|
||||
let mut txs = self.txs.lock().await;
|
||||
std::mem::take(&mut (*txs))
|
||||
// Lock scope ends
|
||||
};
|
||||
|
||||
let new_txhash = if new_gas_price != old_gas_price {
|
||||
// bump the gas price
|
||||
replacement_tx.gas_price = Some(new_gas_price);
|
||||
let len = txs.len();
|
||||
// Pop all transactions and re-insert those that have not been included yet
|
||||
for _ in 0..len {
|
||||
// this must never panic as we're explicitly within bounds
|
||||
let (tx_hash, mut replacement_tx, time, priority) =
|
||||
txs.pop().expect("should have element in vector");
|
||||
|
||||
// the tx hash will be different so we need to update it
|
||||
match self.inner().send_transaction(replacement_tx.clone(), priority).await
|
||||
{
|
||||
Ok(new_tx_hash) => {
|
||||
let new_tx_hash = *new_tx_hash;
|
||||
tracing::trace!(
|
||||
old_tx_hash = ?tx_hash,
|
||||
new_tx_hash = ?new_tx_hash,
|
||||
old_gas_price = ?old_gas_price,
|
||||
new_gas_price = ?new_gas_price,
|
||||
"escalated"
|
||||
);
|
||||
new_tx_hash
|
||||
}
|
||||
Err(err) => {
|
||||
if err.to_string().contains("nonce too low") {
|
||||
// ignore "nonce too low" errors because they
|
||||
// may happen if we try to broadcast a higher
|
||||
// gas price tx when one of the previous ones
|
||||
// was already mined (meaning we also do not
|
||||
// push it back to the pending txs vector)
|
||||
continue
|
||||
} else {
|
||||
return Err(GasEscalatorError::MiddlewareError(err))
|
||||
let receipt = self
|
||||
.inner
|
||||
.get_transaction_receipt(tx_hash)
|
||||
.await
|
||||
.map_err(MiddlewareError::from_err)?;
|
||||
|
||||
tracing::trace!(tx_hash = ?tx_hash, "checking if exists");
|
||||
|
||||
if receipt.is_none() {
|
||||
let old_gas_price = replacement_tx.gas_price.expect("gas price must be set");
|
||||
// Get the new gas price based on how much time passed since the
|
||||
// tx was last broadcast
|
||||
let new_gas_price = self
|
||||
.escalator
|
||||
.get_gas_price(old_gas_price, now.duration_since(time).as_secs());
|
||||
|
||||
let new_txhash = if new_gas_price == old_gas_price {
|
||||
tx_hash
|
||||
} else {
|
||||
// bump the gas price
|
||||
replacement_tx.gas_price = Some(new_gas_price);
|
||||
|
||||
// the tx hash will be different so we need to update it
|
||||
match self.inner.send_transaction(replacement_tx.clone(), priority).await {
|
||||
Ok(new_tx_hash) => {
|
||||
let new_tx_hash = *new_tx_hash;
|
||||
tracing::trace!(
|
||||
old_tx_hash = ?tx_hash,
|
||||
new_tx_hash = ?new_tx_hash,
|
||||
old_gas_price = ?old_gas_price,
|
||||
new_gas_price = ?new_gas_price,
|
||||
"escalated"
|
||||
);
|
||||
new_tx_hash
|
||||
}
|
||||
Err(err) => {
|
||||
if err.to_string().contains("nonce too low") {
|
||||
// ignore "nonce too low" errors because they
|
||||
// may happen if we try to broadcast a higher
|
||||
// gas price tx when one of the previous ones
|
||||
// was already mined (meaning we also do not
|
||||
// push it back to the pending txs vector)
|
||||
continue
|
||||
} else {
|
||||
tracing::error!(
|
||||
err = %err,
|
||||
"Killing escalator backend"
|
||||
);
|
||||
return Err(GasEscalatorError::MiddlewareError(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tx_hash
|
||||
};
|
||||
|
||||
txs.push((new_txhash, replacement_tx, time, priority));
|
||||
};
|
||||
txs.push((new_txhash, replacement_tx, time, priority));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// Boilerplate
|
||||
impl<M: Middleware> MiddlewareError for GasEscalatorError<M> {
|
||||
type Inner = M::Error;
|
||||
|
||||
fn from_err(src: M::Error) -> GasEscalatorError<M> {
|
||||
GasEscalatorError::MiddlewareError(src)
|
||||
}
|
||||
|
||||
fn as_inner(&self) -> Option<&Self::Inner> {
|
||||
match self {
|
||||
GasEscalatorError::MiddlewareError(e) => Some(e),
|
||||
_ => None,
|
||||
// after this big ugly loop, we dump everything back in
|
||||
// we don't replace here, as the vec in the mutex may contain
|
||||
// items!
|
||||
self.txs.lock().await.extend(txs);
|
||||
}}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
/// Error thrown when the GasEscalator interacts with the blockchain
|
||||
pub enum GasEscalatorError<M: Middleware> {
|
||||
#[error("{0}")]
|
||||
/// Thrown when an internal middleware errors
|
||||
MiddlewareError(M::Error),
|
||||
|
||||
#[error("Gas escalation is only supported for EIP2930 or Legacy transactions")]
|
||||
UnsupportedTxType,
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#![doc = include_str!("../README.md")]
|
||||
#![deny(unsafe_code, rustdoc::broken_intra_doc_links)]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
|
||||
/// The [Gas Escalator middleware](crate::gas_escalator::GasEscalatorMiddleware)
|
||||
/// is used to re-broadcast transactions with an increasing gas price to guarantee
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#![doc = include_str!("../README.md")]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
#![allow(clippy::type_complexity)]
|
||||
#![warn(missing_docs)]
|
||||
#![deny(unsafe_code, rustdoc::broken_intra_doc_links)]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
|
||||
mod ext;
|
||||
pub use ext::*;
|
||||
|
|
|
@ -51,7 +51,7 @@ pub(super) fn sig_from_digest_bytes_trial_recovery(
|
|||
|
||||
/// Modify the v value of a signature to conform to eip155
|
||||
pub(super) fn apply_eip155(sig: &mut EthSig, chain_id: u64) {
|
||||
let v = (chain_id * 2 + 35) + ((sig.v - 1) % 2);
|
||||
let v = (chain_id * 2 + 35) + sig.v;
|
||||
sig.v = v;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#![doc = include_str!("../README.md")]
|
||||
#![deny(unsafe_code, rustdoc::broken_intra_doc_links)]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
|
||||
mod wallet;
|
||||
pub use wallet::{MnemonicBuilder, Wallet, WalletError};
|
||||
|
|
|
@ -111,14 +111,14 @@ async = [
|
|||
"futures-util",
|
||||
"criterion/async_tokio",
|
||||
]
|
||||
svm-solc = ["svm-builds", "sha2"]
|
||||
svm-solc = ["svm", "svm-builds", "sha2"]
|
||||
|
||||
# Utilities for creating and testing project workspaces
|
||||
project-util = ["tempfile", "fs_extra", "rand"]
|
||||
|
||||
tests = []
|
||||
openssl = ["svm/openssl"]
|
||||
rustls = ["svm/rustls"]
|
||||
openssl = ["svm?/openssl"]
|
||||
rustls = ["svm?/rustls"]
|
||||
|
||||
# Deprecated
|
||||
asm = []
|
||||
|
|
|
@ -659,6 +659,7 @@ pub trait ArtifactOutput {
|
|||
if let Ok(stripped) = rel_candidate.strip_prefix(artifacts_folder) {
|
||||
rel_candidate = stripped.to_path_buf();
|
||||
}
|
||||
#[allow(clippy::redundant_clone)] // false positive
|
||||
let mut candidate = rel_candidate.clone();
|
||||
let contract_file = contract_file.as_ref();
|
||||
let mut current_parent = contract_file.parent();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#![doc = include_str!("../README.md")]
|
||||
#![deny(rustdoc::broken_intra_doc_links)]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
|
||||
pub mod artifacts;
|
||||
pub mod sourcemap;
|
||||
|
|
|
@ -46,7 +46,9 @@
|
|||
//! [version pragma](https://docs.soliditylang.org/en/develop/layout-of-source-files.html#version-pragma),
|
||||
//! which is defined on a per source file basis.
|
||||
|
||||
use crate::{error::Result, utils, IncludePaths, ProjectPathsConfig, SolcError, Source, Sources};
|
||||
use crate::{
|
||||
error::Result, utils, IncludePaths, ProjectPathsConfig, SolcError, SolcVersion, Source, Sources,
|
||||
};
|
||||
use parse::{SolData, SolDataUnit, SolImport};
|
||||
use rayon::prelude::*;
|
||||
use semver::VersionReq;
|
||||
|
@ -577,8 +579,7 @@ impl Graph {
|
|||
// on first error, instead gather all the errors and return a bundled error message instead
|
||||
let mut errors = Vec::new();
|
||||
// we also don't want duplicate error diagnostic
|
||||
let mut erroneous_nodes =
|
||||
std::collections::HashSet::with_capacity(self.edges.num_input_files);
|
||||
let mut erroneous_nodes = HashSet::with_capacity(self.edges.num_input_files);
|
||||
|
||||
// the sorted list of all versions
|
||||
let all_versions = if offline { Solc::installed_versions() } else { Solc::all_versions() };
|
||||
|
@ -596,11 +597,20 @@ impl Graph {
|
|||
self.retain_compatible_versions(idx, &mut candidates);
|
||||
|
||||
if candidates.is_empty() && !erroneous_nodes.contains(&idx) {
|
||||
let mut msg = String::new();
|
||||
self.format_imports_list(idx, &mut msg).unwrap();
|
||||
errors.push(format!(
|
||||
"Discovered incompatible solidity versions in following\n: {msg}"
|
||||
));
|
||||
// check if the version is even valid
|
||||
if let Some(Err(version_err)) =
|
||||
self.node(idx).check_available_version(&all_versions, offline)
|
||||
{
|
||||
let f = utils::source_name(&self.node(idx).path, &self.root).display();
|
||||
errors.push(format!("Encountered invalid solc version in {f}: {version_err}"));
|
||||
} else {
|
||||
let mut msg = String::new();
|
||||
self.format_imports_list(idx, &mut msg).unwrap();
|
||||
errors.push(format!(
|
||||
"Discovered incompatible solidity versions in following\n: {msg}"
|
||||
));
|
||||
}
|
||||
|
||||
erroneous_nodes.insert(idx);
|
||||
} else {
|
||||
// found viable candidates, pick the most recent version that's already installed
|
||||
|
@ -888,6 +898,38 @@ impl Node {
|
|||
pub fn unpack(&self) -> (&PathBuf, &Source) {
|
||||
(&self.path, &self.source)
|
||||
}
|
||||
|
||||
/// Checks that the file's version is even available.
|
||||
///
|
||||
/// This returns an error if the file's version is invalid semver, or is not available such as
|
||||
/// 0.8.20, if the highest available version is `0.8.19`
|
||||
#[allow(dead_code)]
|
||||
fn check_available_version(
|
||||
&self,
|
||||
all_versions: &[SolcVersion],
|
||||
offline: bool,
|
||||
) -> Option<std::result::Result<(), SourceVersionError>> {
|
||||
fn ensure_version(
|
||||
v: &str,
|
||||
all_versions: &[SolcVersion],
|
||||
offline: bool,
|
||||
) -> std::result::Result<(), SourceVersionError> {
|
||||
let req: VersionReq =
|
||||
v.parse().map_err(|err| SourceVersionError::InvalidVersion(v.to_string(), err))?;
|
||||
|
||||
if !all_versions.iter().any(|v| req.matches(v.as_ref())) {
|
||||
return if offline {
|
||||
Err(SourceVersionError::NoMatchingVersionOffline(req))
|
||||
} else {
|
||||
Err(SourceVersionError::NoMatchingVersion(req))
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
let v = self.data.version.as_ref()?.data();
|
||||
Some(ensure_version(v, all_versions, offline))
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper type for formatting a node
|
||||
|
@ -907,6 +949,18 @@ impl<'a> fmt::Display for DisplayNode<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Errors thrown when checking the solc version of a file
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[allow(unused)]
|
||||
enum SourceVersionError {
|
||||
#[error("Failed to parse solidity version {0}: {1}")]
|
||||
InvalidVersion(String, semver::Error),
|
||||
#[error("No solc version exists that matches the version requirement: {0}")]
|
||||
NoMatchingVersion(VersionReq),
|
||||
#[error("No solc version installed that matches the version requirement: {0}")]
|
||||
NoMatchingVersionOffline(VersionReq),
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -8,6 +8,7 @@ use ethers_solc::{
|
|||
},
|
||||
buildinfo::BuildInfo,
|
||||
cache::{SolFilesCache, SOLIDITY_FILES_CACHE_FILENAME},
|
||||
error::SolcError,
|
||||
info::ContractInfo,
|
||||
project_util::*,
|
||||
remappings::Remapping,
|
||||
|
@ -1199,6 +1200,27 @@ library MyLib {
|
|||
let bytecode = &contract.bytecode.as_ref().unwrap().object;
|
||||
assert!(!bytecode.is_unlinked());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_detect_invalid_version() {
|
||||
let tmp = TempProject::dapptools().unwrap();
|
||||
let content = r#"
|
||||
pragma solidity ^0.100.10;
|
||||
contract A {}
|
||||
"#;
|
||||
tmp.add_source("A", content).unwrap();
|
||||
|
||||
let out = tmp.compile().unwrap_err();
|
||||
match out {
|
||||
SolcError::Message(err) => {
|
||||
assert_eq!(err, "Encountered invalid solc version in src/A.sol: No solc version exists that matches the version requirement: ^0.100.10");
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_recompile_with_changes() {
|
||||
let mut tmp = TempProject::dapptools().unwrap();
|
||||
|
|
|
@ -65,9 +65,8 @@ abigen = ["ethers-contract/abigen"]
|
|||
### abigen without reqwest
|
||||
abigen-offline = ["ethers-contract/abigen-offline"]
|
||||
## solc
|
||||
ethers-solc = ["dep:ethers-solc", "ethers-etherscan/ethers-solc"]
|
||||
solc-full = ["ethers-solc?/full"]
|
||||
solc-tests = ["ethers-solc?/tests"]
|
||||
solc-full = ["ethers-solc/full"]
|
||||
solc-tests = ["ethers-solc/tests"]
|
||||
|
||||
# Deprecated
|
||||
solc-sha2-asm = []
|
||||
|
@ -76,12 +75,15 @@ solc-sha2-asm = []
|
|||
ethers-addressbook.workspace = true
|
||||
ethers-contract.workspace = true
|
||||
ethers-core.workspace = true
|
||||
ethers-etherscan.workspace = true
|
||||
ethers-etherscan = { workspace = true, features = ["ethers-solc"] }
|
||||
ethers-middleware.workspace = true
|
||||
ethers-providers.workspace = true
|
||||
ethers-signers.workspace = true
|
||||
|
||||
ethers-solc = { workspace = true, optional = true }
|
||||
ethers-solc.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { workspace = true, features = ["macros", "rt"] }
|
||||
serde.workspace = true
|
||||
tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
|
||||
ethers-contract.workspace = true
|
||||
ethers-providers = { workspace = true, features = ["rustls"] } # allow https connections
|
||||
ethers-solc = { workspace = true, features = ["svm-solc"] }
|
||||
|
|
|
@ -81,6 +81,7 @@
|
|||
|
||||
#![warn(missing_debug_implementations, missing_docs, rust_2018_idioms, unreachable_pub)]
|
||||
#![deny(rustdoc::broken_intra_doc_links)]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
#![doc(test(no_crate_inject, attr(deny(rust_2018_idioms), allow(dead_code, unused_variables))))]
|
||||
|
||||
#[doc(inline)]
|
||||
|
@ -98,7 +99,6 @@ pub use ethers_providers as providers;
|
|||
#[doc(inline)]
|
||||
pub use ethers_signers as signers;
|
||||
#[doc(inline)]
|
||||
#[cfg(feature = "ethers-solc")]
|
||||
pub use ethers_solc as solc;
|
||||
|
||||
#[doc(inline)]
|
||||
|
@ -121,7 +121,6 @@ pub mod prelude {
|
|||
|
||||
pub use super::signers::*;
|
||||
|
||||
#[cfg(feature = "ethers-solc")]
|
||||
pub use super::solc::*;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
use ethers::{
|
||||
contract::{abigen, ContractFactory, Eip712, EthAbiType},
|
||||
core::{
|
||||
types::{transaction::eip712::Eip712, Address, Bytes, I256, U256},
|
||||
utils::{keccak256, Anvil},
|
||||
},
|
||||
providers::Provider,
|
||||
signers::LocalWallet,
|
||||
solc::Solc,
|
||||
};
|
||||
use std::{path::PathBuf, sync::Arc};
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_derive_eip712() {
|
||||
// Generate Contract ABI Bindings
|
||||
abigen!(
|
||||
DeriveEip712Test,
|
||||
"./ethers-contract/tests/solidity-contracts/derive_eip712_abi.json",
|
||||
event_derives(serde::Deserialize, serde::Serialize)
|
||||
);
|
||||
|
||||
// Create derived structs
|
||||
|
||||
#[derive(Debug, Clone, Eip712, EthAbiType)]
|
||||
#[eip712(
|
||||
name = "Eip712Test",
|
||||
version = "1",
|
||||
chain_id = 1,
|
||||
verifying_contract = "0x0000000000000000000000000000000000000001",
|
||||
salt = "eip712-test-75F0CCte"
|
||||
)]
|
||||
struct FooBar {
|
||||
foo: I256,
|
||||
bar: U256,
|
||||
fizz: Bytes,
|
||||
buzz: [u8; 32],
|
||||
far: String,
|
||||
out: Address,
|
||||
}
|
||||
|
||||
// get ABI and bytecode for the DeriveEip712Test contract
|
||||
let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests");
|
||||
Solc::find_or_install_svm_version("0.6.0").unwrap(); // install solc
|
||||
let result = Solc::default().compile_source(path).unwrap();
|
||||
let (abi, bytecode, _) = result
|
||||
.find("DeriveEip712Test")
|
||||
.expect("failed to get DeriveEip712Test contract")
|
||||
.into_parts_or_default();
|
||||
|
||||
// launch the network & connect to it
|
||||
let anvil = Anvil::new().spawn();
|
||||
let from = anvil.addresses()[0];
|
||||
let provider = Provider::try_from(anvil.endpoint())
|
||||
.unwrap()
|
||||
.with_sender(from)
|
||||
.interval(std::time::Duration::from_millis(10));
|
||||
let client = Arc::new(provider);
|
||||
|
||||
let factory = ContractFactory::new(abi.clone(), bytecode.clone(), client.clone());
|
||||
|
||||
let contract = factory
|
||||
.deploy(())
|
||||
.expect("failed to deploy DeriveEip712Test contract")
|
||||
.legacy()
|
||||
.send()
|
||||
.await
|
||||
.expect("failed to instantiate factory for DeriveEip712 contract");
|
||||
|
||||
let addr = contract.address();
|
||||
|
||||
let contract = DeriveEip712Test::new(addr, client.clone());
|
||||
|
||||
let foo_bar = FooBar {
|
||||
foo: I256::from(10u64),
|
||||
bar: U256::from(20u64),
|
||||
fizz: b"fizz".into(),
|
||||
buzz: keccak256("buzz"),
|
||||
far: String::from("space"),
|
||||
out: Address::from([0; 20]),
|
||||
};
|
||||
|
||||
let derived_foo_bar = derive_eip_712_test::FooBar {
|
||||
foo: foo_bar.foo,
|
||||
bar: foo_bar.bar,
|
||||
fizz: foo_bar.fizz.clone(),
|
||||
buzz: foo_bar.buzz,
|
||||
far: foo_bar.far.clone(),
|
||||
out: foo_bar.out,
|
||||
};
|
||||
|
||||
use ethers::signers::Signer;
|
||||
|
||||
let wallet: LocalWallet = anvil.keys()[0].clone().into();
|
||||
let sig = wallet.sign_typed_data(&foo_bar).await.expect("failed to sign typed data");
|
||||
|
||||
let r = <[u8; 32]>::try_from(sig.r)
|
||||
.expect("failed to parse 'r' value from signature into [u8; 32]");
|
||||
let s = <[u8; 32]>::try_from(sig.s)
|
||||
.expect("failed to parse 's' value from signature into [u8; 32]");
|
||||
let v = u8::try_from(sig.v).expect("failed to parse 'v' value from signature into u8");
|
||||
|
||||
let domain_separator = contract
|
||||
.domain_separator()
|
||||
.call()
|
||||
.await
|
||||
.expect("failed to retrieve domain_separator from contract");
|
||||
let type_hash =
|
||||
contract.type_hash().call().await.expect("failed to retrieve type_hash from contract");
|
||||
let struct_hash = contract
|
||||
.struct_hash(derived_foo_bar.clone())
|
||||
.call()
|
||||
.await
|
||||
.expect("failed to retrieve struct_hash from contract");
|
||||
let encoded = contract
|
||||
.encode_eip_712(derived_foo_bar.clone())
|
||||
.call()
|
||||
.await
|
||||
.expect("failed to retrieve eip712 encoded hash from contract");
|
||||
let verify = contract
|
||||
.verify_foo_bar(wallet.address(), derived_foo_bar, r, s, v)
|
||||
.call()
|
||||
.await
|
||||
.expect("failed to verify signed typed data eip712 payload");
|
||||
|
||||
assert_eq!(
|
||||
domain_separator,
|
||||
foo_bar
|
||||
.domain()
|
||||
.expect("failed to return domain_separator from Eip712 implemented struct")
|
||||
.separator(),
|
||||
"domain separator does not match contract domain separator!"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
type_hash,
|
||||
FooBar::type_hash().expect("failed to return type_hash from Eip712 implemented struct"),
|
||||
"type hash does not match contract struct type hash!"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
struct_hash,
|
||||
foo_bar
|
||||
.clone()
|
||||
.struct_hash()
|
||||
.expect("failed to return struct_hash from Eip712 implemented struct"),
|
||||
"struct hash does not match contract struct hash!"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
encoded,
|
||||
foo_bar
|
||||
.encode_eip712()
|
||||
.expect("failed to return domain_separator from Eip712 implemented struct"),
|
||||
"Encoded value does not match!"
|
||||
);
|
||||
|
||||
assert!(verify, "typed data signature failed!");
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
use crate::simple_storage::SimpleStorage;
|
||||
use ethers::prelude::*;
|
||||
use std::{sync::Arc, time::Duration};
|
||||
|
||||
static CELO_TESTNET_URL: &str = "https://alfajores-forno.celo-testnet.org";
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_send_transaction() {
|
||||
// Celo testnet
|
||||
let provider =
|
||||
Provider::<Http>::try_from(CELO_TESTNET_URL).unwrap().interval(Duration::from_secs(3));
|
||||
let chain_id = provider.get_chainid().await.unwrap().as_u64();
|
||||
|
||||
// Funded with https://celo.org/developers/faucet
|
||||
// Please do not drain this account :)
|
||||
let wallet = "d652abb81e8c686edba621a895531b1f291289b63b5ef09a94f686a5ecdd5db1"
|
||||
.parse::<LocalWallet>()
|
||||
.unwrap()
|
||||
.with_chain_id(chain_id);
|
||||
let client = SignerMiddleware::new(provider, wallet);
|
||||
|
||||
let balance_before = client.get_balance(client.address(), None).await.unwrap();
|
||||
let tx = TransactionRequest::pay(client.address(), 100);
|
||||
let _receipt = client.send_transaction(tx, None).await.unwrap().confirmations(3).await.unwrap();
|
||||
let balance_after = client.get_balance(client.address(), None).await.unwrap();
|
||||
assert!(balance_before > balance_after);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn deploy_and_call_contract() {
|
||||
// Celo testnet
|
||||
let provider =
|
||||
Provider::<Http>::try_from(CELO_TESTNET_URL).unwrap().interval(Duration::from_secs(3));
|
||||
let chain_id = provider.get_chainid().await.unwrap().as_u64();
|
||||
|
||||
// Funded with https://celo.org/developers/faucet
|
||||
let wallet = "58ea5643a78c36926ad5128a6b0d8dfcc7fc705788a993b1c724be3469bc9697"
|
||||
.parse::<LocalWallet>()
|
||||
.unwrap()
|
||||
.with_chain_id(chain_id);
|
||||
let client = provider.with_signer(wallet);
|
||||
let client = Arc::new(client);
|
||||
|
||||
let deploy_tx = SimpleStorage::deploy(client, ()).unwrap();
|
||||
let contract = deploy_tx.send().await.unwrap();
|
||||
|
||||
let value: U256 = contract.value().call().await.unwrap();
|
||||
assert_eq!(value, 0.into());
|
||||
|
||||
// make a state mutating transaction
|
||||
// gas estimation costs are sometimes under-reported on celo,
|
||||
// so we manually set it to avoid failures
|
||||
let call = contract.set_value(1.into()).gas(100000);
|
||||
let pending_tx = call.send().await.unwrap();
|
||||
let _receipt = pending_tx.await.unwrap();
|
||||
|
||||
let value: U256 = contract.method("value", ()).unwrap().call().await.unwrap();
|
||||
assert_eq!(value, 1.into());
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
//! Ethers live tests.
|
||||
//!
|
||||
//! If a feature or external binary is added, like Solc, please also update
|
||||
//! `.github/workflows/ci.yml` at `job.live-test`.
|
||||
|
||||
#![cfg(not(target_arch = "wasm32"))]
|
||||
|
||||
#[cfg(feature = "celo")]
|
||||
mod celo;
|
||||
|
||||
pub(crate) mod simple_storage {
|
||||
ethers::contract::abigen!(SimpleStorage, "../testdata/SimpleStorage.json");
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
//! Ethers integration tests.
|
||||
#![cfg(not(target_arch = "wasm32"))]
|
||||
|
||||
mod eip712;
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "examples-anvil"
|
||||
version = "2.0.0"
|
||||
version = "0.0.0"
|
||||
publish = false
|
||||
authors = ["Andrea Simeoni <andreasimeoni84@gmail.com>"]
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "examples-big-numbers"
|
||||
version = "2.0.0"
|
||||
version = "0.0.0"
|
||||
publish = false
|
||||
authors = ["Andrea Simeoni <andreasimeoni84@gmail.com>"]
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "examples-contracts"
|
||||
version = "2.0.0"
|
||||
version = "0.0.0"
|
||||
publish = false
|
||||
authors = ["Andrea Simeoni <andreasimeoni84@gmail.com>"]
|
||||
|
||||
|
@ -13,7 +13,7 @@ default = ["legacy"]
|
|||
legacy = ["ethers/legacy"]
|
||||
|
||||
[dev-dependencies]
|
||||
ethers = { workspace = true, features = ["abigen", "ethers-solc", "rustls", "ws"] }
|
||||
ethers = { workspace = true, features = ["abigen", "rustls", "ws"] }
|
||||
|
||||
tokio = { workspace = true, features = ["macros"] }
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "examples-events"
|
||||
version = "2.0.0"
|
||||
version = "0.0.0"
|
||||
publish = false
|
||||
authors = ["Andrea Simeoni <andreasimeoni84@gmail.com>"]
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "examples-middleware"
|
||||
version = "2.0.0"
|
||||
version = "0.0.0"
|
||||
publish = false
|
||||
authors = ["Andrea Simeoni <andreasimeoni84@gmail.com>"]
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "examples-providers"
|
||||
version = "2.0.0"
|
||||
version = "0.0.0"
|
||||
publish = false
|
||||
authors = ["Andrea Simeoni <andreasimeoni84@gmail.com>"]
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "examples-queries"
|
||||
version = "2.0.0"
|
||||
version = "0.0.0"
|
||||
publish = false
|
||||
authors = ["Andrea Simeoni <andreasimeoni84@gmail.com>"]
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "examples-subscriptions"
|
||||
version = "2.0.0"
|
||||
version = "0.0.0"
|
||||
publish = false
|
||||
authors = ["Andrea Simeoni <andreasimeoni84@gmail.com>"]
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "examples-transactions"
|
||||
version = "2.0.0"
|
||||
version = "0.0.0"
|
||||
publish = false
|
||||
authors = ["Andrea Simeoni <andreasimeoni84@gmail.com>"]
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "examples-wallets"
|
||||
version = "2.0.0"
|
||||
version = "0.0.0"
|
||||
publish = false
|
||||
authors = ["Andrea Simeoni <andreasimeoni84@gmail.com>"]
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
[package]
|
||||
name = "ethers-wasm"
|
||||
version = "2.0.0"
|
||||
name = "examples-wasm"
|
||||
version = "0.0.0"
|
||||
authors = ["Matthias Seitz <matthias.seitz@outlook.de>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
publish = false
|
||||
|
||||
rust-version.workspace = true
|
||||
edition.workspace = true
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "ethers-wasm",
|
||||
"name": "examples-wasm",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"private": "true",
|
||||
"scripts": {
|
|
@ -5,7 +5,7 @@ use ethers::{
|
|||
signers::Signer,
|
||||
types::Chain,
|
||||
};
|
||||
use ethers_wasm::{utils, SimpleContract};
|
||||
use examples_wasm::{utils, SimpleContract};
|
||||
use std::sync::Arc;
|
||||
use wasm_bindgen_test::*;
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
allow-branch = ["master"]
|
||||
pre-release-commit-message = "chore: release"
|
||||
tag-message = "chore: release {{crate_name}} v{{version}}"
|
Loading…
Reference in New Issue