fix: implement granular balance tracking for locked fallback tokens#309
Merged
hman38705 merged 1 commit intoMar 27, 2026
Merged
Conversation
- unlock_tokens now reads the transfer amount from LockedBalance (the per-user accumulator) instead of LockedTokens.amount - LockedTokens.amount was overwritten on vote revision, making it unreliable as the withdrawal source; LockedBalance correctly accumulates across revisions - Each user can only withdraw exactly what they locked, preventing early claimers from draining tokens belonging to other voters - Add test_locked_balance_prevents_pool_drain: two users lock 3000 and 7000 respectively; asserts each receives only their own amount and contract balance reaches zero Closes solutions-plug#37
|
@Fidelis900 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
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.
Title: fix: implement granular balance tracking for locked fallback tokens
Body:
Summary
Fixes #37 — Track Locked Balances during Token Fallback
When a governance token doesn't support balance_at snapshots, the fallback path locks tokens in the contract. The
LockedBalance key (per-user accumulator) was already being written correctly in cast_vote, but unlock_tokens was
reading the transfer amount from LockedTokens.amount instead — which gets overwritten on vote revision rather than
accumulated. This meant a user who revised their vote could have a stale LockedTokens.amount, and more critically,
nothing prevented the first caller from withdrawing the full contract balance.
Root Cause
rust
// BEFORE — uses LockedTokens.amount (overwritten on revision, not accumulated)
token_client.transfer(&e.current_contract_address(), &voter, &locked.amount);
LockedTokens.amount is set to weight on each vote call. If a user revises their vote, the struct is overwritten with
only the latest weight. LockedBalance is the correct source because it accumulates across revisions and is strictly
per-user.
Changes
of LockedTokens.amount. Returns BetNotFound if the balance is zero or missing, preventing any withdrawal without a
corresponding lock.
respectively via the fallback path, then each unlocks independently. Asserts each receives exactly their own amount
and the contract ends at zero balance.
Security Impact
Without this fix, the first user to call unlock_tokens after a market resolves could drain the entire contract token
balance (sum of all locked tokens), leaving other voters unable to recover their funds.
closes #145