/linear-vesting

Primary LanguageHaskellMIT LicenseMIT

Table of Contents

Linear Vesting

Introduction

Linear Vesting contract aims at providing a reliable mechanism for releasing Cardano Native Tokens gradually over a specified timeframe, with customization options to fit different requirements.

With so many projects launching on Cardano, many a times, there arises a requirement of vesting a project's own tokens to either their core team or supporters of the project. Vesting assets to beneficiary in proportion to the elapsed time, i.e. Linear Vesting is a very straightforward and common preference. While there definitely exist more complex vesting requirements, we hope that the contract here will help those looking for something simple for their use case. Or serve as a reference for those who want to build more elaborate arrangements.

This project is funded by the Cardano Treasury in Catalyst Fund 10.

Documentation

pvalidateVestingScript :: Term s (PVestingDatum :--> PVestingRedeemer :--> PScriptContext :--> PUnit)

The linear vesting validator is not a parameterized one. All its customization needs are fulfilled by the datum (VestingDatum) of the locked UTxO.

data VestingDatum = VestingDatum
  { beneficiary :: Address
  , vestingAsset :: AssetClass
  , totalVestingQty :: Integer
  , vestingPeriodStart :: Integer
  , vestingPeriodEnd :: Integer
  , firstUnlockPossibleAfter :: Integer
  , totalInstallments :: Integer
  }

A single UTxO at the validator address corresponds to a single vesting arrangement. There can be multiple such UTxOs present there to facilitate multiple vestings. A single vesting UTxO can however only release tokens of a single Fungible Token, specified by vestingAsset field.

After firstUnlockPossibleAfter and before vestingPeriodEnd, beneficiary can claim the vested asset in proportion to the time that has passed after vestingPeriodStart. The remaining assets needs to be sent back to the validator address with the original datum intact otherwise the validation will fail. This spending tx requires PartialUnlock redeemer.

data VestingRedeemer
  = PartialUnlock
  | FullUnlock

After the vestingPeriodEnd, beneficiary can claim the entire remaining balance at the UTxO using FullUnlock redeemer.

An important thing to note about the validator is that it only allows one script input to be spent in a single tx. Allowing more than one script input to be spent within it, could result in a critical vulnerability in the form of Double Satisfaction Attack by spending two vesting UTxOs with the exact datum.

Getting Started

Prerequisites

Before you begin, ensure you have Nix installed on your system. Nix is used for package management and to provide a consistent development environment. If you don't have Nix installed, you can do so by running the following command:

Official option

Nix

sh <(curl -L https://nixos.org/nix/install) --daemon

Preferred option

Determinate Systems

curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install

Make sure to enable Nix Flakes by editing either ~/.config/nix/nix.conf or /etc/nix/nix.conf on your machine and add the following configuration entries:

experimental-features = nix-command flakes ca-derivations
allow-import-from-derivation = true

Optionally, to improve build speed, it is possible to set up binary caches by adding additional configuration entries:

substituters = https://cache.nixos.org https://cache.iog.io https://cache.zw3rk.com
trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= loony-tools:pr9m4BkM/5/eSTZlkQyRt57Jz7OMBxNSUiMC4FkcNfk=

To facilitate seamlessly moving between directories and associated Nix development shells we use direnv and nix-direnv:

Your shell and editors should pick up on the .envrc files in different directories and prepare the environment accordingly. Use direnv allow to enable the direnv environment and direnv reload to reload it when necessary. Otherwise, the .envrc file contains a proper Nix target which will be used with the nix develop --accept-flake-config command.

To install both using nixpkgs:

nix profile install nixpkgs#direnv
nix profile install nixpkgs#nix-direnv

Building and developing

Once Nix is installed, you should be able to seamlessly use the repository to develop, build and run packages.

Download the Git repository:

git clone https://github.com/Anastasia-Labs/linear-vesting.git

Navigate to the repository directory:

cd linear-vesting

Activate the development environment with Nix:

nix develop --accept-flake-config

Or

make shell

Please be patient when building nix development environment for the first time, as it may take a very long time. Subsequent builds should be faster. Additionally, when you run nix run .#help you'll get a list of scripts you can run, the Github CI (nix flake check) is setup in a way where it checks the project builds successfully, haskell format is done correctly, and commit message follows conventional commits. Before pushing you should run cabal run , nix run .#haskellFormat (automatically formats all haskell files, including cabal), if you want to commit a correct format message you can run cz commit

Build:

make build

Execute the test suite:

make test

Compile and export Plutarch scripts:

make export

linear-vesting

Tests

For comprehensive information on the test suite for Linear Vesting implementation, including unit tests and property-based tests, please refer to our test documentation.

Demeter Workspace

To provide a seamless experience for running and trying out our application, click the workspace button below. This will start a workspace in Demeter with our repository code automatically cloned.

Code in Workspace

License

© 2023 Anastasia Labs.

All code is licensed under MIT License. See LICENSE file for details.