Cross Pool V1

💡

TLDR: Cross Pool (see allocations) is a "launchpool" on Binance Smart Chain and by extension a launchpool that's compatible with ETH and most EVM networks. It introduces features that we want, not only to launch $HOTCROSS to market but also to allow for other teams in the space to participate in LP staking and single-sided staking without having to reinvent the wheel on-chain as we've done. In the first iteration of Cross Pool, which has been rigorously audited, we support: a) rewards pools with multiple LP token staking pools, b) rewards pools with single-sided staking pools, c) rewards pools with a mix of both, and d) delayed pools that reward users but only after a certain amount of time has passed. The official website for Cross Pool is crosspool.hotcross.com.

Cross Pool Technicals

Cross Pool is driven by a CrossPool.sol smart contract. This is the entity that allows for the secure staking and custody of tokens as well as the distribution of $HOTCROSS tokens, or any tokens for that matter, as rewards. Each Cross Pool ("Rewards Pool") is tightly associated with a specific BEP20 reward token. More specifically, the contract can have multiple pools ("Staking Pools") whereby each pool emits rewards. In the case of the Hot Cross Token launch, the asset will be $HOTCROSS itself. We deploy a single Cross Pool contract per Reward Pool which will have multiple Staking Pools.

Structure

For example, we have shared in our Allocation Summary that 7,500,000 $HOTCROSS will be distributed via Cross Pool. In this case we can say that the Rewards Pool itself contains 7,500,000 $HOTCROSS. Various Staking Pools will exist that allow users to participate in the token launch by simply staking one of the following tokens to the designated pool and receiving $HOTCROSS per block:

📌

The following Rewards Pools are by illustration only and changed during the initial launch. This is a demonstration of the difference between a Reward Pool and a Staking Pool from a technical perspective only and should be viewed as illustrative of how the Cross Pool V1 structure works.

  1. Rewards Pool: 7,500,000 $HOTCROSS - This pool consists of four staking pools that in total hold all rewards for the entire pool. In some ways a staking pool may be viewed as a "sub-pool" of a larger pool. A rewards pool represents the total rewards in an entire pool.
    1. Staking Pool: 3,500,000 $HOTCROSS - HOTCROSS Earned by staking an LP token or a single-sided token, in this case $HOTCROSS tokens.
    2. Staking Pool: 2,000,000 $HOTCROSS - HOTCROSS-BNB LP Earned by staking an LP token or a single-sided token, in this case $HOTCROSS - $BNB LP tokens.
    3. Staking Pool: 1,000,000 $HOTCROSS - BUSD Earned by staking an LP token or a single-sided token, in this case $BUSD tokens.
    4. Staking Pool: 500,000 $HOTCROSS - BNB Earned by staking an LP token or a single-sided token, in this case $BNB tokens.
  2. Rewards Pool: 5,000 $CAKE - This pool consists of three staking pools that in total hold all rewards for the entire pool. In some ways a staking pool may be viewed as a "sub-pool" of a larger pool. A rewards pool represents the total rewards in an entire pool.
    1. Staking Pool: 3,000 $CAKE - HOTCROSS Earned by staking an LP token or a single-sided token, in this case $HOTCROSS tokens.
    2. Staking Pool: 1,500 $CAKE - HOTCROSS-BNB LP Earned by staking an LP token or a single-sided token, in this case $HOTCROSS - $BNB LP tokens.
    3. Staking Pool: 500 $CAKE - ETH Earned by staking an LP token or a single-sided token, in this case $ETH tokens.

💡

$HOTCROSS is now available on both PancakeSwap and KuCoin. The address on Ethereum is here while the address on Binance Smart Chain is here. The canonical source of the token itself is on Ethereum however is has been bridged over to Binance Smart Chain in part to assist in building out infrastructure on the chain. The initial launch of Cross Pool has finished however the second phase of the platform launch is now ongoing, and we do foresee a third and final launch phase where we take lessons and create a version 2 of the platform.

Administration

From the administration point of view the following needs to occur:

  1. For each asset we deploy a separate Cross Pool smart contract and initialize it with the following parameters:
    • the address of the reward token (e.g. $HOTCROSS BEP20);
    • the address of the reward vault contract that will be the decentralized custodian of the unclaimed reward tokens (e.g. $FRONT BEP20 reward vault);
    • the number of tokens to be rewarded in each block (e.g. 300000);
    • the starting block at which the rewards will begin to accumulate (e.g. 7804483);
    • the duration of the pool (e.g. 30 days);
    • and the claim delay on pool rewards, if any. This feature is optional but good to have in some cases where more patience is rewarded by higher incentives (e.g. 14 days).
  2. Each staking pool can handle multiple reward pools and accept either LP tokens or single-sided, standard tokens;
  3. Each staking pool will have an end block (e.g. 8668483), that is to say the last block that a reward will be distributed. This will be translated by turning a specific time duration into block numbers based on the assumption that in 24 hours Binance Smart Chain will process 28,800 blocks. This can be adjusted at any time should those assumptions change;
  4. Adding a new rewards pool involves simply calling a smart contract method. At the moment, logic dictates that only the owner can perform this action. In the future this may be handled by a $HOTCROSS governance mechanism;
  5. And an accurate amount of BEP20 tokens will be transferred to the staking pool smart contracts so that they are able to fund the reward vaults and ultimately distribute tokens to users who have a stake in one of our supported pools.

