Skip to content

sending a Tempo transaction via cast send #395

@Dargon789

Description

@Dargon789

Reviewer's Guide

Implements full support for Tempo transactions across Foundry (building, signing, and sending), refines Optimism base-fee handling using network-specific parameters, adjusts artifact lookup and documentation output behavior, introduces CLI options and workflows, and updates dependency and CI configurations.

Sequence diagram for sending a Tempo transaction via cast send

sequenceDiagram actor User participant CastSend as Cast_send participant CastTxBuilder participant WalletSigner participant FoundryTxReq as FoundryTransactionRequest participant FoundryTypedTx participant NetworkWallet as NetworkWallet_FoundryNetwork participant CastTxSender participant ProviderNode as Ethereum_Node User->>CastSend: cast send --tempo.fee-token ... CastSend->>CastTxBuilder: new(provider, tx_opts) CastTxBuilder->>CastTxBuilder: is_tempo() // checks other[feeToken] CastSend->>CastTxBuilder: build(&WalletSigner) CastTxBuilder->>CastTxBuilder: _build(sender, fill_defaults=true, for_signing=false) CastTxBuilder-->>CastSend: (WithOtherFields<TransactionRequest>, fn) CastSend->>FoundryTxReq: FoundryTransactionRequest::new(tx) Note over CastSend,WalletSigner: Tempo path selected (is_tempo == true) CastSend->>WalletSigner: sign_request(FoundryTransactionRequest) WalletSigner->>WalletSigner: default_signer_address() WalletSigner->>FoundryTxReq: build_typed_tx() FoundryTxReq->>FoundryTxReq: is_tempo(), complete_tempo() FoundryTxReq-->>WalletSigner: FoundryTypedTx::Tempo WalletSigner->>NetworkWallet: sign_transaction_from(sender, FoundryTypedTx::Tempo) NetworkWallet->>WalletSigner: validate sender == default_signer_address NetworkWallet->>FoundryTypedTx: sign_transaction(self, &mut TempoTx) FoundryTypedTx-->>NetworkWallet: Signature NetworkWallet->>FoundryTypedTx: into_signed(TempoSignature) NetworkWallet-->>WalletSigner: FoundryTxEnvelope::Tempo WalletSigner-->>CastSend: FoundryTxEnvelope::Tempo CastSend->>CastSend: encode_2718_len(), encode_2718(raw_tx) CastSend->>CastTxSender: new(provider) CastSend->>CastTxSender: send_raw(raw_tx) CastTxSender->>ProviderNode: eth_sendRawTransaction(raw_tx) ProviderNode-->>CastTxSender: PendingTransaction CastTxSender-->>CastSend: PendingTransactionBuilder CastSend-->>User: tx_hash / receipt 
Loading

Updated class diagram for Tempo transaction support and signing

classDiagram class FoundryTransactionRequest { - inner : WithOtherFields_TransactionRequest + new(inner : WithOtherFields_TransactionRequest) FoundryTransactionRequest + into_inner() WithOtherFields_TransactionRequest + is_deposit() bool + is_tempo() bool + get_tempo_fee_token() Option_Address + complete_tempo() Result_void_vec_str + preferred_type() FoundryTxType + try_build() Option_FoundryTypedTx + build_typed_tx() Result_FoundryTypedTx_vec_str + build_unsigned() Result_FoundryTypedTx_vec_str } class FoundryTxType { <<enum>> Legacy Eip2930 Eip1559 Eip4844 Eip7702 Deposit Tempo } class FoundryTypedTx { <<enum>> Legacy Eip2930 Eip1559 Eip4844 Eip7702 Deposit Tempo } class TempoTransaction { + chain_id : u64 + fee_token : Option_Address + max_fee_per_gas : u128 + max_priority_fee_per_gas : u128 + gas_limit : u128 + nonce_key : U256 + nonce : u64 + calls : Vec_Call + access_list : AccessList + encoded_for_signing() Vec_u8 + into_signed(sig : TempoSignature) Self } class Call { + to : Address + value : U256 + input : Bytes } class FoundryTxEnvelope { <<enum>> Legacy Eip2930 Eip1559 Eip4844 Eip7702 Deposit Tempo + encode_2718_len() usize + encode_2718(buf : Vec_u8) void } class TempoSignature { } class WalletSigner { + default_signer_address() Address + has_signer_for(address : Address) bool + signer_addresses() Iterator_Address + sign_transaction_from(sender : Address, tx : FoundryTypedTx) Result_FoundryTxEnvelope + sign_request(request : FoundryTransactionRequest) Result_FoundryTxEnvelope } class TxSigner_Signature { <<trait>> + sign_transaction(self, tx : T) Future_Result_Signature } class NetworkWallet_FoundryNetwork { <<trait>> + default_signer_address() Address + has_signer_for(address : Address) bool + signer_addresses() Iterator_Address + sign_transaction_from(sender : Address, tx : FoundryTypedTx) Result_FoundryTxEnvelope + sign_request(request : FoundryTransactionRequest) Result_FoundryTxEnvelope } class DevSigner { + sign_transaction(tx : FoundryTypedTx) Result_Signature } class CastTxBuilder_P_InputState { + tx : WithOtherFields_TransactionRequest + build(sender : SenderKind) Result_FoundryTransactionRequest_Option_Function + build_unsigned_raw(from : Address) Result_String + is_tempo() bool + _build(sender : SenderKind, fill_defaults : bool, for_signing : bool) Result_WithOtherFields_TransactionRequest_Option_Function } class CastTxBuilder_P_InitState { } class CastTxBuilder_P_ToState { } class CastTxSender_P { + provider : Provider_AnyNetwork + new(provider : Provider_AnyNetwork) Self + send(tx_request : WithOtherFields_TransactionRequest) Result_PendingTransactionBuilder_AnyNetwork + send_raw(raw_tx : Vec_u8) Result_PendingTransactionBuilder_AnyNetwork + receipt(hash : String, block : Option_u64, confirmations : Option_u64, timeout : Option_Duration, cast_async : bool) Result_TransactionReceipt } FoundryTransactionRequest --> FoundryTypedTx : builds FoundryTypedTx o-- TempoTransaction : contains TempoTransaction o-- Call : contains FoundryTypedTx --> FoundryTxEnvelope : wrapped as FoundryTxEnvelope --> TempoSignature : uses WalletSigner ..|> TxSigner_Signature WalletSigner ..|> NetworkWallet_FoundryNetwork DevSigner ..> FoundryTypedTx : signs DevSigner ..> TempoSignature : converts Signature to TempoSignature CastTxBuilder_P_InputState --> FoundryTransactionRequest : build() CastTxBuilder_P_InputState --> WithOtherFields_TransactionRequest : internal tx CastTxSender_P --> Provider_AnyNetwork : uses 
Loading

