Skip to main content

LinearVesting

Git Source

Inherits: DerivativeModule, ILinearVesting, LinearVestingCard

A derivative module that allows for the creation of linearly vesting tokens

This module allows for the creation of linearly vesting tokens, where the vesting period is defined by a start and expiry timestamp. The tokens can be wrapped and unwrapped, and the underlying tokens can be redeemed once vested. The start timestamp enables vesting tokens to have a cliff, after which vesting commences.

State Variables

_VESTING_PARAMS_LEN

uint256 internal immutable _VESTING_PARAMS_LEN = 64;

_IMPLEMENTATION

Stores the clonable implementation of the wrapped derivative token

address internal immutable _IMPLEMENTATION;

userClaimed

Stores the amount that a user has claimed

mapping(address owner_ => mapping(uint256 tokenId_ => uint256 claimed_)) public userClaimed;

Functions

constructor

constructor(address parent_) Module(parent_) LinearVestingCard();

TYPE

2 byte identifier for the module type

This enables the parent contract to check that the module Keycode specified

function TYPE() public pure override returns (Type);

VEECODE

7 byte, versioned identifier for the module. 2 characters from 0-9 that signify the version and 3-5 characters from A-Z.

function VEECODE() public pure override returns (Veecode);

onlyValidTokenId

modifier onlyValidTokenId(uint256 tokenId_);

onlyDeployedWrapped

modifier onlyDeployedWrapped(uint256 tokenId_);

transfer

Transfers are disabled

Vesting tokens are soulbound/not transferable

function transfer(address, uint256, uint256) public virtual override returns (bool);

transferFrom

Transfers are disabled

Vesting tokens are soulbound/not transferable

function transferFrom(address, address, uint256, uint256) public virtual override returns (bool);

approve

Transfers are disabled

Vesting tokens are soulbound/not transferable

function approve(address, uint256, uint256) public virtual override returns (bool);

deploy

Deploy a new derivative token. Optionally, deploys an ERC20 wrapper for composability.

This function performs the following:

  • Validates the parameters
  • Deploys the derivative token if it does not already exist

This function reverts if:

  • The parameters are in an invalid format
  • The parameters fail validation
function deploy(
address underlyingToken_,
bytes memory params_,
bool wrapped_
) external virtual override returns (uint256 tokenId_, address wrappedAddress_);

Parameters

NameTypeDescription
underlyingToken_addressThe address of the underlying token
params_bytesABI-encoded parameters for the derivative to be created
wrapped_boolWhether (true) or not (false) the derivative should be wrapped in an ERC20 token for composability

Returns

NameTypeDescription
tokenId_uint256The ID of the newly created derivative token
wrappedAddress_addressThe address of the ERC20 wrapped derivative token, if wrapped_ is true, otherwise, it's the zero address.

_mintDeployed

Mints the derivative token to the recipient, assuming that the derivative token has already been deployed

function _mintDeployed(
address to_,
uint256 tokenId_,
uint256 amount_,
Token storage token_,
bool wrapped_
) internal;

Parameters

NameTypeDescription
to_addressThe address of the recipient of the derivative token
tokenId_uint256The ID of the derivative token
amount_uint256The amount of the derivative token to mint
token_TokenThe metadata for the derivative token
wrapped_boolWhether or not to wrap the derivative token

mint

Mint new derivative tokens.

This function performs the following:

  • Validates the parameters
  • Deploys the derivative token if it does not already exist
  • Mints the derivative token to the recipient

This function reverts if:

  • The parameters are in an invalid format
  • The parameters fail validation
  • amount_ is 0

A derivative token can be minted after vesting expiry, which prevents mitigates problems with auctions that settle late.

function mint(
address to_,
address underlyingToken_,
bytes memory params_,
uint256 amount_,
bool wrapped_
)
external
virtual
override
returns (uint256 tokenId_, address wrappedAddress_, uint256 amountCreated_);

Parameters

NameTypeDescription
to_addressThe address to mint the derivative tokens to
underlyingToken_addressThe address of the underlying token
params_bytesABI-encoded parameters for the derivative to be created
amount_uint256The amount of derivative tokens to create
wrapped_boolWhether (true) or not (false) the derivative should be wrapped in an ERC20 token for composability

Returns

NameTypeDescription
tokenId_uint256The ID of the newly created derivative token
wrappedAddress_addressThe address of the ERC20 wrapped derivative token, if wrapped_ is true, otherwise, it's the zero address.
amountCreated_uint256The amount of derivative tokens created

mint

Mint new derivative tokens.

This function performs the following:

  • Mints the derivative token to the recipient

This function reverts if:

  • tokenId_ does not exist
  • The amount to mint is 0

A derivative token can be minted after vesting expiry, which prevents mitigates problems with auctions that settle late.

function mint(
address to_,
uint256 tokenId_,
uint256 amount_,
bool wrapped_
) external virtual override onlyValidTokenId(tokenId_) returns (uint256, address, uint256);

