veNOTE
fact Source contracts/src/governance/veNOTE.sol. veNOTE is a non-transferable voting-weight record in the Curve tradition: you lock NOTE for a fixed term and receive weight that falls linearly to zero at the unlock time. It implements IVotes in timestamp mode and is the IVotes source for both governors and for gauge votes.
The rule
Section titled “The rule”endis the unlock time you choose, floored to a week boundary (Thursday 00:00 UTC). A lock ending in 4 years from today has a weight of about 1 veNOTE per NOTE; a 1-year lock starts at about 0.25.- Weight decays every second. Nothing decays your principal: the NOTE amount stays fixed and is returned in full by
withdraw()once the lock expires. - One lock per address. There is no delegation:
delegates(a)returnsa, anddelegateordelegateBySigrevertDelegationNotSupported. - Weight is exact:
balanceOfAtandtotalSupplyAtuse a binary search on checkpointed points, so a governor snapshot at any past timestamp reads the true value at that instant.
Decay curve
Section titled “Decay curve”amount × (end − now) / MAXTIME at creation to zero at its unlock time. Longer locks start higher and fall more slowly in relative terms.Numeric example
Section titled “Numeric example”illustrative Same locks as the worked weekly example.
| Alice | Bob | |
|---|---|---|
| Locked | 100,000 NOTE | 60,000 NOTE |
| Term | 4 years (max) | 2 years |
Slope amount / MAXTIME | 100,000e18 / 126,144,000 ≈ 7.93e11 per second | 60,000e18 / 126,144,000 ≈ 4.76e11 per second |
| Weight at lock | 100,000 × 4/4 = 100,000 ve | 60,000 × 2/4 = 30,000 ve |
| Weight after 1 week | 100,000 − 7.93e11 × 604,800 / 1e18 ≈ 99,520 ve | 30,000 − 4.76e11 × 604,800 / 1e18 ≈ 29,712 ve |
| Weight after 1 year | 75,000 ve | 15,000 ve |
| Weight at unlock | 0 | 0 |
| Share of total (130,000 at lock) | 76.9% | 23.1% |
Bob’s lock loses 0.96% of its weight in the first week; Alice’s loses 0.48%. The shorter lock decays faster in relative terms, so relative weights drift toward longer lockers between votes unless Bob extends.
Functions
Section titled “Functions”fact
| Function | Who | Reverts |
|---|---|---|
createLock(amount, unlockTime) | anyone, whenNotPaused | ZeroAmount, LockExists, UnlockTimeInPast, UnlockTimeTooFar (more than 4 years) |
increaseAmount(amount) | the locker | NoLock, LockExpired |
depositFor(account, amount) | anyone | adds NOTE to another address’s lock; NoLock, LockExpired |
increaseUnlockTime(unlockTime) | the locker | UnlockTimeNotIncreased, UnlockTimeTooFar, LockExpired |
lockFromStaked(shares, unlockTime) | anyone | pulls sNOTE shares and credits their convertToAssets value; unlockTime must be non-zero for a new lock and 0 for a top-up (UnlockTimeMustBeZero) |
withdraw() | the locker, never pausable | NoLock, LockNotExpired; returns NOTE and any escrowed sNOTE shares |
checkpoint() | anyone | fills the global point history |
balanceOf, balanceOfAt(account, ts), totalSupply, totalSupplyAt(ts) | view | FutureLookup for ts > now |
getVotes, getPastVotes, getPastTotalSupply, clock, CLOCK_MODE | view (IVotes) | getPast* need timepoint < clock() |
locked, lockedEnd, getLastUserSlope, userPointHistory, pointHistory, userPointEpoch, epoch | view |
Every mutating call re-checkpoints the user and the global supply, so totalSupply is never stale by more than the caller’s own change.
Locking from sNOTE
Section titled “Locking from sNOTE”lockFromStaked does not redeem the vault shares (sNOTE withdrawals need requestWithdraw plus a cooldown). It escrows the shares inside veNOTE and credits the lock with their asset value at that moment. Voting weight is fixed at lock time and does not track later vault yield, which is the conservative choice; the shares, including any yield accrued while escrowed, come back with withdraw().
What veNOTE is used for
Section titled “What veNOTE is used for”| Consumer | Reads | Note |
|---|---|---|
| NoteGovernor | getPastVotes(voter, snapshot), getPastTotalSupply | Snapshot is proposal creation plus votingDelay (1 day). Proposal threshold is 0.5% of supply at clock() − 1. |
| UpgradeGovernor | same | Quorum 8% of supply at snapshot. |
| GaugeController | getLastUserSlope, lockedEnd | Allocates your slope across gauges; the lock must extend past the next week boundary (LockExpiresTooSoon). |
Limits and non-features
Section titled “Limits and non-features”- No transfer, no wrapping, no delegation. Weight belongs to the address that locked.
- No early exit.
withdraw()revertsLockNotExpireduntilend. - Not a boost. sNOTE staking rewards are not multiplied by veNOTE in v1; bribe markets and lock boost are listed as future work in the contract documentation.
- Pausable creation only. The guardian can pause
createLock,increaseAmount,depositFor,increaseUnlockTimeandlockFromStaked;withdrawalways works.