- Disclaimer
- License
- Introduction
- API Reference
- Basic terminology
- GAS Cost analysis
- Model simulation examples
This is a highly experimental software component. It can be subjected to bugs and will likely evolve significantly over time. Use at your own risk.
All the material in this repository is released under the CC0 (Creative Common) license.
This repo contains the ETHLend microstaking smart contracts. The readme describes the functionalities of the contracts involved and the basic flow of operation.
Microstaking is a new approach to manage the economy of a token and provides a new low velocity approach for potentially any ERC20 token used in the context of distributed applications on the ethereum blockchain. For further information on the idea behind this implementation please refer to the following medium post:
The idea behind microstaking is to let users interact with the token in a seamless way to obtain the rights to use the distributed application. It can be assimilated to the process of purchasing a tiket to access a service, using the application currency (token) as a medium. The amount to be paid is calculated off chain by the application itself, and must keep into consideration the gas costs of using the solution to avoid eccessive costs on the user side. The ticket will actually be purchased using ETH, and the staking smart contract will take charge of converting the paid tickets to ERC20 using a trader smart contract. The default implementation for the LEND token uses Kyber but the trader can be replaced at any time into the staking smart contract if other trading solutions are preferred. The ERC20 into the smart contract will periodically be redistributed to the users of the dapp in a decentralized way. Hereafter we present a more in depth analysis of the process and a description of the API.
First step of the model is collecting the payments. Payments are sent to the staking smart contract (please refere to the StakingContract
in the API Reference section) using the receive()
function. The function stores the ETH received into the smart contract, and keeps track of the data of the user (total amount of ETH received, active date).
The conversion from ETH to LEND is performed by the convert()
fuction, that calls the Kyber network trade()
method through the KyberTokenTrader
smart contract.
The smart contract keeps track of the global stake deposit through the calculateGlobalStakeSize()
method.
The periodic reward is calculated using the generateReward()
method. the call to generateReward()
marks the start of a new reward round in which users can claim their rewards. The reward is a percentage of the global stake deposit (the percentage is stored into the REWARD_PERCENTAGE
contract variable) and it's 5% by default. When a reward is generated, users will need to claim their rewards using the claimRewards()
function. Users can wait for multiple reward rounds before claiming their rewards. The total will be calculated automatically using the history data stored for each user.
The withdraw of the stake can be done by the users using the withdrawStake()
method. When withdrawing, users will need to take into account in which phase of the staking period they are withdrawing. Withdrawing while still being active on the platform can be subjected to a fee, called withdrawal penalty. The penalty is a percentage of the user's stake, the percentage is stored into the WITHDRAWING_WHILE_ACTIVE_PENALTY
contract variable. Once a user becomes inactive, he enters in a time period called "withdrawal timeframe". During this period he can withdraw the stake without any penalty. The duration of the withdrawal timeframe is stored into the WITHDRAWAL_TIMEFRAME variable and by default is 30 days. After the withdrawal timeframe, the withdrawal becomes locked and any call to withdrawStake()
results in a error. The only way for the user to unlock the stake is to become active again by using the platform.
Defines the data structures needed to keep track of the reward rounds, the stakes of the users and the history data of the users.
-
Stores the stake size for the users, the total amount of eth sent to the staking smart contract, the active timeframe for the user.
-
Stores the historical data (active date and total eth sent) for the user for each reward round in which the use has sent ETH to the smart contract
-
Keeps track of the rewards data for each reward round.
The core of the model. Keeps track of the ETH received, converts to the ERC20 Token and calculates the rewards for the users. By calling this smart contract users are able to claim their rewards and withdraw their stakes.
-
Called whenever payments are collected from the users. It updates the user data increasing the active time window, the total amount of ETH sent to the smart contract and the history data for the current reward round.
-
Called to convert the ETH stored into the staking smart contract to the ERC20 token.
-
Starts a new rewand round. Reward for the round is calculated and data is stored into the `RewardData` mapping.
-
Allows the user to claim their rewards for all the reward rounds he has not claimed. Updates the `UserStakeData` accordingly.
-
Called by the users to withdraw their stake. Every time a user withdraws, their current data (total amount of ETH sent, starting reward round, stake size) and the hystorical data is cleared.
Converts the ETH sent to ERC20 token
*#### 1. tradeTokens()
Calls the Kyber network trade()
function to convert ETH to the target ERC20 token.
-
Identifies the amount of ERC20 token stored into the smart contract, that is periodically distributed to the users.
-
Is one reward period. Rewards can be generated every 90 days by default. For every reward round, every user can claim part of the total reward for the round. The portion of the total reward for each user is proportional to the total amount of ETH he sent to the staking smart contract.
-
The withdrawal period in which the user can withdraw his entire stake without penalty
When adopting the microstaking model it's very important to keep in mind the gas costs involved in using the solution. The amount paid from the user to contribute to the microstaking should be high enough compared to the gas cost of the transaction to be meaningful, but not too high to avoid burden the users too much. Following there are some gas cost calculation for the main methods that will be used by the users, receive()
, convert()
, claimRewards()
and withdrawStake()
.
The most critical one. As It's called every time the users sends his ETH to the staking smart contract, we tried to reduce the costs as much as possible.
Worst case scenario | Average | Best case | |
---|---|---|---|
GAS | 82000 | 47000 | 37000 |
USD at safelow 3 | 0.07 | 0.04$ | 0.03$ |
USD at safelow 60 | 1.33 | 0.76$ | 0.6$ |
ETH/USD = 272$
It's the most expensive in term of gas consumption. But since it's not called directly by the user, it can be executed whenever the gas price is low enough.
Average | |
---|---|
GAS | 25000 |
USD at safelow 3 | 0.20$ |
USD at safelow 60 | 4.06$ |
ETH/USD = 272$
Average | |
---|---|
GAS | 90000 |
USD at safelow 3 | 0.08 |
USD at safelow 60 | 1.50 |
[Coming soon]