Skip to content

fix(conflict): assign result of bail.Quo so non-voters are bailed at 1/5 stake#2293

Open
Tsunami43 wants to merge 1 commit into
lavanet:mainfrom
Tsunami43:fix/conflict-vote-bail-slashing
Open

fix(conflict): assign result of bail.Quo so non-voters are bailed at 1/5 stake#2293
Tsunami43 wants to merge 1 commit into
lavanet:mainfrom
Tsunami43:fix/conflict-vote-bail-slashing

Conversation

@Tsunami43

Copy link
Copy Markdown

Description

Issue: #2292

In HandleAndCloseVote (x/conflict/keeper/vote.go), the bail amount for providers that failed to vote was computed as:

bail := stake
bail.Quo(sdk.NewIntFromUint64(BailStakeDiv))

sdk.Int (cosmossdk.io/math v1.3.0) is immutable: Quo has a value receiver and returns a freshly allocated Int (SafeQuo → div() does new(big.Int).Quo(...)). The receiver is never mutated, so the return value here was discarded and bail stayed equal to the full stake.

As a result JailEntry received the entire stake as bail instead of stake / BailStakeDiv (BailStakeDiv = 5, i.e. 20%). The call just below at line ~137 (halfTotalVotes := totalVotes.Quo(...)) uses the correct assigning form, confirming this was an oversight.

Current blast radius: pairingKeeper.JailEntry is still a // todo stub that does not consume the bail coin, so this bug has no on chain effect today and the change is not consensus-breaking. It is a latent correctness bug that would surface as a 5x over bail for non-voting providers the moment JailEntry is implemented. Fixing now so that implementation lands against correct input.

Fix: assign the division result.

bail := stake.Quo(sdk.NewIntFromUint64(BailStakeDiv))

Files to review

  • x/conflict/keeper/vote.go — the only changed file (3-line diff: the fix plus an explanatory comment on sdk.Int immutability).

…1/5 stake

In HandleAndCloseVote, the bail amount for providers that failed to vote
was computed as:

    bail := stake
    bail.Quo(sdk.NewIntFromUint64(BailStakeDiv))

sdk.Int (cosmossdk.io/math v1.3.0) is immutable: Quo has a value
receiver and returns a freshly allocated Int (div() does
new(big.Int).Quo(...)). The receiver is never mutated, so the return
value here was discarded and `bail` stayed equal to the full `stake`.

As a result JailEntry received the entire stake as bail instead of
stake / BailStakeDiv (BailStakeDiv = 5, i.e. 20%). The contract just
below at line ~137 (totalVotes.Quo(...)) uses the correct assigning
form, confirming this was an oversight.

Note on current blast radius: pairingKeeper.JailEntry is still a TODO
stub that does not consume the bail coin, so this bug has no on-chain
effect today. It is a latent correctness bug that would surface as a
5x over-bail for non-voting providers the moment JailEntry is
implemented. Fixing now so the implementation lands against correct
input.

Fix: assign the division result.

    bail := stake.Quo(sdk.NewIntFromUint64(BailStakeDiv))
@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant