cli-cast
Imported from paulrberg/agent-skills/skills/cli-cast.
Install
npx skills add https://github.com/PaulRBerg/agent-skills/tree/main/skills/cli-cast
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install paulrberg-agent-skills@llmmart
git clone https://github.com/PaulRBerg/agent-skills.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole paulrberg/agent-skills collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Foundry Cast CLI
This skill is coordination-exempt: skip the ai-coord gate for its declared work.
Separate read, preparation, simulation, signing, and broadcast so no state-changing action is hidden inside command construction.
For EIP-7702 authorization or delegation revocation, read references/eip7702.md before preparation. It defines signer selection, authority versus transaction sender, conditional staged approval, and authorization verification in addition to the transaction receipt.
Resolve Chain and Provider
Invoke $evm-atlas before every network operation. It owns chain resolution, discrete reads, and bounded live
subscriptions. Pass the explicit chain name or ID, JSON-RPC method and exact parameters or call object, block selector
or checkpoint requirement, and why the result is needed. Require its read packet containing the resolved chain name and
ID, provider route, result, observed block or checkpoint, and coverage gaps.
If the chain is absent from evm-atlas, stop RPC-dependent work. Do not accept an arbitrary RPC URL as an escape hatch
and never infer Ethereum when the chain is ambiguous.
Use an RPC URL in this skill only for a trace, fork, or send flow that cannot be expressed as bounded discrete reads.
For RouteMesh-backed continuous transport, first require evm-atlas to confirm current RouteMesh coverage, then use the
explicit Foundry alias when it is configured:
ROUTEMESH_CHAIN_ID="$CHAIN_ID" cast COMMAND --rpc-url routemesh
Otherwise use the nonsecret public RPC verified by evm-atlas. Never construct, inspect, or print a RouteMesh URL.
Treat Cast stderr as secret-bearing because Foundry may reveal a resolved alias URL on transport failure; never repeat
that output in chat, logs, or external reports.
Resolve every RPC value from evm-atlas's current read packet or the RouteMesh alias above; hard-coding a public RPC
URL, such as a literal https:// endpoint typed from memory or a prior response, in a prepare, simulate, or verify
command violates this delegation even when the chain matches. When a local cast command against that provider returns
a --json hex quantity, decode it with cast to-dec <hex> or a field-select form such as cast receipt <hash> <field>
or cast tx <hash> <field>; do not pipe --json output through jq tonumber, which fails on hex strings and on
null.
Authority Phases
Read
Local ABI encoding/decoding and selector derivation may run without transaction approval. Delegate chain, block, fee,
nonce, eth_call, eth_estimateGas, transaction, receipt, log, balance, code, storage, proof, and ENS reads to
$evm-atlas, including reads needed to prepare or verify a transaction. Do not ask evm-atlas to hand a read back to
this skill merely because later work may change state.
Use env -i PATH="$PATH" cast <command> --help for exact local syntax. Cast help can print inherited environment
values, including API keys; do not load credentials or decrypted dotenv for capability checks. Typical local operations:
cast calldata 'transfer(address,uint256)' "$TO" "$AMOUNT"
cast decode-calldata 'transfer(address,uint256)' "$CALLDATA"
Prepare
Resolve and validate chain ID, sender, target, function signature, arguments, calldata, native value, nonce, and fee
assumptions without signing. Obtain every on-chain fact through evm-atlas; do not request or load key material during
preparation. Select a supported signer under Sign and Broadcast and check its command capabilities before simulation or
helper construction.
Request both the confirmed nonce at the numeric checkpoint block and the pending nonce. When they differ, or a wallet
reports replacement transaction underpriced, a queued transaction occupies the lowest unconfirmed nonce, and later
nonces stay stuck behind it. Target that nonce with fees that clear the node's replacement bump, usually 10-20% on both
the fee cap and the tip, instead of queueing another transaction behind it.
For Ethereum mainnet, the default gas policy is references/ethereum-gas.md: fetch a fresh
Rabby slow quote and bind its EIP-1559 fee pair before simulation. The user or a consuming skill may explicitly choose
a different gas policy, including a fixed legacy gas price for an exact-zero sweep. Honor that choice; it does not
require a separate policy-exception approval. Record its source, transaction type, fee values, and any constraints in
the transaction review. Apply the selected policy to every signer and do not silently substitute a different tier or
transaction type. Do not reuse Ethereum fee values on another chain.
Elsewhere, absent a selected policy, set an EIP-1559 max fee with headroom over the latest base fee, such as
2 * baseFee + priorityFee, instead of passing eth_gasPrice as the cap. The charge stays base fee plus tip, while an
exact cap can fall below the base fee before signing and force a revised review.
Chain-specific gas accounting
Resolve the chain's active fee model before choosing a transaction type or subtracting fees from a balance. Use current
official protocol documentation for semantics and $evm-atlas for the target chain's parameters, fee-oracle calls,
estimates, and receipts. EVM compatibility, a native symbol of ETH, and support for legacy transactions do not establish
Ethereum fee semantics. A chain absent from atlas remains unsupported.
For the exact transaction, retain a public fee record containing the chain/checkpoint, active fork and sources, transaction type, gas estimate and limit, price/caps, expected total fee, upfront fee reserve with each component and margin, and refund behavior. Identify which charges are included in estimated gas and which are additional native debits. Use arbitrary-precision integer arithmetic and round reserves up. Never count a component twice or subtract an anticipated refund from the upfront funding requirement. Re-estimate when value, calldata, nonce, type, gas, or fees change; serialization can change the L1 charge even for an empty-calldata transfer.
- Ethereum-style accounting: establish that all fees for this transaction are covered by gas. Reserve
gasLimit * gasPricefor legacy, orgasLimit * maxFeePerGasfor EIP-1559. Actual cost uses receiptgasUsedandeffectiveGasPrice. Exact-zero native sweeps require evidence of a fixed charged price, fixed gas used, and no additional charges or credits; a plain undelegated EOA transfer on Ethereum with empty calldata and legacy pricing can use exactly 21000 gas. Do not apply that constant to other fee models. - Arbitrum Nitro: use the complete
eth_estimateGasresult, orNodeInterface.gasEstimateComponents()through atlas. It includes the parent-chain posting charge converted into child-chain gas. Budget the full gas limit at the reviewed price cap; do not add a second L1 fee. Legacy transactions are supported, but their charged price depends on the active ArbOS version and tip-collection setting. Verify that behavior through atlas and the current fee processor: newer versions make tip collection configurable. When tips are disabled, prefer EIP-1559 with zero priority fee; legacy bids and equal caps still charge the inclusion base fee. When tips are collected, apply the active effective-price rules. A fixed charged price alone does not fix the variable posting-gas component or prove an exact-zero sweep. Reconcile unused gas/price headroom against the reviewed residual policy. Use receiptgasUsed * effectiveGasPricefor total cost;gasUsedForL1is an included gas component, not an extra wei charge. See gas and fees and estimation. - OP Stack: reserve execution gas plus the L1 data fee and any enabled operator fee. Through atlas, query the
verified
GasPriceOracleforgetL1Fee(bytes)using the serialized unsigned transaction, and, where supported,getL1FeeUpperBound(uint256)using its unsigned byte length. These interfaces account for signature overhead; do not add it twice. The latter is a practical size bound at the current oracle prices, not a cap on fees at inclusion. QuerygetOperatorFee(gasLimit)for upfront budgeting and reconstruct the included operator charge using the inclusion fork's parameters, gas use, and exact client rounding/refund semantics. Before Isthmus it is absent; Isthmus and Jovian use different scalar formulas. Establish absence from fork/configuration evidence, not a failed call or a missing provider field. Receipt total is execution cost plusl1Feeplus operator cost, each once. See transaction fees, Fjord oracle, Isthmus operator accounting, and Jovian changes. - Other models, including ZKsync: obtain the current chain-native estimator and receipt semantics through atlas and
official docs. Establish coverage of pubdata, resource overhead, custom debits, and refunds for the actual transaction
type. Use an ordinary type
0/2transfer only if the chain and browser transport support it with complete fee coverage. Do not substitute a deprecated estimator or add custom transaction fields without a supported signing path. ZKsync's fee structure includes pubdata/overhead and refunds; neither 21000 gas nor exact-zero accounting follows from EVM compatibility. Stop with the missing component when complete accounting cannot be established.
On chains with fees outside transaction caps, label the total as an estimated reserve, disclose the uncovered price
movement, and recheck affordability immediately before signing. A margin is not a protocol-enforced maximum. Require
value + upfront fee reserve <= balance; ordinary gas estimation or a successful eth_call alone does not prove this.
If final wallet fee edits are allowed, recompute dependent additional fees and affordability from those values. Sweeps
whose value depends on the reserve must preserve all reviewed fields under the fixed-fee exception below.
Refunded or unspent gas is normally already reflected in the final charged fee and sender balance; do not subtract it again. Treat asynchronous refunds, such as Arbitrum retryable tickets, separately: never spend an expected credit before it arrives or claim a snapshot balance is permanent. Discovery of unrelated pending refunds is not implicit in a plain transfer. A consuming sweep must state its residual-balance policy and any known pending credits before approval.
Simulate
Simulate the exact prepared call, preserving sender, target, value, calldata, nonce, transaction type, gas limit, and
fee fields, then estimate gas. Delegate bounded eth_call and eth_estimateGas evidence to evm-atlas. When an RPC
error contradicts the supplied gas or checkpointed balance, have atlas diagnose the exact simulation path before
attributing it to transaction invalidity or chain-wide type support. Changing fields to make a diagnostic call pass does
not validate the prepared transaction. Preserve the consuming workflow's simulation and approval requirements. Use a
local fork, project simulation, or Cast trace only when the simulation requires a continuous provider, following Resolve
Chain and Provider. A successful simulation is evidence, not authorization to sign.
When exact EIP-7702 simulation needs a signed authorization, use the reference's approved authorization-signing stage first; transaction signing and broadcast still follow simulation and transaction approval.
Review
Before a transaction signature or broadcast, present one concrete review containing:
- chain name and ID, RPC source, and latest block used;
- sender, target, function, decoded arguments, calldata, and native value;
- nonce, gas estimate/limit, fee assumptions, expected total cost, upfront reserve, and any protocol-enforced fee caps;
- chain-specific fee components, inclusion-price uncertainty outside those caps, and expected refunds or residuals;
- the selected gas policy and source; for Rabby Slow, the oracle URL, tier, quote time, estimated inclusion time, max fee per gas, and max priority fee per gas; for a legacy policy, the fixed gas price and transaction type;
- expected approvals, transfers, or other state changes;
- simulation command and outcome;
- selected signer and the exact signing/broadcast command with secrets redacted.
Lead the review with ### ⚠️ Transaction approval required. Put repeated fields in a compact table, keep the exact
command in a fenced block, and state precisely what confirmation authorizes. Stop and require explicit user confirmation
of this review in a subsequent message. If any reviewed field changes outside the browser-wallet exception below,
simulate again and present a revised review. Existing explicit approval of the concrete payload and its stated use
remains valid; EIP-7702 authorization signatures follow the reference's conditional staged review.
For browser signing only, the reviewed gas limit and fees are starting values unless the consuming workflow requires them to remain fixed. The user may deliberately change the gas limit, gas price, max fee per gas, or max priority fee per gas in the wallet confirmation UI. Their approval of that final wallet screen authorizes those edited gas settings; apply chain-specific accounting to the additional fees and resulting affordability. Do not stop, require a second approval, or resimulate solely because they differ from the prepared values. Continue only when the chain, sender, target, calldata, native value, nonce, authorization list (if present), and decoded intent still match the approved review. Wallet changes to any of those fields require rejection and a revised review.
When fees determine the transfer value or another reviewed invariant, such as leaving exactly zero native balance, the browser exception does not apply. Preserve the reviewed transaction type, gas limit, and fee values. If the wallet changes them, reject before signing, recompute the dependent values, simulate, and obtain approval of the revised review.
Sign and Broadcast
Read references/browser-signing.md for browser capability checks and sender handling; open a signing request only after approval. Prefer browser, encrypted keystore, or hardware wallet in that order unless the user or consuming skill restricts the signer. A browser-only workflow must stop if browser signing is unavailable; never substitute another signer. Use an environment-backed private key only when the user explicitly opts in or no safer method is available; never ask for a key in chat or print it.
cast send signs and broadcasts in one command. Run it only after the review approval. So do the Cast 1.8.3+ helpers
cast erc20-token transfer|approve|mint|burn, cast erc20-token permit --broadcast,
cast erc4626 deposit|mint|withdraw|redeem, and cast safe propose|sign|execute: apply the same Prepare, Simulate, and
Review phases to them; a Safe proposal or confirmation is a signature artifact that needs its own payload review. Treat
any other subcommand whose installed help shows it signs or submits, such as cast safe create, add-delegate, or
remove-delegate, the same way. Signing a message or typed data, including cast erc20-token permit without
--broadcast, also requires a review of the exact payload, domain, chain binding, and intended use before approval.
Pass the selected fees explicitly: EIP-1559 uses --gas-price and --priority-gas-price; a fixed legacy policy uses
--legacy --gas-price without --priority-gas-price. Under the default Ethereum policy, use the approved Rabby Slow
pair. Before opening the signer, recheck the active chain's gas and additional-fee requirements and that the approved
cap or legacy gas price covers its current base fee where applicable. If fees must change before signing, simulate again
and present a revised review; never silently change the selected policy. Wallet fee edits follow Review, including its
fixed-fee exception. Message and typed-data signatures consume no gas.
After broadcast, capture the transaction hash and have evm-atlas verify the receipt on the reviewed chain. When a
receipt is still pending, it may use one bounded RouteMesh newHeads subscription to wait for the next block before
checking again. Receipt verification remains required; a pending-transaction or log notification alone cannot confirm
the transaction. Reconcile actual fees under the active chain's model, including additional receipt components and
refunds without double counting. Missing fee evidence is incomplete accounting, not zero fees. Report status, block, gas
used, actual total fee or its exact evidence gap, and the explorer link under ### ✅ Transaction confirmed for a
successful receipt or ### ↩ Transaction reverted for a mined failure. For an ambiguous outcome, lead with
### ⛔ Broadcast unresolved — do not retry and state the evidence still needed. Do not retry a failed or uncertain
broadcast without first checking whether the transaction exists — for browser-wallet signing specifically, read
references/browser-signing.md's Timing and Recovering sections before concluding
nothing was sent: a killed or timed-out process does not prove non-broadcast, since wallet approval is an unbounded
human wait and the wallet may broadcast via its own RPC provider.
Stop Conditions
Stop before signing when the signer, sender, chain, target, or decoded intent is unresolved. Transaction signing also
requires resolved fee accounting, affordability, and simulation. Only the explicitly approved EIP-7702 authorization
stage may precede those transaction checks; its authorization payload, signer, and intended use must already be
resolved. Review must distinguish enforced caps from an estimated reserve; browser approval of edited gas settings
authorizes those settings but does not establish coverage of omitted chain-specific charges. Stop before retrying when
broadcast outcome is ambiguous. Completion requires either a verified read result, a local encoding result, an approved
signature artifact, or a mined receipt verified by evm-atlas that matches the reviewed transaction apart from
user-approved browser-wallet gas settings. Never decorate or truncate addresses, calldata, signatures, hashes, RPC URLs,
fee values, commands, or safety wording. Revocation completion additionally requires the authorization and cleared-code
checks in references/eip7702.md.
Files (agent-skills)
-
agents
-
openai.yaml 42 B
policy: allow_implicit_invocation: true
-
-
references
-
browser-signing.md 10.9 KB
# Browser Wallet Signing Check capabilities and establish the public sender during preparation. Open a signing request only after the transaction or message review in `SKILL.md` has been explicitly approved. ## Availability Confirm the installed Cast supports browser signing: ```sh CAST_SEND_HELP=$(env -i PATH="$PATH" cast send --help) || exit 1 printf '%s\n' "$CAST_SEND_HELP" | rg --no-config -- '--browser' ``` Check the help command's exit status as well as the match. Use a clean environment for help output because Cast may print environment-backed credential defaults. Browser support is specific to each subcommand; `send --browser` does not imply `wallet address --browser` or `wallet sign --browser` exists. If unavailable in a browser-only workflow, stop without a signer fallback. Otherwise the signer preferences in `SKILL.md` apply. Browser signing requires an interactive browser and local port `9545`; it does not work in ordinary headless CI or SSH sessions. ### EIP-7702 Authorization Boundary Read [eip7702.md](eip7702.md) before preparing delegation or revocation. Check `cast wallet sign-auth --help` in a clean environment separately: `send --browser` does not establish authorization-signing support. When `sign-auth` lacks browser support, a browser-only request needing a new authorization is blocked before opening a signer. Report the missing capability and supported next step; never substitute message/typed-data signing or introduce secret-entry automation. A different signer requires authorization under the user's signer constraints. An already approved, verified authorization can accompany `cast send --auth "$SIGNED_AUTH" --browser` when the installed Cast and connected wallet support that type-4 transaction. The browser signs the outer transaction as its sender/fee payer; the authorization's recovered authority may differ. An address-valued `--auth` needs a local signer and cannot obtain a new authorization through the browser sender. Preserve the full reviewed authorization list and transaction type in the wallet; reject unsupported transport, dropped tuples, or substituted authorizations. Apply the existing fee-edit exception only to gas settings. Verify authorization application and account code after inclusion as well as the receipt. ## Resolve the Sender Use the public address supplied by the user or already known from the connected wallet as `OWNER` for preparation. Resolve ENS through `$evm-atlas`. Do not load key material to discover an address. Use `cast wallet address --browser` only if that exact subcommand's current help exposes `--browser`; otherwise ask for the public address. `cast send --browser` does not enforce `--from` or `--nonce`: the wallet signs with its active account and may substitute that account's nonce, so a mismatch broadcasts from the wrong sender. Immediately before each approved broadcast, run `cast wallet address --browser` (when its help exposes `--browser`) and require the result to equal the reviewed `OWNER`; otherwise have the user confirm the active wallet account first. On a mismatch, stop and ask the user to switch accounts; an account change requires a revised review. After broadcast, verify the transaction's `from` and nonce against the review as part of receipt verification. ## Approved Broadcast Run the exact reviewed command, for example: ```sh cast send "$CONTRACT" 'transfer(address,uint256)' "$TO" "$AMOUNT" \ --rpc-url "$RPC_URL" \ --from "$OWNER" \ --gas-price "$RABBY_SLOW_MAX_FEE_WEI" \ --priority-gas-price "$RABBY_SLOW_PRIORITY_FEE_WEI" \ --async \ --browser ``` `$RPC_URL` is the reviewed continuous-provider transport selected under `SKILL.md`; never use it for a standalone read. The example uses the default Ethereum fee policy. Use the user- or consumer-selected policy from `SKILL.md` when one is specified. For a fixed legacy policy, replace the fee pair with `--legacy --gas-price "$GAS_PRICE"` and preserve the reviewed gas limit. Do not pass EIP-1559 priority-fee flags with a legacy transaction. Unless the reviewed workflow fixes its fees, the user may deliberately edit the gas limit, gas price, max fee per gas, or max priority fee per gas in Rabby's confirmation UI, including by selecting a different tier. Treat their approval of the final wallet screen as authorization for those gas settings. Apply `SKILL.md`'s chain-specific accounting to the resulting reserve, additional fees, and affordability; an execution fee cap may not cap the total cost. Do not reject, stop, request another approval, or resimulate solely because those values differ from the reviewed command. This exception applies only to gas settings changed and approved in the wallet UI. Confirm the chain, account, target, calldata, native value, nonce, and authorization list (if present) still match the reviewed transaction; reject the request if any of those fields change. For a workflow whose transfer value depends on its fee reserve, including exact-zero and best-effort sweeps, preserve the reviewed transaction type, gas limit, and gas price or both EIP-1559 fee caps. Reject wallet changes before signing and rebuild, simulate, and review the dependent transfer value. Cast 1.8.3+ forwards an explicit `--legacy` type to the browser wallet; earlier versions could drop it at the provider boundary, so confirm the wallet screen shows the reviewed type. If the wallet cannot preserve a legacy request, stop without submitting an EIP-1559 substitute. Do not combine `--browser` with another signer flag. Capture the transaction hash, then have `$evm-atlas` verify the receipt before reporting success. ## Timing Wallet approval is an unbounded human-interaction step, not network latency: the wait is for a person to notice and click a prompt, which can exceed a typical command timeout. Run the broadcast command with a generous timeout, or in the background, so the process outlives the approval wait. A short synchronous timeout risks killing the process after the wallet has already broadcast but before `cast` prints the hash back — the transaction still lands on-chain, but the operator loses the hash and cannot immediately confirm it. Add `--async` to every browser-signed broadcast, not only as a fallback: it prints the transaction hash as soon as signing and broadcast succeed and exits without also waiting for a receipt, shrinking the window in which a timeout can outrace the printed output. Poll for the receipt separately afterward. ## Recovering From a Killed or Timed-Out Process If the process is killed or times out before printing a hash, its exit status alone does not prove nothing was broadcast — the wallet may have submitted the transaction via its own configured RPC provider, independent of the `--rpc-url` passed to `cast`, and mempool visibility lags and varies across providers (especially behind a load-balanced RPC aggregator). Do not treat a single provider's pending-transaction count or a single provider lookup miss as proof of non-broadcast. Before concluding nothing was sent: - Ask `$evm-atlas` to repeat the raw `eth_getTransactionByHash` lookup over 30-60 seconds to allow mempool propagation, rather than accepting one immediate miss as final. - Ask the user to check their wallet's own pending-activity view — the wallet knows definitively whether it submitted the transaction, independent of any RPC endpoint the agent queries. Only report the outcome as resolved (confirmed or genuinely never sent) once one of these gives a positive or a stable, repeated negative result. ## Message Signing Cast supports browser signing of plain messages and EIP-712 typed data. Confirm the installed version's capabilities before preparation, using clean-environment help: ```sh env -i PATH="$PATH" cast wallet sign --help env -i PATH="$PATH" cast wallet verify --help ``` Require `sign` to expose `--browser` and `--from`; for typed data, also require `--data` and `--from-file` on both subcommands. If unavailable, stop a browser-only flow without loading a key or substituting a transaction signature. Use an EIP-712 JSON file containing `domain`, `types`, `primaryType`, and `message`. An API's `values` object is not a Cast `message`: use the consuming workflow's validated adapter and preserve the domain, type definitions, and all signed values exactly. Keep large integers as exact decimal strings or losslessly parsed integers. Do not infer a primary type from JSON key order or sign the raw API response. Present the exact plain-message bytes or full decoded EIP-712 domain, primary type, and payload. Review the owner, chain, verifying contract, authorizations, amounts, nonces, deadlines, and intended recipient of the signature where applicable. Bind the browser account to `OWNER`. Only after approval, sign and verify the same payload: ```sh SIGNATURE="$(cast wallet sign --data --from-file "$TYPED_DATA_JSON" --from "$OWNER" --browser)" || exit 1 cast wallet verify --address "$OWNER" --data --from-file "$TYPED_DATA_JSON" "$SIGNATURE" || exit 1 ``` For plain messages, use `cast wallet sign "$MESSAGE" --from "$OWNER" --browser`, then `cast wallet verify --address "$OWNER" "$MESSAGE" "$SIGNATURE"`. Do not use `--no-hash` for EIP-712 documents or ordinary prefixed messages. Message signing is a human-interaction wait: preserve the process until the wallet responds. `--async` applies to broadcasts, not `wallet sign`. Treat sign or verify failure as blocking; never return or submit an unverified signature. This local recovery check requires a signature recoverable to `OWNER`; it does not verify EIP-1271 contract-wallet signatures. If that check cannot establish the reviewed signer, stop this flow. Return the verified signature and signer address. Submit it elsewhere only when approval explicitly covers that submission. For Permit2, the consuming workflow must bind the permit to its reviewed quote and state; a refreshed quote or changed payload requires a new review and signature. Never silently reuse or modify a signed payload. ## Failure Handling On a port conflict, missing browser, rejected wallet request, timeout, chain mismatch, or account mismatch, stop and report the failure. Do not silently fall back to a private key or retry a broadcast. If the user selects another signer, update the transaction review when the sender or command changes. Classify each failure before retrying: - `Wallet connection timeout` before `Wallet connected`, or `ChainSwitch rejected`: nothing was signed. Confirm the sender nonce is unchanged, then retry the same reviewed command. - A signed request rejected by an RPC for another chain, such as `nonce too low` with a different chain ID or `minNonce` in the error: the wallet's network state is inconsistent. The printed hash was signed; look it up on the reviewed chain and confirm the nonce is unchanged. Ask the user to reset the `localhost:9545` site network in the wallet before retrying. - Each command switches the wallet to its chain. Sending first on the already connected chain avoids a switch prompt. -
eip7702.md 14.3 KB
# EIP-7702 Delegation Revocation Use Cast's native authorization commands to clear delegation. Follow [the EIP-7702 specification](https://eips.ethereum.org/EIPS/eip-7702) and verify that each selected chain's active fork supports type-4 transactions through `$evm-atlas` and current official chain documentation. All state, simulation, estimation, and verification reads belong to atlas under `SKILL.md`. ## Select the Signer and Native Route First Before transaction preparation or secret access, check the installed capabilities in a clean environment: ```sh env -i PATH="$PATH" cast wallet sign-auth --help env -i PATH="$PATH" cast send --help env -i PATH="$PATH" cast recover-authority --help env -i PATH="$PATH" cast from-rlp --help ``` Check each producer's exit status; when filtering, capture successful help first as in [browser-signing.md](browser-signing.md). Do not infer authorization signing from `send --browser` or ordinary message signing. Check hardware support for this operation as well as the CLI flag; a listed device is not proof its firmware can sign the authorization digest. | Route | When to use it | Signing boundary | | ----------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `cast send --auth "$ZERO_DELEGATE"` with a supported local signer | Authority is also the transaction sender and no separately signed artifact is needed before final approval | Cast constructs the authorization with the selected chain and transaction nonce plus one, then signs and broadcasts the outer transaction. This is never preparation. | | `cast wallet sign-auth`, then `cast send --auth "$SIGNED_AUTH"` | Exact simulation needs a signature, the fee payer differs, or the outer transaction uses a browser | Approve the authorization before creating it; submit the unchanged verified artifact only within its approved use and the transaction approval. | Resolve the public authority, public sender, and supported signer for each before investing in simulation. Reuse an existing encrypted keystore, supported hardware signer, or an explicitly supported target-project secret consumer, subject to `SKILL.md`'s signer preferences and the user's restrictions. Discover a project's secret-manager adapter and its owning instructions at runtime; do not assume a particular repository or secret-manager setup. Preparation does not load credentials. Never ask for secrets in chat, print them, or expose them through command logs. If the necessary integration is absent, report the precise missing prerequisite and supported next step: an existing supported signer, an authorization produced through an approved supported route, or separately authorized adapter work in its owning project. Do not invent keystore cryptography, automate secret-entry terminals, or build a signing/approval framework incidentally. In a browser-only flow without authorization-signing support, stop before a signing request; never fall back silently. See [browser-signing.md](browser-signing.md) for using an existing authorization with a browser outer transaction. ## Bind the Authorization and Nonces The **authority** signs permission to change its own code. The **sender** signs, funds, and submits the containing transaction; it may be the authority or a separate fee payer. Revocation sets the authorization's delegate to `0x0000000000000000000000000000000000000000`. This delegate is distinct from the outer transaction's `to` address. An ordinary transfer to zero does not revoke delegation. Review the outer destination, value, and calldata independently; type 4 requires a destination and cannot create a contract. Prepare one clearing authorization per selected chain. Review authority, chain ID, zero delegate, authorization nonce, signer, and intended transaction sender. Use the selected chain's nonzero ID explicitly; wildcard chain ID `0` requires explicit cross-chain scope authorization. Never infer it from a multi-chain request or bypass its warning with `--force`. Repeat state checks, fee accounting, approvals within their stated scope, and outcome verification for every chain. Ask atlas for a canonical checkpoint (block number/hash), authority code and nonce, sender nonce and balance, and pending nonce evidence for both accounts. Code `0x` already satisfies clearing at that checkpoint; report the observed state without manufacturing a revocation transaction. A delegation indicator is `0xef0100` followed by a 20-byte delegate; other code requires investigation. Resolve pending activity and nonce changes before signing, then refresh again before submission. A single provider's pending count does not exclude every outstanding authorization. For one tuple and no intervening nonce changes: | Sender relationship | Outer transaction nonce | Authorization nonce | | ------------------- | -------------------------------- | --------------------------------------------------------------------- | | Self-broadcast | Authority's applicable nonce `N` | `N + 1`: the sender increment happens before authorization processing | | Separate fee payer | Payer's applicable nonce `P` | Authority's applicable nonce `A`, without a self-broadcast increment | A successfully applied authorization increments the authority nonce once more. Do not reuse the table blindly for multiple tuples or pending sequences; reconcile their processing order. If state changes invalidate the reviewed nonce, stop and rebuild/review the changed payload instead of retrying the old signature. Check installed behavior against the matching [wallet source](https://github.com/foundry-rs/foundry/blob/master/crates/cast/src/cmd/wallet/mod.rs) and [transaction builder's `resolve_auth`](https://github.com/foundry-rs/foundry/blob/master/crates/cast/src/tx.rs). `sign-auth --nonce` supplies the authorization nonce directly; `--self-broadcast` derives a nonce by RPC and adds one, and currently conflicts with `--nonce`. Use atlas's explicit `--chain` and computed `--nonce`, omitting `--self-broadcast`, so `sign-auth` performs no implicit standalone chain/nonce lookup. For address-valued `send --auth`, pass the outer nonce `N`; Cast adds one internally. Never add that increment twice. ## Approval and Simulation Use staged approval when exact simulation needs a real signature or a separately approved authorization artifact is required. This conditional route does not add stages to ordinary transactions. Existing explicit approval covering a concrete payload and its subsequent use remains valid; do not request it again merely because work enters a new phase. 1. **Review authorization intent without signing.** Present all authorization fields, signer, intended sender, exact signing command, and intended use. Name the later simulation/provider disclosure the approval covers. The signature authorizes code clearing and is independently submit-able by anyone while its chain/nonce conditions hold; it is not bound to the outer transaction's sender, fees, destination, calldata, or value. Require explicit approval of this payload and scope before accessing secrets or creating the signature. This approval does not itself authorize an outer transaction signature or broadcast. 2. **Sign and recover locally.** Refresh nonces through atlas, create the approved authorization using the selected supported signer, decode it, and recover its authority as below. Do not broadcast. Handle the signature as an authorization capability: keep it out of ordinary logs and transmit it to a simulation provider only when the approval covers that disclosure. A failed simulation does not cancel an already issued authorization. 3. **Simulate, estimate, and review the outer transaction.** Through atlas, use the actual authorization in the exact type-4 call object/`authorizationList`, with reviewed sender, nonce, destination, value, calldata, and fees. Require evidence that the provider applies the tuple and models its nonce transition and gas effects. An accepted RPC field, dummy signature, skipped tuple, or code-only state override does not prove the complete signed transaction. If the provider lacks support, resolve a supported simulation route under `SKILL.md` or report the exact gap. Complete chain-specific fee accounting and present the concrete transaction under `SKILL.md`'s Review before its signature/send. 4. **Refresh and submit within approval.** Recheck authority code/nonces, sender nonce/balance, pending activity, fee validity, and affordability through atlas. Preserve the approved authorization and outer fields. Changed payloads require a revised review and simulation; wallet gas edits retain only the existing browser exception. Submit with the exact approved signer and command, then verify both outcomes below. The one-command local route is available only when simulation can establish the complete reviewed authorization's effects without first creating its signature, or equivalent exact evidence is already available. State the simulation method and its limits. Its transaction review must include the authorization intent and explicitly approve both signatures and broadcast. If simulation instead requires an actual signature, select the staged route; never invoke `cast send` to obtain a preparation artifact. ## Native Commands These are signing/broadcast templates, executable only at their approved phase. Populate public variables from the review and atlas; use the selected fee policy. `KEYSTORE_FILE` denotes an existing approved keystore, not a request to create one. Replace its signer option only with the reviewed supported signer. `RPC_URL` means the continuous transport selected under `SKILL.md`, including its alias and stderr rules. For an approved local self-broadcast, `AUTHORITY` equals the sender and `TX_NONCE` is `N`: ```sh ZERO_DELEGATE='0x0000000000000000000000000000000000000000' cast send "$TX_TO" --data "$CALLDATA" --value "$VALUE_WEI" \ --auth "$ZERO_DELEGATE" --chain "$CHAIN_ID" --nonce "$TX_NONCE" \ --from "$AUTHORITY" --keystore "$KEYSTORE_FILE" --rpc-url "$RPC_URL" \ --gas-limit "$GAS_LIMIT" --gas-price "$MAX_FEE_WEI" \ --priority-gas-price "$PRIORITY_FEE_WEI" --async ``` For a separately approved authorization, `AUTH_NONCE` is `N + 1` for self-broadcast or `A` for a different payer: ```sh ZERO_DELEGATE='0x0000000000000000000000000000000000000000' SIGNED_AUTH=$(cast wallet sign-auth "$ZERO_DELEGATE" \ --chain "$CHAIN_ID" --nonce "$AUTH_NONCE" --keystore "$KEYSTORE_FILE") || exit 1 ``` Decode locally with `cast from-rlp "$SIGNED_AUTH"`. Its six fields are `[chain_id, address, nonce, y_parity, r, s]`; verify chain, zero delegate, and nonce against the approved intent. Losslessly map those fields to the authorization JSON keys `chainId`, `address`, `nonce`, `yParity`, `r`, and `s`, preserving integer precision and using RPC hex quantities (`0x0` for integer zero, not RLP's empty `0x`). Recover with `cast recover-authority "$AUTH_JSON"` and require an exact address match with the reviewed authority. The RLP artifact is not a plain message signature; do not pass it to `wallet verify` as one. Keep the decoded tuple and signed RLP bound together through simulation and submission; recovery alone does not prove on-chain nonce validity. After simulation and transaction approval, submit the same signed authorization. The sender's signer can differ: ```sh cast send "$TX_TO" --data "$CALLDATA" --value "$VALUE_WEI" \ --auth "$SIGNED_AUTH" --chain "$CHAIN_ID" --nonce "$TX_NONCE" \ --from "$SENDER" --keystore "$SENDER_KEYSTORE_FILE" --rpc-url "$RPC_URL" \ --gas-limit "$GAS_LIMIT" --gas-price "$MAX_FEE_WEI" \ --priority-gas-price "$PRIORITY_FEE_WEI" --async ``` For a supported browser outer transaction, replace the keystore option with `--browser`, following [browser-signing.md](browser-signing.md); do not combine signer options. Always preserve the authorization list and type. Type-4 revocations use EIP-1559 fee caps, not `--legacy`. Retain the default Ethereum [Rabby Slow policy](ethereum-gas.md) unless another compatible policy is selected. Include authorization intrinsic costs, applicable refunds, and chain-specific additional fees in the full estimate/reserve under `SKILL.md` and current official sources. Do not subtract expected refunds from upfront funding or reuse a 21000-gas exact-zero transfer assumption. A legacy sweep, if separately requested, is a separate reviewed transaction after clearing is verified. ## Verify and Recover Have atlas obtain the outer transaction and canonical receipt, reconcile the selected tuple's chain, recovered authority, delegate, and nonce against transaction evidence, and query `eth_getCode` for the authority at a canonical checkpoint at or after inclusion. Require code `0x` for successful clearing. Reconcile nonce transitions and tuple ordering as needed to establish application; investigate later transactions or reorgs when evidence conflicts. Code already empty before inclusion does not by itself prove this tuple applied. Report the transaction outcome and authorization outcome separately, with the code checkpoint and ordinary receipt, fee, nonce, and explorer evidence: - A successful outer receipt can contain a skipped authorization. Unchanged delegation means clearing was not achieved; missing application evidence is unresolved, not success. - An applied authorization survives a reverted transaction body. Recognize cleared code even when receipt status is failure; do not blindly submit another revocation. - For an uncertain broadcast, preserve `SKILL.md`'s no-retry handling and the browser recovery rules. Check transaction existence and actual authority state before any retry, replacement, or new authorization. Clearing delegation removes code; it does not erase account storage or revoke unrelated token approvals. Keep those effects and any separately requested cleanup distinct. -
ethereum-gas.md 3.8 KB
# Ethereum Slow Gas This is the default policy for Ethereum mainnet transactions. The user or consuming skill may explicitly select another policy under `SKILL.md`, including fixed legacy pricing for an exact-zero sweep. In that case, use and review the selected policy instead of fetching or enforcing this fee pair. Do not treat an API failure as an implicit override. Rabby's keyless gas-market endpoint supplies the same `slow`, `normal`, and `fast` tiers used by the wallet, including separate EIP-1559 max-fee and priority-fee values. It is a public runtime API, not a documented third-party SLA; stop on an outage or schema change instead of substituting another source. ## Fetch the Quote Resolve `scripts/rabby-slow-gas.sh` relative to this skill and run it immediately before simulation and review: ```sh RABBY_SLOW_QUOTE=$("$CLI_CAST_SKILL_DIR/scripts/rabby-slow-gas.sh") RABBY_SLOW_MAX_FEE_WEI=$(printf '%s\n' "$RABBY_SLOW_QUOTE" | jq -er '.max_fee_per_gas_wei') RABBY_SLOW_PRIORITY_FEE_WEI=$(printf '%s\n' "$RABBY_SLOW_QUOTE" | jq -er '.max_priority_fee_per_gas_wei') RABBY_SLOW_ESTIMATED_SECONDS=$(printf '%s\n' "$RABBY_SLOW_QUOTE" | jq -er '.estimated_seconds') RABBY_SLOW_QUOTED_AT=$(printf '%s\n' "$RABBY_SLOW_QUOTE" | jq -er '.quoted_at') ``` Set `CLI_CAST_SKILL_DIR` to the absolute directory containing this `SKILL.md`. The helper calls `https://api.rabby.io/v2/wallet/gas_market`, selects exactly one `slow` entry, and rejects malformed, non-integer, incoherent, or incorrectly ordered tiers. Do not reuse a quote for another transaction or a restarted review. Ask `$evm-atlas` for one read packet containing the resolved Ethereum chain ID, latest block number and hash, and that block's base fee. Require chain ID `1`, then bind the returned values locally: ```sh test "$EVM_ATLAS_CHAIN_ID" = '1' RABBY_SLOW_BLOCK="$EVM_ATLAS_BLOCK_NUMBER" RABBY_SLOW_BASE_FEE_WEI="$EVM_ATLAS_BASE_FEE_WEI" test "$RABBY_SLOW_MAX_FEE_WEI" -ge "$RABBY_SLOW_BASE_FEE_WEI" ``` If validation fails, fetch once more. Stop if the second result fails; do not fall back to `cast gas-price`, `eth_gasPrice`, Normal, or Fast. ## Bind the Fees When this policy is selected, pass both values to simulation where supported and to every transaction-building or `cast send` command: ```sh cast send "$CONTRACT" 'transfer(address,uint256)' "$TO" "$AMOUNT" \ --rpc-url "$RPC_URL" \ --gas-price "$RABBY_SLOW_MAX_FEE_WEI" \ --priority-gas-price "$RABBY_SLOW_PRIORITY_FEE_WEI" \ SIGNER_FLAGS ``` For EIP-1559 transactions, Cast interprets `--gas-price` as the max fee per gas and `--priority-gas-price` as the max priority fee per gas. Start browser (`--browser`), encrypted-keystore, hardware-wallet, and environment-backed private-key commands with the same fee pair. Use one reviewed signer suffix such as `--browser`, `--keystore "$KEYSTORE_FILE"`, `--ledger`, or `--private-key "$ETH_PRIVATE_KEY"`; the signer preference and approval rules in `SKILL.md` still apply. For browser signing, these flags are starting values: the user may deliberately edit the gas limit or fee caps in the wallet confirmation UI, and the approved final wallet values govern the transaction. Do not use `--legacy` for this policy. For `cast publish`, inspect the signed transaction first and verify it already contains the approved fee pair; fees cannot be changed after signing. The Rabby quote covers execution gas only, so a blob transaction still needs an independently reviewed blob-gas price. Immediately before broadcast, have `$evm-atlas` fetch the latest block and base fee again. If it exceeds the reviewed max fee, the transaction is not currently includable: obtain a new Slow quote, simulate again, and present a revised review. For replacements or cancellations, stop when Slow does not satisfy the required fee bump rather than silently increasing the tier. -
version.txt 6 B
1.8.3
-
-
scripts
-
rabby-slow-gas.sh 2.2 KB
#!/bin/bash set -euo pipefail command -v curl >/dev/null 2>&1 || { echo 'rabby-slow-gas: curl is required' >&2 exit 1 } command -v jq >/dev/null 2>&1 || { echo 'rabby-slow-gas: jq is required' >&2 exit 1 } endpoint='https://api.rabby.io/v2/wallet/gas_market' response=$( curl --fail --silent --show-error \ --connect-timeout 5 \ --max-time 10 \ --retry 2 \ --retry-delay 1 \ --request POST \ --header 'content-type: application/json' \ --data '{"chain_id":"eth"}' \ "$endpoint" ) quoted_at_unix=$(date +%s) quoted_at=$(date -u '+%Y-%m-%dT%H:%M:%SZ') printf '%s\n' "$response" | jq -ce \ --arg endpoint "$endpoint" \ --arg quoted_at "$quoted_at" \ --argjson quoted_at_unix "$quoted_at_unix" ' def one_tier($name): [.[] | select(.level == $name)] as $matches | if ($matches | length) == 1 then $matches[0] else error("expected exactly one \($name) tier") end; def valid_tier: (.price | type) == "number" and (.price | floor) == .price and .price > 0 and (.priority_price | type) == "number" and (.priority_price | floor) == .priority_price and .priority_price >= 0 and .priority_price <= .price and (.estimated_seconds | type) == "number" and (.estimated_seconds | floor) == .estimated_seconds and .estimated_seconds >= 0; if type != "array" then error("expected a tier array") else . end | . as $tiers | ($tiers | one_tier("slow")) as $slow | ($tiers | one_tier("normal")) as $normal | ($tiers | one_tier("fast")) as $fast | if (($slow | valid_tier) and ($normal | valid_tier) and ($fast | valid_tier)) and $slow.price <= $normal.price and $normal.price <= $fast.price and $slow.priority_price <= $normal.priority_price and $normal.priority_price <= $fast.priority_price then { endpoint: $endpoint, chain_id: 1, chain_server_id: "eth", tier: "slow", max_fee_per_gas_wei: ($slow.price | tostring), max_priority_fee_per_gas_wei: ($slow.priority_price | tostring), estimated_seconds: $slow.estimated_seconds, quoted_at_unix: $quoted_at_unix, quoted_at: $quoted_at } else error("invalid or incorrectly ordered gas tiers") end '
-
-
SKILL.md 19 KB
--- coordination: exempt name: cli-cast skill-dependencies: - evm-atlas user-invocable: false description: "Use for Foundry cast transaction actions: prepare, trace, simulate, sign, or broadcast; sign messages; or encode/decode ABI/calldata. Delegate every standalone RPC read to evm-atlas." --- # Foundry Cast CLI This skill is coordination-exempt: skip the ai-coord gate for its declared work. Separate read, preparation, simulation, signing, and broadcast so no state-changing action is hidden inside command construction. For EIP-7702 authorization or delegation revocation, read [references/eip7702.md](references/eip7702.md) before preparation. It defines signer selection, authority versus transaction sender, conditional staged approval, and authorization verification in addition to the transaction receipt. ## Resolve Chain and Provider Invoke `$evm-atlas` before every network operation. It owns chain resolution, discrete reads, and bounded live subscriptions. Pass the explicit chain name or ID, JSON-RPC method and exact parameters or call object, block selector or checkpoint requirement, and why the result is needed. Require its read packet containing the resolved chain name and ID, provider route, result, observed block or checkpoint, and coverage gaps. If the chain is absent from `evm-atlas`, stop RPC-dependent work. Do not accept an arbitrary RPC URL as an escape hatch and never infer Ethereum when the chain is ambiguous. Use an RPC URL in this skill only for a trace, fork, or send flow that cannot be expressed as bounded discrete reads. For RouteMesh-backed continuous transport, first require `evm-atlas` to confirm current RouteMesh coverage, then use the explicit Foundry alias when it is configured: ```sh ROUTEMESH_CHAIN_ID="$CHAIN_ID" cast COMMAND --rpc-url routemesh ``` Otherwise use the nonsecret public RPC verified by `evm-atlas`. Never construct, inspect, or print a RouteMesh URL. Treat Cast stderr as secret-bearing because Foundry may reveal a resolved alias URL on transport failure; never repeat that output in chat, logs, or external reports. Resolve every RPC value from `evm-atlas`'s current read packet or the RouteMesh alias above; hard-coding a public RPC URL, such as a literal `https://` endpoint typed from memory or a prior response, in a prepare, simulate, or verify command violates this delegation even when the chain matches. When a local `cast` command against that provider returns a `--json` hex quantity, decode it with `cast to-dec <hex>` or a field-select form such as `cast receipt <hash> <field>` or `cast tx <hash> <field>`; do not pipe `--json` output through `jq tonumber`, which fails on hex strings and on `null`. ## Authority Phases ### Read Local ABI encoding/decoding and selector derivation may run without transaction approval. Delegate chain, block, fee, nonce, `eth_call`, `eth_estimateGas`, transaction, receipt, log, balance, code, storage, proof, and ENS reads to `$evm-atlas`, including reads needed to prepare or verify a transaction. Do not ask `evm-atlas` to hand a read back to this skill merely because later work may change state. Use `env -i PATH="$PATH" cast <command> --help` for exact local syntax. Cast help can print inherited environment values, including API keys; do not load credentials or decrypted dotenv for capability checks. Typical local operations: ```sh cast calldata 'transfer(address,uint256)' "$TO" "$AMOUNT" cast decode-calldata 'transfer(address,uint256)' "$CALLDATA" ``` ### Prepare Resolve and validate chain ID, sender, target, function signature, arguments, calldata, native value, nonce, and fee assumptions without signing. Obtain every on-chain fact through `evm-atlas`; do not request or load key material during preparation. Select a supported signer under Sign and Broadcast and check its command capabilities before simulation or helper construction. Request both the confirmed nonce at the numeric checkpoint block and the pending nonce. When they differ, or a wallet reports `replacement transaction underpriced`, a queued transaction occupies the lowest unconfirmed nonce, and later nonces stay stuck behind it. Target that nonce with fees that clear the node's replacement bump, usually 10-20% on both the fee cap and the tip, instead of queueing another transaction behind it. For Ethereum mainnet, the default gas policy is [references/ethereum-gas.md](references/ethereum-gas.md): fetch a fresh Rabby `slow` quote and bind its EIP-1559 fee pair before simulation. The user or a consuming skill may explicitly choose a different gas policy, including a fixed legacy gas price for an exact-zero sweep. Honor that choice; it does not require a separate policy-exception approval. Record its source, transaction type, fee values, and any constraints in the transaction review. Apply the selected policy to every signer and do not silently substitute a different tier or transaction type. Do not reuse Ethereum fee values on another chain. Elsewhere, absent a selected policy, set an EIP-1559 max fee with headroom over the latest base fee, such as `2 * baseFee + priorityFee`, instead of passing `eth_gasPrice` as the cap. The charge stays base fee plus tip, while an exact cap can fall below the base fee before signing and force a revised review. #### Chain-specific gas accounting Resolve the chain's active fee model before choosing a transaction type or subtracting fees from a balance. Use current official protocol documentation for semantics and `$evm-atlas` for the target chain's parameters, fee-oracle calls, estimates, and receipts. EVM compatibility, a native symbol of ETH, and support for legacy transactions do not establish Ethereum fee semantics. A chain absent from atlas remains unsupported. For the exact transaction, retain a public fee record containing the chain/checkpoint, active fork and sources, transaction type, gas estimate and limit, price/caps, expected total fee, upfront fee reserve with each component and margin, and refund behavior. Identify which charges are included in estimated gas and which are additional native debits. Use arbitrary-precision integer arithmetic and round reserves up. Never count a component twice or subtract an anticipated refund from the upfront funding requirement. Re-estimate when value, calldata, nonce, type, gas, or fees change; serialization can change the L1 charge even for an empty-calldata transfer. - **Ethereum-style accounting:** establish that all fees for this transaction are covered by gas. Reserve `gasLimit * gasPrice` for legacy, or `gasLimit * maxFeePerGas` for EIP-1559. Actual cost uses receipt `gasUsed` and `effectiveGasPrice`. Exact-zero native sweeps require evidence of a fixed charged price, fixed gas used, and no additional charges or credits; a plain undelegated EOA transfer on Ethereum with empty calldata and legacy pricing can use exactly 21000 gas. Do not apply that constant to other fee models. - **Arbitrum Nitro:** use the complete `eth_estimateGas` result, or `NodeInterface.gasEstimateComponents()` through atlas. It includes the parent-chain posting charge converted into child-chain gas. Budget the full gas limit at the reviewed price cap; do not add a second L1 fee. Legacy transactions are supported, but their charged price depends on the active ArbOS version and tip-collection setting. Verify that behavior through atlas and the current [fee processor](https://github.com/OffchainLabs/nitro/blob/master/arbos/tx_processor.go): newer versions make tip collection configurable. When tips are disabled, prefer EIP-1559 with zero priority fee; legacy bids and equal caps still charge the inclusion base fee. When tips are collected, apply the active effective-price rules. A fixed charged price alone does not fix the variable posting-gas component or prove an exact-zero sweep. Reconcile unused gas/price headroom against the reviewed residual policy. Use receipt `gasUsed * effectiveGasPrice` for total cost; `gasUsedForL1` is an included gas component, not an extra wei charge. See [gas and fees](https://docs.arbitrum.io/how-arbitrum-works/deep-dives/gas-and-fees) and [estimation](https://docs.arbitrum.io/arbitrum-essentials/how-to-estimate-gas). - **OP Stack:** reserve execution gas plus the L1 data fee and any enabled operator fee. Through atlas, query the verified `GasPriceOracle` for `getL1Fee(bytes)` using the serialized unsigned transaction, and, where supported, `getL1FeeUpperBound(uint256)` using its unsigned byte length. These interfaces account for signature overhead; do not add it twice. The latter is a practical size bound at the current oracle prices, not a cap on fees at inclusion. Query `getOperatorFee(gasLimit)` for upfront budgeting and reconstruct the included operator charge using the inclusion fork's parameters, gas use, and exact client rounding/refund semantics. Before Isthmus it is absent; Isthmus and Jovian use different scalar formulas. Establish absence from fork/configuration evidence, not a failed call or a missing provider field. Receipt total is execution cost plus `l1Fee` plus operator cost, each once. See [transaction fees](https://docs.optimism.io/op-stack/transactions/fees), [Fjord oracle](https://specs.optimism.io/protocol/fjord/predeploys.html), [Isthmus operator accounting](https://specs.optimism.io/protocol/isthmus/exec-engine.html), and [Jovian changes](https://specs.optimism.io/protocol/jovian/exec-engine.html). - **Other models, including ZKsync:** obtain the current chain-native estimator and receipt semantics through atlas and official docs. Establish coverage of pubdata, resource overhead, custom debits, and refunds for the actual transaction type. Use an ordinary type `0`/`2` transfer only if the chain and browser transport support it with complete fee coverage. Do not substitute a deprecated estimator or add custom transaction fields without a supported signing path. ZKsync's [fee structure](https://docs.zksync.io/zksync-protocol/era-vm/transactions/fee-model/fee-structure) includes pubdata/overhead and refunds; neither 21000 gas nor exact-zero accounting follows from EVM compatibility. Stop with the missing component when complete accounting cannot be established. On chains with fees outside transaction caps, label the total as an **estimated reserve**, disclose the uncovered price movement, and recheck affordability immediately before signing. A margin is not a protocol-enforced maximum. Require `value + upfront fee reserve <= balance`; ordinary gas estimation or a successful `eth_call` alone does not prove this. If final wallet fee edits are allowed, recompute dependent additional fees and affordability from those values. Sweeps whose value depends on the reserve must preserve all reviewed fields under the fixed-fee exception below. Refunded or unspent gas is normally already reflected in the final charged fee and sender balance; do not subtract it again. Treat asynchronous refunds, such as Arbitrum retryable tickets, separately: never spend an expected credit before it arrives or claim a snapshot balance is permanent. Discovery of unrelated pending refunds is not implicit in a plain transfer. A consuming sweep must state its residual-balance policy and any known pending credits before approval. ### Simulate Simulate the exact prepared call, preserving sender, target, value, calldata, nonce, transaction type, gas limit, and fee fields, then estimate gas. Delegate bounded `eth_call` and `eth_estimateGas` evidence to `evm-atlas`. When an RPC error contradicts the supplied gas or checkpointed balance, have atlas diagnose the exact simulation path before attributing it to transaction invalidity or chain-wide type support. Changing fields to make a diagnostic call pass does not validate the prepared transaction. Preserve the consuming workflow's simulation and approval requirements. Use a local fork, project simulation, or Cast trace only when the simulation requires a continuous provider, following Resolve Chain and Provider. A successful simulation is evidence, not authorization to sign. When exact EIP-7702 simulation needs a signed authorization, use the reference's approved authorization-signing stage first; transaction signing and broadcast still follow simulation and transaction approval. ### Review Before a transaction signature or broadcast, present one concrete review containing: - chain name and ID, RPC source, and latest block used; - sender, target, function, decoded arguments, calldata, and native value; - nonce, gas estimate/limit, fee assumptions, expected total cost, upfront reserve, and any protocol-enforced fee caps; - chain-specific fee components, inclusion-price uncertainty outside those caps, and expected refunds or residuals; - the selected gas policy and source; for Rabby Slow, the oracle URL, tier, quote time, estimated inclusion time, max fee per gas, and max priority fee per gas; for a legacy policy, the fixed gas price and transaction type; - expected approvals, transfers, or other state changes; - simulation command and outcome; - selected signer and the exact signing/broadcast command with secrets redacted. Lead the review with `### ⚠️ Transaction approval required`. Put repeated fields in a compact table, keep the exact command in a fenced block, and state precisely what confirmation authorizes. Stop and require explicit user confirmation of this review in a subsequent message. If any reviewed field changes outside the browser-wallet exception below, simulate again and present a revised review. Existing explicit approval of the concrete payload and its stated use remains valid; EIP-7702 authorization signatures follow the reference's conditional staged review. For browser signing only, the reviewed gas limit and fees are starting values unless the consuming workflow requires them to remain fixed. The user may deliberately change the gas limit, gas price, max fee per gas, or max priority fee per gas in the wallet confirmation UI. Their approval of that final wallet screen authorizes those edited gas settings; apply chain-specific accounting to the additional fees and resulting affordability. Do not stop, require a second approval, or resimulate solely because they differ from the prepared values. Continue only when the chain, sender, target, calldata, native value, nonce, authorization list (if present), and decoded intent still match the approved review. Wallet changes to any of those fields require rejection and a revised review. When fees determine the transfer value or another reviewed invariant, such as leaving exactly zero native balance, the browser exception does not apply. Preserve the reviewed transaction type, gas limit, and fee values. If the wallet changes them, reject before signing, recompute the dependent values, simulate, and obtain approval of the revised review. ### Sign and Broadcast Read [references/browser-signing.md](references/browser-signing.md) for browser capability checks and sender handling; open a signing request only after approval. Prefer browser, encrypted keystore, or hardware wallet in that order unless the user or consuming skill restricts the signer. A browser-only workflow must stop if browser signing is unavailable; never substitute another signer. Use an environment-backed private key only when the user explicitly opts in or no safer method is available; never ask for a key in chat or print it. `cast send` signs and broadcasts in one command. Run it only after the review approval. So do the Cast 1.8.3+ helpers `cast erc20-token transfer|approve|mint|burn`, `cast erc20-token permit --broadcast`, `cast erc4626 deposit|mint|withdraw|redeem`, and `cast safe propose|sign|execute`: apply the same Prepare, Simulate, and Review phases to them; a Safe proposal or confirmation is a signature artifact that needs its own payload review. Treat any other subcommand whose installed help shows it signs or submits, such as `cast safe create`, `add-delegate`, or `remove-delegate`, the same way. Signing a message or typed data, including `cast erc20-token permit` without `--broadcast`, also requires a review of the exact payload, domain, chain binding, and intended use before approval. Pass the selected fees explicitly: EIP-1559 uses `--gas-price` and `--priority-gas-price`; a fixed legacy policy uses `--legacy --gas-price` without `--priority-gas-price`. Under the default Ethereum policy, use the approved Rabby Slow pair. Before opening the signer, recheck the active chain's gas and additional-fee requirements and that the approved cap or legacy gas price covers its current base fee where applicable. If fees must change before signing, simulate again and present a revised review; never silently change the selected policy. Wallet fee edits follow Review, including its fixed-fee exception. Message and typed-data signatures consume no gas. After broadcast, capture the transaction hash and have `evm-atlas` verify the receipt on the reviewed chain. When a receipt is still pending, it may use one bounded RouteMesh `newHeads` subscription to wait for the next block before checking again. Receipt verification remains required; a pending-transaction or log notification alone cannot confirm the transaction. Reconcile actual fees under the active chain's model, including additional receipt components and refunds without double counting. Missing fee evidence is incomplete accounting, not zero fees. Report status, block, gas used, actual total fee or its exact evidence gap, and the explorer link under `### ✅ Transaction confirmed` for a successful receipt or `### ↩ Transaction reverted` for a mined failure. For an ambiguous outcome, lead with `### ⛔ Broadcast unresolved — do not retry` and state the evidence still needed. Do not retry a failed or uncertain broadcast without first checking whether the transaction exists — for browser-wallet signing specifically, read [references/browser-signing.md](references/browser-signing.md)'s Timing and Recovering sections before concluding nothing was sent: a killed or timed-out process does not prove non-broadcast, since wallet approval is an unbounded human wait and the wallet may broadcast via its own RPC provider. ## Stop Conditions Stop before signing when the signer, sender, chain, target, or decoded intent is unresolved. Transaction signing also requires resolved fee accounting, affordability, and simulation. Only the explicitly approved EIP-7702 authorization stage may precede those transaction checks; its authorization payload, signer, and intended use must already be resolved. Review must distinguish enforced caps from an estimated reserve; browser approval of edited gas settings authorizes those settings but does not establish coverage of omitted chain-specific charges. Stop before retrying when broadcast outcome is ambiguous. Completion requires either a verified read result, a local encoding result, an approved signature artifact, or a mined receipt verified by `evm-atlas` that matches the reviewed transaction apart from user-approved browser-wallet gas settings. Never decorate or truncate addresses, calldata, signatures, hashes, RPC URLs, fee values, commands, or safety wording. Revocation completion additionally requires the authorization and cleared-code checks in [references/eip7702.md](references/eip7702.md).
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.