This repository contains the implementation of the staking pool with hourly compounding, hardcap, contribution limits and expiry date.
Staking pool can be in one of these states during it's lifetime :
Deployed --> Initialized --> Open --> Expired --> Swept
Transitions
Deployed - smart contract deployed to the network or terminate() called when in Initialized state
Initialized - init() function executed
Open - block.timestamp >= start
Expired - block.timestamp >= end
Swept - sweep() function executed
State vs staking pool operations
Rewards locked | Staking | Unstaking | Compounding | |
---|---|---|---|---|
Deployed | No | No | No | No |
Initialized | Yes | No | No | No |
Open | Yes | Yes | Yes | Yes |
Expired | Yes | No | Yes | No |
Swept | No | No | Yes | No |
Our implementation is using linear compounding function
compounded = compounded * (1+ratio)**n
compounded: deposit+compounded rewards
ratio: hourly compounding ratio
n: amount of hourly intervals
Power function used in the compounding equation comes from ABDKMath64x64solidity math library.
To keep the smart contract state minimal, Stake
struct in the stakes
mapping keeps compounded value that is being updated on every additional stake and unstake function calls, in other words in any function that changes the stake.deposit
.
mapping(address => Stake) public stakes;
Our staking pool requires the owner to provide the funds to cover all potential rewards given hardCap
, ratio
and staking pool time dimension.
The equation for total future rewards is:
maxFutureRewards = hardCap - hardCap * compound(1+ratio)**((end-start)/1 hour)
Since the funding requires maximum amount of rewards to be provided the sweeping functionality is required for staking pool owner to reclaim unnecessary funds.
Sweep
can only be called by owner
after reaching staking pool expiry, where compounding has stopped and thus total amount of rewards is fixed.
We define unnecessary funds as the difference between maxFutureRewards
and rewards at the staking pool expiry.
remainingRewards = maxFutureRewards - sum(withdrawnRewards)
sweepAmount(t == end) = remainingRewards - sum(stakedRewards)
sweepAmount(t) = maxFutureRewards - sum(withdrawnRewards(t)) - sum(stakedRewards(t))
In order to build after a successful clone
:
- npm install
- npm run compile
- npm run test
- npm run deploy:dev
- Create a
.env
file and set the variable
DEPLOYER_PRIV_KEY = <private_key>
-
Make sure the corresponding address has enough funds on
Volta
testnet. If needed, get someVolta tokens (VT)
on Volta faucet. -
run following command
npm deploy:volta
More information to come...