The contract allows locking tokens for a selected period of time and receiving rewards from the RewardsDistribution contract in return. It utilizes the VotingEscrow contract from Curve as its implementation.


VotingEscrow.vyopen in new window

MaxLock Time and Lock Durations

The creator of the VE-System must choose the maximum lock duration (MAXTIME), which should be more than 1 week.
The voting power of each user's lock is calculated based on MAXTIME. You can find a calculation example at the provided linkopen in new window.
When selecting MAXTIME, the VE-System creator should consider the planned reward distribution period in the RewardDistributor contract (and, if applicable, RewardFaucet contract).

Interactions with other smart contracts (Smart-Wallets)

By default, the VotingEscrow contract restricts locking for other smart contracts. If you want to configure access for other smart contracts, you need to use the functionality of the third-party SmartWalletWhitelist smart contract. With SmartWalletWhitelist, you can grant access to all possible smart contracts or only a specific list. Refer to the instructions for deploying and configuring access for smart contracts to VotingEscrow.

View functions


function token() external view returns (address)

Returns the address of the token that can be deposited into VotingEscrow.


function name() external view returns (string memory)

Returns name of the current VotingEscrow contract.



function create_lock(uint256 _value, uint256 _unlock_time) external;

Deposit _value tokens for msg.sender and lock until _unlock_time.
_value - amount to deposit. VotingEscrow should have already given an allowance of at least _value on the deposited token.
_unlock_time - epoch time when tokens unlock, rounded down to whole weeks.


function increase_amount(uint256 _value) external;

Deposit _value additional tokens for msg.sender without modifying the unlock time.
_value - amount to deposit. VotingEscrow should have already given an allowance of at least _value on the deposited token.


function increase_unlock_time(uint256 _unlock_time) external;

Extend the unlock time for msg.sender to _unlock_time
_unlock_time - new epoch time for unlocking


function withdraw() external;

Withdraw all tokens for msg.sender when lock has expired.

Early Unlock

By default, the option for early unlocking is disabled in the contract. There are two types of unlocks that can be enabled by the contract administrator.

Unlock with penalty (soft unlock)

Allows users to withdraw their funds before the lockup period ends. Users are penalized proportionally to the time remaining until the end of the lockup. The administrator can also configure the penalty rate (speed) using set_early_unlock_penalty_speed() function. See formula below:

  L - lock amount
  k - penalty coefficient [0: 5], defined by admin (default 1)
  Tleft - left time to unlock
  Tmax - MAXLOCK time
  Penalty amount = L * k * (Tlast / Tmax)

To prevent front-run attack (from VotingEscrow admin) the delay of 60 seconds is used, before new penalty speed is enabled.

To enable unlock with penalties the function set_early_unlock(true) must be called:

function set_early_unlock(bool _early_unlock) external;

_early_unlock - A boolean indicating whether early unlock is allowed or not. Sets the availability for users to unlock their locks before lock-end with penalty

To set penalty rate (speed) for early unlocking:

function set_early_unlock_penalty_speed(uint256 _penalty_k) external;

_penalty_k - Coefficient indicating the penalty speed for early unlock. Must be between 0 and 50, inclusive. Default 10.
This function provides a dynamic way for the admin to control how quickly penalties increase for early unlocking. The _penalty_k coefficient determines the rate at which penalties accumulate based on the remaining time until the lock-end. Since the PENALTY_DENOMINATOR = 10 values below 10 will decrease penalty rate, and values above 10 will increase penalty rate. In case when _penalty_k = 10 the k value of the formula above is equal 1.
To prevent front-run attack (from VotingEscrow admin) the delay of 60 seconds is used, before new penalty speed is set.

To withdraw early with penalty:

function withdraw_early()

Withdraws locked tokens for msg.sender before lock-end with penalty.

Unlock All Locks (hard unlock)

Allows all users to withdraw their funds ahead of schedule. Attention! In case this option is activated, the contract effectively terminates (there is no turning back!). New locks cannot be created. Consider this fact when distributing rewards in RewardFaucet and RewardDistributor contracts.

To enable unlock for all locks the function set_all_unlock() must be called:

function set_all_unlock() external;

Deactivates VotingEscrow and allows users to unlock their locks before lock-end. New deposits will no longer be accepted.

External Rewards (BAL Claim)

Claim External Rewards

The contract provides functionality for claiming rewards that can be accrued by holders of gauge tokens. By default, rewards are distributed to the RewardDistributor contract. The function claimExternalRewards() is used to claim additional rewards.

function claimExternalRewards() external;

Reward Receiver Update

Additionally, the contract administrator can change the address eligible to receive additional rewards (rewardReceiver). Changing such an address is only possible if an address was not set as zero-address (address(0)) as the rewardReceiver when creating the ve-system. To change the address of the recipient of additional rewards (rewardReceiver), use the function changeRewardReceiver(address newReceiver):

function changeRewardReceiver(address newReceiver) external;

newReceiver - New address to set as the reward (BAL) receiver

Admin functions

Ownership transfer

function commit_transfer_ownership(address newAdmin) external;

newAdmin - Address to have ownership transferred to Transfers ownership of VotingEscrow contract to newAdmin

functions apply_transfer_ownership() external();

Applies ownership transfer

Adding smart wallet checker

function commit_smart_wallet_checker(address smartChecker) external;

Sets an external contract to check for approved smart contract wallets
smartChecker - Address of Smart contract checker

function apply_smart_wallet_checker() external;

Applies setting external contract to check approved smart contract wallets

Additional information

Additional info can also be found hereopen in new window