Install
$ agentstack add skill-omermaksutii-rugproof-ve-lock-governance ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README — it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming — see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps — measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Vote-escrow lock governance detection
When this applies
Trigger on any of:
- Locking tokens for time-decayed voting power (
create_lock,increase_amount,increase_unlock_time) - Reading
balanceOf/balanceOfNFT/votingPowerfrom a ve contract during a vote or weight calc - Gauge-weight voting, gauge controller
vote_for_gauge_weights, emission direction - Bribe / incentive markets (Votium, Hidden Hand, Velodrome
BribeVotingReward) - veNFT transfer,
merge,split,withdraw,delegate - Proposal systems that read voting power without a snapshot block
Detection patterns
Live vote weight, no snapshot (HIGH / CRITICAL)
function castVote(uint256 proposalId, bool support) external {
uint256 weight = ve.balanceOf(msg.sender); // ← read NOW, not at proposal start
proposals[proposalId].votes[support] += weight;
}
Signal: voting power read at vote time enables flash-lock: borrow, lock, vote, then exit if withdraw allowed same block, or vote with freshly minted power. Snapshot at proposal-creation block (getPastVotes).
Gauge-weight manipulation (HIGH)
Last-block vote stuffing before the weekly checkpoint redirects emissions. If gauge weights are read at the instant of checkpoint_gauge with no time-weighting, a single-block max vote captures a full epoch of emissions (Curve gauge-war griefing class). Signal: emission direction determined by instantaneous weight, not a bias-weighted moving average.
veNFT merge / split double-vote (HIGH)
function merge(uint256 from, uint256 to) external { ... } // does it clear `voted[from]`?
Signal: Velodrome-class finding — split/merge not resetting the per-NFT voted flag or per-epoch vote accounting lets one underlying balance vote twice in an epoch. Also check transferFrom mid-epoch carrying voting power to a non-voted recipient.
Lock-decay / max-lock precision (MEDIUM)
Linear-decay bias - slope * (t - t0) underflowing past expiry, or assuming MAXTIME lock when unlock_time was rounded down to the week. Off-by-one-week rounding inflates or deflates power at epoch boundaries.
Bribe-market timing (MEDIUM)
Claiming bribes for an epoch you voted in, then re-voting next epoch with the same balance, or claiming on a transferred veNFT — verify bribe accounting is keyed to (tokenId, epoch) and frozen at the vote.
Severity rubric
| Pattern | Severity | Notes | |---|---|---| | Flash-lock vote with same-block exit | Critical | Direct governance capture | | Live (un-snapshotted) vote weight | High | Borrowed-power voting | | merge/split/transfer double-vote | High | Velodrome-class veNFT bug | | Last-block gauge stuffing | High | Emission theft per epoch | | Decay/rounding precision at week boundary | Medium | Bounded mis-weighting | | Bribe claim re-use across epochs | Medium | Incentive leakage |
Remediation patterns
- Snapshot voting power at proposal-creation block via
ERC20Votes.getPastVotes/ checkpoint history — neverbalanceOfat vote time. - Time-bias gauge weights (Curve's
points_weightslope/bias with future-epoch bias) so a single block cannot dominate an epoch. - Reset per-NFT vote state on
merge/split/transferand forbid transfer of a veNFT that has voted in the current epoch (Velodromevotedlock). - Key bribe accounting to (tokenId, epoch) and freeze the balance used at vote time.
- Disallow withdraw before unlock and round
unlock_timeconsistently (floor to week) everywhere.
False-positive notes
- Snapshot-based systems (
ERC20Votes, CompoundgetPriorVotes) that already pin to a past block are safe — don't flag livebalanceOfused only for display. - A non-transferable, non-mergeable ve lock with no early withdraw materially narrows the surface; note but don't escalate.
Related
- [[flash-loan-attacks]] — flash-borrowed capital funds the flash-lock vote
- [[signature-replay]] — delegated/gasless vote signatures need nonce + epoch binding
- [[centralization-risk]] — gauge controller / emission admin keys
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: omermaksutii
- Source: omermaksutii/RugProof
- License: MIT
- Homepage: https://omermaksutii.github.io/RugProof
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.