Parameters

NameTypeDescription
to_addressThe address to mint the derivative tokens to
tokenId_uint256
amount_uint256The amount of derivative tokens to create
wrapped_boolWhether (true) or not (false) the derivative should be wrapped in an ERC20 token for composability

Returns

NameTypeDescription
<none>uint256tokenId_ The ID of the newly created derivative token
<none>addresswrappedAddress* The address of the ERC20 wrapped derivative token, if wrapped* is true, otherwise, it's the zero address.
<none>uint256amountCreated_ The amount of derivative tokens created

_redeem

Redeems the derivative token for the underlying base token

This function assumes that validation has already been performed

function _redeem(uint256 tokenId_, address user_, uint256 amount_) internal;

Parameters

NameTypeDescription
tokenId_uint256The ID of the derivative token
user_addressThe address of the owner of the derivative token
amount_uint256The amount of the derivative token to redeem

redeemMax

Redeem all available derivative tokens for underlying collateral

function redeemMax(uint256 tokenId_) external virtual override onlyValidTokenId(tokenId_);

Parameters

NameTypeDescription
tokenId_uint256The ID of the derivative token to redeem

redeem

Redeem derivative tokens for underlying collateral

This function reverts if:

  • amount_ is 0
  • The redeemable amount is less than amount_
  • The derivative token with tokenId_ has not been deployed
function redeem(
uint256 tokenId_,
uint256 amount_
) external virtual override onlyValidTokenId(tokenId_);

Parameters

NameTypeDescription
tokenId_uint256The ID of the derivative token to redeem
amount_uint256The amount of derivative tokens to redeem

redeemable

Determines the amount of redeemable tokens for a given derivative token

The redeemable amount is computed as:

  • The amount of tokens that have vested
  • x: number of vestable tokens
  • t: current timestamp
  • s: start timestamp
  • T: expiry timestamp
  • _Vested = x _ (t - s) / (T - s)*
  • Minus the amount of tokens that have already been redeemed
function redeemable(
address owner_,
uint256 tokenId_
) public view virtual override onlyValidTokenId(tokenId_) returns (uint256);

Parameters

NameTypeDescription
owner_addressThe owner of the derivative token
tokenId_uint256The ID of the derivative token

Returns

NameTypeDescription
<none>uint256amount The amount of redeemable tokens

exercise

Exercise a conversion of the derivative token per the specific implementation logic

Not implemented

function exercise(uint256, uint256) external virtual override;

Parameters

NameTypeDescription
<none>uint256
<none>uint256

exerciseCost

Determines the cost to exercise a derivative token in the quoted token

Not implemented

function exerciseCost(uint256, uint256) external view virtual override returns (uint256);

Parameters

NameTypeDescription
<none>uint256
<none>uint256

Returns

NameTypeDescription
<none>uint256cost The cost to exercise the derivative token

reclaim

Reclaim posted collateral for a derivative token which can no longer be exercised

Not implemented

function reclaim(uint256) external virtual override;

Parameters

NameTypeDescription
<none>uint256

transform

Transforms an existing derivative issued by this contract into something else. Derivative is burned and collateral sent to the auction house.

Not implemented

function transform(uint256, address, uint256) external virtual override;

Parameters

NameTypeDescription
<none>uint256
<none>address
<none>uint256

wrap

Wrap an existing derivative into an ERC20 token for composability Deploys the ERC20 wrapper if it does not already exist

This function will revert if:

  • The derivative token with tokenId_ has not been deployed
  • amount_ is 0
function wrap(uint256 tokenId_, uint256 amount_) external override onlyValidTokenId(tokenId_);

Parameters

NameTypeDescription
tokenId_uint256The ID of the derivative token to wrap
amount_uint256The amount of derivative tokens to wrap

unwrap

Unwrap an ERC20 derivative token into the underlying ERC6909 derivative

This function will revert if:

  • The derivative token with tokenId_ has not been deployed
  • A wrapped derivative for tokenId_ has not been deployed
  • amount_ is 0
function unwrap(
uint256 tokenId_,
uint256 amount_
) external override onlyValidTokenId(tokenId_) onlyDeployedWrapped(tokenId_);

Parameters

NameTypeDescription
tokenId_uint256The ID of the derivative token to unwrap
amount_uint256The amount of derivative tokens to unwrap

_validate

Validates the parameters for a derivative token

This function performs the following checks:

  • The start and expiry times are not 0
  • The start time is before the expiry time
  • The underlying token is not the zero address

The start and expiry times do not have to be before the current block timestamp, as it is possible to deploy and mint derivative tokens after the vesting expiry. Otherwise, it would be possible to brick funds by delaying the auction settlement.

function _validate(
address underlyingToken_,
VestingParams memory data_
) internal pure returns (bool);

Parameters

NameTypeDescription
underlyingToken_addressThe address of the underlying token
data_VestingParamsThe parameters for the derivative token

Returns