Based on the above information we can accurately calculate the amount of reward tokens that will be distributed to the staking account. Additionally, we can calculate the APR for each of the pools hosted by the Cross Pool contract.

image

Testnet state of Cross Pool. Deploying to mainnet in a week. Launching to public for farming soon after that.

Testnet state of Cross Pool. Deploying to mainnet in a week. Launching to public for farming soon after that.
Testnet state of Cross Pool. Deploying to mainnet in a week. Launching to public for farming soon after that.

📌

TODO: Finish up the portion underneath this callout. It's a little messy. Yes, you're reading an internal note in a public abstract. That's how we do things here.

Implementation

Basic concepts within the Cross Pool code are:

  • Reward per block: This is the number of CROSS tokens that will be rewarded in each block starting from the block height at which there are some staked tokens. This reward will be split amongst all pools
  • Pool allocation points: A figure that in combination with the total allocation points define the portion of the reward per block that a pool is entitled to. For example, pool 1 might have 500 allocation points and the total allocation points are 1000. In that case, pool 1 is entitled to 50% of the reward per block.
  • Total allocation points: The sum of the allocation points for all pools
  • Accumulated reward per share: This is a mathematical technique we use to be able to calculate the accumulated CROSS that each share i.e. staked token will receive at each block height. This is a useful trick to avoid expensive mathematical equations and storing too many data on-chain to make the calculations. It also help understand the pending reward that each user will receive at any given time based on the number of shares i.e. staked tokens she has at that point in time.
  • Reward debt: This figure is used in combination with the accumulated reward per share to accomplish what we described above.
  • Pending reward: The number of CROSS tokens that are pending to be claimed by a user

The two most important function in the smart contract are:

  1. deposit
  2. withdraw

The concepts are straightforward; the deposit function allows users to stake an amount of staking tokens to a designated pool.

For example, Alice want to stake some tokens into the MX BEP20 - BNB LP pool. Her actions would be:

  1. Use the Cross Pool DApp to enter the amount that she want to stake
  2. Sign and send a BEP20 approve transactions using her wallet
  3. Sign and send a deposit transaction

Similarly the withdraw function has the opposite effect. It allows Alice to withdraw her stake from the pool.

💡

The deposit and withdraw events are also eagerly distributing any pending rewards to the user. In practise, a deposit of 0 tokens is equal to a claim of the pending reward at the time of the transaction.

Example

Let's take an example where Alice and Bob are staking some tokens into the same pool with the goal to receive CROSS. The pool in this example will be the MX BEP20 - BNB LP. The parameters of the Cross Pool are:

  • The reward per block is 1 CROSS
  • The total allocation points are 1000
  • The MX BEP20 - BNB LP pool allocation points are 1000; basically this the only pool we have at the moment so it claims the entire reward per block (refer to calculating allocation points section for more information)

Below we show the timeline of events and what calculation that are taking place in the Cross Pool contract.

  1. Alice deposits 200 MX BEP20 - BNB LP tokens at block height #10
    • she doesn't receive an reward as she has not stake at height #10. The stake will count starting from that height.
  2. Bob deposits 200 MX BEP20 - BNB LP tokens at block height #20
    1. The reward at that point is
    2. Reward = (currentBlock - lastBlockHeight) * rewardPerBlock * (allocationPoints/totalAllocationPoints)

      that is

      Reward = (20 - 10) * 1 * 1000/1000 = 10

Also the accumulated reward per share is calculated via the following formula

AccRewardPerShare += Reward / number of MX BEP20 - BNB LP staked = 10 / 200 = 0.05

Next we calculate the reward that is pending and we need to send to Bob.

PendingReward = Bob's MX BEP20 - BNB LP * AccRewardPerShare - RewardDebt = 0 * 0.05 - 0 = 0

💡

Note that number of MX BEP20 - BNB LP staked does not include the 200 tokens that Bob staked because as mentioned earlier a stake counts after the block it was deposited.

Finally we calculate the Reward debt

RewardDebt = Bob's MX BEP20 - BNB LP (including the current deposited amount) * AccRewardPerShare = 200 * 0.05 = 10

3. Bob deposits 0 MX BEP20 - BNB LP at #30

Based on the above formulas the figures will be

Reward = 10
AccRewardPerShare = 0.075
PendingReward = 5
RewardDebt = 15

4. Alice deposits 0 MX BEP20 - BNB LP at #30

Reward = 0
AccRewardPerShare = 0.075
PendingReward = 15
RewardDebt = 15

