# Permalock Positions Technical Specification

ApeBond locking positions are managed through the veABOND contract. Users receive NFT-based lock positions that can be regular, rolling, or permanent (Permalock). Rewards are distributed separately through the Reward Distributor contract.

### Contracts

veABOND\
`0xDF1dD618f3B564765e3ffc9F229637942ef601B2`

Reward Distributor\
`0x49135331B7A7dde8601Deea11dA4939Afac033c5`

### Retrieving User Lock Positions

To fetch all lock positions of a user:

1. On the veABOND contract, call `getUserTokenIds` passing the user’s address.\
   This returns all NFT token IDs owned by that user.
2. For each returned token ID, call `lockDetails` on the veABOND contract.

The `lockDetails` response contains all relevant information about the position, including `lockType`, `amount`, timestamps and rolling duration.

### Lock Types

The `lockType` field inside `lockDetails` determines the type of position:

If `lockType === 0`\
This is a regular position. It has a fixed unlock timestamp.

If `lockType === 1`\
This is a rolling position. It has a fixed lock duration, but this duration is renewed every week. There is no fixed unlock timestamp until the user stops rolling the position and converts it into a regular lock.

If `lockType === 2`\
This is a Permalock position. Tokens are locked permanently and will never unlock.

### Locked ABOND Amount Calculation

The `amount` value returned by `lockDetails` must be interpreted depending on the lock type.

For non-permalock positions (`lockType === 0` or `lockType === 1`), the locked ABOND amount is:

`lockDetails.amount`

For Permalock positions (`lockType === 2`), the effective locked ABOND amount is:

`lockDetails.amount / 2`

This division by two is required due to the internal accounting logic of the Permalock mechanism. Indexers and frontends must apply this adjustment to correctly reflect the user’s locked balance.

### Unlock Date Calculation

For regular positions (`lockType === 0`), the unlock timestamp is:

`lockDetails.endTime`\
This value is expressed in seconds.

For rolling positions (`lockType === 1`), there is no fixed unlock timestamp.\
To determine the locked duration, use:

`lockDetails.rollingDuration`

This represents the amount of locked time in seconds. The duration does not decrease while the position is rolling. When the user stops rolling, the position becomes a regular lock and receives a fixed `endTime`.

For Permalock positions (`lockType === 2`), the position never unlocks.\
There is no unlock timestamp. Frontends should display it as a permanent lock, for example with a “Permalock” label.

### Reward Calculation

Rewards are distributed through the Reward Distributor contract and are linked to the user’s address, not to individual NFT positions.

To calculate unclaimed rewards:

On the Reward Distributor contract, call:

`earned(userAddress, rewardTokenAddress)`

For USDT rewards, use:

`0x55d398326f99059fF775485246999027B3197955`

The `earned` method returns the amount of USDT currently unclaimed by the user.

Since rewards are address-based and not NFT-based, indexers should aggregate rewards per user address rather than per position.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.ape.bond/apebond/where-dev/permalock-positions-technical-specification.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
