xdefilab / xdefi-governance-token Goto Github PK
View Code? Open in Web Editor NEWXDeFi Yield Farming & XDEX on Ethereum
Home Page: https://farm.xdefi.com
License: MIT License
XDeFi Yield Farming & XDEX on Ethereum
Home Page: https://farm.xdefi.com
License: MIT License
二测的逻辑是
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
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;
原为(建议注释,方便审计判断功能统一,仅数学简化)
//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))
···
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
直接把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的人支付了这些转账费用。
现在:
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可以一起做
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.