在区块链中以Shares为量计算挖矿,是现在流行的pool设计。设定每区块奖励、算法等参数就可以开启挖矿啰!这里的算法设计可供大家参考。
rewardsPerShare
全局参数,当用户存款、取出或是提现奖励时会更新。
user.shares
用户私有参数,表示用户的存款量。
user.availableRewards
用户私有参数,表示用户已经获取的奖励。
user.debtRewards
用户私有参数,表示计算该用户奖励时需要剔除的奖励额度。
然后再引入三个计算公式:
rewardsPerShare = rewardsPerShare + Rewards[from, to]/totalShares[from, to]
其中rewardsPerShare初始值为0,Rewards[from, to]代表一定区块高度所新产生的奖励,totalShares[from, to0]表示当前总的存款量。
user.rewards = user.shares * rewardsPerShare - user.debtRewards
其中user.rewards表示用户在当前区块下所能获得的奖励,user.shares 是用户更新前的值,刚进入时为0.
user.debtRewards = user.shares * rewardsPerShare
其中user.shares表示用户的存款量,是更新后的值
只有一位用户时的情况
A在0区块存入10shares,每个区块一个奖励,此时:
rewardsPerShare = 0
A.shares = 10
A.availableRewards = 0
A.debtRewards = 0
totalShares = 10
- 当在10区块时A的奖励(只是计算并没有提现,所有参数并没有更新):
rewardsPerShare = rewardsPerShare + Rewards[0, 10]/totalShares[0, 10]
= 0 + 10/10 = 1
A.rewards = user.shares * rewardsPerShare - user.debtRewards
= 10 * 1 - 0 = 10
- 当在20区块时提现:
提现会更新rewardsPerShare,同时会更新A的参数。
rewardsPerShare = rewardsPerShare + Rewards[0, 20]/totalShares[0, 20]
= 0 + 20/10 = 2
A.rewards = A.shares * rewardsPerShare - A.debtRewards
= 10 * 2 - 0 = 20
A.debtRewards = A.shares * rewardsPerShare
= 10 * 2 = 20
多位用户
假设有这些操作:A在0区块存入10shares,B在10区块存入20shares,A在20区块增加至20shares,此时:
0区块时(增加A的参数):
rewardsPerShare = 0
A.shares = 10
A.availableRewards = 0
A.debtRewards = 0
totalShares = 10
10区块时(A的私有参数不受影响,增加B的参数):
rewardsPerShare = rewardsPerShare + Rewards[0, 10]/totalShares[0, 10]
= 0 + 10/10 = 1
B.shares = 20
B.availableRewards = 0
B.debtRewards = B.shares * rewardsPerShare
= 20 * 1 = 20
totalShares = 30
20区块时(A增加至20shares,B的私有参数不受影响):
此时A会将之前的奖励提取到availableRewards这个参数,同时更新shares和debtRewards。
rewardsPerShare = rewardsPerShare + Rewards[10, 20]/totalShares[10, 20]
= 1 + 10/30 = 4/3
A.availableRewards = A.shares(更新之前) * rewardsPerShare - A.debtRewards(更新之前)
= 10 * 4/3 - 0 = 40/3 = 13.333
A.shares = 20
A.debtRewards = A.shares(更新之后) * rewardsPerShare
= 20 * 4/3 = 80/3
totalShares = 40
50区块时计算各自的奖励:
rewardsPerShare = rewardsPerShare + Rewards[20, 50]/totalShares[20, 50]
= 4/3 + 30/40 = 25/12
A.rewards = A.shares * rewardsPerShare - A.debtRewards
= 20 * 25/12 - 80/3 = 15
B.rewards = B.shares * rewardsPerShare - B.debtRewards
= 20 * 25/12 - 20 = 65/3 = 21.666
注: totalRewards = A.availableRewards + A.rewards + B.rewards = 50
因为Solidity中不能有小数点,这里的rewardsPerShare最好都 *1e18来提高精度。 这种算法很实用,当前Nutbox就是用的此类算法。有想法的朋友不妨动手试试。
@tipu curate
Upvoted 👌 (Mana: 42/112) Liquid rewards.