Commit 09af6a8
chore: migrate motoko/icrc2-swap to icp-cli (#1386)
* chore: migrate motoko/icrc2-swap to icp-cli
Replace dfx.json with icp.yaml, migrate Motoko sources from src/swap/ to
backend/, add icp-dev-env-motoko:0.3.2 CI workflow, update mops.toml to
moc 1.9.0 / core 2.5.0 with --default-persistent-actors. Remove JS/Jest
test suite, old deploy.sh, and prettier config; add Makefile with deploy
and test targets that handle the multi-step deployment (token_a, token_b
ICRC-1 ledger canisters via pre-built WASM, then backend swap canister
with dynamic init args containing the token canister IDs).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore(icrc2-swap): remove old Motoko workflow and Candid section from README
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(icrc2-swap): add --query flag to query canister calls
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs(icrc2-swap): remove GitHub link and Overview heading from README
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(icrc2-swap): fix deploy/test commands and improve example quality
Deploy:
- --argument → --args (correct icp-cli flag)
- icp canister id → icp canister status X -i
Tests:
- Replace single-user contrived test with real two-user scenario:
Alice deposits token_a, Bob deposits token_b, they swap 1:1,
each withdraws the other's token
- Use --identity test-alice/test-bob for two distinct callers
README:
- Credit original author 0xAegir (AegirFinance)
- Remove "DeFi is experimental" disclaimer
- Fix security link: old URL → docs.internetcomputer.org/guides/security/inter-canister-calls
- Note that make deploy must be used instead of icp deploy
- Explain what make test actually tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs(icrc2-swap): clarify why icp deploy alone fails — make deploy required
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor(icrc2-swap): use Runtime.envVar for token discovery, remove init args
- Change from actor class Swap(init_args) to plain actor Swap
- Token principals read from PUBLIC_CANISTER_ID:token_a / token_b via
Runtime.envVar<system>() — injected automatically by icp-cli during deploy
- Remove --args from make deploy backend step; no init args needed
- Backend deploys last so icp-cli has both token IDs to inject
- Makefile deploy and test use correct icp-cli flags (--args, status -i)
- M0155 (Nat subtraction may trap) intentionally left as a warning —
subtraction is guarded by explicit balance check but Motoko's type
checker lacks path-sensitive refinement
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(icrc2-swap): pre-fund named identities, no minting needed in tests
- Create icrc2-alice and icrc2-bob identities in make deploy (idempotent)
- token_a initial_balances → icrc2-alice; token_b → icrc2-bob
- No funding/minting step needed in make test — identities start with tokens
- Tests use --identity icrc2-alice/icrc2-bob for realistic two-user flow
- README updated to explain the named identities and env var discovery
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(icrc2-swap): use single shell block in make deploy to fix ordering
$(eval ALICE := $(shell ...)) in Make recipe bodies expands before any
recipe commands run — so icp identity principal ran before icp identity new.
Fix: use a single shell block with set -e so identity creation and principal
lookup happen in the correct order within one shell process.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(icrc2-swap): DX review — clean up, improve README, fix tests
.gitignore: remove stale token_a.args/token_b.args/backend.args entries
from the old dfx arg-file approach
Makefile:
- Tests 5/6 use single shell block to capture balance delta (before/after)
making them idempotent across multiple make test runs
- Fee arithmetic comments added to approve/withdraw steps
README:
- Lead with the two key safety patterns (debit-before-transfer, atomic swap)
which are the core educational content — previously buried in code comments
- Add ic-mops to prerequisites
- Explain ICRC.mo inline type definitions
- Add fee handling section explaining the approve/withdraw arithmetic
- Clarify make deploy vs icp deploy and why
- Tighten known limitations section
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore(icrc2-swap): remove redundant .gitignore — covered by root
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs(icrc2-swap): clarify "perform the transfer on the token ledger"
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(icrc2-swap): security review — try/catch on withdraw, anonymous rejection
From canister-security skill review:
Pitfall #11 (callback trap after state mutation):
- withdraw: balance is debited before await icrc1_transfer
- if the token ledger TRAPS (not just returns an error), the callback
never ran and the refund in the #Err branch is skipped
- Fix: wrap await icrc1_transfer in try/catch; on trap, refund and
return #CallFailed with the error message
- Add #CallFailed error variant to WithdrawError
Pitfall #2 (anonymous principal):
- withdraw uses msg.caller as balance key but never rejected anonymous
- Fix: trap on anonymous caller at entry
README known limitations updated to accurately describe:
- the async edge case for trusted-only token canisters (not "deadlock")
- the deposit ambiguous-outcome scenario
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs(icrc2-swap): clarify #CallFailed retry guidance and ledger operator escalation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(icrc2-swap): check non-zero balances before swap, add error test
swap() now returns InsufficientBalance if either user has no deposit —
previously it silently succeeded moving zero tokens.
Add Test 2 (before any deposits) to verify InsufficientBalance fires,
making the guard visible in the test output.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs(icrc2-swap): remove "on-chain" — replace with clearer phrasing
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs(icrc2-swap): link ICRC-2 to digital asset standards reference
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(icrc2-swap): use --storage plaintext for identity creation in CI
The default --storage keyring requires a system keyring unavailable in
CI containers. --storage plaintext stores the key as a plain PEM file,
which works in both CI and local dev.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>1 parent 96c5861 commit 09af6a8
24 files changed
Lines changed: 313 additions & 12043 deletions
File tree
- .github/workflows
- motoko/icrc2-swap
- backend
- test
- swap
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
| 1 | + | |
2 | 2 | | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
3 | 36 | | |
4 | | - | |
5 | | - | |
6 | | - | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
0 commit comments