Skip to content

Wire missing contract views into CLI, fix fee display, tighten error handling#65

Merged
entrius merged 6 commits into
testfrom
fix/cli-contract-audit
Apr 17, 2026
Merged

Wire missing contract views into CLI, fix fee display, tighten error handling#65
entrius merged 6 commits into
testfrom
fix/cli-contract-audit

Conversation

@LandynDev
Copy link
Copy Markdown
Collaborator

Summary

End-to-end audit of the alw CLI against the refactored smart contract (lib.rs). All 27 messages + 26 queries are wired; this PR surfaces state the contract exposed but the CLI never read, fixes a handful of display + state-handling bugs, and rewrites error messages so contract rejection vs RPC failure is obvious.

New data surfaced

  • view minersStatus column with reserved <tao_amount>, in-swap, and cooldown <n>b derived from get_reservation_data / get_miner_snapshot / get_fulfillment_timeout. New --full flag to opt out of address truncation
  • view reservationChain Amounts row verifies on-chain reservation (get_reservation_data) matches local state; mismatch flagged in red
  • view contractSystem Status row from get_halted
  • swap now reserve loop — live on-chain vote count from get_pending_reserve_vote_count so you can tell whether validators are actively voting

Bug fixes

  • swap.py::display_receipt — hardcoded fee_divisor = 100 replaced with FEE_DIVISOR; receipt now shows protocol fee in TAO against raw swap amount instead of computing it off the post-deduction destination amount
  • resume.py — "reservation expired" message now covers both possibilities (actually expired vs already initiated/completed) since the contract clears reservations in both cases
  • view.py::view_contract — dead default=None kwarg to read_safe removed

Error handling

  • New print_contract_error helper in helpers.py routes ContractError through is_contract_rejection so NotOwner/InsufficientCollateral/etc. read cleanly, while RPC failures get a retry hint
  • collateral.py pre-flight checks now abort on contract rejection (e.g. ExceedsMaxCollateral) instead of warning and proceeding
  • admin.py, claim.py, miner_commands.py, post_tx.py rewired to the helper
  • swap.py bare except Exception at proof-signing and transfer paths now include the exception type name for debuggability

UX polish

  • admin recycle-fees — previews accumulated amount, destination, and total recycled before confirming; short-circuits if 0
  • admin danger halt — shows count of in-flight swaps that will be unaffected
  • admin set-recycle-address / transfer-ownership — validate SS58 before submitting; detect no-op (same address)
  • Swap now address prompts — reminder to paste only PUBLIC addresses, never private keys / seed phrases

Docs update (aligned on entrius/allways-docs-ui branch docs/cleanup-pass-1 — PR #18).

Test plan

  • ruff format . && ruff check . (passes)
  • alw --help / alw view --help / alw view miners --help render correctly
  • Dry-run against local dev environment: alw view miners --full, alw view reservation, alw view contract
  • alw swap quote still works unchanged
  • alw admin recycle-fees preview shows accumulated fees
  • alw admin danger halt shows in-flight count
  • E2E suite 02 still passes: ./alw-utils/dev-environment/tests/run.sh --chains btc --suite 02

…r handling

Surface on-chain state the contract already exposes but the CLI ignored:
- view miners now shows live Status (reserved with locked TAO, in-swap,
  cooldown blocks remaining) and a --full flag for untruncated addresses
- view reservation verifies on-chain amounts against local state
- view contract adds a System Status row (halted/running)
- swap reserve flow shows live on-chain vote count while polling for quorum

Fix display bugs in swap.py: hardcoded fee_divisor replaced with FEE_DIVISOR
constant, receipt now shows protocol fee in TAO against raw swap amount.

Tighten error handling across admin / collateral / claim / miner / post_tx:
new print_contract_error helper distinguishes explicit contract rejection
(NotOwner, InsufficientCollateral, etc.) from RPC or client failures so
messages match the user's actual failure mode. Collateral pre-flight now
aborts on contract rejection instead of warning and proceeding.

UX polish for admin: recycle-fees previews accumulated amount and destination;
halt shows count of in-flight swaps; set-recycle-address and
transfer-ownership validate SS58 before confirming. Address prompts now
include a reminder to paste only public addresses.

resume.py reservation-gone path now surfaces both possibilities (expired
vs already initiated/completed) instead of assuming expiry.
@LandynDev
Copy link
Copy Markdown
Collaborator Author

The contract clears its Reservation struct both when the TTL expires and
when vote_initiate consumes it, so get_miner_reserved_until == 0 alone
cannot distinguish the two. Probe miner_has_active_swap + match against
user_from_address / receive_address to detect the consumed case and
report it as INITIATED (swap #N) with a watch hint, instead of telling
the user their reservation expired when in fact their swap is in flight.
Previously all three were required options and invoking `alw swap quote`
bare returned a usage error. Now each unset flag drops into a Click
prompt with a Choice type for chains, matching the `alw swap now`
interactive style. Flags still work for scripting.
Adds a Status column that computes the on-chain tao_amount for each row
and checks it against the miner's collateral plus the contract's
min_swap / max_swap bounds. Rows that would be rejected by vote_initiate
now read 'insufficient collateral (X TAO needed)', 'below min swap', or
'above max swap' in red instead of looking equally viable next to
genuinely fulfillable options. A footer flags when no miner can fulfill
at all so the user knows to try a smaller amount.
Quote is a previewer — swap now is the entry point that actually lets
users commit funds, so the viability guard has to live there too. Added
check_swap_viability and derive_tao_leg to allways.utils.rate, mirroring
the guards in vote_reserve (min/max swap bounds) and vote_initiate
(collateral covers tao_amount). Both quote and swap now call it, so the
rules can't drift.

swap now now also blocks the flow before reservation if the selected
miner's collateral can't cover the TAO leg — previously the user could
reserve, send funds, and only learn at vote_initiate time that the swap
would never land.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants