# Vote escrow architecture

![Plenty's "ve" architecture](https://3426972714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVIKTsDadrIG7W2qBrlds%2Fuploads%2FXUYJ8rUpq9xXK0lljhG9%2Fimage.png?alt=media\&token=9794baf3-d0bd-4b4f-8593-111f91253828)

## PLY Holder

The `PLY` token is based on the FA1.2 standard on [Tezos](https://tezos.com/). `PLY` holders can lock their `PLY` for an integral number of weeks between 1 and 208. The Lock-up period is rounded up to the nearest whole week as `(Expiry // Week) * Week`, so the lock period can be slightly (always < 7 days) higher or lower than the number of days your chosen number of weeks resolve to.

Locking is done by calling the `create_lock` entrypoint in the `VoteEscrow` contract. The entrypoint pulls the required number of `PLY` from the user balance and returns a `vePLY` NFT that represents the lock.

{% hint style="info" %}
Each `vePLY` NFT has an associated **voting power** that is linearly decreasing as `bias - slope * t`. The slope is calculated based on your `PLY` lock-up value and lock-up period.
{% endhint %}

At its core, the `VoteEscrow` contract is based on the FA2 standard. It maintains a `ledger` that keeps track of the ownership of all `vePLY` NFTs. Only the owner of a `vePLY` NFT can unlock it after expiry and redeem the underlying PLY tokens by calling the `withdraw` entrypoint.

## VePLY Holder

A **`vePLY` holder** can vote on the distribution of weekly `PLY` emission across the different `gauges`, and in return collect fees and bribes for the AMM they vote for. Besides, the holder can also claim inflation for their locked `PLY`, that is proportional to the global supply inflation. This is required in order to prevent dilution of locked stake overtime.

Each `vePLY` NFT has voting power that can be retrieved through the `get_token_voting_power` onchain view in the `VoteEscrow` contract. The voting power can be distributed as voting weights across different gauges the owner is intending to receive fees from and direct emissions to.

Voting is handled by the `Voter` contract. `VePLY` holders can call the `vote` entrypoint at each epoch to distribute their voting power (i.e vote) for the liquidity pools of their choice.

{% hint style="info" %}
An epoch is a voting period that is a week long and ideally starts at every Thursday, 12 AM (UTC). When a `vePLY` holder votes, their voting power at 12 AM (UTC) on the past Thursday is used.
{% endhint %}

When an epoch ends, the next epoch can be started by anyone calling the `next_epoch` entrypoint in the `Voter` contract. Besides updating the epoch, this entrypoint also calculates and updates current `PLY` inflation value, and adds a proportional inflation to the `PLY` locks.

To claim bribes and trading fees for a specific epoch, the `vePLY` holder (who has voted) can call the `claim_bribe` and `claim_fees` entrypoints respectively, in `Voter`. These entrypoints send internal transactions to `FeeDistributor` and associated `Bribe` contract, and they in turn transfer the required amount to the holder.

To claim inflation, the holder can call `claim_inflation` entrypoint in `VoteEscrow`, once for every epoch. The inflation is added directly to the underlying lock with the bias and slope being adjusted.

## AMM Liquidity Provider

**AMM Liquidity Providers** can stake their LP tokens in the gauge associated with their AMM and receive `PLY` emissions. The `gauge` contracts essentially acts like a farms. Every week, the `recharge_gauge` entrypoint of the `Voter` contract can be called to recharge a specific gauge, based on the emissions and gauge weights of the last epoch.

Stakers can also **boost** their emission rewards by a **maximum of 2.5x** by attaching a `vePLY` NFT that they own, to their stake. Boosting is achieved using the following formula: `MIN(Staked-Balance, (0.4 * Staked-Balance) + (0.6 * Staked-Supply * Voting-power-of-vePLY / Total-voting-power))`

## Briber

An individual or even a protocol can bribe i.e essentially reward those who vote for a pool of their preference in a particular epoch.

Every AMM has an associated `Bribe` contract that handles the process. Bribes can be given in any FA1.2 or FA2 standard based token by calling the `add_bribe` entrypoint.

## Admin

The `CoreFactory` contract has control over addition/deletion of AMMs in the vote-escrow system. The factory is controlled by a multisig.

When a new AMM is added, the associated `Gauge` and `Bribe` contracts are deployed and the AMM and it's token pair is stored in the `Voter` and `FeeDistributor` contract.&#x20;

## Architecture FAQs

### How is the voting power calculated in VoteEscrow contract?

In order to calculate the voting power of a specific `vePLY` NFT, or the global voting power at any timestamp **t**, we record **checkpoints** whenever any operation related to the vote escrow mechanism takes place. These operations include the creations of locks, increments of lock value and increments of lock period.

These checkpoints are recorded in the `token_checkpoints` and `global_checkpoints` bigmap. Further to keep track of lock expiry, we keep the `slope_changes` bigmap.

To find the voting power at any specific timestamp, we binary search through the checkpoints to a timestamp closest to required, and extrapolate the values stored in the checkpoint to calculate voting power at the given timestamp.

### How is boosting achieved in Gauges?

The staked balance of the user is dialled down and kept in the range 40%-100% of the initial balance. This is stored as `derived_balances` and its associated `derived_supply`. The dialing down is achieved using the formula stated in the **AMM Liquidity Provider** section. The derived values are further used to calculate the emission share.

For stakers who do not attach a `vePLY` NFT to their stake, their derived balance is always 40% of the staked balance. To get maximum out of their stake i.e a 2.5x boost, they have to attach a `vePLY` NFT with enough voting power to their stake.

### How does 'attaching' affect the vePLY NFT?

When a `vePLY` NFT is attached to an LP stake in a particular gauge, it becomes un-transferrable and cannot be used as boost in any other gauge.

### Why are timestamps stored as `nat`?

The operations in the `vePLY` system require a ton of arithmetic calculations to be made on timestamps. Since Michelson `timestamp` is not versatile when it comes to arithmetic calculations, `nat` is chosen at the primary type to store UNIX timestamp values.<br>