File-Level Changes

Change Details Files
Add end-to-end support for Tempo (type 0x76) transactions in transaction building, signing, and Cast/CLI flows.
  • Expose FoundryTransactionRequest::into_inner and use FoundryTransactionRequest as the primary builder output type.
  • Detect Tempo transactions via transaction_type or feeToken in other fields and compute their preferred type as Tempo.
  • Implement complete_tempo to validate required Tempo fields and integrate it into completeness checks and TransactionBuilder::can_build.
  • Construct TempoTransaction instances from FoundryTransactionRequest (including fee token, gas fields, nonce, calls, access list) and support conversion back to TransactionRequest with feeToken in OtherFields and TEMPO_TX_TYPE_ID set.
  • Extend WalletSigner with NetworkWallet to sign FoundryTypedTx variants, including Tempo via TempoSignature, and use this in Cast send/mktx for local Tempo signing and raw submission.
  • Teach CastTxBuilder and Send/MakeTx commands about Tempo (is_tempo, tempo.fee-token option, building unsigned/raw, browser wallet restrictions, and use of eth_sendRawTransaction for Tempo).
crates/primitives/src/transaction/request.rs
crates/wallets/src/signer.rs
crates/cast/src/cmd/send.rs
crates/cast/src/tx.rs
crates/cast/src/cmd/mktx.rs
crates/cli/src/opts/tempo.rs
crates/cli/src/opts/transaction.rs
crates/wallets/Cargo.toml
crates/anvil/src/eth/sign.rs
crates/anvil/Cargo.toml
Cargo.toml
Use network-specific base-fee parameters (especially Optimism Canyon) in Anvil and add a regression test.
  • Extend NetworkConfigs with base_fee_params, selecting Optimism Canyon or pre-Canyon params using OpChainHardforks and timestamp.
  • Pass BaseFeeParams from NodeConfig into FeeManager::new and store them inside FeeManager alongside elasticity.
  • Use FeeManager::base_fee_params when computing next_block_base_fee in mem backend and document calculate_next_block_base_fee as Ethereum-mainnet specific.
  • Add an anvil Optimism integration test that fills consecutive full blocks and asserts Optimism Canyon base-fee increase (2%) instead of Ethereum’s 12.5%.
  • Wire in additional alloy-* dependencies required for base-fee and hardfork handling.
