owned this note
owned this note
Published
Linked with GitHub
# Regen Farm Smart Contract Guide
GIVeconomy is a collection of audited smart contracts which work together to provide capabilities, including: token streaming, airdropping, and various types of farming. Contracts and scripts can be found at the **Giveth** [giv-token-contracts](https://github.com/Giveth/giv-token-contracts) repository.
## Contracts
### Streaming
The streaming allows any rewards (e.g. airdrop, liquidity mining reward, ...) to be released gradually across a given time span instead of the whole sum moving immediately to the end user's wallet. To achieve that, every reward payment to users will be an `allocate` on stream instead of a traditional `transfer/safeTransfer`.
Each instance of a **Stream** is deployed with these configuration parameters:
* **Total Tokens:** Total amount of tokens that will be distributed over the stream period
* **Start Time:** The time stamp that the stream begins
* **Duration:** Total duration of the stream. At the end of stream 100% of tokens are released and can be claimed by recipients.
* **Cliff Period:** The length of an initial period after the start of the stream. During this period, only the intitial percentage of the stream can be claimed and not more.
* **Initial Percentage:** The percentage of immediately claimable rewards during the *Cliff Period*
The **TokenDistro** is the smart contract which has implemented the streaming feature. Any eligible smart contract or eligible user can call `allocate` method on the **TokenDistro** to add to the recipient's balance of their stream. Eligible contracts or users who can call `allocate` should have the **DISTRIBUTOR** role for the **TokenDistro** smart contract. They are called **Distributors**. Each Distributor has a balance that they can distribute. Therefore, on each allocation the allocated amount sent is decreased from the distributor's balance and is added to recipient's balance.
A percentage of the allocated amount is claimable immediately, and the remaining percent goes into increasing recipient's stream flowrate. The flowrate is an expression of how many tokens become claimable from their stream over a weekly period. Over time, a greater percentage of the recipient's balance will be claimable immediately following the continued expansion of the stream.
### Air Drop
The initial token distribution can be done by the **MerkleDistro** smart contract. It utilizes *Merkle Tree* theory and each eligible recipient should provide its own unique proof data to claim their air drop. The air drop value actually will be allocated by calling `allocate` on **TokenDistro** and will be added to user's stream balance.
Each instance of **MerkleDistro** is deployed with these configuration parameters:
* **Merkle Tree Root:** The key of the merkle tree root (read blow).
* **Token Distro Address:** The address of the deployed TokenDistro instance.
In order to deploy the **MerkleDistro** smart contract, the deployer must generate a merkle tree. The value of root will be used on the smart contract at deployment time, and the whole tree data is needed to obtain each user unique path to root. In [giv-token-contracts](https://github.com/Giveth/giv-token-contracts) repo, there is a script to generate merkle tree data.
```
ts-node scripts/generate-merkle-root.ts --input <airdrop json file path> --output <output file path>
```
A JSON format of the airdrop data is not easy to generate for everyone, an `airdrop json file` can be generated by a separate script from a CSV file, which is a more convenient format.
```
ts-node scripts/csv2json.ts <airdrop csv list path> <airdrop json file path>
```
### Farming
Giveth uses the **UnipoolTokenDistro**, a derivative of the *Unipool* smart contract, for farming purposes. The difference is that **UnipoolTokenDistro** pays stakers' rewards by calling `allocate` method on the *TokenDistro(stream)* instead of transferring real tokens to the recipient's address.
Generally, the Unipool contract rewards stakers based on the liquidity they have staked. The liquidity token is named `uni` deposited by stakers, and can be any token such as native token (e.g. GIV, FOX, ...) or a LP token obtained by staking in a pool (e.g. UniswapV2, SushiSwap, HoneySwap, ...).
The Unipool reward amount is set by calling the `notifyRewardAmount(uint256 reward)` method by the admin role. Each time this method is called, the Unipool will set to disperse rewards in the `duration` length period to stakers. Therefore, admins need to regularly call `notifyRewardAmount` to keep a positive reward rate, and adjust the reward rate as it can be different on each round.
Each instance of the **UnipoolTokenDistro** is deployed with these configuration parameters:
* **TokenDistro Address:** The address of deployed TokenDistro instance.
* **Uni Token Address:** The liquidity token address
* **Duration:** Each rewarding program round length
## Deployment
Deployment of a stream with farms and an airdrop is complicated and would be error prone to be done manually. Therefore, [giv-token-contracts](https://github.com/Giveth/giv-token-contracts) has scripts to make it easier. Most of these scripts are tailored for GIVeconomy use cases.
However, a script is ready for DAOs to deploy their own stream (tokenDistro) and farming programs (Unipools). The script can be found in the path `deployments/regenFarms/1_regenFarm.ts`. The script reads the deployment configuration from `deployments/regenFarms/config.ts` file. The configuration format in `config.ts` is as below:
```
const config: IRegenConfig = {
alreadyDeployedTokenDistroAddress: "",
newTokenDistroParams: {
startTime: <start time timestamp>
cliffPeriod: <cliff time duration seconts>
duration: <duration seconds>
initialPercentage: <percentage number, like 20_00>, // two decimals of precision, 20_00 means 20%
tokenAddress: <Reward token address>
totalTokens: <Total number of tokens to distribute limit>, // In ether format
cancelable: <boolean>, // whether admins can cancel an allocation
},
unipools: {
<Key>: {
uniTokenAddress: <unit token address>,
lmDuration: <unipool reward round duration seconds>
rewardAmount: <Unipool balance on token distro>, // Number of tokens it can allocate
},
...
},
};
```
To deploy via script these environmental variables should be set:
* **INFURA_PROJECT_ID:** When the network is not xDai (Gnosis-Chain)
* **PRIVATE_KEY:** The private key of deployer account, used when network is not xDAI (Gnosis-Chain)
* **PRIVATE_KEY_XDAI:** The private key of deployer account, used when network is xDAI (Gnosis-Chain)
The script can be run by this command
```
HARDHAT_NETWORK=<network e.g. xDAI, mainnet, kovan> ts-node deployments/regenFarms/1_regenFarm.ts
```