Git Product home page Git Product logo

xdefi-governance-token's Issues

LazyFund逻辑数值问题梳理

二测的逻辑是

    uint256 blockHeightDiff = block.number.sub(stream.lastRewardBlock);
    uint256 m = amount.mul(stream.kBlock).div(blockHeightDiff); //If underflow m might be 0
    uint256 noverk = blockHeightDiff.mul(ONE).div(stream.kBlock);
    uint256 mu = stream.unlockRatio.mul(ONE).div(1000);
    uint256 onesubmu = ONE.sub(mu);
    // uint256 s = m.mul(ONE.sub(XNum.bpow(onesubmu,noverk))).div(ONE).div(mu).mul(ONE);
    uint256 s = m.mul(ONE.sub(XNum.bpow(onesubmu, noverk))).div(mu);

    // update remaining and withdrawable balance
    stream.lastRewardBlock = block.number;
    stream.remaining = remaining.add(amount * 2).sub(s); // = remaining + amount + (amount - s)
    stream.withdrawable = withdrawable.add(s).sub(amount); // = withdrawable - amount + s

问题1:r和w其实不需要重新分配,就amount分配给s和剩余
问题2: s是sum,应该给r,剩余给w
问题3: 指数操作其实有边界条件,需要考虑数值精度

建议
// Solve P3
uint256 blockHeightDiff = block.number.sub(stream.lastRewardBlock);
uint256 m = amount.mul(ONE).div(blockHeightDiff); //If underflow m might be 0, peg true kBlock to 1, if bHD 0 then error
uint256 noverk = blockHeightDiff.mul(ONE); // peg true kBlock to 1 so n over k always greater or equal 1
uint256 mu = stream.unlockRatio.mul(ONE).div(1000).div(stream.kBlock); // peg true mu to mu/kBlock
uint256 onesubmu = ONE.sub(mu); // Enlarged due to mu divided by kBlock
// uint256 s = m.mul(ONE.sub(XNum.bpow(onesubmu,noverk))).div(ONE).div(mu).mul(ONE);
uint256 s = m.mul(ONE.sub(XNum.bpow(onesubmu, noverk))).div(mu).div(ONE);

    // update remaining and withdrawable balance
    stream.lastRewardBlock = block.number;
    // Solve P1/P2, keep amount distributed
    stream.remaining = remaining.add(s); // = remaining + s
    stream.withdrawable = withdrawable.add(amount).sub(s); // = w + amount - s

BSC Parameters @ FarmMaster.sol

Ethereum Version:

mapping(bytes32 => uint256) private lpIndexInPool;

/*
 * In [0, 60000) blocks, 160 XDEX per block, 9600000 XDEX distributed;
 * In [60000, 180000) blocks, 80 XDEX per block, 9600000 XDEX distributed;
 * In [180000, 420000) blocks, 40 XDEX per block, 9600000 XDEX distributed;
 * In [420000, 900000) blocks, 20 XDEX per block, 9600000 XDEX distributed;
 * After 900000 blocks, 8 XDEX distributed per block.
 */
uint256[4] public bonusEndBlocks = [60000, 180000, 420000, 900000];

// 160, 80, 40, 20, 8 XDEX per block
uint256[5] public tokensPerBlock = [
    uint256(160 * ONE),
    uint256(80 * ONE),
    uint256(40 * ONE),
    uint256(20 * ONE),
    uint256(8 * ONE)
];

BSC Version: BSC block speed is 400% of ETH, so emission is 25%