crates/evm/networks/src/lib.rs
crates/anvil/src/config.rs
crates/anvil/src/eth/fees.rs
crates/anvil/src/eth/backend/mem/mod.rs
crates/anvil/tests/it/optimism.rs
crates/evm/networks/Cargo.toml
crates/anvil/Cargo.toml
Improve artifact lookup and error behavior for cheatcodes fs and strengthen docs generation semantics.
  • Refactor get_artifact_code to return None when there are no matching artifacts and only build a manual path when artifact metadata is missing or no artifact matched, improving error messages when reading artifacts fails.
  • Change artifact selection to wrap multiple-match resolution in an Option<Result<...>> and only error when there are still multiple artifacts after filtering by version/profile.
  • Make fs read errors from artifacts path surface a generic no matching artifact found when available_artifacts is set, preserving IO errors otherwise.
  • Simplify doc writer behavior by replacing write_dev_content with italic output, generating function headings from function names plus type-only parameter lists, filtering out @custom variant comments from enum descriptions while using them in variant tables, and adjusting inheritdoc resolution to use function names.
  • Tweak Comments / CommentsRef utilities (From<Vec>, iteration) to support new filtering behaviors and update enum-variant table rendering accordingly.
crates/cheatcodes/src/fs.rs
crates/doc/src/writer/as_doc.rs
crates/doc/src/writer/buf_writer.rs
crates/doc/src/parser/comment.rs
Adjust CLI, scripting, and simulation UX and robustness (transaction options, suggestions, script-sequence, gas reporting, error messaging).
  • Introduce TempoOpts and flatten it into TransactionOpts so CLI users can pass --tempo.fee-token for Tempo transactions.
  • Update CastTxBuilder::build to return FoundryTransactionRequest and adjust all call-sites (send, mktx, unsigned raw) to unwrap via into_inner where they still expect TransactionRequest.
  • Allow CastTxBuilder::build_unsigned_raw to produce signing payloads for all supported FoundryTypedTx variants, including Tempo.
  • In simulate scripts, always label estimated amount required as ETH (and drop chain-specific token symbols) for simpler JSON output and logs.
  • Change suggestions::get_predictions and ContractsByArtifact::best_match to use partial_cmp with Ordering::Equal fallback instead of total_cmp, improving compatibility across Rust versions.
  • Improve RestrictionsError::BothExactAndRelative message to be more user-friendly and explicit about configuration constraints.
  • Add a chisel-serial test group and widen nextest slow-timeout/overrides for certain tests.
  • Comment-only or cosmetic tweaks in script-sequence (marker comments) and flake.nix (shell toolchain cleanups).
crates/cli/src/opts/mod.rs
crates/cli/src/opts/transaction.rs
crates/cast/src/cmd/send.rs
crates/cast/src/tx.rs
crates/cast/src/cmd/mktx.rs
crates/script/src/simulate.rs
crates/cli/src/utils/suggestions.rs
crates/common/src/contracts.rs
crates/config/src/compilation.rs
.config/nextest.toml
crates/script-sequence/src/sequence.rs
flake.nix
Update dependency management, CI workflows, and add example Solidity counter project and assorted templates.
  • Replace the previous reusable dependencies workflow with an in-repo cargo update workflow that opens weekly PRs (peter-evans/create-pull-request) with a detailed log.
  • Relax tempo-primitives features in the workspace (disable default-features, enable serde) and add it as a dependency where Tempo support is used (anvil, wallets).
  • Introduce multiple GitHub Actions templates (Docker builds, GKE deploy, CodeQL, Snyk container scan, APIsec scan, Foundry build/deploy) and CircleCI configs (basic hello-world, Rust cargo CI, and a custom web3 GameFi config).
  • Add a sample counter Solidity project under counter/ (foundry.toml, Counter.sol, script, tests, README, gitignore, forge-std and openzeppelin submodules, CI workflow).
  • Vendor Remix testing helper contracts under .deps/remix-tests and add generic GitHub issue templates for bugs, features, and custom issues; also commit .codesandbox/tasks.json and .gitmodules placeholders and switch Cargo.lock from ignored to tracked.
.github/workflows/dependencies.yml
Cargo.toml
crates/anvil/Cargo.toml
crates/wallets/Cargo.toml
.github/workflows/google.yml
.github/workflows/docker.yml
.github/workflows/codeql.yml
.github/workflows/snyk-container.yml
.github/workflows/apisec-scan.yml
.github/workflows/deploy.yml
.github/workflows/docker-image.yml
.circleci/config.yml
.circleci/cargo.yml
.circleci/ci-web3-gamefi.yml
counter/README.md
counter/foundry.toml
counter/src/Counter.sol
counter/script/Counter.s.sol
counter/test/Counter.t.sol
counter/.github/workflows/test.yml
.deps/remix-tests/remix_tests.sol
.deps/remix-tests/remix_accounts.sol
.github/ISSUE_TEMPLATE/bug_report.md
.github/ISSUE_TEMPLATE/feature_request.md
.github/ISSUE_TEMPLATE/custom.md
.codesandbox/tasks.json
.gitmodules
.gitignore
Cargo.lock
counter/.gitignore
counter/lib/forge-std
counter/lib/openzeppelin-contracts

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Originally posted by @sourcery-ai[bot] in #303 (comment)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions