Recommendations

Airdrops

Since airdrops are trivial to calculate off-chain, Passport Labs recommends teams to use the Passport API to calculate airdrop-related logic. This approach can help teams quickly integrate with the Passport API to get a snapshot of scores for users and construct their own Merkle tree for the airdrop.

Staking rewards

Staking rewards in Terra are calculated on-chain (Anchor, Mirror, Pylon, Valkyrie, and others have nearly identical code for this) and the logic is more complicated.

When a wallet stakes a token, the staking smart contract starts tracking that wallet's staked amount. Pending rewards are calculated whenever that wallet interacts with that smart contract again (like to stake more tokens). When a transaction occurs, the following is added to the wallet's pending rewards:

amount bonded by staker * (global_reward_index - reward_index)

The global reward index can be thought of as the reward that 1 token staked when the smart contract is initially deployed (instantiated) would receive.

The reward index is the amount that the wallet is not due to receive. This could be because the wallet staked their token after the contract is deployed or because they've already claimed tokens in the past. This can be thought of as the amount of tokens that the wallet is not owed.

As the name suggests, the global_reward_index is a global value that isn't tied to any wallet. It gets updated whenever any wallet performs an action, and is dependent on all staked tokens getting the same reward.

Because of this method of calculating rewards (which relies on all staked tokens getting the same reward) there is an impression given off that wallets are accruing rewards block by block, whereas they technically only accrue rewards when a transaction is initiated. The webapps for these projects also show an amount that can be claimed in real time, but that is a reward that is constructed through a read operation (so that reward hasn't yet been written anywhere on-chain for that wallet)

To start giving wallets boosted rewards based off their scores, protocols can either figure out a way to update the current logic to calculate rewards while giving off the block by block impression, or protocols can use a forward facing multiplier (which is the same logic used by Curve to calculate veCRV boosting rewards)

When the wallet stakes their tokens initially, the loyalty score multiplier will get saved in the smart contract state. This will then be the value used to calculate rewards for the wallet until they initiate another transaction. Since the score is used to determine future rewards, it is the forward facing multiplier.

There are a few core advantages to this approach

  • The wallet knows exactly what multiplier will apply to their token

  • Wallets that initially have a low multiplier can initiate a transaction to "refresh" their multiplier once their loyalty score improves

  • Since protocols will know the exact multiplier for each wallet at any given time, they can change the base token reward rate to leave their token rewards unchanged. For example, if they have 1M tokens to distribute in Jan 2021 and they were previously going to give 1 incentive token to each staked LP token, they can change their base rate to be .9 tokens per LP token and then have the wallets with greater multipliers get greater rewards. Thus, the multiplier will help change each wallet's weighted reward

There is one main loophole: wallets that initially have a high multiplier have no incentive to initiate any transaction to decrease their boost, so they can continue collecting boosted rewards even if they have a low score. Protocols can get around this by writing a daemon to update wallet scores every N weeks.

Last updated