NameTypeDescription
<none>boolbool True if the parameters are valid, otherwise false

validate

Validate derivative params for the specific implementation The parameters should be the same as what is passed into deploy() or mint()

function validate(
address underlyingToken_,
bytes memory params_
) public pure override returns (bool);

Parameters

NameTypeDescription
underlyingToken_addressThe address of the underlying token
params_bytesThe abi-encoded VestingParams for the derivative token

Returns

NameTypeDescription
<none>boolisValid Whether or not the params are valid

_getTokenMetadata

function _getTokenMetadata(uint256 tokenId_) internal view returns (ERC20, VestingParams memory);

getTokenVestingParams

Get the vesting parameters for a derivative token

function getTokenVestingParams(
uint256 tokenId_
) external view onlyValidTokenId(tokenId_) returns (VestingParams memory);

Parameters

NameTypeDescription
tokenId_uint256

Returns

NameTypeDescription
<none>VestingParamsvestingParams The vesting parameters

computeId

Compute a unique token ID, given the parameters for the derivative

function computeId(
address underlyingToken_,
bytes memory params_
) external pure virtual override returns (uint256);

Parameters

NameTypeDescription
underlyingToken_addressThe address of the underlying token
params_bytesThe abi-encoded VestingParams for the derivative token

Returns

NameTypeDescription
<none>uint256tokenId The unique token ID

_decodeVestingParams

Decodes the ABI-encoded VestingParams for a derivative token

This function will revert if the parameters are not the correct length

function _decodeVestingParams(bytes memory params_) internal pure returns (VestingParams memory);

_computeId

Computes the ID of a derivative token

The ID is computed as the hash of the parameters and hashed again with the module identifier.

function _computeId(ERC20 base_, uint48 start_, uint48 expiry_) internal pure returns (uint256);

Parameters

NameTypeDescription
base_ERC20The address of the underlying token
start_uint48The timestamp at which the vesting starts
expiry_uint48The timestamp at which the vesting expires

Returns

NameTypeDescription
<none>uint256uint256 The ID of the derivative token

_computeNameAndSymbol

Computes the name and symbol of a derivative token

function _computeNameAndSymbol(
ERC20 base_,
uint48 expiry_
) internal view returns (string memory, string memory);

Parameters

NameTypeDescription
base_ERC20The address of the underlying token
expiry_uint48The timestamp at which the vesting expires

Returns

NameTypeDescription
<none>stringstring The name of the derivative token
<none>stringstring The symbol of the derivative token

_deployIfNeeded

Deploys the derivative token if it does not already exist

If the derivative token does not exist, it will be deployed using a token id computed from the parameters.

function _deployIfNeeded(
address underlyingToken_,
VestingParams memory params_,
bool wrapped_
) internal returns (uint256 tokenId_, address wrappedAddress_);

Parameters

NameTypeDescription
underlyingToken_addressThe address of the underlying token
params_VestingParamsThe parameters for the derivative token
wrapped_boolWhether or not to wrap the derivative token

Returns

NameTypeDescription
tokenId_uint256The ID of the derivative token
wrappedAddress_addressThe address of the wrapped derivative token

_deployWrapIfNeeded

Deploys the wrapped derivative token if it does not already exist

If the wrapped derivative token does not exist, it will be deployed

function _deployWrapIfNeeded(
uint256 tokenId_,
Token storage token_
) internal returns (address wrappedAddress);

Parameters

NameTypeDescription
tokenId_uint256The ID of the derivative token
token_TokenThe metadata for the derivative token

Returns

NameTypeDescription
wrappedAddressaddressThe address of the wrapped derivative token

name

Returns the name of the token

This function reverts if:

  • The token ID does not exist
function name(
uint256 tokenId_
) public view override onlyValidTokenId(tokenId_) returns (string memory);

Parameters

NameTypeDescription
tokenId_uint256The ID of the token

Returns

NameTypeDescription
<none>stringstring The name of the token

symbol

Returns the symbol of the token

This function reverts if:

  • The token ID does not exist
function symbol(
uint256 tokenId_
) public view override onlyValidTokenId(tokenId_) returns (string memory);

Parameters

NameTypeDescription
tokenId_uint256The ID of the token

Returns

NameTypeDescription
<none>stringstring The symbol of the token

decimals

Returns the number of decimals used by the token

This function reverts if:

  • The token ID does not exist
function decimals(
uint256 tokenId_
) public view override onlyValidTokenId(tokenId_) returns (uint8);

Parameters

NameTypeDescription
tokenId_uint256The ID of the token

Returns

NameTypeDescription
<none>uint8uint8 The number of decimals used by the token

tokenURI

Returns the URI of the token

This function reverts if:

  • The token ID does not exist
function tokenURI(
uint256 tokenId_
) public view override onlyValidTokenId(tokenId_) returns (string memory);

Parameters

NameTypeDescription
tokenId_uint256The ID of the token

Returns

NameTypeDescription
<none>stringstring The URI of the token