首页项目动态文章详细

DeFi开辟者:怎样挪用NEST预言机代价数据
  • 项目动态

NEST爱好者2020-11-22 15:44:35 19
摘要:NEST生态开辟者履历分享,教你轻松挪用 NEST 预言机代价数据。

NEST 预言机-获得链上代价

先容

NEST 预言机接纳双边报价机制天生链上代价,质押双边资产来包管代价的正确性;完整去中央化的链上代价天生机制。

白皮书:https://nestprotocol.org/doc/zhnestwhitepaper.pdf

GitHub:https://github.com/NEST-Protocol

NEST Protocol:https://nestprotocol.org/

实验获得链上代价

相识机制

NEST 预言机以区块为单元天生代价,假如区块内不代价,则利用近来的区块代价。

利用报价的体式格局天生区块代价,假如一个区块内有多笔报价,则加权均匀。

每一笔报价有 25 区块的考证工夫(吃单),假如考证工夫内不被吃单则代表市场承认这笔报价,将会正在报价区块后的 25 个区块代价见效。

NEST预言机代价合约 sol 文件

GitHub:

https://github.com/NEST-Protocol/NEST-oracle-V3/blob/master/NestOffer/Nest_3_OfferPrice.sol

代码剖析

增长代价

function addPrice(uint256 ethAmount, uint256 tokenAmount, uint256 endBlock, address tokenAddress, address offerOwner) public onlyOfferMain{
// Add effective block price information
TokenInfo storage tokenInfo = _tokenInfo[tokenAddress];
PriceInfo storage priceInfo = tokenInfo.priceInfoList[endBlock];
priceInfo.ethAmount = priceInfo.ethAmount.add(ethAmount);
priceInfo.erc20Amount = priceInfo.erc20Amount.add(tokenAmount);
if (endBlock != tokenInfo.latestOffer) {
// If different block offer
priceInfo.frontBlock = tokenInfo.latestOffer;
tokenInfo.latestOffer = endBlock;
}
}

该办法限定了只要“报价合约”才能够挪用,包管增加到代价合约中的代价数据的数据源精确。

输出参数 形貌

ethAmount 报价 以太坊 数目

tokenAmount 报价 ERC20 Token数目

endBlock 代价见效区块号

tokenAddress 报价的 ERC20 Token 合约地点

offerOwner 报价者钱包地点

PriceInfo storage priceInfo = tokenInfo.priceInfoList[endBlock];
priceInfo.ethAmount = priceInfo.ethAmount.add(ethAmount);
priceInfo.erc20Amount = priceInfo.erc20Amount.add(tokenAmount);

这三行代码完成正在统一个区块内加权均匀。

修正代价

function changePrice(uint256 ethAmount, uint256 tokenAmount, address tokenAddress, uint256 endBlock) public onlyOfferMain {
TokenInfo storage tokenInfo = _tokenInfo[tokenAddress];
PriceInfo storage priceInfo = tokenInfo.priceInfoList[endBlock];
priceInfo.ethAmount = priceInfo.ethAmount.sub(ethAmount);
priceInfo.erc20Amount = priceInfo.erc20Amount.sub(tokenAmount);
}

异样限定了只要“报价合约”才有权限挪用。只要正在触发吃单操纵后,才会修正对于应见效区块中的代价,将”增加代价“时的报价数目依照”吃单“范围减失落。

输出参数   形貌

ethAmount 吃单 以太坊 数目

tokenAmount 吃单 ERC20 数目

tokenAddress 报价 ERC20 地点

endBlock 代价见效区块号

获得代价(最新)

