VotingEscrow
Create, manage, and read veSPECTRA lock NFTs on Base.
Overview
VotingEscrow holds locked SPECTRA and represents each position as an ERC-721 NFT. The Base veSPECTRA contract is 0x6a89228055C7C28430692E342F149f37462B478B. A wallet can own multiple lock NFTs; contract calls identify an individual lock by its uint256 token ID.
Use the locking guide for the app flow. The methods below cover common lock integrations. RewardsDistributor handles recorded rebases, while Voter handles pool voting and voting-reward claims.
Create a lock
function token() external view returns (address)
function createLock(uint256 _value, uint256 _lockDuration) external returns (uint256)
function createLockFor(uint256 _value, uint256 _lockDuration, address _to) external returns (uint256)Approve the escrow to transfer _value units of token() before creating a lock. Amounts use the ERC-20 token's smallest units. _lockDuration is a duration in seconds, not an absolute timestamp. The contract rounds block.timestamp + _lockDuration down to a week boundary; the result must be in the future and no more than four years ahead.
createLock mints the NFT to the caller. createLockFor mints it to _to while taking the SPECTRA from the caller. Both return the new NFT token ID.
Add tokens or extend a lock
function depositFor(uint256 _tokenId, uint256 _value) external
function increaseAmount(uint256 _tokenId, uint256 _value) external
function increaseUnlockTime(uint256 _tokenId, uint256 _lockDuration) externaldepositFor lets a caller add their SPECTRA to an existing, unexpired or permanent lock without changing its owner or unlock time. Adding to a managed NFT through depositFor is restricted to its distributor; an NFT deposited into a managed lock cannot receive a direct deposit.
increaseAmount requires the NFT owner or an approved operator. Both deposit methods require an ERC-20 allowance and a positive amount.
increaseUnlockTime requires the owner or an approved operator and an unexpired, nonpermanent normal lock. The new unlock time is calculated from the current timestamp and rounded down to a week boundary. It must exceed the existing unlock time and remain within the four-year maximum.
Read ownership, lock state, and voting power
function ownerOf(uint256 _tokenId) external view returns (address)
function balanceOf(address _owner) external view returns (uint256)
function ownerToNFTokenIdList(address _owner, uint256 _index) external view returns (uint256)
function locked(uint256 _tokenId) external view returns (LockedBalance memory)
function balanceOfNFT(uint256 _tokenId) external view returns (uint256)
function balanceOfNFTAt(uint256 _tokenId, uint256 _t) external view returns (uint256)
function totalSupply() external view returns (uint256)
function totalSupplyAt(uint256 _timestamp) external view returns (uint256)The LockedBalance tuple contains int128 amount, uint256 end, and bool isPermanent. Timed locks lose voting power as their unlock time approaches; permanent locks do not decay.
balanceOf(address) counts owned NFTs. It is not the wallet's voting power. Enumerate those NFTs with ownerToNFTokenIdList using indices from zero to balanceOf(owner) - 1, or use the voting-power aggregator for a weighted total across registered escrows.
balanceOfNFT returns the current voting power of one NFT and returns zero in the block of an ownership change. balanceOfNFTAt reads its voting power at a Unix timestamp. The totalSupply methods return aggregate voting power, rather than an NFT count or the amount of SPECTRA locked.
Withdraw an expired lock
function withdraw(uint256 _tokenId) externalRequires the NFT owner or an approved operator, a normal lock whose unlock time has passed, and no active pool-voting flag. A permanent lock cannot be withdrawn directly. Withdrawal transfers the locked SPECTRA to the caller and burns the NFT; claim its recorded rebases and voting rewards before burning the position.
Permanent locks
function lockPermanent(uint256 _tokenId) external
function unlockPermanent(uint256 _tokenId) externalThe owner or an approved operator can make an unexpired normal lock permanent. Its voting power then stops decaying. unlockPermanent starts a new timed lock with an unlock time four years from the call, rounded down to a week boundary; it does not make the SPECTRA immediately withdrawable. Unlocking also removes delegation and requires the NFT to have no active pool-voting flag.