fix: prevent asserter from disputing their own assertion - #117
Open
Kayce10 wants to merge 1 commit into
Open
Conversation
An asserter calling dispute() on their own pending assertion would consume the one dispute slot and guarantee both bonds back regardless of the resolver vote (since resolve() pays the winner and winner == asserter == disputer in both branches), nullifying the bond-forfeiture deterrent. Fix: - Add Error::SelfDispute = 22 to the Error enum - Add a disputer == assertion.asserter check in dispute() immediately after the NotPending and ChallengeWindowClosed guards, before any state is mutated or any bond is transferred Test: - Add test_asserter_cannot_dispute_own_assertion: verifies SelfDispute is returned, assertion remains Pending, disputer field stays None, and the asserter's token balance is unchanged after the rejected call Closes drydocs#113
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.
Summary
dispute(contracts/tholos/src/lib.rs) requireddisputer.require_auth()and checked the assertion wasPendingand within the challenge window, but never checkeddisputer != assertion.asserter. An asserter could calldisputeon their own pending assertion, consuming the assertion's one dispute slot and locking out any honest third party. Becauseresolve's winner is selected purely fromassertion.asserter/assertion.disputer, whendisputer == asserterthe winner is the same address regardless of the resolver committee's actual vote, guaranteeing both bonds back and nullifying the bond-forfeiture deterrent.Changes:
Error::SelfDispute = 22to theErrorenum with a doc comment explaining the invariantdisputer == assertion.assertercheck indispute()after the auth check andNotPending/ChallengeWindowClosedguards, before any state is mutated or any bond is transferredtest_asserter_cannot_dispute_own_assertionwhich verifiesSelfDisputeis returned, the assertion remainsPending, thedisputerfield staysNone, and the asserter's token balance is unchangedTest plan
cargo fmt --check,cargo clippy --workspace --all-targets -- -D warnings, andcargo testpass locallyCONTRACT.mdupdated if the public interface changedscripts/testnet-smoke.shrun against testnet, if this changes contract behavior in a way that affects the deployed flowtest_asserter_cannot_dispute_own_assertionadded and passing; all 100 existing tests continue to passCloses #113