You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Adds an external-signer payload to dry-run JSON responses:
source
operation
chain_id
caip2
from
transaction { to, value, data, chain_id, gas }
quote
risk
Supports:
operation="swap_execute" for swap execute --dry-run
operation="approve" for swap approve --dry-run
operation="revoke" for swap revoke --dry-run
Keeps existing legacy JSON fields for compatibility.
Fixes symbol-token approve dry-run by using resolved TokenRef.decimals, so swap approve --token USDC --dry-run does not require an extra RPC decimals lookup after token resolution.
Rejects native token approvals with a clear error.
P1src/commands/swap.rs:1389: swap execute --dry-run succeeds without a wallet, but silently omits the entire external-signer contract (source, operation, transaction, quote, and risk). This contradicts clap’s promise that dry-run emits an unsigned payload and can break consumers expecting data.transaction. Require a resolved sender for dry-run and return a structured error when neither signer, --wallet, nor global wallet is available.
P2src/commands/swap.rs:979: execute dry-run ignores --gas-limit and --max-fee-gwei; it always uses quote gas and emits no max fee. Thus the unsigned transaction differs from the requested transaction. Pass these overrides into build_dry_run_execute_payload and encode the fee in wei hex. Clarify whether --gas-buffer-pct and --skip-estimate apply to dry-run.
P2README.md:248: both README tables still say dry-run “Build and simulate” (README_CN.md says the equivalent), while clap and the new skill define it as payload construction without execution. Update both descriptions to avoid implying an RPC simulation.
Project Checks
Output convention: complete. No new direct println!/print! was introduced; command results use print_output.
Clap help: changed commands and arguments have help text. The gas-option dry-run applicability remains unclear as noted above.
Skills: skills/chainpilot/SKILL.md was updated for the new workflow.
Multi-language README: English and Chinese updates are synchronized, aside from the shared stale dry-run wording above.
Verification: cargo test --quiet and git diff --check pass.
High: approve/revoke dry-run can emit an unusable payload without from.swap.rs and swap.rs allow dry-run with neither signer nor WALLET_ADDRESS; build_dry_run_approval_result then serializes transaction while omitting from. This contradicts the documented stable external-signer contract and differs from execute dry-run, which returns NoDryRunWallet. Require a resolved sender for approve/revoke too, or explicitly document and model sender-less payloads.
Medium: approve help describes the wrong quote-derived spender.swap.rs says --quote-id derives the “router address,” while swap.rs actually selects the chain’s dodo_approve contract. Update the clap text to say DODOApprove/approval contract so users know what they authorize.
Project checks:
Output convention: complete. No new direct println!/print!; changed command results use print_output.
Skills: skills/chainpilot/SKILL.md covers the new workflow, subject to the missing-sender mismatch above.
README: English and Chinese READMEs were both updated consistently, with the same mismatch above.
Tests: git diff --check passed. cargo test --locked could not complete because the restricted environment could not resolve index.crates.io.
[P1] Explicit dry-run wallet is ignored when a signer is configured — src/commands/swap.rs:844 dry_run_from_address prioritizes the address derived from PRIVATE_KEY/keystore over --wallet and --wallet-address. Thus swap execute --dry-run --wallet 0xExternal... can emit a payload whose from belongs to an unrelated configured signer. This contradicts the flag help and normal CLI-over-environment precedence, and an external signer may reject or incorrectly authorize the transaction. Prefer subcommand_wallet.or(global_wallet).or(derived_from_signer).
[P2] Global wallet help is stale for the new workflow — src/cli/mod.rs:43 --wallet-address is described only as “quote/simulate context,” but the PR makes it required sender input for approve/revoke dry-runs. Update the help text to include those commands and explain that it populates the unsigned transaction sender.
Project-specific checks:
Output convention: complete. No new direct println!/print! calls; changed handler results use print_output.
Help docs: incomplete due to the stale global --wallet-address description above.
Skills: skills/chainpilot/SKILL.md was updated for execute/approve/revoke dry-runs.
Multi-language README: README.md and README_CN.md contain matching updates.
Tests: could not run because dependencies were unavailable locally and network access to crates.io failed.
High: Approval dry-run reports incorrect risk.token_in.amount_usd. swap.rs always derives USD value from the saved quote’s original input amount. This is wrong when --amount differs from the quote or --token overrides the quote token, potentially misleading external signer risk checks. Compute USD value from the actual approval token and approval amount, or omit it when unavailable.
Low: Execute dry-run sender documentation does not match resolution behavior. mod.rs says global --wallet-address applies only to approve/revoke, and SKILL.md explicitly says execute uses --wallet, but swap.rs also accepts global --wallet-address/WALLET_ADDRESS. Either document this fallback consistently or remove it.
Project checks:
Output convention: complete; no new direct println!/print!.
Help docs: updated, except for the sender-resolution mismatch above.
Skills: updated, but contains the same mismatch.
READMEs: both English and Chinese were updated and remain synchronized.
High:src/commands/swap.rs:1022 treats quote.to_amount_min as base units, but the quote model stores it as a human-readable amount. It then exposes the original value as min_amount_raw at line 1060. For a 2970 USDC minimum, the payload reports raw "2970" and display "0.00297" instead of raw "2970000000" and display "2970". External signer risk checks could therefore substantially underestimate the minimum output. Keep to_amount_min as min_amount_display and derive min_amount_raw with to_raw_amount(..., quote.to_token.decimals).
Project-specific checks:
Output convention: complete. No new direct println!/print! calls were introduced.
Clap help: updated consistently for the changed dry-run behavior and arguments.
Skills: skills/chainpilot/SKILL.md documents the new external-signer workflow.
READMEs: both English and Chinese READMEs were updated with equivalent content.
Tests: could not run because dependencies were unavailable locally and network access to crates.io failed.
P2: Unlimited approval dry-runs expose "unlimited" in risk.token_in.amount_raw (src/commands/swap.rs). amount_raw should contain the actual decimal U256::MAX value so external signer/risk systems can parse it consistently. Keep "unlimited" only in the legacy top-level field, or add an explicit unlimited indicator.
Project-specific checks:
Output convention: no new direct stdout printing; changed handlers use print_output.
Help text: updated and consistent with the changed dry-run behavior.
Skills: skills/chainpilot/SKILL.md documents the new workflow.
READMEs: English and Chinese documentation were both updated consistently.
Tests could not run because dependencies were unavailable locally and network access to crates.io failed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR replaces the previous
swap prepareapproach with a dry-run transaction contract on existing swap commands.It keeps the CLI surface unchanged:
swap preparesubcommandswap execute --dry-run --jsonreturns a standard unsigned transaction payloadswap approve --dry-run --jsonreturns ERC-20 approve calldataswap revoke --dry-run --jsonreturns ERC-20 revoke calldataSupersedes #8.
What Changed
Adds an external-signer payload to dry-run JSON responses:
sourceoperationchain_idcaip2fromtransaction { to, value, data, chain_id, gas }quoteriskSupports:
operation="swap_execute"forswap execute --dry-runoperation="approve"forswap approve --dry-runoperation="revoke"forswap revoke --dry-runKeeps existing legacy JSON fields for compatibility.
Fixes symbol-token approve dry-run by using resolved
TokenRef.decimals, soswap approve --token USDC --dry-rundoes not require an extra RPC decimals lookup after token resolution.Rejects native token approvals with a clear error.
Bumps version to
1.2.0-rc.3.Example