Skip to content

Instantly share code, notes, and snippets.

@JamesEarle
Last active December 13, 2021 04:35
Show Gist options
  • Save JamesEarle/c33dbeaadb9b123a2dede2d4dead7273 to your computer and use it in GitHub Desktop.
Save JamesEarle/c33dbeaadb9b123a2dede2d4dead7273 to your computer and use it in GitHub Desktop.

Abstract

zFI introduces the notion of staking into the Wilder community. It allows holders to stake their WILD or their WILD <> ETH LP tokens, given by Uniswap for providing liquidity to the pool here. When staking, users earn rewards at a rate of XYZ%. Users are also optionally able to lock their stake for a maximum of a year for 2x rewards. When a stake is locked it means that it is inaccessible during the specified period. This period cannot be longer than 365 days from the time of staking. Rewards are processed automatically when a user makes a change to their position by either staking more or unstaking unlocked token. This sends their rewards to a token vault where they are then locked for one year from the time of redemption. When an amount of token has completed its lock period it will by default remain in the pool until redeemed by the user. Once a user has claimed their unlocked token back, it is moved out of the staking pools and into their wallet again.

Locking

When a user is creating a staked deposit they have the option to lock their deposit for a period of time to increase the rewards they gain during the specified period. This must be no more than 365 days from the stake submission. Additionally, at any point the user is able to update their locking period. This extension of their existing locking period must be a point in the future that is no longer than 365 days. This means that the longest theoretical lock period is 2 years. If you stake a deposit and lock it for a period of 365 days, you are able to add to that lock period on the final day for another full year. Calculating the locking period programmatically requires two steps. First, we can use the Date.Now() provided in TypeScript to get the Unix timestamp at that exact moment. A problem exists that this is in milliseconds, not seconds which block.timestamp uses in Solidity. This is easy enough to fix by doing Date.now() / 1000. Now that we have the correct timestamp all we have to do is multiply for the given number of seconds in a day (86400), and the number of days the user specified to lock their stake. For example, if a user requests to lock their stake for 120 days, the calculation would be as follows.

lock = (Date.now() / 1000) + (86400 * 120)
lockPeriod = ethers.BigNumber.from(lock)

SDK

The SDK acts as an interface for consumers to use the zFI smart contracts in their code without directly calling to them. Various functionality is made available. The zFI SDK is instantiated by first calling to createInstance with a Config object. A config has the following properties

config: Config = { 
  wildPoolAddress: string,
  lpTokenPoolAddress: string,
  factoryAddress: string,
  provider: ethers.providers.Provider
}

Where the addresses provided are the given addresses from running the zFI deployment scripts of the contracts on mainnet. Afterwards, you will have an accessible object that is able to operate on both pools as well as the factory in a single instance. Functions that are made available to you apply identically to either pool as they are based on the same contract, so they will only be referred to as "Pool Functions" here. There are also functions provided by the factory directly referred to as "Factory Functions"

Pool Functions

For any signer argument, the actor will always be the user that it applies to.

.stake(amount: string, lockUntil: ethers.BigNumber, signer: ethers.Signer) Make a deposit of the specified amount for the given locking period. The lockUntil parameter has to be provided as a Unix timestamp in the future. See the locking page for more specifics on calculating lock periods.

.unstake(depositId: string, amount: string, signer: ethers.Signer) Remove a specific deposit in whole or in part from a given pool if it is unlocked.

.processRewards(signer: ethers.Signer) Manually handle any pending rewards from all deposits and move them into the rewards pool where they will be staked for one year.

.updateStakeLock(depositId: string, lockUntil: ethers.BigNumber, signer: ethers.Signer) Update the locking period for a specific deposit for up to an additional 365 days.

.pendingYieldRewards(address: string) View a given user's unclaimed rewards from all deposits

.getAllDeposits(address: string) Get a list of all the deposits a user has made

.getUser(address: string) Get a set of user data for a pool. The response is a user object that includes their total tokenAmount in that pool. Calling to this mapping also exposes the totalWeight and subYieldRewards of a user which are values used internally for calculating rewards and can be ignored.

.getPoolToken() Get the token being staked in the pool

.calculateUserValueLocked(address: string) Calculate a user's value that is still locked and unlocked in the pool

Factory Functions

.getPoolAddress(poolToken: string) Gets the pool address given the pool token being staked.

.getPoolData(poolAddress: string) Gets a collection of data about the given pool including the poolToken, poolAddress, weight, and an isFlashPool flag.

.getRewardTokensPerBlock() Get the reward tokens allocated per block on chain

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment