A decentralized voting escrow system for HEMI tokens implementing time-locked staking with voting power and incentive distribution.
veHemi consists of two main contracts:
- veHemi - Main voting escrow contract handling token locking, voting power calculation, and NFT transfers
- HemiVoteDelegation - Delegation system for voting power
veHemi uses a linear decay system where both voting power and incentives are calculated using the same formula:
- Formula:
locked_amount * (lock_end_time - current_time) / max_lock_duration - Voting power: Determines governance voting weight
- Incentive distribution: Determines reward allocation proportion
- Longer locks = more weight: Users locking for longer durations get proportionally more voting power and incentives
Consider two users in veHemi:
- User A: Locks 100 HEMI for 4 years (single lock)
- User B: Locks 100 HEMI for 2 years, then relocks for 2 more years
User A gets more weight because:
- Single 4-year lock has higher average voting power over the entire period
- Linear decay curve favors longer initial lock durations
- More consistent incentive distribution throughout the lock period
- Duration: Up to 4 years maximum
- NFT representation: Each lock is a unique NFT
- Transferability: Default transferable, can be non-transferable
- Extensions: Only NFT owner can extend lock duration
- Amount increases: Anyone can increase locked amount
- Default: Transferable by default
- Non-transferable: Created with
transferable = false(e.g., protocol distributions) - Auto-transferable: Non-transferable NFTs become transferable after first lock duration ends
- Delegation reset: Transfers automatically move delegation to self
- Epoch-based: Delegations take effect at next day boundary
- Flexible: Delegate to any token ID or self
- Revocable: Change or revoke at any time
# Install and build
forge install
forge build
# Run tests
forge test// Transferable lock
uint256 tokenId = veHemi.createLock(amount, 4 * 365 days);
// Non-transferable lock
uint256 tokenId = veHemi.createLockFor(amount, 4 * 365 days, recipient, false);// Direct delegation
hemiVoteDelegation.delegate(delegatorTokenId, delegateeTokenId);
// Check voting power
uint256 votes = hemiVoteDelegation.getVotes(tokenId);// Check transferability
bool isTransferable = veHemi.isTransferable(tokenId);
// Transfer NFT
veHemi.transferFrom(from, to, tokenId);This repo uses both foundry and hardhat frameworks, it uses npm to manages all dependencies (foundry libs included), meaning the foundry test will only work after running:
npm iforge tBefore any deployment/upgrade it's recommended to run scripts against local fork chain:
Make sure that the .env file has correct params and then run:
./scripts/start-forked-node.sh
./scripts/test-next-deployment-on-fork.shMake sure that the .env file has correct params and then run:
npx hardhat deploy --network heminpx hardhat etherscan-verify --network hemiMIT License