function updateAndCheckPriceNow(address tokenAddress) public payable returns(uint256 ethAmount, uint256 erc20Amount, uint256 blockNum) {
require(checkUseNestPrice(address(msg.sender)));
mapping(uint256 => PriceInfo) storage priceInfoList = _tokenInfo[tokenAddress].priceInfoList;
uint256 checkBlock = _tokenInfo[tokenAddress].latestOffer;
while(checkBlock > 0 && (checkBlock >= block.number || priceInfoList[checkBlock].ethAmount == 0)) {
checkBlock = priceInfoList[checkBlock].frontBlock;
}
require(checkBlock != 0);
PriceInfo memory priceInfo = priceInfoList[checkBlock];
address nToken = _tokenMapping.checkTokenMapping(tokenAddress);
if (nToken == address(0x0)) {
_abonus.switchToEth.value(_priceCost)(address(_nestToken));
} else {
_abonus.switchToEth.value(_priceCost)(address(nToken));
}
if (msg.value > _priceCost) {
repayEth(address(msg.sender), msg.value.sub(_priceCost));
}
emit NowTokenPrice(tokenAddress,priceInfo.ethAmount, priceInfo.erc20Amount);
return (priceInfo.ethAmount,priceInfo.erc20Amount, checkBlock);
}


输出参数 形貌

tokenAddress ERC20 Token 合约地点

输入参数 形貌

ethAmount 以太坊 数目

erc20Amount ERC20 Token 数目

blockNum 见效代价区块

require(checkUseNestPrice(address(msg.sender)));

查抄能否有权限利用 NEST 代价。

mapping(uint256 => PriceInfo) storage priceInfoList = _tokenInfo[tokenAddress].priceInfoList;

获得对于应 Token 的代价数据源。

uint256 checkBlock = _tokenInfo[tokenAddress].latestOffer;
while(checkBlock > 0 && (checkBlock >= block.number || priceInfoList[checkBlock].ethAmount == 0)) {
checkBlock = priceInfoList[checkBlock].frontBlock;
}

表明一下 while 轮回的判定,必要从最新的报价区块开端今后倒推找到以后曾经见效而且不被吃单的代价数据地点的区块号(checkBlock)。

require(checkBlock != 0);

这个判定团体推测是为了避免有些 token 刚开端报价,尚未有用代价天生,又由于挪用代价是要付费的。以是加了限定,假如没找到见效代价的区块号,生意业务间接失利。

PriceInfo memory priceInfo = priceInfoList[checkBlock];
address nToken = _tokenMapping.checkTokenMapping(tokenAddress);
if (nToken == address(0x0)) {
_abonus.switchToEth.value(_priceCost)(address(_nestToken));
} else {
_abonus.switchToEth.value(_priceCost)(address(nToken));
}
if (msg.value > _priceCost) {
repayEth(address(msg.sender), msg.value.sub(_priceCost));
}

这部门代码是将挪用者付出的预言机用度,分派到对于应的收益池中。过剩的用度退还给挪用者。

链下获得代价(最新代价)

// Check real-time price - user account only
function checkPriceNow(address tokenAddress) public view returns (uint256 ethAmount, uint256 erc20Amount, uint256 blockNum) {
require(address(msg.sender) == address(tx.origin), "It can't be a contract");
mapping(uint256 => PriceInfo) storage priceInfoList = _tokenInfo[tokenAddress].priceInfoList;
uint256 checkBlock = _tokenInfo[tokenAddress].latestOffer;
while(checkBlock > 0 && (checkBlock >= block.number || priceInfoList[checkBlock].ethAmount == 0)) {
checkBlock = priceInfoList[checkBlock].frontBlock;
}
if (checkBlock == 0) {
return (0,0,0);
}
PriceInfo storage priceInfo = priceInfoList[checkBlock];
return (priceInfo.ethAmount,priceInfo.erc20Amount, checkBlock);
}

道理以及上一个办法同样。差别是克制了合约挪用以及没有必要付费。该当是为了给链下使用检察代价利用。

激活挪用权限

function activation() public {
_nestToken.safeTransferFrom(address(msg.sender), _destructionAddress, destructionAmount);
_addressEffect[address(msg.sender)] = now.add(effectTime);
}

利用 NEST 预言机必要质押肯定数目的 NEST 以及等候一天。这个操纵该当是为了避免”合约偷取代价“。假如不这个限定能够写个署理合约,获得代价,只要要付出一次用度,其余的挪用者能够一同利用代价。

DEMO

民间文档

