# TokenVesting

{% hint style="info" %}

### 📋 Contract Overview

{% endhint %}

| Property        | Value                  |
| --------------- | ---------------------- |
| 📁 **File**     | `src/TokenVesting.sol` |
| 🔧 **Type**     | Upgradeable UUPS Proxy |
| ⚙️ **Solidity** | 0.8.33                 |
| 📜 **License**  | MIT                    |

{% hint style="info" %}
**🎯 Purpose:** Manages BLTBY token vesting schedules for investors, team members, and stakeholders—ensuring tokens are released gradually over time.
{% endhint %}

***

{% tabs %}
{% tab title="📊 Vesting Types" %}

### 📊 Vesting Types

| Type                         |   Cliff   |  Duration | Release |
| ---------------------------- | :-------: | :-------: | ------- |
| 👼 **Investor (Angel)**      |  3 months | 12 months | Linear  |
| 💰 **Investor (VentureOne)** |  6 months | 24 months | Linear  |
| 🏛️ **Investor (Trust)**     |  6 months | 36 months | Custom  |
| 👥 **Team**                  | 12 months | 48 months | Linear  |
| 🎓 **Advisor**               |  6 months | 24 months | Linear  |
| 🌐 **Ecosystem**             |     0     | 36 months | Linear  |
| {% endtab %}                 |           |           |         |

{% tab title="⚙️ Specifications" %}

### ⚙️ Technical Specifications

| Property           | Value              |
| ------------------ | ------------------ |
| 🔄 **Upgradeable** | ✅ Yes (UUPS Proxy) |
| 🔐 **Reentrancy**  | Protected          |

#### Inherits From

* `Initializable`
* `AccessControlUpgradeable`
* `ReentrancyGuardUpgradeable`
* `UUPSUpgradeable`
  {% endtab %}

{% tab title="🔐 Roles" %}

### 🔐 Access Control Roles

| Role                    | Description                    |
| ----------------------- | ------------------------------ |
| 👑 `DEFAULT_ADMIN_ROLE` | Can grant/revoke all roles     |
| ⏱️ `VESTING_ADMIN_ROLE` | Can create vesting schedules   |
| ❌ `REVOKER_ROLE`        | Can revoke revocable schedules |
| {% endtab %}            |                                |
| {% endtabs %}           |                                |

***

## 🔧 Functions

{% tabs %}
{% tab title="📝 Create" %}

### 📝 Schedule Creation

#### Create Single Schedule

```solidity
function createVestingSchedule(
    address beneficiary,
    uint256 amount,
    uint256 startTime,
    uint256 cliffDuration,
    uint256 vestingDuration,
    VestingType vestingType,
    bool revocable
) external onlyRole(VESTING_ADMIN_ROLE) returns (bytes32 scheduleId)
```

**Requirements:**

* Beneficiary not zero address
* Amount greater than zero
* Sufficient BLTBY in contract
* Duration greater than cliff

#### Batch Create

```solidity
function createBatchVestingSchedules(
    address[] calldata beneficiaries,
    uint256[] calldata amounts,
    uint256 startTime,
    uint256 cliffDuration,
    uint256 vestingDuration,
    VestingType vestingType,
    bool revocable
) external onlyRole(VESTING_ADMIN_ROLE) returns (bytes32[] memory scheduleIds)
```

{% endtab %}

{% tab title="📤 Release" %}

### 📤 Token Release

#### Release Single

```solidity
function release(bytes32 scheduleId) external nonReentrant
```

**Access:** Beneficiary or authorized caller

Releases vested tokens to beneficiary.

#### Release All

```solidity
function releaseAll() external nonReentrant
```

Releases all vested tokens across all schedules for caller.
{% endtab %}

{% tab title="❌ Revoke" %}

### ❌ Revocation

```solidity
function revoke(bytes32 scheduleId) external onlyRole(REVOKER_ROLE)
```

{% hint style="warning" %}
Only revocable schedules can be revoked. Vested tokens go to beneficiary, unvested return to treasury.
{% endhint %}
{% endtab %}

{% tab title="👁️ View" %}

### 👁️ Query Functions

#### Get Vested Amount

```solidity
function getVestedAmount(bytes32 scheduleId) external view returns (uint256)
```

Returns total vested (including released).

#### Get Releasable Amount

```solidity
function getReleasableAmount(bytes32 scheduleId) external view returns (uint256)
```

Returns amount that can be released now.

#### Get Schedule

```solidity
function getSchedule(bytes32 scheduleId) external view returns (VestingSchedule memory)
```

#### Get All for Beneficiary

```solidity
function getSchedulesForBeneficiary(address beneficiary)
    external view returns (VestingSchedule[] memory)
```

