AELIP-30: Multiple Vesting Schedules


Simple Summary

This AELIP proposes adding the ability for deal creators to configure multiple vesting schedules within the same deal to be sold at different prices. The purchaser will be able to choose the vesting schedule they prefer for the corresponding token price.


This AELIP proposes modifications to the Up Front Deal contracts; including AelinUpFrontDeal.sol, AelinUpFrontDealFactory.sol, and the IAelinUpFrontDeal.sol interface. Up Front Deals already work on a price per token input model, these changes will allow multiple prices to be set to correspond with different vestingCliffPeriod and vestingPeriod inputs, enabling different vesting schedules to be purchased at different prices.

For the traditional pool-deal contracts, this AELIP proposes a refactor to use a price per deal token purchasing model like the direct deals instead of pricing the underlying deal tokens by the _purchaseTokenTotalForDeal and _underlyingDealTokenTotal inputs when creating the deal.

When a deallocation occurs, all users will be deallocated at the same rate regardless of the vesting schedule.

Purchasers will be able to purchase in any combination of the available vesting schedules in different transactions.

If a user has purchased in multiple vesting schedules, all deal tokens will be minted at once and the vesting logic to manage the different schedules' unlocks is handled in the contracts.

A purchaser will be able to individually manage their tokens for each vesting schedule or all schedules at once. Meaning that a purchaser can claim the available unlocked underlying tokens from one vesting schedule, or all at once.


The current state of the protocol only allows for one vesting schedule and one static price. If a deal creator wants to offer different prices and/or schedules, they would have to create multiple deal contracts; all requiring the creator to determine the token amount at that price point up front, fragmenting the token quantities available for each price point.

By offering the ability for a deal creator to set multiple price points and vesting schedules, it fixes this token quantity fragmentation issue allowing the creator to have one contract to manage the deal and deposit the underlying. The main motivation being to increase the flexibility/configurability of deals so that deal creators have more tools to create the deal that works best for them, and allow them to offer more options for purchasers.



Up Front Deals:

This AELIP will require modifications to the Up Front Deal contracts; including AelinUpFrontDeal.sol, AelinUpFrontDealFactory.sol, and the IAelinUpFrontDeal.sol interface. Many function interfaces and events will require modifications to their parameters.

IAelinUpFrontDeal.sol: Included in these changes will be making a VestingSchedule struct which will include purchaseTokenPerDealToken price, vestingCliffPeriod, and vestingPeriod to make up the schedule parameters. The UpFrontDealConfig struct which is used to create the deal will feature an array of VestingSchedules. Also requiring a change to the CreateUpFrontDealConfig event. More events will require updates to account for this change to the UpFrontDealConfig.

AelinUpFrontDealFactory.sol: createUpFrontDeal input parameters will be effected by the update to the UpFrontDealConfig struct.

AelinUpFrontDeal.sol: User specific contract data moved to a nested mapping to keep track of data per vesting schedule. Expiry times changed to arrays to keep track of these times per vesting schedule. Multiple functions will get an added _vestingIndex input to specify which vesting schedule the function is meant to use; including acceptDeal and claimUnderlyingPerSchedule. There will be two underlying claim functions, claimUnderlyingPerSchedule and claimUnderlyingAllSchedules, claim from one schedule or all schedules at once. In the event of a deallocation from over purchase, all purchasers will deallocated at the same percentage; the minimumRaise configuration can be used by the deal creator to ensure that the amount raised after the deallocation still meets a minimum requirement for the deal to go through. Lastly, because for loops will be used for vesting schedules, to ensure the function call does not run out of gas, the total amount of vesting schedules will be limited by a hardcoded number that is TBD.

Traditional Pool-Deal:

Pricing will no longer be calculated by the _purchaseTokenTotalForDeal and _underlyingDealTokenTotal inputs, and instead be set directly in the vestingSchedule struct. All downstream effects to create the price per deal token input will have to be considered and implemented like in the Up Front Deal contracts. These changes will effect the AelinPoolFactory.sol, AelinPool.sol, and AelinDeal.sol contracts. Part of the refactor being to implement the libraries developed for the allow list and nft gating features that are implemented in the Up Front Deal contracts.


For the traditional pool-deal contracts, going through the refactor to use the price per deal token model will make the architecture more like the direct deals for consistency and allow future upgrades to be implemented more easily.

The Up Front Deals contracts were designed with variable prices in mind; because they already works on a price per deal token purchasing model, it is simple to expand this to use arrays/nested mappings for different vesting schedules at different price rates. It allows for greater configurability when creating deals without the need for a large refactor.

Some small tradeoffs being added function inputs, slight increase in contract size for AelinUpFrontDeal.sol, slightly more gas for some of the function calls.

Technical Specification


Test Cases

Up Front Deals:

Tests will be done in AelinUpFrontDealFactory.t.sol and AelinUpFrontDeal.t.sol

Tradition Pool-Deal:

Tests will be done in AelinPoolFactory.t.sol, AelinPool.t.sol, AelinPoolPurchase.t.sol, and AelinDeal.t.sol

Copyright and related rights waived via CC0.