/**
* @dev Get a single price
* @param token Token address of the price
*/
function getSinglePrice(address token) public payable {
// In consideration of future upgrades, the possibility of upgrading the price contract is not ruled out, and the voting contract must be used to query the price contract address.
Nest_3_OfferPrice _offerPrice = Nest_3_OfferPrice(address(_voteFactory.checkAddress("nest.v3.offerPrice")));
// Request the latest price, return the eth quantity, token quantity, and effective price block number. Tentative fee.
(uint256 ethAmount, uint256 tokenAmount, uint256 blockNum) = _offerPrice.updateAndCheckPriceNow.value(0.001 ether)(token);
uint256 ethMultiple = ethAmount.div(1 ether);
uint256 tokenForEth = tokenAmount.div(ethMultiple);
// If the eth paid for the price is left, it needs to be processed.
// ........

emit price(ethAmount, tokenAmount, blockNum, ethMultiple, tokenForEth);
}

/**
* @dev Get multiple prices
* @param token The token address of the price
* @param priceNum Get the number of prices, sorted from the latest price
*/
function getBatchPrice(address token, uint256 priceNum) public payable {
// In consideration of future upgrades, the possibility of upgrading the price contract is not ruled out, and the voting contract must be used to query the price contract address.
Nest_3_OfferPrice _offerPrice = Nest_3_OfferPrice(address(_voteFactory.checkAddress("nest.v3.offerPrice")));
/**
* The returned array is an integer multiple of 3, 3 data is a price data.
* Corresponding respectively, eth quantity, token quantity, effective price block number.
*/
uint256[] memory priceData = _offerPrice.updateAndCheckPriceList.value(0.01 ether)(token, priceNum);
// Data processing
uint256 allTokenForEth = 0;
uint256 priceDataNum = priceData.length.div(3);
for (uint256 i = 0; i < priceData.length;) {
uint256 ethMultiple = priceData[i].div(1 ether);
uint256 tokenForEth = priceData[i.add(1)].div(ethMultiple);
allTokenForEth = allTokenForEth.add(tokenForEth);
i = i.add(3);
}
// Average price
uint256 calculationPrice = allTokenForEth.div(priceDataNum);
// If the eth paid for the price is left, it needs to be processed.
// ........


emit averagePrice(calculationPrice);
}


CoFiX

GitHub:

https://github.com/Computable-Finance/CoFiX/blob/master/contracts/CoFiXController.sol#L282

function getLatestPrice(address token) internal returns (uint256 _ethAmount, uint256 _erc20Amount, uint256 _blockNum) {
uint256 _balanceBefore = address(this).balance;
address oracle = voteFactory.checkAddress("nest.v3.offerPrice");
uint256[] memory _rawPriceList = INest_3_OfferPrice(oracle).updateAndCheckPriceList{value: msg.value}(token, 1);
require(_rawPriceList.length == 3, "CoFiXCtrl: bad price len");
// validate T
uint256 _T = block.number.sub(_rawPriceList[2]).mul(timespan);
require(_T < 900, "CoFiXCtrl: oralce price outdated");
uint256 oracleFeeChange = msg.value.sub(_balanceBefore.sub(address(this).balance));
if (oracleFeeChange > 0) TransferHelper.safeTransfer以太坊(msg.sender, oracleFeeChange);
return (_rawPriceList[0], _rawPriceList[1], _rawPriceList[2]);
// return (K_EXPECTED_VALUE, _rawPriceList[0], _rawPriceList[1], _rawPriceList[2], KInfoMap[token][2]);
}

NEST 开辟者交换:https://t.me/nestdevs(收益支付、预言机代价挪用、前端接入等开辟交换)





本文标题:DeFi开辟者:怎样挪用NEST预言机代价数据  文章来自网络收集整理,文章观点不代表 【HI币圈导航 】观点,不构成投资建议!若有侵权或不实内容请联系客服处理,转载请标明出处!

快审站点推荐

发表评论

  • * 评论内容:
  •  

精彩评论

  • 无任何评论信息!
打赏本站
欢迎投稿
欢迎投稿
风险提示
交易平台 行情数据 区块查询 挖矿矿池 资讯门户 极客社区 基础公链 匿名隐私 跨链侧链 平台币类 区块链钱包 应用分发 区块链资讯 快注册自助提交
火币交易所