Fix permanent fund lock in pending slashes#27
Open
paulee wants to merge 1 commit intoentrius:testfrom
Open
Conversation
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Problem
During a security audit of the ink! smart contract, I found a critical fund-lock vulnerability in the pending slash mechanism.
Flow that locks funds permanently:
timeout_swapslashes miner collateral and callstransfer(swap.user, actual_slash)pending_slashesmapping and swap data is deleted (line 839)claim_slash— but if their account is destroyed/reaped, the transfer fails again. The function re-inserts the pending slash (line 916-918)On Substrate chains, accounts are reaped when balance drops below existential deposit. Once reaped, all subsequent transfers to that account fail, making
claim_slasha dead end.Fix
Added
rescue_pending_slash— an owner-callable method that redirects stuck funds to an alternative recipient, breaking the permanent lock cycle.ensure_owner())SlashClaimedevent for trackingTests
Added 8 unit tests covering the full slash lifecycle:
test_timeout_slash_transfer_succeeds— happy path timeout with successful transfertest_timeout_slash_depletes_collateral_deactivates_miner— collateral fully depletedtest_claim_slash_pays_out— user successfully claims pending slashtest_claim_slash_wrong_user_rejected— wrong caller can't claimtest_claim_slash_nonexistent— claim on non-existent slash failstest_owner_rescue_pending_slash— owner redirects stuck fundstest_rescue_pending_slash_not_owner— non-owner can't rescuetest_rescue_nonexistent— rescue on non-existent slash failsTest plan
cargo test— all 8 tests passrescue_pending_slashcorrectly transfers funds to alternative recipientrescue_pending_slash