M-C02: fix(rpc/core): apply finalize escrow deposit correctly#644
M-C02: fix(rpc/core): apply finalize escrow deposit correctly#644nksazonov merged 1 commit intofix/audit-findingsfrom
Conversation
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
📝 WalkthroughWalkthroughThis PR adds comprehensive test coverage for escrow deposit transition validation in Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
pkg/core/types_test.go (1)
225-239: Use a reachable escrow-deposit fixture in this subtest.
ValidateAdvancementonly accepts escrow deposits whose amount matches the preceding mutual lock, but this case seedsEscrowLedger.UserBalance = 100and appliesamount = 10. That exercises a partial finalize path the validator will never accept. Prefer constructing the fixture viaApplyMutualLockTransition(or matching the escrow balances/flows toamount) so the regression stays aligned with the real validator path.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pkg/core/types_test.go` around lines 225 - 239, The subtest seeds EscrowLedger.UserBalance=100 and then calls ApplyEscrowDepositTransition with amount=10 which creates an escrow-deposit that ValidateAdvancement will reject because it must match the preceding mutual lock; fix by making the test construct a compatible prior mutual lock (use ApplyMutualLockTransition to create the mutual lock with the same amount) or else set EscrowLedger.UserBalance and the transition amount to match the mutual lock semantics so that ApplyEscrowDepositTransition produces a reachable escrow-deposit that ValidateAdvancement would accept; update the test to call ApplyMutualLockTransition (or adjust EscrowLedger.UserBalance to equal amount) before calling ApplyEscrowDepositTransition so the fixture mirrors real validator flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@pkg/core/types_test.go`:
- Around line 225-239: The subtest seeds EscrowLedger.UserBalance=100 and then
calls ApplyEscrowDepositTransition with amount=10 which creates an
escrow-deposit that ValidateAdvancement will reject because it must match the
preceding mutual lock; fix by making the test construct a compatible prior
mutual lock (use ApplyMutualLockTransition to create the mutual lock with the
same amount) or else set EscrowLedger.UserBalance and the transition amount to
match the mutual lock semantics so that ApplyEscrowDepositTransition produces a
reachable escrow-deposit that ValidateAdvancement would accept; update the test
to call ApplyMutualLockTransition (or adjust EscrowLedger.UserBalance to equal
amount) before calling ApplyEscrowDepositTransition so the fixture mirrors real
validator flow.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 79687cbf-aa81-463b-a41a-74db69d334b9
📒 Files selected for processing (3)
pkg/core/state_advancer_test.gopkg/core/types.gopkg/core/types_test.go
Description
A user submits an
EscrowDepositfinalize request to the off-chain API, the backend validates it with the state model, signs it with the node key, and stores it immediately as the latest signed state before any on-chain execution is confirmed.The problem is that the Go validator models
EscrowDepositdifferently from the smart contract. Off-chain,ApplyEscrowDepositTransitionincreases the user’s home balance and also increases homeNodeNetFlow.However, on-chain, home-chain
FINALIZE_ESCROW_DEPOSITrequires the node allocation to be cleared and both home-side net-flow deltas to remain unchanged.So the backend can sign and store an escrow-finalize state that the contract itself would reject.
That mismatch is exploitable because the attacker does not need to execute the invalid escrow-finalize state on-chain. They only need the backend to accept it as the latest signed state. Once that happens, the inflated off-chain home balance can be used as the basis for a later normal
HomeWithdrawalrequest. That later state can still satisfy the contract’s withdrawal checks when compared against the real on-chain channel state, allowing the attacker to withdraw node liquidity that was never actually credited on-chain.Summary by CodeRabbit
Bug Fixes
Tests