{% endtab %}
{% endtabs %}

***

## 📈 Vesting Calculation

{% hint style="info" %}
Linear vesting after cliff period.
{% endhint %}

```solidity
function computeVestedAmount(...) public view returns (uint256) {
    uint256 currentTime = block.timestamp;

    // Before cliff: nothing vested
    if (currentTime < startTime + cliffDuration) {
        return 0;
    }

    // After full vesting: everything vested
    if (currentTime >= startTime + vestingDuration) {
        return totalAmount;
    }

    // During vesting: linear calculation
    uint256 timeVested = currentTime - startTime;
    return (totalAmount * timeVested) / vestingDuration;
}
```

***

## 📊 Timeline Example

{% hint style="info" %}
Example: 1,000,000 BLTBY over 24 months with 6-month cliff
{% endhint %}

|    Month    |   Vested  |      Releasable      |
| :---------: | :-------: | :------------------: |
| 0-6 (Cliff) |     0     |           0          |
|      7      | \~291,667 |        291,667       |
|      12     |  500,000  |  500,000 - released  |
|      24     | 1,000,000 | 1,000,000 - released |

***

## 📜 Events & Errors

{% tabs %}
{% tab title="📢 Events" %}

```solidity
event VestingScheduleCreated(
    bytes32 indexed scheduleId,
    address indexed beneficiary,
    uint256 amount,
    uint256 startTime,
    uint256 cliffDuration,
    uint256 vestingDuration
);
event TokensReleased(
    bytes32 indexed scheduleId,
    address indexed beneficiary,
    uint256 amount
);
event VestingRevoked(
    bytes32 indexed scheduleId,
    uint256 unvestedReturned
);
```

{% endtab %}

{% tab title="⛔ Errors" %}

```solidity
error ScheduleNotFound(bytes32 scheduleId);
error NothingToRelease(bytes32 scheduleId);
error ScheduleNotRevocable(bytes32 scheduleId);
error ScheduleAlreadyRevoked(bytes32 scheduleId);
error InvalidBeneficiary(address beneficiary);
error InvalidAmount(uint256 amount);
error InvalidDuration(uint256 cliff, uint256 vesting);
error InsufficientTokens(uint256 required, uint256 available);
```

{% endtab %}
{% endtabs %}

***

## 🔗 Contract Interactions

| Contract                                                          | Interaction                        |
| ----------------------------------------------------------------- | ---------------------------------- |
| 🪙 [BLTBYToken](/developers/contracts/bltby-token.md)             | Holds and transfers vesting tokens |
| 🔧 [InvestorMintContract](/developers/contracts/investor-mint.md) | Creates investor schedules         |
| 🏦 [Treasury](/developers/contracts/treasury.md)                  | Receives revoked unvested tokens   |

***

## 🔗 Investor Integration

The [InvestorMintContract](/developers/contracts/investor-mint.md) creates vesting schedules automatically:

```solidity
// In InvestorMintContract.invest()
vestingContract.createVestingSchedule(
    investor,
    bltbyAmount,
    block.timestamp,
    tierCliff,
    tierDuration,
    VestingType.Investor,
    false  // Not revocable for investors
);
```

***

<details>

<summary>💻 Integration Examples</summary>

#### Creating a Schedule

```javascript
const tx = await vestingContract.createVestingSchedule(
    beneficiaryAddress,
    parseEther("1000000"),  // 1M BLTBY
    Math.floor(Date.now() / 1000),  // Now
    6 * 30 * 24 * 60 * 60,  // 6 month cliff
    24 * 30 * 24 * 60 * 60, // 24 month total
    0,  // VestingType.Investor
    false  // Not revocable
);
```

#### Checking Releasable

```javascript
const releasable = await vestingContract.getReleasableAmount(scheduleId);
console.log(`Can release: ${formatEther(releasable)} BLTBY`);
```

#### Releasing Tokens

```javascript
await vestingContract.release(scheduleId);
// Tokens transferred to beneficiary
```

</details>

***

## 🔗 Related Pages

{% content-ref url="/pages/DE5T7PakaRq9xaiiY3yW" %}
[BLTBYToken](/developers/contracts/bltby-token.md)
{% endcontent-ref %}

{% content-ref url="/pages/WO6aki9lKfddce25yEOE" %}
[InvestorMintContract](/developers/contracts/investor-mint.md)
{% endcontent-ref %}

{% content-ref url="/pages/HdsFywC5nPpuADDVeO1d" %}
[Investment Tiers](/investors/tiers.md)
{% endcontent-ref %}


---

# 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.builtbydao.com/developers/contracts/token-vesting.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.