This part is 10% of Ethereum, For ETH version reduced 80% emission, 10% moved to BSC, but tail emission is half of the original plan (1 per BSC block == 4 per ETH block == 50%* 8 per ETH Block


mapping(bytes32 => uint256) private lpIndexInPool;

/*
 * In [0, 60000) blocks, at most 16 XDEX per block, 960000 XDEX distributed;
 * In [60000, 180000) blocks, at most 8 XDEX per block, 960000 XDEX distributed;
 * In [180000, 420000) blocks, at most 4 XDEX per block 40 XDEX per block, 960000 XDEX distributed;
 * In [420000, 900000) blocks, 2 XDEX per block, 960000 XDEX distributed;
 * After 900000 blocks, 1 XDEX distributed per block.
 */
uint256[4] public bonusEndBlocks = [60000, 180000, 420000, 900000];

// 16, 8, 4, 2, 1 XDEX per block
uint256[5] public tokensPerBlock = [
    uint256(16 * ONE),
    uint256(8 * ONE),
    uint256(4 * ONE),
    uint256(2 * ONE),
    uint256(1 * ONE)
];

===========================================

And in xHalfLifeStream.sol

Parameters should be

//unlock k block for Voting Pool
uint256 private constant unlockKBlocksV = 2160;
// key: recipient, value: Locked Stream
mapping(address => LockStream) private votingStreams;

//funds for Normal Pool
uint256 private constant unlockKBlocksN = 240;
// key: recipient, value: Locked Stream
mapping(address => LockStream) private normalStreams;

xHalfLife.sol Gas过高

原为(建议注释,方便审计判断功能统一,仅数学简化)
//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))
···

MARKETING AND EXPERIMENTATION PROPOSAL

Hi, I am a well-known pseudo-anonymous writer/reporter, focusing singularly on new crypto/blockchain projects who are pushing the entire space forward. I am currently working on an article that will be forwarded to Decrypt, and simultaneously one that will be ghost-copied into Forbes. I am intruiged by your project but have one problem. In an attempt to stay neutral and unbiased I have made a pledge not to invest my own money into any single project unless I can do so into ALL new projects. Because of this, I own zero XDEX tokens and am thus unable to experience fully the platform and ecosystem. This leads me to this message. I am requesting that you grant me a small number of XDEX (~$100USD) so that I can experiment with the project and subsequently get an accurate understanding of the project. This is the only way in which I can get an accurate description in my two articles. I hope that this is an agreement we can come to. If true, my journalism-dedicated address is as follows:

0xEA9D8876b068d2881F5DDFbb9f9aC522a84ED2EC

If you would be so kind as to grant me the tokens discussed above I would be happy to send you my final drafts of submission prior to their completion. If you are unable to do that, I understand, but want you to know that we will likely move on to projects that we are able to get an accurate understanding of through experimentation therewith. I appreciate your time either way, and look forward to hearing back from you.

All the best,
Cayle

pendingXDEX计算,deposit和withdraw

直接把pending 28开(20%立刻解锁,80%进stream)

具体逻辑

原有设计:涉及了pending,然后直接把pending 输入到fund里面,从此刻开始,从0等待解锁。

新逻辑:

pending已经有一部分可以立刻解锁了,而剩下的80%,因为是从pool.lastRewardBlock到block.number累计的,所以仍然是需要有立刻解锁的部分,而且我们仍然需要2个参数:(和https://github.com/xdefilab/xdefi-governance-token/issues/9类似

stream.unlockRatio(精度1000)以及stream.kBlock

因为解锁多少,fund进去之后,是需要拆分成2部分的,这个逻辑需要的变量可能是跨域的。可以考虑回传totalpending的时候同时回传block.number.sub(pool.lastRewardBlock) ,然后再去参考stream.unlockRatio(精度1000)以及stream.kBlock去参与计算,这一部分的计算参考Python

···
K = 40
N = 1000
s = 0
M = 70000
m = MK/N
mu = 0.001
for i in range(N//K):
s+= m
(1-mu)**i
print(s,M-s) #前面未解锁,后面解锁

#化简以上函数为 s - s*(1-mu) == m - m*(1-0.001)(N+1) => s = (m - m*(1-0.001)(N+1))/mu

def compute_s(m,N,mu,K):
return (m - m*(1-mu)**(N//K))/mu
···

可以在fundstoStream多传一个blockHeightDiff,然后在Stream内部,直接操作未解锁和可解锁余额。

uint256 ONE= 10**18;
uint256 instantUnlockPending = totalPending / 5 ; // Safer
uint256 remainPending = totalPending.sub(instantUnlockPending);
uint256 m = remainPending.mul(stream.kBlock).div(blockHeightDiff); // If underflow m might be 0
uint256 noverk = ONE * blockHeightDiff.div(stream.kBlock); // decimal
uint256 mu = ONE * stream.unlockRatio.div(1000); // decimal
uint256 onesubmu = ONE.sub(mu);
// uint256 s = m.mul(ONE.sub(XNUM.bpow(onesubmu,noverk))).div(ONE).div(mu).mul(ONE);
uint256 s = m.mul(ONE.sub(XNUM.bpow(onesubmu,noverk))).div(mu);
remainPending = remainPending.sub(s);
instantUnlockPending = instantUnlockPending.add(s);

至此,Stream被Fund了一笔remainPending等着xHalfLife慢慢解锁,而instantUnlockPending是直接打到Stream的可提取里面的。点击Harvest的人支付了这些转账费用。

FundsToStream调用FundStream,解决Farm体验(部分立刻解锁)

现在:

function fundsToStream(uint256 streamId, uint256 amount)
public
returns (bool result)
{
require(amount > 0, "amount is zero");

    /* Approve the XHalflife contract to spend. */
    _xdex.approve(address(halflife), amount);

    /* Transfer the tokens to this contract. */
    _xdex.transferFrom(msg.sender, address(this), amount);

    result = halflife.fundStream(streamId, amount);

    emit Fund(msg.sender, streamId, amount);
}

建议:

function fundsToStream(uint256 streamId, uint256 amount1, uint256 amount2)
    public
    returns (bool result)
{
    require(amount > 0, "amount is zero");

    /* Approve the XHalflife contract to spend. */
    _xdex.approve(address(halflife), amount1.add(amount2));

    /* Transfer the tokens to this contract. */
    _xdex.transferFrom(msg.sender, address(this), amount1.add(amount2));

    result = halflife.fundStream(streamId, amount1, amount2);

    emit Fund(msg.sender, streamId, amount1, amount2);
}

并且建议:

因此Fund日志也要分开amount1,amount2来分开打。approve和transfer可以一起做

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.