专栏名称: viiimaus
目录
相关文章推荐
51好读  ›  专栏  ›  viiimaus

NEST预言机-获取链上价格

viiimaus  · CSDN  ·  · 2020-11-09 18:16

正文

NEST预言机-获取链上价格

介绍

NEST预言机采用双边报价机制生成链上价格,质押双边资产来保证价格的准确性。是完全去中心化的链上价格生成机制。

白皮书: https://nestprotocol.org/doc/zhnestwhitepaper.pdf
github: https://github.com/NEST-Protocol

详细的介绍可以查看 https://nestprotocol.org/

尝试获取链上价格

了解机制

  1. NEST预言机以区块为单位生成价格,如果区块内没有价格,则使用最近的区块价格。
  2. 使用报价的方式生成区块价格,如果一个区块内有多笔报价,则加权平均。
  3. 每笔报价有25区块的验证时间(吃单),如果验证时间内没有被吃单则代表市场认可这笔报价,将会在报价区块后的25个区块价格生效。

“获取价格合约”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;
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

该方法限制了只有“报价合约”才可以调用,保证添加到价格合约中的价格数据的数据源正确。

输入参数 描述
ethAmount 报价ETH数量
tokenAmount 报价ERC20数量
endBlock 价格生效区块号
tokenAddress 报价ERC20地址
offerOwner 报价者地址
PriceInfo storage priceInfo = tokenInfo.priceInfoList[endBlock];
priceInfo.ethAmount = priceInfo.ethAmount.add(ethAmount);
priceInfo.erc20Amount = priceInfo.erc20Amount.add(tokenAmount);
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

这三行代码实现在同一个区块内加权平均。

修改价格

	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);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

同样限制了只有“报价合约”才有权限调用。只有在触发吃单操作后,才会修改对应生效区块中的价格,将”添加价格“时的报价数量按照”吃单“规模减掉。

输入参数 描述
ethAmount 吃单ETH数量
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);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
输入参数 描述
tokenAddress 查询价格的ERC20地址
输出参数 描述
ethAmount ETH数量
erc20Amount ERC20数量
blockNum 生效价格区块
require(checkUseNestPrice(address(msg.sender)));
  • 1
  • 1

检查是否有权限使用NEST价格。

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

获取对应Token的价格数据源。

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

解释一下while循环的判断,需要从最新的报价区块开始往后倒推找到当前已经生效并且没有被吃单的价格数据所在的区块号(checkBlock)。

require(checkBlock != 0);
  • 1
  • 1

这个判断个人猜测是为了防止有些token刚开始报价,还没有有效价格生成,又因为调用价格是要付费的。所以加了限制,如果没找到生效价格的区块号,交易直接失败。

		PriceInfo memory priceInfo = priceInfoList[checkBlock];
        address nToken = _tokenMapping.checkTokenMapping(tokenAddress);
        if (nToken == address(0x0)) {
            _abonus.switchToEth.value(_priceCost)(






请到「今天看啥」查看全文


推荐文章
真叫卢俊的地产观  ·  娱乐至死的美国体育产业
7 年前