💡

Let's pause and see what has happened. We're at the moment at block height #30. This is 20 blocks after the first MX BEP20 - BNB LP were staked. During this range the total reward is 20 CROSS tokens. Alice has received 15 and Bob 5 of that which if we sum up do make up the full rewards that the pool is entitled to.

5. Bob deposits 0 MX BEP20 - BNB LP at #40

Reward = 10
AccRewardPerShare = 0.1
PendingReward = 5
RewardDebt = 20

6. Alice deposits 100 MX BEP20 - BNB LP at #50

Reward = 10
AccRewardPerShare = 0.125
PendingReward = 10
RewardDebt = 37.5

7. Bob withdraws 100 MX BEP20 - BNB LP at #60

Reward = 10
AccRewardPerShare = 0.145
PendingReward = 9
RewardDebt = 14.5

8. Alice withdraws 100 MX BEP20 - BNB LP at #70

Reward = 10
AccRewardPerShare = 0.17
PendingReward = 13.5
RewardDebt = 34

9. Alice withdraws 200 MX BEP20 - BNB LP at #80

Reward = 10
AccRewardPerShare = 0.203333
PendingReward = 6.6666
RewardDebt = 0

10. Bon withdraws 100 MX BEP20 - BNB LP at #80

Reward = 0
AccRewardPerShare = 0.203333
PendingReward = 5.83333
RewardDebt = 0

By block #80 the entire pool accumulated 80 - 10 * 1 = 70 Reward tokens out of which

Alice received = 15 + 10 + 13.5 + 6.6666 = 45.1666

Bob received = 5 + 5 + 9 + 5.83333 = 24.83333

where Bob received + Alice Received = 70 which is the total accumulated reward for the pool

The above simple mathematical formulas have managed to distribute the rewards pro rata to Alice and Bob.

Graphical Explanation

Below we graphically explain the concepts of AccRewardPerShare and RewardDebt and how they are used to fairly distribute the rewards.

image

Each event i.e. A deposit or a withdraw is marked with two letters; the firs letter shows the user's stake at the moment of event and the complementary letter shows the balance after the event. For example A is the event of Alice depositing 200 staking tokens. At the moment of the deposit, Alice's stake is 0, since this is her first deposit. However, at the end of the event, the balance will become 200 which is illustrated with the letter A'.

The pending reward that each user received is essentially the subtraction of two areas; one are describes the RewardDebt and the other the AccRewardPerShare. These values, in combination with the user stake are used in the formula we introduced above.

PendingReward = Bob's MX BEP20 - BNB LP * AccRewardPerShare - RewardDebt

More specifically:

  • Bob's pending reward at B is 0 since he had no stake before that point
  • Bob's pending reward at C is the subtraction of the areas
Area AC-A'B' 

where  AC = the accumulated reward until that point

and A'B' is the RewardDebt that is what Bob would have already 
received if he had some stake until point B' which is the last time he interacted 
with the Cross Pool contract

In a similar manner we calculate the pending rewards after each event.

Timelock

An optional feature of the Cross Pool is the concept of timelocks. This is rather a simplistic feature that locks the accumulated rewards of each use until a specific point in time. More specifically, users can deposit and withdraw staking tokens before the timelock block height. Non of the accumulated claims will be distributed during that period, however they would still be able to claim the accumulated reward after the timelock is passed. It is important to note, that claiming accumulated rewards after the timelock does not require users have any stake in the pool.The rewards are accumulated for any tokens that have been staked prior or after the timelock. The only restriction is the time when they will be distributed to the user. In essence, withdrawing before the timelock will not nullify any accrued claims until that moment.

Calculating pool allocation points

The pool allocation points is what decides the portion of the block reward that will be distributed to the users that staked to a specific pool. Below are the three steps that we need to follow when we want to translate a percentage into this specific figure.

  1. We start with a total allocation points of 1000
  2. For each new pool we decide the share (%) of the block reward it will receive and calculate the allocation points using the following formula.
allocationPoints / (allocationPoints + totalAllocationPoints) = share (%) / 100

3. If we decide to update the share % of an existing pool we have to do:

allocationPoints / (allocationPoints - (totalAllocationPoints - prevAllocationPoints)) = share (%) / 100

APR calculation

Let's take an example that demonstrates how we can calculate the APR.

  • Reward per block 40
  • allocation points 25
  • total allocation points 100
  • Total tokens staked in the pool 74,923,611

  1. Calculate the reward the pool is entitled at each block. This will be 40 * 25/100 = 10
  2. 1 staked token will have the following share in the pool 1 / 74,923,611 = 0.000000001334692
  3. At each block 1 staked token will reward user with 0.000000001334692 * 10 = 0.0000001334692
  4. Multiplying the above figure with the total blocks per year which is 15,770,000 (based on a 3 sec block on BSC) will get us 1.4032. In a nutshell, 1 staked token will reward user with 1.4032 or a total 140.32% APR