Repository navigation
docs: add deployment guide and fix issues found on staging - #263
gregorydemay wants to merge 12 commits into
Conversation
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…nd getSignatureStatuses The 2 MB response size estimate made the SOL RPC canister charge about 220B cycles per call on the 34-node fiduciary subnet, while the minter attached only 50B cycles for `getTransaction`. Every call was rejected before reaching a provider, so finalized sweeps were never credited. The SOL RPC canister's per-method defaults fit the minter's responses: 10 KiB for `getTransaction` and 256 bytes per signature for `getSignatureStatuses`. With them the calls cost about 3.2B and 10.7B cycles (256 signatures) on mainnet. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…l status The field was always `None`. A user pays the fixed `withdrawal_fee`, which is already visible as the difference between the burned amount and the transferred amount, while the Solana transaction fee is paid by the minter and shared by the withdrawals of a batch. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
The new address test fails enforced Clippy checks, and the critical RPC configuration fix lacks regression coverage.
3 open findings
What changed in this PR
Adds ckSOL deployment guidance and fixes staging issues affecting sweep finalization and withdrawal status reporting.
Changes:
- Uses SOL RPC default response-size estimates.
- Removes the unused withdrawal transaction-fee field.
- Documents deployment, nonce-account setup, and deposit testing.
| File | Description |
|---|---|
docs/deployment.md |
Adds deployment and testing guide. |
libs/types/src/lib.rs |
Updates withdrawal status type. |
minter/cksol_minter.did |
Updates the Candid interface. |
minter/src/address/tests.rs |
Verifies deployed minter addresses. |
minter/src/constants.rs |
Removes obsolete response-size constant. |
minter/src/rpc/mod.rs |
Uses endpoint-specific RPC defaults. |
minter/src/state/mod.rs |
Updates finalized withdrawal responses. |
minter/src/state/tests.rs |
Updates state expectations. |
minter/src/withdraw/tests.rs |
Updates withdrawal expectations. |
🧠 Review effort: Balanced
Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.
There was a problem hiding this comment.
🔵 Needs a closer look
The critical RPC configuration fix lacks regression coverage preventing the oversized estimate from being reintroduced.
2 open findings
1 resolved since last review
🧠 Review effort: Balanced
Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.
A sweep fetched its blockhash at finalized commitment, so the block was already old when the minter learned about it. Together with the getBlock calls and the threshold signatures, the transaction could reach the RPC providers after the blockhash expired. On Devnet, where 150 blocks last about 36 s, two sweeps were rejected with BlockhashNotFound and their 18 deposits were dropped. The sweep now fetches the slot and the block at confirmed commitment and runs the preflight simulation at the same commitment, since a finalized simulation would not know the newer blockhash. The monitor keeps fetching the current block height at finalized commitment for the expiry check. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
🔵 Needs a closer look
The production-critical response-size fixes lack automated regression coverage.
2 open findings
🧠 Review effort: Balanced
Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.
…ocks The sweep now fetches its block at confirmed commitment and the monitor at finalized commitment, so the getBlock request carries a commitment that the mocks must match. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…the default response size estimate A 2 MB estimate made the SOL RPC canister charge more cycles than the minter attaches, so every getTransaction call was rejected. These tests fail if an explicit estimate is set again on either call. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
🔵 Needs a closer look
Regression tests should assert both affected RPC calls retain default response-size estimates.
0 open findings
2 resolved since last review
🧠 Review effort: Balanced
Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.
There was a problem hiding this comment.
🟢 Approval recommended
The production fixes are consistently implemented with focused regression and integration coverage.
0 open findings
🧠 Review effort: Balanced
Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.
|
✅ No security or compliance issues detected. Reviewed everything up to ec3970c. Security OverviewDetected Code Changes
|
mbjorkqvist
left a comment
There was a problem hiding this comment.
Thanks @gregorydemay! For the PR title, perhaps something like fix: would be more accurate than docs:, since this PR also contains production code changes.
| pub const MAX_HTTP_OUTCALL_RESPONSE_BYTES: u64 = 2_000_000; | ||
|
|
||
| /// Cycles to attach for `getTransaction` RPC calls. | ||
| pub const GET_TRANSACTION_CYCLES: u128 = 50_000_000_000; |
There was a problem hiding this comment.
🤖 With the 2 MB estimate gone, the attached cycles no longer match what the calls cost. GET_SIGNATURE_STATUSES_CYCLES (1T, line 50) was sized for the 2 MB reservation, while a call now costs about 10.7B for 256 signatures and 2.3B for one. check_transaction_statuses sends up to MAX_CONCURRENT_RPC_CALLS = 10 of them at once, so the minter needs about 10T of spare cycles above its freezing threshold for a round that actually costs at most ~107B; a minter running low would fail these calls and stall finalization, even though the unused part is refunded. GET_TRANSACTION_CYCLES (50B against ~3.2B) is harmless but has lost its rationale. Lowering both, with comments tied to the default estimates and some headroom for the SOL RPC canister doubling the reservation on an oversized response, would keep them meaningful.
|
|
||
| ## Test | ||
|
|
||
| ### Deposit SOL |
There was a problem hiding this comment.
🤖 The description mentions a full deposit and withdrawal round trip on staging, but the Test section covers deposits only. Adding the withdrawal steps (icrc2_approve on the ledger, the withdrawal call, and following its status) would make the guide cover what was verified.
| | `deposit_sol_fee` | 45B cycles | Covers the threshold signature and the RPC calls of a sweep containing a single deposit. | | ||
| | `deposit_sol_required_cycles` | 1T cycles | Must be at least `GET_BALANCE_CYCLES` (10B) plus `deposit_sol_fee`; unused cycles are refunded. | | ||
| | `minimum_deposit_amount` | 0.02 SOL (20,000,000) | Must be at least twice the rent exemption threshold plus the fee of one signature. | | ||
| | `withdrawal_fee` | 0.001 SOL (1,000,000) | Covers `getAccountInfo`, `sendTransaction`, `getSignatureStatuses` and the threshold signature. | |
There was a problem hiding this comment.
🤖 Once #260 lands, withdrawals are no longer finalized with getSignatureStatuses but with a getAccountInfo read of the nonce account and a getTransaction call for the outcome, so this rationale becomes stale. Whichever of the two PRs lands second could update it, together with §3.3.2 of the design.


DEFI-3029
Adds a deployment guide (
docs/deployment.md) for the ckSOL minter, ledger and index, and fixes the issues found while doing a full deposit and withdrawal round trip and a deposit stress test on the staging minter (Devnet).Guide:
Fixes:
getTransactionwas sent with a 2 MB response size estimate, which the SOL RPC canister prices at about 220B cycles on the fiduciary subnet, while the minter attaches 50B. Every call was rejected before reaching a provider and surfaced as "Inconsistent RPC results".getTransactionandgetSignatureStatusesnow use the SOL RPC canister's default estimates (about 3.2B and 10.7B cycles for 256 signatures). Verified on staging: the stuck deposit was minted after the upgrade.BlockhashNotFoundand their 18 deposits were dropped: the blockhash, fetched atfinalizedcommitment, was already close to expiry when the transactions were sent (on Devnet, 150 blocks last about 36 s). Sweeps now fetch their blockhash atconfirmedcommitment and run the preflight simulation at the same commitment. The expiry check keeps usingfinalized. Details in the stress test report.effective_transaction_feeis removed from the withdrawal status. It was alwaysnull; the user pays the fixedwithdrawal_fee, while the Solana transaction fee is paid by the minter.🤖 Generated with Claude Code