xdefilab / xdefi-governance-token

XDeFi Yield Farming & XDEX on Ethereum
https://farm.xdefi.com
MIT License
12 stars 3 forks source link

xHalfLife.sol Gas过高 #9

Closed tturbulence closed 3 years ago

tturbulence commented 3 years ago

原为(建议注释,方便审计判断功能统一,仅数学简化) //If remaining not equal zero, it means there have been added funds. uint256 r = stream.remaining; uint256 w = 0; uint256 n = block.number.sub(stream.lastRewardBlock).div(stream.kBlock); for (uint256 i = 0; i < n; i++) { uint256 reward = r.mul(stream.unlockRatio).div(1000); w = w.add(reward); r = r.sub(reward); if (r < effectiveValues[streamId]) { break; } }

改进:把循环简化到乘方

   uint256 n = block.number.sub(stream.lastRewardBlock).div(stream.kBlock);
   uint256 k = stream.unlockRatio.div(1000); // k=0.001 For Standard HalfLife
   uint256 mu = 1.sub(k); // mu=0.999 For Standard HalfLife
   uint256 r = stream.remaining.mul(mu.pow(n)); // Same Result With Commented Lines
   uint256 w = stream.remaining.sub(r); // withdrawable, if n is float this process will be smooth, slightly higher gas

  更进一步的,因为BalanceOf简化了,因此k=[0.0000167, 0.00000185,0.000000555,0.000000278] while kBlock==1
  corresponding to kBlock=[60,540,1800,3600] when k=0.001

可以用Python参考校验 ··· def compute1(k,r,n): w = 0 rr = r for i in range(np.int(n)): reward = rr * k w = w + reward rr = rr - reward return (w,rr)

def compute2(k,r,n): rr = r * ((1 - k)**np.int(n)) w = r - rr return (w,rr)

for i in range(20): n = np.random.randint(100) k = np.random.uniform(0,1) r = np.random.exponential() print(n,k,r,compute1(k,r,n)) print(n,k,r,compute2(k,r,n)) ···