nest3.0从架构解析到克隆四(NestOffer之Nest_3_MiningContract、Nest_3_OfferPrice)
我们之前介绍的是报价机NestOffer的核心部分Nest_3_OfferMain,我们在本节将继续介绍Nest_3_MiningContract与Nest_3_OfferPrice。
[返回总章](https://learnblockchain.cn/article/2125) 我们之前介绍的是报价机NestOffer的核心部分Nest_3_OfferMain,我们在本节将继续介绍Nest_3_MiningContract与Nest_3_OfferPrice。 1.Nest_3_OfferMain报价系统,调用挖矿合约Nest_3_MiningContract,调用Nest_3_OfferPrice报价系统。 2.Nest_3_MiningContract是报价机的辅助部分,主要是负责矿池存储和出矿逻辑。 3.Nest_3_OfferPrice则主要进行报价过程中的价格查询与调用。 我们将在下面进行更加详细的说明。 # Nest_3_MiningContract Nest_3_MiningContract较为简单,都是跟出块的产量有关。 ``` /** * @title Mining contract 挖矿合约 * @dev Mining pool + mining logic 矿池存储 + 出矿逻辑 */ contract Nest_3_MiningContract { using address_make_payable for address; using SafeMath for uint256; uint256 _blockAttenuation = 2400000; // Block decay time interval // 区块衰减间隔 uint256[10] _attenuationAmount; // Mining decay amount // 挖矿数量衰减 uint256 _afterMiningAmount = 40 ether; // Stable period mining amount // 平稳期出矿量 uint256 _firstBlockNum; // Starting mining block // 起始挖矿区块 uint256 _latestMining; // Latest offering block // 最新报价区块 Nest_3_VoteFactory _voteFactory; // Voting contract // 投票合约(这个需要先弄) ERC20 _nestContract; // NEST contract address // NEST 合约 address _offerFactoryAddress; // Offering contract address // 报价工厂合约地址 // Current block, current block mining amount //当前区块,当前块出矿量 event OreDrawingLog(uint256 nowBlock, uint256 blockAmount); /** * @dev Initialization method 初始化方法 * @param voteFactory voting contract address Current block, current block mining amount 做一个假的nest.v3.offerMain,然后就弄, */ constructor(address voteFactory) public { _voteFactory = Nest_3_VoteFactory(address(voteFactory)); _offerFactoryAddress = address(_voteFactory.checkAddress("nest.v3.offerMain")); _nestContract = ERC20(address(_voteFactory.checkAddress("nest"))); // Initiate mining parameters //初始化挖矿参数 _firstBlockNum = 6236588; _latestMining = block.number; uint256 blockAmount = 400 ether; for (uint256 i = 0; i < 10; i ++) { _attenuationAmount[i] = blockAmount; blockAmount = blockAmount.mul(8).div(10); } } /** * @dev Reset voting contract 重置投票合约 * @param voteFactory Voting contract address 投票合约地址 */ function changeMapping(address voteFactory) public onlyOwner { _voteFactory = Nest_3_VoteFactory(address(voteFactory)); _offerFactoryAddress = address(_voteFactory.checkAddress("nest.v3.offerMain")); _nestContract = ERC20(address(_voteFactory.checkAddress("nest"))); } /** * @dev Offering mining 报价出矿 * @return Current block mining amount 当前区块出矿量 */ function oreDrawing() public returns (uint256) { require(address(msg.sender) == _offerFactoryAddress, "No authority"); //这个说明,报价是由nest.v3.offerMain提出的 // Update mining amount list //更新出矿量列表 uint256 miningAmount = changeBlockAmountList(); //这个就是获得多少币的关键函数 // Transfer NEST if (_nestContract.balanceOf(address(this)) < miningAmount){ //这里balanceOf说的是这个智能合约地址里面有没有nest miningAmount = _nestContract.balanceOf(address(this)); } if (miningAmount > 0) { _nestContract.transfer(address(msg.sender), miningAmount); emit OreDrawingLog(block.number,miningAmount); } //如果里面的币够,就发送出去 return miningAmount; } /** * @dev Update mining amount list 更新出矿量列表 */ function changeBlockAmountList() private returns (uint256) { uint256 createBlock = _firstBlockNum;//6236588 uint256 recentlyUsedBlock = _latestMining;//初始化的时候,是以当时的block.number为时间点 uint256 attenuationPointNow = block.number.sub(createBlock).div(_blockAttenuation); //block.number-createBlock/_blockAttenuation,为衰减系数 uint256 miningAmount = 0; uint256 attenuation; if (attenuationPointNow > 9) { attenuation = _afterMiningAmount; } else { attenuation = _attenuationAmount[attenuationPointNow];//大概是400 } miningAmount = attenuation.mul(block.number.sub(recentlyUsedBlock));//400x(当前块数-初始化时的块数) _latestMining = block.number; return miningAmount; } /** * @dev Transfer all NEST 转移所有 NEST * @param target Transfer target address target 转移目标地址 */ function takeOutNest(address target) public onlyOwner { _nestContract.transfer(address(target),_nestContract.balanceOf(address(this))); } // Check block decay time interval //查看区块衰减间隔 function checkBlockAttenuation() public view returns(uint256) { return _blockAttenuation; } // Check latest offering block //查看最新报价区块 function checkLatestMining() public view returns(uint256) { return _latestMining; } // Check mining amount decay //查看挖矿数量衰减 function checkAttenuationAmount(uint256 num) public view returns(uint256) { return _attenuationAmount[num]; } // Check NEST balance //查看 NEST 余额 function checkNestBalance() public view returns(uint256) { return _nestContract.balanceOf(address(this)); } // Modify block decay time interval //修改区块衰减间隔 function changeBlockAttenuation(uint256 blockNum) public onlyOwner { require(blockNum > 0); _blockAttenuation = blockNum; } // Modify mining amount decay //修改挖矿数量衰减 function changeAttenuationAmount(uint256 firstAmount, uint256 top, uint256 bottom) public onlyOwner { uint256 blockAmount = firstAmount; for (uint256 i = 0; i < 10; i ++) { _attenuationAmount[i] = blockAmount; blockAmount = blockAmount.mul(top).div(bottom); } } // Administrator only modifier onlyOwner(){ require(_voteFactory.checkOwners(msg.sender), "No authority"); _; } } ``` # Nest_3_OfferPrice Nest_3_OfferPrice主要负责与价格相关的内容。 主要分定义部分,增加报价,和更新报价,之后剩下的内容都比较简单,就不说了。 ## 定义部分 ``` using SafeMath for uint256; using address_make_payable for address; using SafeERC20 for ERC20; Nest_3_VoteFactory _voteFactory; // Voting contract // 投票合约 ERC20 _nestToken; // NestToken Nest_NToken_TokenMapping _tokenMapping; // NToken mapping // NToken映射 Nest_3_OfferMain _offerMain; // Offering main contract // 报价工厂合约 Nest_3_Abonus _abonus; // Bonus pool // 分红池 address _nTokeOfferMain; // NToken offering main contract // NToken报价工厂合约 address _destructionAddress; // Destruction contract address // 销毁合约地址 address _nTokenAuction; // NToken auction contract address // NToken拍卖合约地址 struct PriceInfo { // Block price // 区块价格 uint256 ethAmount; // ETH 数量 // ETH amount uint256 erc20Amount; // ERC20 数量 // Erc20 amount uint256 frontBlock; // 上一个生效区块 // Last effective block address offerOwner; // 报价地址 // Offering address } struct TokenInfo { // token报价信息 // Token offer information mapping(uint256 => PriceInfo) priceInfoList; // 区块价格列表,区块号 => 区块价格 // Block price list, block number => block price uint256 latestOffer; // 最新生效区块 // Latest effective block uint256 priceCostLeast; // 价格 ETH 最少费用 // Minimum ETH cost for prices uint256 priceCostMost; // 价格 ETH 最多费用 // Maximum ETH cost for prices uint256 priceCostSingle; // 价格 ETH 单条数据费用 // ETH cost for single data uint256 priceCostUser; // 价格 ETH 费用用户比例 // User ratio of cost } uint256 destructionAmount = 10000 ether; // 调用价格销毁 NEST 数量 // Amount of NEST to destroy to call prices uint256 effectTime = 1 days; // 可以调用价格等待时间 // Waiting time to start calling prices mapping(address => TokenInfo) _tokenInfo; // token报价信息 // Token offer information mapping(address => bool) _blocklist; // 禁止名单 // Block list mapping(address => uint256) _addressEffect; // 调用价格地址生效时间 // Effective time of address to call prices mapping(address => bool) _offerMainMapping; // 报价合约映射 // Offering contract mapping // Real-time price token, ETH amount, erc20 amount // 实时价格 token, eth数量, erc20数量 event NowTokenPrice(address a, uint256 b, uint256 c); /** * @dev Initialization method 初始化方法 * @param voteFactory Voting contract address voteFactory 投票合约地址 */ constructor (address voteFactory) public { Nest_3_VoteFactory voteFactoryMap = Nest_3_VoteFactory(address(voteFactory)); _voteFactory = voteFactoryMap; _offerMain = Nest_3_OfferMain(address(voteFactoryMap.checkAddress("nest.v3.offerMain"))); _nTokeOfferMain = address(voteFactoryMap.checkAddress("nest.nToken.offerMain")); _abonus = Nest_3_Abonus(address(voteFactoryMap.checkAddress("nest.v3.abonus"))); _destructionAddress = address(voteFactoryMap.checkAddress("nest.v3.destruction")); _nestToken = ERC20(address(voteFactoryMap.checkAddress("nest"))); _tokenMapping = Nest_NToken_TokenMapping(address(voteFactoryMap.checkAddress("nest.nToken.tokenMapping"))); _nTokenAuction = address(voteFactoryMap.checkAddress("nest.nToken.tokenAuction")); _offerMainMapping[address(_offerMain)] = true; _offerMainMapping[address(_nTokeOfferMain)] = true; } ``` ## 增加报价 /** * @dev Modify voting contract 修改投票射合约 * @param voteFactory Voting contract address 投票合约地址 */ function changeMapping(address voteFactory) public onlyOwner { Nest_3_VoteFactory voteFactoryMap = Nest_3_VoteFactory(address(voteFactory)); _voteFactory = voteFactoryMap; _offerMain = Nest_3_OfferMain(address(voteFactoryMap.checkAddress("nest.v3.offerMain"))); _nTokeOfferMain = address(voteFactoryMap.checkAddress("nest.nToken.offerMain")); _abonus = Nest_3_Abonus(address(voteFactoryMap.checkAddress("nest.v3.abonus"))); _destructionAddress = address(voteFactoryMap.checkAddress("nest.v3.destruction")); _nestToken = ERC20(address(voteFactoryMap.checkAddress("nest"))); _tokenMapping = Nest_NToken_TokenMapping(address(voteFactoryMap.checkAddress("nest.nToken.tokenMapping"))); _nTokenAuction = address(voteFactoryMap.checkAddress("nest.nToken.tokenAuction")); _offerMainMapping[address(_offerMain)] = true; _offerMainMapping[address(_nTokeOfferMain)] = true; } /** * @dev Initialize token price charge parameters 初始化 token 价格收费参数 * @param tokenAddress Token address tokenAddress token地址 */ function addPriceCost(address tokenAddress) public { require(msg.sender == _nTokenAuction); TokenInfo storage tokenInfo = _tokenInfo[tokenAddress]; tokenInfo.priceCostLeast = 0.001 ether; tokenInfo.priceCostMost = 0.01 ether; tokenInfo.priceCostSingle = 0.0001 ether; tokenInfo.priceCostUser = 2; } /** * @dev Add price 增加价格 * @param ethAmount ETH amount eth数量 * @param tokenAmount Erc20 amount erc20数量 * @param endBlock Effective price block 生效价格区块 * @param tokenAddress Erc20 address erc20地址 * @param offerOwner Offering address 报价地址 */ 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); priceInfo.offerOwner = offerOwner; if (endBlock != tokenInfo.latestOffer) { // If different block offer // 不同区块报价 priceInfo.frontBlock = tokenInfo.latestOffer; tokenInfo.latestOffer = endBlock; } } /** * @dev Price modification in taker orders 吃单修改价格 * @param ethAmount ETH amount * @param tokenAmount Erc20 amount * @param tokenAddress Token address * @param endBlock Block of effective price 生效价格区块 */ 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); } ## 更新报价 ``` /** * @dev Update and check the latest price 更新并查看最新价格 * @param tokenAddress Token address * @return ethAmount ETH amount * @return erc20Amount Erc20 amount * @return blockNum Price block */ function updateAndCheckPriceNow(address tokenAddress) public payable returns(uint256 ethAmount, uint256 erc20Amount, uint256 blockNum) { require(checkUseNestPrice(address(msg.sender))); TokenInfo storage tokenInfo = _tokenInfo[tokenAddress]; uint256 checkBlock = tokenInfo.latestOffer; while(checkBlock > 0 && (checkBlock >= block.number || tokenInfo.priceInfoList[checkBlock].ethAmount == 0)) { checkBlock = tokenInfo.priceInfoList[checkBlock].frontBlock; } require(checkBlock != 0); PriceInfo memory priceInfo = tokenInfo.priceInfoList[checkBlock]; address nToken = _tokenMapping.checkTokenMapping(tokenAddress); if (nToken == address(0x0)) { _abonus.switchToEth.value(tokenInfo.priceCostLeast.sub(tokenInfo.priceCostLeast.mul(tokenInfo.priceCostUser).div(10)))(address(_nestToken)); } else { _abonus.switchToEth.value(tokenInfo.priceCostLeast.sub(tokenInfo.priceCostLeast.mul(tokenInfo.priceCostUser).div(10)))(address(nToken)); } repayEth(priceInfo.offerOwner, tokenInfo.priceCostLeast.mul(tokenInfo.priceCostUser).div(10)); repayEth(address(msg.sender), msg.value.sub(tokenInfo.priceCostLeast)); emit NowTokenPrice(tokenAddress,priceInfo.ethAmount, priceInfo.erc20Amount); return (priceInfo.ethAmount,priceInfo.erc20Amount, checkBlock); } /** * @dev Update and check the latest price-internal use 更新并查看最新价格-内部使用 * @param tokenAddress Token address * @return ethAmount ETH amount * @return erc20Amount Erc20 amount */ function updateAndCheckPricePrivate(address tokenAddress) public view onlyOfferMain returns(uint256 ethAmount, uint256 erc20Amount) { TokenInfo storage tokenInfo = _tokenInfo[tokenAddress]; uint256 checkBlock = tokenInfo.latestOffer; while(checkBlock > 0 && (checkBlock >= block.number || tokenInfo.priceInfoList[checkBlock].ethAmount == 0)) { checkBlock = tokenInfo.priceInfoList[checkBlock].frontBlock; } if (checkBlock == 0) { return (0,0); } PriceInfo memory priceInfo = tokenInfo.priceInfoList[checkBlock]; return (priceInfo.ethAmount,priceInfo.erc20Amount); } /** * @dev Update and check the effective price list 更新并查看生效价格列表 * @param tokenAddress Token address * @param num Number of prices to check * @return uint256[] price list */ function updateAndCheckPriceList(address tokenAddress, uint256 num) public payable returns (uint256[] memory) { require(checkUseNestPrice(address(msg.sender))); TokenInfo storage tokenInfo = _tokenInfo[tokenAddress]; // Charge uint256 thisPay = tokenInfo.priceCostSingle.mul(num); if (thisPay < tokenInfo.priceCostLeast) { thisPay=tokenInfo.priceCostLeast; } else if (thisPay > tokenInfo.priceCostMost) { thisPay = tokenInfo.priceCostMost; } // Extract data uint256 length = num.mul(3); uint256 index = 0; uint256[] memory data = new uint256[](length); address latestOfferOwner = address(0x0); uint256 checkBlock = tokenInfo.latestOffer; while(index < length && checkBlock > 0){ if (checkBlock < block.number && tokenInfo.priceInfoList[checkBlock].ethAmount != 0) { // Add return data data[index++] = tokenInfo.priceInfoList[checkBlock].ethAmount; data[index++] = tokenInfo.priceInfoList[checkBlock].erc20Amount; data[index++] = checkBlock; if (latestOfferOwner == address(0x0)) { latestOfferOwner = tokenInfo.priceInfoList[checkBlock].offerOwner; } } checkBlock = tokenInfo.priceInfoList[checkBlock].frontBlock; } require(latestOfferOwner != address(0x0)); require(length == data.length); // Allocation address nToken = _tokenMapping.checkTokenMapping(tokenAddress); if (nToken == address(0x0)) { _abonus.switchToEth.value(thisPay.sub(thisPay.mul(tokenInfo.priceCostUser).div(10)))(address(_nestToken)); } else { _abonus.switchToEth.value(thisPay.sub(thisPay.mul(tokenInfo.priceCostUser).div(10)))(address(nToken)); } repayEth(latestOfferOwner, thisPay.mul(tokenInfo.priceCostUser).div(10)); repayEth(address(msg.sender), msg.value.sub(thisPay)); return data; } // Activate the price checking function // 激活使用价格合约 function activation() public { _nestToken.safeTransferFrom(address(msg.sender), _destructionAddress, destructionAmount); _addressEffect[address(msg.sender)] = now.add(effectTime); } ```
返回总章 我们之前介绍的是报价机NestOffer的核心部分Nest_3_OfferMain,我们在本节将继续介绍Nest_3_MiningContract与Nest_3_OfferPrice。 1.Nest_3_OfferMain报价系统,调用挖矿合约Nest_3_MiningContract,调用Nest_3_OfferPrice报价系统。 2.Nest_3_MiningContract是报价机的辅助部分,主要是负责矿池存储和出矿逻辑。 3.Nest_3_OfferPrice则主要进行报价过程中的价格查询与调用。 我们将在下面进行更加详细的说明。
Nest_3_MiningContract
Nest_3_MiningContract较为简单,都是跟出块的产量有关。
/**
* @title Mining contract
挖矿合约
* @dev Mining pool + mining logic
矿池存储 + 出矿逻辑
*/
contract Nest_3_MiningContract {
using address_make_payable for address;
using SafeMath for uint256;
uint256 _blockAttenuation = 2400000; // Block decay time interval
// 区块衰减间隔
uint256[10] _attenuationAmount; // Mining decay amount
// 挖矿数量衰减
uint256 _afterMiningAmount = 40 ether; // Stable period mining amount
// 平稳期出矿量
uint256 _firstBlockNum; // Starting mining block
// 起始挖矿区块
uint256 _latestMining; // Latest offering block
// 最新报价区块
Nest_3_VoteFactory _voteFactory; // Voting contract
// 投票合约(这个需要先弄)
ERC20 _nestContract; // NEST contract address
// NEST 合约
address _offerFactoryAddress; // Offering contract address
// 报价工厂合约地址
// Current block, current block mining amount
//当前区块,当前块出矿量
event OreDrawingLog(uint256 nowBlock, uint256 blockAmount);
/**
* @dev Initialization method
初始化方法
* @param voteFactory voting contract address
Current block, current block mining amount
做一个假的nest.v3.offerMain,然后就弄,
*/
constructor(address voteFactory) public {
_voteFactory = Nest_3_VoteFactory(address(voteFactory));
_offerFactoryAddress = address(_voteFactory.checkAddress("nest.v3.offerMain"));
_nestContract = ERC20(address(_voteFactory.checkAddress("nest")));
// Initiate mining parameters
//初始化挖矿参数
_firstBlockNum = 6236588;
_latestMining = block.number;
uint256 blockAmount = 400 ether;
for (uint256 i = 0; i < 10; i ++) {
_attenuationAmount[i] = blockAmount;
blockAmount = blockAmount.mul(8).div(10);
}
}
/**
* @dev Reset voting contract
重置投票合约
* @param voteFactory Voting contract address
投票合约地址
*/
function changeMapping(address voteFactory) public onlyOwner {
_voteFactory = Nest_3_VoteFactory(address(voteFactory));
_offerFactoryAddress = address(_voteFactory.checkAddress("nest.v3.offerMain"));
_nestContract = ERC20(address(_voteFactory.checkAddress("nest")));
}
/**
* @dev Offering mining
报价出矿
* @return Current block mining amount
当前区块出矿量
*/
function oreDrawing() public returns (uint256) {
require(address(msg.sender) == _offerFactoryAddress, "No authority");
//这个说明,报价是由nest.v3.offerMain提出的
// Update mining amount list
//更新出矿量列表
uint256 miningAmount = changeBlockAmountList();
//这个就是获得多少币的关键函数
// Transfer NEST
if (_nestContract.balanceOf(address(this)) < miningAmount){
//这里balanceOf说的是这个智能合约地址里面有没有nest
miningAmount = _nestContract.balanceOf(address(this));
}
if (miningAmount > 0) {
_nestContract.transfer(address(msg.sender), miningAmount);
emit OreDrawingLog(block.number,miningAmount);
}
//如果里面的币够,就发送出去
return miningAmount;
}
/**
* @dev Update mining amount list
更新出矿量列表
*/
function changeBlockAmountList() private returns (uint256) {
uint256 createBlock = _firstBlockNum;//6236588
uint256 recentlyUsedBlock = _latestMining;//初始化的时候,是以当时的block.number为时间点
uint256 attenuationPointNow = block.number.sub(createBlock).div(_blockAttenuation);
//block.number-createBlock/_blockAttenuation,为衰减系数
uint256 miningAmount = 0;
uint256 attenuation;
if (attenuationPointNow > 9) {
attenuation = _afterMiningAmount;
} else {
attenuation = _attenuationAmount[attenuationPointNow];//大概是400
}
miningAmount = attenuation.mul(block.number.sub(recentlyUsedBlock));//400x(当前块数-初始化时的块数)
_latestMining = block.number;
return miningAmount;
}
/**
* @dev Transfer all NEST
转移所有 NEST
* @param target Transfer target address
target 转移目标地址
*/
function takeOutNest(address target) public onlyOwner {
_nestContract.transfer(address(target),_nestContract.balanceOf(address(this)));
}
// Check block decay time interval
//查看区块衰减间隔
function checkBlockAttenuation() public view returns(uint256) {
return _blockAttenuation;
}
// Check latest offering block
//查看最新报价区块
function checkLatestMining() public view returns(uint256) {
return _latestMining;
}
// Check mining amount decay
//查看挖矿数量衰减
function checkAttenuationAmount(uint256 num) public view returns(uint256) {
return _attenuationAmount[num];
}
// Check NEST balance
//查看 NEST 余额
function checkNestBalance() public view returns(uint256) {
return _nestContract.balanceOf(address(this));
}
// Modify block decay time interval
//修改区块衰减间隔
function changeBlockAttenuation(uint256 blockNum) public onlyOwner {
require(blockNum > 0);
_blockAttenuation = blockNum;
}
// Modify mining amount decay
//修改挖矿数量衰减
function changeAttenuationAmount(uint256 firstAmount, uint256 top, uint256 bottom) public onlyOwner {
uint256 blockAmount = firstAmount;
for (uint256 i = 0; i < 10; i ++) {
_attenuationAmount[i] = blockAmount;
blockAmount = blockAmount.mul(top).div(bottom);
}
}
// Administrator only
modifier onlyOwner(){
require(_voteFactory.checkOwners(msg.sender), "No authority");
_;
}
}
Nest_3_OfferPrice
Nest_3_OfferPrice主要负责与价格相关的内容。 主要分定义部分,增加报价,和更新报价,之后剩下的内容都比较简单,就不说了。
定义部分
using SafeMath for uint256;
using address_make_payable for address;
using SafeERC20 for ERC20;
Nest_3_VoteFactory _voteFactory; // Voting contract
// 投票合约
ERC20 _nestToken; // NestToken
Nest_NToken_TokenMapping _tokenMapping; // NToken mapping
// NToken映射
Nest_3_OfferMain _offerMain; // Offering main contract
// 报价工厂合约
Nest_3_Abonus _abonus; // Bonus pool
// 分红池
address _nTokeOfferMain; // NToken offering main contract
// NToken报价工厂合约
address _destructionAddress; // Destruction contract address
// 销毁合约地址
address _nTokenAuction; // NToken auction contract address
// NToken拍卖合约地址
struct PriceInfo { // Block price
// 区块价格
uint256 ethAmount; // ETH 数量 // ETH amount
uint256 erc20Amount; // ERC20 数量 // Erc20 amount
uint256 frontBlock; // 上一个生效区块 // Last effective block
address offerOwner; // 报价地址 // Offering address
}
struct TokenInfo { // token报价信息 // Token offer information
mapping(uint256 => PriceInfo) priceInfoList; // 区块价格列表,区块号 => 区块价格 // Block price list, block number => block price
uint256 latestOffer; // 最新生效区块 // Latest effective block
uint256 priceCostLeast; // 价格 ETH 最少费用 // Minimum ETH cost for prices
uint256 priceCostMost; // 价格 ETH 最多费用 // Maximum ETH cost for prices
uint256 priceCostSingle; // 价格 ETH 单条数据费用 // ETH cost for single data
uint256 priceCostUser; // 价格 ETH 费用用户比例 // User ratio of cost
}
uint256 destructionAmount = 10000 ether; // 调用价格销毁 NEST 数量 // Amount of NEST to destroy to call prices
uint256 effectTime = 1 days; // 可以调用价格等待时间 // Waiting time to start calling prices
mapping(address => TokenInfo) _tokenInfo; // token报价信息 // Token offer information
mapping(address => bool) _blocklist; // 禁止名单 // Block list
mapping(address => uint256) _addressEffect; // 调用价格地址生效时间 // Effective time of address to call prices
mapping(address => bool) _offerMainMapping; // 报价合约映射 // Offering contract mapping
// Real-time price token, ETH amount, erc20 amount
// 实时价格 token, eth数量, erc20数量
event NowTokenPrice(address a, uint256 b, uint256 c);
/**
* @dev Initialization method
初始化方法
* @param voteFactory Voting contract address
voteFactory 投票合约地址
*/
constructor (address voteFactory) public {
Nest_3_VoteFactory voteFactoryMap = Nest_3_VoteFactory(address(voteFactory));
_voteFactory = voteFactoryMap;
_offerMain = Nest_3_OfferMain(address(voteFactoryMap.checkAddress("nest.v3.offerMain")));
_nTokeOfferMain = address(voteFactoryMap.checkAddress("nest.nToken.offerMain"));
_abonus = Nest_3_Abonus(address(voteFactoryMap.checkAddress("nest.v3.abonus")));
_destructionAddress = address(voteFactoryMap.checkAddress("nest.v3.destruction"));
_nestToken = ERC20(address(voteFactoryMap.checkAddress("nest")));
_tokenMapping = Nest_NToken_TokenMapping(address(voteFactoryMap.checkAddress("nest.nToken.tokenMapping")));
_nTokenAuction = address(voteFactoryMap.checkAddress("nest.nToken.tokenAuction"));
_offerMainMapping[address(_offerMain)] = true;
_offerMainMapping[address(_nTokeOfferMain)] = true;
}
增加报价
/**
* @dev Modify voting contract
修改投票射合约
* @param voteFactory Voting contract address
投票合约地址
*/
function changeMapping(address voteFactory) public onlyOwner {
Nest_3_VoteFactory voteFactoryMap = Nest_3_VoteFactory(address(voteFactory));
_voteFactory = voteFactoryMap;
_offerMain = Nest_3_OfferMain(address(voteFactoryMap.checkAddress("nest.v3.offerMain")));
_nTokeOfferMain = address(voteFactoryMap.checkAddress("nest.nToken.offerMain"));
_abonus = Nest_3_Abonus(address(voteFactoryMap.checkAddress("nest.v3.abonus")));
_destructionAddress = address(voteFactoryMap.checkAddress("nest.v3.destruction"));
_nestToken = ERC20(address(voteFactoryMap.checkAddress("nest")));
_tokenMapping = Nest_NToken_TokenMapping(address(voteFactoryMap.checkAddress("nest.nToken.tokenMapping")));
_nTokenAuction = address(voteFactoryMap.checkAddress("nest.nToken.tokenAuction"));
_offerMainMapping[address(_offerMain)] = true;
_offerMainMapping[address(_nTokeOfferMain)] = true;
}
/**
* @dev Initialize token price charge parameters
初始化 token 价格收费参数
* @param tokenAddress Token address
tokenAddress token地址
*/
function addPriceCost(address tokenAddress) public {
require(msg.sender == _nTokenAuction);
TokenInfo storage tokenInfo = _tokenInfo[tokenAddress];
tokenInfo.priceCostLeast = 0.001 ether;
tokenInfo.priceCostMost = 0.01 ether;
tokenInfo.priceCostSingle = 0.0001 ether;
tokenInfo.priceCostUser = 2;
}
/**
* @dev Add price
增加价格
* @param ethAmount ETH amount
eth数量
* @param tokenAmount Erc20 amount
erc20数量
* @param endBlock Effective price block
生效价格区块
* @param tokenAddress Erc20 address
erc20地址
* @param offerOwner Offering address
报价地址
*/
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);
priceInfo.offerOwner = offerOwner;
if (endBlock != tokenInfo.latestOffer) {
// If different block offer
// 不同区块报价
priceInfo.frontBlock = tokenInfo.latestOffer;
tokenInfo.latestOffer = endBlock;
}
}
/**
* @dev Price modification in taker orders
吃单修改价格
* @param ethAmount ETH amount
* @param tokenAmount Erc20 amount
* @param tokenAddress Token address
* @param endBlock Block of effective price
生效价格区块
*/
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);
}
更新报价
/**
* @dev Update and check the latest price
更新并查看最新价格
* @param tokenAddress Token address
* @return ethAmount ETH amount
* @return erc20Amount Erc20 amount
* @return blockNum Price block
*/
function updateAndCheckPriceNow(address tokenAddress) public payable returns(uint256 ethAmount, uint256 erc20Amount, uint256 blockNum) {
require(checkUseNestPrice(address(msg.sender)));
TokenInfo storage tokenInfo = _tokenInfo[tokenAddress];
uint256 checkBlock = tokenInfo.latestOffer;
while(checkBlock > 0 && (checkBlock >= block.number || tokenInfo.priceInfoList[checkBlock].ethAmount == 0)) {
checkBlock = tokenInfo.priceInfoList[checkBlock].frontBlock;
}
require(checkBlock != 0);
PriceInfo memory priceInfo = tokenInfo.priceInfoList[checkBlock];
address nToken = _tokenMapping.checkTokenMapping(tokenAddress);
if (nToken == address(0x0)) {
_abonus.switchToEth.value(tokenInfo.priceCostLeast.sub(tokenInfo.priceCostLeast.mul(tokenInfo.priceCostUser).div(10)))(address(_nestToken));
} else {
_abonus.switchToEth.value(tokenInfo.priceCostLeast.sub(tokenInfo.priceCostLeast.mul(tokenInfo.priceCostUser).div(10)))(address(nToken));
}
repayEth(priceInfo.offerOwner, tokenInfo.priceCostLeast.mul(tokenInfo.priceCostUser).div(10));
repayEth(address(msg.sender), msg.value.sub(tokenInfo.priceCostLeast));
emit NowTokenPrice(tokenAddress,priceInfo.ethAmount, priceInfo.erc20Amount);
return (priceInfo.ethAmount,priceInfo.erc20Amount, checkBlock);
}
/**
* @dev Update and check the latest price-internal use
更新并查看最新价格-内部使用
* @param tokenAddress Token address
* @return ethAmount ETH amount
* @return erc20Amount Erc20 amount
*/
function updateAndCheckPricePrivate(address tokenAddress) public view onlyOfferMain returns(uint256 ethAmount, uint256 erc20Amount) {
TokenInfo storage tokenInfo = _tokenInfo[tokenAddress];
uint256 checkBlock = tokenInfo.latestOffer;
while(checkBlock > 0 && (checkBlock >= block.number || tokenInfo.priceInfoList[checkBlock].ethAmount == 0)) {
checkBlock = tokenInfo.priceInfoList[checkBlock].frontBlock;
}
if (checkBlock == 0) {
return (0,0);
}
PriceInfo memory priceInfo = tokenInfo.priceInfoList[checkBlock];
return (priceInfo.ethAmount,priceInfo.erc20Amount);
}
/**
* @dev Update and check the effective price list
更新并查看生效价格列表
* @param tokenAddress Token address
* @param num Number of prices to check
* @return uint256[] price list
*/
function updateAndCheckPriceList(address tokenAddress, uint256 num) public payable returns (uint256[] memory) {
require(checkUseNestPrice(address(msg.sender)));
TokenInfo storage tokenInfo = _tokenInfo[tokenAddress];
// Charge
uint256 thisPay = tokenInfo.priceCostSingle.mul(num);
if (thisPay < tokenInfo.priceCostLeast) {
thisPay=tokenInfo.priceCostLeast;
} else if (thisPay > tokenInfo.priceCostMost) {
thisPay = tokenInfo.priceCostMost;
}
// Extract data
uint256 length = num.mul(3);
uint256 index = 0;
uint256[] memory data = new uint256[](length);
address latestOfferOwner = address(0x0);
uint256 checkBlock = tokenInfo.latestOffer;
while(index < length && checkBlock > 0){
if (checkBlock < block.number && tokenInfo.priceInfoList[checkBlock].ethAmount != 0) {
// Add return data
data[index++] = tokenInfo.priceInfoList[checkBlock].ethAmount;
data[index++] = tokenInfo.priceInfoList[checkBlock].erc20Amount;
data[index++] = checkBlock;
if (latestOfferOwner == address(0x0)) {
latestOfferOwner = tokenInfo.priceInfoList[checkBlock].offerOwner;
}
}
checkBlock = tokenInfo.priceInfoList[checkBlock].frontBlock;
}
require(latestOfferOwner != address(0x0));
require(length == data.length);
// Allocation
address nToken = _tokenMapping.checkTokenMapping(tokenAddress);
if (nToken == address(0x0)) {
_abonus.switchToEth.value(thisPay.sub(thisPay.mul(tokenInfo.priceCostUser).div(10)))(address(_nestToken));
} else {
_abonus.switchToEth.value(thisPay.sub(thisPay.mul(tokenInfo.priceCostUser).div(10)))(address(nToken));
}
repayEth(latestOfferOwner, thisPay.mul(tokenInfo.priceCostUser).div(10));
repayEth(address(msg.sender), msg.value.sub(thisPay));
return data;
}
// Activate the price checking function
// 激活使用价格合约
function activation() public {
_nestToken.safeTransferFrom(address(msg.sender), _destructionAddress, destructionAmount);
_addressEffect[address(msg.sender)] = now.add(effectTime);
}
区块链技术网。
- 发表于 2021-02-02 09:41
- 阅读 ( 521 )
- 学分 ( 1 )
- 分类:NEST
评论