Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
NestMiningV1
Compiler Version
v0.6.12+commit.27d51765
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;
import "./libminingv1/MiningV1Data.sol";
import "./libminingv1/MiningV1Calc.sol";
import "./libminingv1/MiningV1Op.sol";
import "./lib/SafeMath.sol";
import "./lib/SafeERC20.sol";
import './lib/TransferHelper.sol';
import "./lib/ABDKMath64x64.sol";
import "./iface/INestPool.sol";
import "./iface/INestStaking.sol";
import "./iface/INTokenLegacy.sol";
import "./iface/INestMining.sol";
import "./iface/INestDAO.sol";
// import "hardhat/console.sol";
/// @title NestMiningV1
/// @author Inf Loop - <inf-loop@nestprotocol.org>
/// @author Paradox - <paradox@nestprotocol.org>
contract NestMiningV1 {
using SafeMath for uint256;
using MiningV1Calc for MiningV1Data.State;
using MiningV1Op for MiningV1Data.State;
/* ========== STATE VARIABLES ============== */
uint8 public flag; // 0: | 1: | 2: | 3:
uint64 public version;
uint8 private _entrant_state;
uint176 private _reserved;
MiningV1Data.State state;
// NOTE: _NOT_ENTERED is set to ZERO such that it needn't constructor
uint8 private constant _NOT_ENTERED = 0;
uint8 private constant _ENTERED = 1;
uint8 constant MINING_FLAG_UNINITIALIZED = 0;
uint8 constant MINING_FLAG_SETUP_NEEDED = 1;
uint8 constant MINING_FLAG_UPGRADE_NEEDED = 2;
uint8 constant MINING_FLAG_ACTIVE = 3;
/* ========== ADDRESSES ============== */
address public governance;
address private C_NestPool;
/* ========== STRUCTURES ============== */
struct Params {
uint8 miningEthUnit;
uint32 nestStakedNum1k;
uint8 biteFeeRate;
uint8 miningFeeRate;
uint8 priceDurationBlock;
uint8 maxBiteNestedLevel;
uint8 biteInflateFactor;
uint8 biteNestInflateFactor;
}
/* ========== CONSTRUCTOR ========== */
constructor() public { }
function initialize(address NestPool) external
{
// check flag
require(flag == MINING_FLAG_UNINITIALIZED, "Nest:Mine:!flag");
uint256 amount = MiningV1Data.MINING_NEST_YIELD_PER_BLOCK_BASE;
for (uint i =0; i < 10; i++) {
state._mining_nest_yield_per_block_amount[i] = amount;
amount = amount.mul(MiningV1Data.MINING_NEST_YIELD_CUTBACK_RATE).div(100);
}
amount = MiningV1Data.MINING_NTOKEN_YIELD_PER_BLOCK_BASE;
for (uint i =0; i < 10; i++) {
state._mining_ntoken_yield_per_block_amount[i] = amount;
amount = amount.mul(MiningV1Data.MINING_NTOKEN_YIELD_CUTBACK_RATE).div(100);
}
// set a temporary governance
governance = msg.sender;
// increase version number
version = uint64(block.number);
// set the address of NestPool
C_NestPool = NestPool;
// set flag
flag = MINING_FLAG_SETUP_NEEDED;
}
/// @dev This function can only be called once immediately right after deployment
function setup(
uint32 genesisBlockNumber,
uint128 latestMiningHeight,
uint128 minedNestTotalAmount,
Params calldata initParams
) external onlyGovernance
{
// check flag
require(flag == MINING_FLAG_SETUP_NEEDED, "Nest:Mine:!flag");
// set system-wide parameters
state.miningEthUnit = initParams.miningEthUnit;
state.nestStakedNum1k = initParams.nestStakedNum1k;
state.biteFeeRate = initParams.biteFeeRate; // 0.1%
state.miningFeeRate = initParams.miningFeeRate; // 0.1% on testnet
state.priceDurationBlock = initParams.priceDurationBlock; // 5 on testnet
state.maxBiteNestedLevel = initParams.maxBiteNestedLevel;
state.biteInflateFactor = initParams.biteInflateFactor; // 1 on testnet
state.biteNestInflateFactor = initParams.biteNestInflateFactor; // 1 on testnet
state.latestMiningHeight = latestMiningHeight;
state.minedNestAmount = minedNestTotalAmount;
// genesisBlock = 6236588 on mainnet
state.genesisBlock = genesisBlockNumber;
// increase version number
version = uint64(block.number);
// set flag
flag = MINING_FLAG_UPGRADE_NEEDED;
}
/// @dev The function will be kicking off Nest Protocol v3.5.
/// After upgrading, `post/post2()` are ready to be invoked.
/// Before that, `post2Only4Upgrade()` is used to do posting.
/// The purpose is to limit post2Only4Upgrade() to run
function upgrade() external onlyGovernance
{
require(flag == MINING_FLAG_UPGRADE_NEEDED, "Nest:Mine:!flag");
flag = MINING_FLAG_ACTIVE;
}
/// @notice Write the block number as a version number
/// @dev It shall be invoked *manually* whenever the contract is upgraded(behind proxy)
function incVersion() external onlyGovernance
{
version = uint64(block.number);
}
receive() external payable { }
/* ========== MODIFIERS ========== */
function _onlyGovernance() private view
{
require(msg.sender == governance, "Nest:Mine:!GOV");
}
modifier onlyGovernance()
{
_onlyGovernance();
_;
}
function _noContract() private view {
require(address(msg.sender) == address(tx.origin), "Nest:Mine:contract!");
}
modifier noContract()
{
_noContract();
_;
}
modifier noContractExcept(address _contract)
{
require(address(msg.sender) == address(tx.origin) || address(msg.sender) == _contract, "Nest:Mine:contract!");
_;
}
modifier onlyGovOrBy(address _contract)
{
require(msg.sender == governance || msg.sender == _contract, "Nest:Mine:!sender");
_;
}
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_entrant_state != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_entrant_state = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_entrant_state = _NOT_ENTERED;
}
modifier onlyByNestOrNoContract()
{
require(address(msg.sender) == address(tx.origin)
|| msg.sender == state.C_NestDAO
|| msg.sender == state.C_NestStaking
|| msg.sender == state.C_NNRewardPool
|| msg.sender == state.C_NestQuery, "Nest:Mine:!Auth");
_;
}
/* ========== GOVERNANCE ========== */
/// @dev Load real governance from NestPool, invalidate the temporary
function loadGovernance() external
{
governance = INestPool(C_NestPool).governance();
}
function loadContracts() external onlyGovOrBy(C_NestPool)
{
state.C_NestPool = C_NestPool;
state.C_NestToken = INestPool(state.C_NestPool).addrOfNestToken();
state.C_NestStaking = INestPool(state.C_NestPool).addrOfNestStaking();
state.C_NestQuery = INestPool(state.C_NestPool).addrOfNestQuery();
state.C_NNRewardPool = INestPool(state.C_NestPool).addrOfNNRewardPool();
state.C_NestDAO = INestPool(state.C_NestPool).addrOfNestDAO();
}
function setParams(Params calldata newParams) external
onlyGovernance
{
state.miningEthUnit = newParams.miningEthUnit;
state.nestStakedNum1k = newParams.nestStakedNum1k;
state.biteFeeRate = newParams.biteFeeRate;
state.miningFeeRate = newParams.miningFeeRate;
state.priceDurationBlock = newParams.priceDurationBlock;
state.maxBiteNestedLevel = newParams.maxBiteNestedLevel;
state.biteInflateFactor = newParams.biteInflateFactor;
state.biteNestInflateFactor = newParams.biteNestInflateFactor;
emit MiningV1Data.SetParams(state.miningEthUnit, state.nestStakedNum1k, state.biteFeeRate,
state.miningFeeRate, state.priceDurationBlock, state.maxBiteNestedLevel,
state.biteInflateFactor, state.biteNestInflateFactor);
}
/// @dev only be used when upgrading 3.0 to 3.5
/// @dev when the upgrade is complete, this function is disabled
function setParams1(
uint128 latestMiningHeight,
uint128 minedNestTotalAmount
) external onlyGovernance
{
require(flag == MINING_FLAG_UPGRADE_NEEDED, "Nest:Mine:!flag");
state.latestMiningHeight = latestMiningHeight;
state.minedNestAmount = minedNestTotalAmount;
}
/* ========== HELPERS ========== */
function addrOfGovernance() view external
returns (address)
{
return governance;
}
function parameters() view external
returns (Params memory params)
{
params.miningEthUnit = state.miningEthUnit;
params.nestStakedNum1k = state.nestStakedNum1k;
params.biteFeeRate = state.biteFeeRate;
params.miningFeeRate = state.miningFeeRate;
params.priceDurationBlock = state.priceDurationBlock;
params.maxBiteNestedLevel = state.maxBiteNestedLevel;
params.biteInflateFactor = state.biteInflateFactor;
params.biteNestInflateFactor = state.biteNestInflateFactor;
}
/* ========== POST/CLOSE Price Sheets ========== */
/// @notice Post a price sheet for TOKEN
/// @dev It is for TOKEN (except USDT and NTOKENs) whose NTOKEN has a total supply below a threshold (e.g. 5,000,000 * 1e18)
/// @param token The address of TOKEN contract
/// @param ethNum The numbers of ethers to post sheets
/// @param tokenAmountPerEth The price of TOKEN
function post(
address token,
uint256 ethNum,
uint256 tokenAmountPerEth
)
external
payable
noContract
{
// check parameters
require(ethNum == state.miningEthUnit, "Nest:Mine:!(ethNum)");
require(tokenAmountPerEth > 0, "Nest:Mine:!(price)");
INestPool _C_NestPool = INestPool(state.C_NestPool);
address _ntoken = _C_NestPool.getNTokenFromToken(token);
require(_ntoken != address(0) && _ntoken != address(state.C_NestToken) && token != _ntoken, "Nest:Mine:!(ntoken)");
// check if the totalsupply of ntoken is less than MINING_NTOKEN_NON_DUAL_POST_THRESHOLD, otherwise use post2()
require(INToken(_ntoken).totalSupply() < MiningV1Data.MINING_NTOKEN_NON_DUAL_POST_THRESHOLD, "Nest:Mine:!ntoken");
// calculate eth fee
// NOTE: fee = ethAmount * (feeRate * 1/10k)
uint256 _ethFee = ethNum.mul(state.miningFeeRate).mul(1e18).div(10_000);
{ // settle ethers and tokens
// save the changes into miner's virtual account
if (msg.value.sub(_ethFee) > 0) {
_C_NestPool.depositEth{value:msg.value.sub(_ethFee)}(address(msg.sender));
}
// load addresses
INestStaking _C_NestStaking = INestStaking(state.C_NestStaking);
INestDAO _C_NestDAO = INestDAO(state.C_NestDAO);
// 60% fee => NestStaking
_C_NestStaking.addETHReward{value:_ethFee.mul(MiningV1Data.MINING_NTOKEN_FEE_DIVIDEND_RATE).div(100)}(_ntoken);
// 20% fee => NestDAO[NTOKEN]
_C_NestDAO.addETHReward{value:_ethFee.mul(MiningV1Data.MINING_NTOKEN_FEE_DAO_RATE).div(100)}(_ntoken);
// 20% fee => NestDAO[NEST]
_C_NestDAO.addETHReward{value:_ethFee.mul(MiningV1Data.MINING_NTOKEN_FEE_NEST_DAO_RATE).div(100)}(address(state.C_NestToken));
// freeze eths and tokens inside NestPool
_C_NestPool.freezeEthAndToken(msg.sender, ethNum.mul(1 ether),
token, tokenAmountPerEth.mul(ethNum));
_C_NestPool.freezeNest(msg.sender, uint256(state.nestStakedNum1k).mul(1000 * 1e18));
}
{
MiningV1Data.PriceSheet[] storage _sheetToken = state.priceSheetList[token];
// append a new price sheet
_sheetToken.push(MiningV1Data.PriceSheet(
uint160(msg.sender), // miner
uint32(block.number), // atHeight
uint32(ethNum), // ethNum
uint32(ethNum), // remainNum
uint8(0), // level
uint8(MiningV1Data.PRICESHEET_TYPE_TOKEN), // typ
uint8(MiningV1Data.PRICESHEET_STATE_POSTED), // state
uint8(0), // _reserved
uint32(ethNum), // ethNumBal
uint32(ethNum), // tokenNumBal
uint32(state.nestStakedNum1k), // nestNum1k
uint128(tokenAmountPerEth) // tokenAmountPerEth
));
emit MiningV1Data.PricePosted(msg.sender, token, (_sheetToken.length - 1), ethNum.mul(1 ether), tokenAmountPerEth.mul(ethNum));
}
{ // mining; NTOKEN branch only
// load mining record from `minedAtHeight`
uint256 _minedH = state.minedAtHeight[token][block.number];
// decode `_ntokenH` & `_ethH`
uint256 _ntokenH = uint256(_minedH >> 128);
uint256 _ethH = uint256(_minedH % (1 << 128));
if (_ntokenH == 0) { // the sheet is the first in the block
// calculate the amount the NTOKEN to be mined
uint256 _ntokenAmount = mineNToken(_ntoken);
// load `Bidder` from NTOKEN contract
address _bidder = INToken(_ntoken).checkBidder();
if (_bidder == state.C_NestPool) { // for new NTokens, 100% to miners
_ntokenH = _ntokenAmount;
INToken(_ntoken).mint(_ntokenAmount, address(state.C_NestPool));
} else { // for old NTokens, 95% to miners, 5% to the bidder
_ntokenH = _ntokenAmount.mul(MiningV1Data.MINING_LEGACY_NTOKEN_MINER_REWARD_PERCENTAGE).div(100);
INTokenLegacy(_ntoken).increaseTotal(_ntokenAmount);
INTokenLegacy(_ntoken).transfer(state.C_NestPool, _ntokenAmount);
INestPool(state.C_NestPool).addNToken(_bidder, _ntoken, _ntokenAmount.sub(_ntokenH));
}
}
// add up `_ethH`
_ethH = _ethH.add(ethNum);
// store `_ntokenH` & `_ethH` into `minedAtHeight`
state.minedAtHeight[token][block.number] = (_ntokenH * (1<< 128) + _ethH);
}
// calculate averge and volatility
state._stat(token);
return;
}
/// @notice Post two price sheets for a token and its ntoken simultaneously
/// @dev Support dual-posts for TOKEN/NTOKEN, (ETH, TOKEN) + (ETH, NTOKEN)
/// @param token The address of TOKEN contract
/// @param ethNum The numbers of ethers to post sheets
/// @param tokenAmountPerEth The price of TOKEN
/// @param ntokenAmountPerEth The price of NTOKEN
function post2(
address token,
uint256 ethNum,
uint256 tokenAmountPerEth,
uint256 ntokenAmountPerEth
)
external
payable
noContract
{
// check parameters
require(ethNum == state.miningEthUnit, "Nest:Mine:!(ethNum)");
require(tokenAmountPerEth > 0 && ntokenAmountPerEth > 0, "Nest:Mine:!(price)");
address _ntoken = INestPool(state.C_NestPool).getNTokenFromToken(token);
require(_ntoken != token && _ntoken != address(0), "Nest:Mine:!(ntoken)");
// calculate eth fee
uint256 _ethFee = ethNum.mul(state.miningFeeRate).mul(1e18).div(10_000);
{ // settle ethers and tokens
INestPool _C_NestPool = INestPool(state.C_NestPool);
// save the changes into miner's virtual account
if (msg.value.sub(_ethFee) > 0) {
_C_NestPool.depositEth{value:msg.value.sub(_ethFee)}(address(msg.sender));
}
// load addresses
INestStaking _C_NestStaking = INestStaking(state.C_NestStaking);
INestDAO _C_NestDAO = INestDAO(state.C_NestDAO);
if (_ntoken == address(state.C_NestToken)) {
// %80 => NestStaking
_C_NestStaking.addETHReward{value:_ethFee.mul(MiningV1Data.MINING_NEST_FEE_DIVIDEND_RATE).div(100)}(_ntoken);
// %20 => NestDAO
_C_NestDAO.addETHReward{value:_ethFee.mul(MiningV1Data.MINING_NEST_FEE_DAO_RATE).div(100)}(_ntoken);
} else {
// 60% => NestStaking
_C_NestStaking.addETHReward{value:_ethFee.mul(MiningV1Data.MINING_NTOKEN_FEE_DIVIDEND_RATE).div(100)}(_ntoken);
// 20% => NestDAO[NTOKEN]
_C_NestDAO.addETHReward{value:_ethFee.mul(MiningV1Data.MINING_NTOKEN_FEE_DAO_RATE).div(100)}(_ntoken);
// 20% => NestDAO[NEST]
_C_NestDAO.addETHReward{value:_ethFee.mul(MiningV1Data.MINING_NTOKEN_FEE_NEST_DAO_RATE).div(100)}(address(state.C_NestToken));
}
// freeze assets inside NestPool
_C_NestPool.freezeEthAndToken(msg.sender, ethNum.mul(1 ether),
token, tokenAmountPerEth.mul(ethNum));
_C_NestPool.freezeEthAndToken(msg.sender, ethNum.mul(1 ether),
_ntoken, ntokenAmountPerEth.mul(ethNum));
_C_NestPool.freezeNest(msg.sender, uint256(state.nestStakedNum1k).mul(2).mul(1000 * 1e18));
}
{
uint8 typ1;
uint8 typ2;
if (_ntoken == address(state.C_NestToken)) {
typ1 = MiningV1Data.PRICESHEET_TYPE_USD;
typ2 = MiningV1Data.PRICESHEET_TYPE_NEST;
} else {
typ1 = MiningV1Data.PRICESHEET_TYPE_TOKEN;
typ2 = MiningV1Data.PRICESHEET_TYPE_NTOKEN;
}
MiningV1Data.PriceSheet[] storage _sheetToken = state.priceSheetList[token];
// append a new price sheet
_sheetToken.push(MiningV1Data.PriceSheet(
uint160(msg.sender), // miner
uint32(block.number), // atHeight
uint32(ethNum), // ethNum
uint32(ethNum), // remainNum
uint8(0), // level
uint8(typ1), // typ
uint8(MiningV1Data.PRICESHEET_STATE_POSTED), // state
uint8(0), // _reserved
uint32(ethNum), // ethNumBal
uint32(ethNum), // tokenNumBal
uint32(state.nestStakedNum1k), // nestNum1k
uint128(tokenAmountPerEth) // tokenAmountPerEth
));
MiningV1Data.PriceSheet[] storage _sheetNToken = state.priceSheetList[_ntoken];
// append a new price sheet for ntoken
_sheetNToken.push(MiningV1Data.PriceSheet(
uint160(msg.sender), // miner
uint32(block.number), // atHeight
uint32(ethNum), // ethNum
uint32(ethNum), // remainNum
uint8(0), // level
uint8(typ2), // typ
uint8(MiningV1Data.PRICESHEET_STATE_POSTED), // state
uint8(0), // _reserved
uint32(ethNum), // ethNumBal
uint32(ethNum), // tokenNumBal
uint32(state.nestStakedNum1k), // nestNum1k
uint128(ntokenAmountPerEth) // tokenAmountPerEth
));
emit MiningV1Data.PricePosted(msg.sender, token, (_sheetToken.length - 1), ethNum.mul(1 ether), tokenAmountPerEth.mul(ethNum));
emit MiningV1Data.PricePosted(msg.sender, _ntoken, (_sheetNToken.length - 1), ethNum.mul(1 ether), ntokenAmountPerEth.mul(ethNum));
}
{ // mining; NEST branch & NTOKEN branch
if (_ntoken == address(state.C_NestToken)) {
// load mining records `minedAtHeight` in the same block
uint256 _minedH = state.minedAtHeight[token][block.number];
// decode `_nestH` and `_ethH` from `minedAtHeight`
uint256 _nestH = uint256(_minedH >> 128);
uint256 _ethH = uint256(_minedH % (1 << 128));
if (_nestH == 0) { // the sheet is the first in the block
// calculate the amount of NEST to be mined
uint256 _nestAmount = mineNest();
// update `latestMiningHeight`, the lastest NEST-mining block
state.latestMiningHeight = uint32(block.number);
// accumulate the amount of NEST
state.minedNestAmount += uint128(_nestAmount);
//
_nestH = _nestAmount.mul(MiningV1Data.MINER_NEST_REWARD_PERCENTAGE).div(100);
// 15% of NEST to NNRewardPool
INestPool(state.C_NestPool).addNest(state.C_NNRewardPool, _nestAmount.mul(MiningV1Data.NN_NEST_REWARD_PERCENTAGE).div(100));
INNRewardPool(state.C_NNRewardPool).addNNReward(_nestAmount.mul(MiningV1Data.NN_NEST_REWARD_PERCENTAGE).div(100));
// 5% of NEST to NestDAO
INestPool(state.C_NestPool).addNest(state.C_NestDAO, _nestAmount.mul(MiningV1Data.DAO_NEST_REWARD_PERCENTAGE).div(100));
INestDAO(state.C_NestDAO).addNestReward(_nestAmount.mul(MiningV1Data.DAO_NEST_REWARD_PERCENTAGE).div(100));
}
// add up `ethNum` into `minedAtHeight`
_ethH = _ethH.add(ethNum);
// encode `_nestH` and `_ethH` into `minedAtHeight`
state.minedAtHeight[token][block.number] = (_nestH * (1<< 128) + _ethH);
} else {
// load mining records `minedAtHeight` in the same block
uint256 _minedH = state.minedAtHeight[token][block.number];
// decode `_ntokenH` and `_ethH` from `minedAtHeight`
uint256 _ntokenH = uint256(_minedH >> 128);
uint256 _ethH = uint256(_minedH % (1 << 128));
if (_ntokenH == 0) { // the sheet is the first in the block
// calculate the amount of NEST to be mined
uint256 _ntokenAmount = mineNToken(_ntoken);
// load `Bidder` from NTOKEN contract
address _bidder = INToken(_ntoken).checkBidder();
if (_bidder == state.C_NestPool) { // for new NTokens, 100% to miners
// save the amount of NTOKEN to be mined
_ntokenH = _ntokenAmount;
// mint NTOKEN(new, v3.5) to NestPool
INToken(_ntoken).mint(_ntokenAmount, address(state.C_NestPool));
} else { // for old NTokens, 95% to miners, 5% to the bidder
// mint NTOKEN(old, v3.0)
INTokenLegacy(_ntoken).increaseTotal(_ntokenAmount);
// transfer NTOKEN(old) to NestPool
INTokenLegacy(_ntoken).transfer(state.C_NestPool, _ntokenAmount);
// calculate the amount of NTOKEN, 95% => miner
_ntokenH = _ntokenAmount.mul(MiningV1Data.MINING_LEGACY_NTOKEN_MINER_REWARD_PERCENTAGE).div(100);
// 5% NTOKEN => `Bidder`
INestPool(state.C_NestPool).addNToken(_bidder, _ntoken, _ntokenAmount.sub(_ntokenH));
}
}
// add up `ethNum` into `minedAtHeight`
_ethH = _ethH.add(ethNum);
// encode `_nestH` and `_ethH` into `minedAtHeight`
state.minedAtHeight[token][block.number] = (_ntokenH * (1<< 128) + _ethH);
}
}
// calculate the average-prices and volatilities for (TOKEN. NTOKEN)
state._stat(token);
state._stat(_ntoken);
return;
}
/// @notice Close a price sheet of (ETH, USDx) | (ETH, NEST) | (ETH, TOKEN) | (ETH, NTOKEN)
/// @dev Here we allow an empty price sheet (still in VERIFICATION-PERIOD) to be closed
/// @param token The address of TOKEN contract
/// @param index The index of the price sheet w.r.t. `token`
function close(address token, uint256 index)
public
noContract
{
// call library
state._close(token, index);
// calculate average-price and volatility (forward)
state._stat(token);
}
/// @notice Close a price sheet and withdraw assets for WEB users.
/// @dev Contracts aren't allowed to call it.
/// @param token The address of TOKEN contract
/// @param index The index of the price sheet w.r.t. `token`
function closeAndWithdraw(address token, uint256 index)
external
noContract
{
// call library
state._closeAndWithdraw(token, index);
// calculate average-price and volatility (forward)
state._stat(token);
}
/// @notice Close a batch of price sheets passed VERIFICATION-PHASE
/// @dev Empty sheets but in VERIFICATION-PHASE aren't allowed
/// @param token The address of TOKEN contract
/// @param indices A list of indices of sheets w.r.t. `token`
function closeList(address token, uint32[] memory indices)
external
noContract
{
// call library
state._closeList(token, indices);
// calculate average-price and volatility (forward)
state._stat(token);
}
/// @notice Call the function to buy TOKEN/NTOKEN from a posted price sheet
/// @dev bite TOKEN(NTOKEN) by ETH, (+ethNumBal, -tokenNumBal)
/// @param token The address of token(ntoken)
/// @param index The position of the sheet in priceSheetList[token]
/// @param biteNum The amount of bitting (in the unit of ETH), realAmount = biteNum * newTokenAmountPerEth
/// @param newTokenAmountPerEth The new price of token (1 ETH : some TOKEN), here some means newTokenAmountPerEth
function biteToken(address token, uint256 index, uint256 biteNum, uint256 newTokenAmountPerEth)
external
payable
noContract
{
// call library
state._biteToken(token, index, biteNum, newTokenAmountPerEth);
// calculate average-price and volatility (forward)
state._stat(token);
}
/// @notice Call the function to buy TOKEN/NTOKEN from a posted price sheet
/// @dev bite TOKEN(NTOKEN) by ETH, (+ethNumBal, -tokenNumBal)
/// @param token The address of token(ntoken)
/// @param index The position of the sheet in priceSheetList[token]
/// @param biteNum The amount of bitting (in the unit of ETH), realAmount = biteNum * newTokenAmountPerEth
/// @param newTokenAmountPerEth The new price of token (1 ETH : some TOKEN), here some means newTokenAmountPerEth
function biteEth(address token, uint256 index, uint256 biteNum, uint256 newTokenAmountPerEth)
external
payable
noContract
{
// call library
state._biteEth(token, index, biteNum, newTokenAmountPerEth);
// calculate average-price and volatility (forward)
state._stat(token);
}
/* ========== CALCULATION ========== */
function stat(address _token) public
{
// call library
return state._stat(_token);
}
/* ========== PRICE QUERIES ========== */
/// @notice Get the latest effective price for a token
/// @dev It shouldn't be read from any contracts other than NestQuery
function latestPriceOf(address token)
public
view
onlyByNestOrNoContract
returns(uint256 ethAmount, uint256 tokenAmount, uint256 blockNum)
{
MiningV1Data.PriceSheet[] storage _plist = state.priceSheetList[token];
uint256 len = _plist.length;
uint256 _ethNum;
MiningV1Data.PriceSheet memory _sheet;
if (len == 0) {
revert("Nest:Mine:no(price)");
}
uint256 _first = 0;
for (uint i = 1; i <= len; i++) {
_sheet = _plist[len-i];
if (_first == 0 && uint256(_sheet.height) + state.priceDurationBlock < block.number) {
_ethNum = uint256(_sheet.remainNum);
if (_ethNum == 0) {
continue; // jump over a bitten sheet
}
_first = uint256(_sheet.height);
tokenAmount = _ethNum.mul(uint256(_sheet.tokenAmountPerEth));
ethAmount = _ethNum.mul(1 ether);
blockNum = _first;
} else if (_first == uint256(_sheet.height)) {
_ethNum = uint256(_sheet.remainNum);
tokenAmount = tokenAmount.add(_ethNum.mul(uint256(_sheet.tokenAmountPerEth)));
ethAmount = ethAmount.add(_ethNum.mul(1 ether));
} else if (_first > uint256(_sheet.height)) {
break;
}
}
blockNum = blockNum + uint256(state.priceDurationBlock); // safe math
require(ethAmount > 0 && tokenAmount > 0, "Nest:Mine:no(price)");
}
/// @dev It shouldn't be read from any contracts other than NestQuery
function priceOf(address token)
public
view
noContractExcept(state.C_NestQuery)
returns(uint256 ethAmount, uint256 tokenAmount, uint256 blockNum)
{
MiningV1Data.PriceInfo memory pi = state.priceInfo[token];
require(pi.height > 0, "Nest:Mine:NO(price)");
ethAmount = uint256(pi.ethNum).mul(1 ether);
tokenAmount = uint256(pi.tokenAmount);
blockNum = uint256(pi.height + state.priceDurationBlock);
require(ethAmount > 0 && tokenAmount > 0, "Nest:Mine:no(price)");
}
/// @dev It shouldn't be read from any contracts other than NestQuery
function priceAvgAndSigmaOf(address token)
public
view
onlyByNestOrNoContract
returns (uint128 price, uint128 avgPrice, int128 vola, uint32 bn)
{
MiningV1Data.PriceInfo memory pi = state.priceInfo[token];
require(pi.height > 0, "Nest:Mine:NO(price)");
vola = ABDKMath64x64.sqrt(ABDKMath64x64.abs(pi.volatility_sigma_sq));
price = uint128(uint256(pi.tokenAmount).div(uint256(pi.ethNum)));
avgPrice = pi.avgTokenAmount;
bn = pi.height + uint32(state.priceDurationBlock);
require(price > 0 && avgPrice > 0, "Nest:Mine:no(price)");
}
function priceOfTokenAtHeight(address token, uint64 atHeight)
public
view
noContractExcept(state.C_NestQuery)
returns(uint256 ethAmount, uint256 tokenAmount, uint256 bn)
{
(ethAmount, tokenAmount, bn) = state._priceOfTokenAtHeight(token, atHeight);
require(ethAmount > 0 && tokenAmount > 0, "Nest:Mine:no(price)");
}
/// @notice Return a consecutive price list for a token
/// @dev
/// @param token The address of token contract
/// @param num The length of price list
function priceListOfToken(address token, uint8 num)
external view
noContractExcept(state.C_NestQuery)
returns (uint128[] memory data, uint256 bn)
{
return state._priceListOfToken(token, num);
}
/* ========== MINING ========== */
function mineNest() public view returns (uint256)
{
uint256 _period = block.number.sub(state.genesisBlock).div(MiningV1Data.MINING_NEST_YIELD_CUTBACK_PERIOD);
uint256 _nestPerBlock;
if (_period > 9) {
_nestPerBlock = MiningV1Data.MINING_NEST_YIELD_OFF_PERIOD_AMOUNT;
if (block.number > MiningV1Data.MINING_FINAL_BLOCK_NUMBER) {
return 0; // NEST is empty
}
} else {
_nestPerBlock = state._mining_nest_yield_per_block_amount[_period];
}
return _nestPerBlock.mul(block.number.sub(state.latestMiningHeight));
}
function minedNestAmount() external view returns (uint256)
{
return uint256(state.minedNestAmount);
}
function latestMinedHeight() external view returns (uint64)
{
return uint64(state.latestMiningHeight);
}
function mineNToken(address ntoken) public view returns (uint256)
{
(uint256 _genesis, uint256 _last) = INToken(ntoken).checkBlockInfo();
uint256 _period = block.number.sub(_genesis).div(MiningV1Data.MINING_NEST_YIELD_CUTBACK_PERIOD);
uint256 _ntokenPerBlock;
if (_period > 9) {
_ntokenPerBlock = MiningV1Data.MINING_NTOKEN_YIELD_OFF_PERIOD_AMOUNT;
} else {
_ntokenPerBlock = state._mining_ntoken_yield_per_block_amount[_period];
}
uint256 _interval = block.number.sub(_last);
if (_interval > MiningV1Data.MINING_NTOKEN_YIELD_BLOCK_LIMIT) {
_interval = MiningV1Data.MINING_NTOKEN_YIELD_BLOCK_LIMIT;
}
// NOTE: no NTOKEN rewards if the mining interval is greater than a pre-defined number
uint256 yieldAmount = _ntokenPerBlock.mul(_interval);
return yieldAmount;
}
/* ========== WITHDRAW ========== */
function withdrawEth(uint256 ethAmount)
external nonReentrant
{
INestPool(state.C_NestPool).withdrawEth(address(msg.sender), ethAmount);
}
function withdrawEthAndToken(uint256 ethAmount, address token, uint256 tokenAmount)
external nonReentrant
{
INestPool(state.C_NestPool).withdrawEthAndToken(address(msg.sender), ethAmount, token, tokenAmount);
}
function withdrawNest(uint256 nestAmount)
external nonReentrant
{
INestPool(state.C_NestPool).withdrawNest(address(msg.sender), nestAmount);
}
function withdrawEthAndTokenAndNest(uint256 ethAmount, address token, uint256 tokenAmount, uint256 nestAmount)
external nonReentrant
{
INestPool(state.C_NestPool).withdrawEthAndToken(address(msg.sender), ethAmount, token, tokenAmount);
INestPool(state.C_NestPool).withdrawNest(address(msg.sender), nestAmount);
}
/* ========== VIEWS ========== */
function lengthOfPriceSheets(address token)
view
external
returns (uint256)
{
return state.priceSheetList[token].length;
}
function priceSheet(address token, uint256 index)
view external
returns (MiningV1Data.PriceSheetPub memory sheet)
{
return state._priceSheet(token, index);
}
function fullPriceSheet(address token, uint256 index)
view
public
noContract
returns (MiningV1Data.PriceSheet memory sheet)
{
uint256 len = state.priceSheetList[token].length;
require (index < len, "Nest:Mine:>(len)");
return state.priceSheetList[token][index];
}
function unVerifiedSheetList(address token)
view
public
noContract
returns (MiningV1Data.PriceSheetPub2[] memory sheets)
{
return state.unVerifiedSheetList(token);
}
function unClosedSheetListOf(address miner, address token, uint256 fromIndex, uint256 num)
view
public
noContract
returns (MiningV1Data.PriceSheetPub2[] memory sheets)
{
return state.unClosedSheetListOf(miner, token, fromIndex, num);
}
function sheetListOf(address miner, address token, uint256 fromIndex, uint256 num)
view
public
noContract
returns (MiningV1Data.PriceSheetPub2[] memory sheets)
{
return state.sheetListOf(miner, token, fromIndex, num);
}
/*
/// @dev The function will be disabled when the upgrading is completed
/// TODO: (TBD) auth needed?
function post2Only4Upgrade(
address token,
uint256 ethNum,
uint256 tokenAmountPerEth,
uint256 ntokenAmountPerEth
)
external
noContract
{
// only avialble in upgrade phase
require (flag == MINING_FLAG_UPGRADE_NEEDED, "Nest:Mine:!flag");
state._post2Only4Upgrade(token, ethNum, tokenAmountPerEth, ntokenAmountPerEth);
address _ntoken = INestPool(state.C_NestPool).getNTokenFromToken(token);
// calculate average price and volatility
state._stat(token);
state._stat(_ntoken);
}
*/
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.6.12;
import "../iface/INestPool.sol";
import "../iface/INestStaking.sol";
import "../iface/INToken.sol";
import "../iface/INNRewardPool.sol";
import "../lib/SafeERC20.sol";
/// @author Inf Loop - <inf-loop@nestprotocol.org>
/// @author 0x00 - <0x00@nestprotocol.org>
library MiningV1Data {
/* ========== CONSTANTS ========== */
uint256 constant MINING_NEST_YIELD_CUTBACK_PERIOD = 2400000; // ~ 1 years
uint256 constant MINING_NEST_YIELD_CUTBACK_RATE = 80; // percentage = 80%
// yield amount (per block) after the first ten years
uint256 constant MINING_NEST_YIELD_OFF_PERIOD_AMOUNT = 40 ether;
// yield amount (per block) in the first year, it drops to 80% in the following nine years
uint256 constant MINING_NEST_YIELD_PER_BLOCK_BASE = 400 ether;
uint256 constant MINING_NTOKEN_YIELD_CUTBACK_RATE = 80;
uint256 constant MINING_NTOKEN_YIELD_OFF_PERIOD_AMOUNT = 0.4 ether;
uint256 constant MINING_NTOKEN_YIELD_PER_BLOCK_BASE = 4 ether;
uint256 constant MINING_FINAL_BLOCK_NUMBER = 173121488;
uint256 constant MINING_NEST_FEE_DIVIDEND_RATE = 80; // percentage = 80%
uint256 constant MINING_NEST_FEE_DAO_RATE = 20; // percentage = 20%
uint256 constant MINING_NTOKEN_FEE_DIVIDEND_RATE = 60; // percentage = 60%
uint256 constant MINING_NTOKEN_FEE_DAO_RATE = 20; // percentage = 20%
uint256 constant MINING_NTOKEN_FEE_NEST_DAO_RATE = 20; // percentage = 20%
uint256 constant MINING_NTOKEN_YIELD_BLOCK_LIMIT = 100;
uint256 constant NN_NEST_REWARD_PERCENTAGE = 15;
uint256 constant DAO_NEST_REWARD_PERCENTAGE = 5;
uint256 constant MINER_NEST_REWARD_PERCENTAGE = 80;
uint256 constant MINING_LEGACY_NTOKEN_MINER_REWARD_PERCENTAGE = 95;
uint256 constant MINING_LEGACY_NTOKEN_BIDDER_REWARD_PERCENTAGE = 5;
uint8 constant PRICESHEET_STATE_CLOSED = 0;
uint8 constant PRICESHEET_STATE_POSTED = 1;
uint8 constant PRICESHEET_STATE_BITTEN = 2;
uint8 constant PRICESHEET_TYPE_USD = 1;
uint8 constant PRICESHEET_TYPE_NEST = 2;
uint8 constant PRICESHEET_TYPE_TOKEN = 3;
uint8 constant PRICESHEET_TYPE_NTOKEN = 4;
uint8 constant PRICESHEET_TYPE_BITTING = 8;
uint8 constant STATE_FLAG_UNINITIALIZED = 0;
uint8 constant STATE_FLAG_SETUP_NEEDED = 1;
uint8 constant STATE_FLAG_ACTIVE = 3;
uint8 constant STATE_FLAG_MINING_STOPPED = 4;
uint8 constant STATE_FLAG_CLOSING_STOPPED = 5;
uint8 constant STATE_FLAG_WITHDRAW_STOPPED = 6;
uint8 constant STATE_FLAG_PRICE_STOPPED = 7;
uint8 constant STATE_FLAG_SHUTDOWN = 127;
uint256 constant MINING_NTOKEN_NON_DUAL_POST_THRESHOLD = 5_000_000 ether;
/// @dev size: (2 x 256 bit)
struct PriceSheet {
uint160 miner; // miner who posted the price (most significant bits, or left-most)
uint32 height; //
uint32 ethNum;
uint32 remainNum;
uint8 level; // the level of bitting, 1-4: eth-doubling | 5 - 127: nest-doubling
uint8 typ; // 1: USD | 2: NEST | 3: TOKEN | 4: NTOKEN
uint8 state; // 0: closed | 1: posted | 2: bitten
uint8 _reserved; // for padding
uint32 ethNumBal;
uint32 tokenNumBal;
uint32 nestNum1k;
uint128 tokenAmountPerEth;
}
/// @dev size: (3 x 256 bit)
struct PriceInfo {
uint32 index;
uint32 height; // NOTE: the height of being posted
uint32 ethNum; // the balance of eth
uint32 _reserved;
uint128 tokenAmount; // the balance of token
int128 volatility_sigma_sq;
int128 volatility_ut_sq;
uint128 avgTokenAmount; // avg = (tokenAmount : perEth)
uint128 _reserved2;
}
/// @dev The struct is for public data in a price sheet, so as to protect prices from being read
struct PriceSheetPub {
uint160 miner; // miner who posted the price (most significant bits, or left-most)
uint32 height;
uint32 ethNum;
uint8 typ; // 1: USD | 2: NEST | 3: TOKEN | 4: NTOKEN(Not Available)
uint8 state; // 0: closed | 1: posted | 2: bitten
uint32 ethNumBal;
uint32 tokenNumBal;
}
struct PriceSheetPub2 {
uint160 miner; // miner who posted the price (most significant bits, or left-most)
uint32 height;
uint32 ethNum;
uint32 remainNum;
uint8 level; // the level of bitting, 1-4: eth-doubling | 5 - 127: nest-doubling
uint8 typ; // 1: USD | 2: NEST | 3: TOKEN | 4: NTOKEN(Not Available)
uint8 state; // 0: closed | 1: posted | 2: bitten
uint256 index; // return to the quotation of index
uint32 nestNum1k;
uint128 tokenAmountPerEth;
}
/* ========== EVENTS ========== */
event PricePosted(address miner, address token, uint256 index, uint256 ethAmount, uint256 tokenAmount);
event PriceClosed(address miner, address token, uint256 index);
event Deposit(address miner, address token, uint256 amount);
event Withdraw(address miner, address token, uint256 amount);
event TokenBought(address miner, address token, uint256 index, uint256 biteEthAmount, uint256 biteTokenAmount);
event TokenSold(address miner, address token, uint256 index, uint256 biteEthAmount, uint256 biteTokenAmount);
event VolaComputed(uint32 h, uint32 pos, uint32 ethA, uint128 tokenA, int128 sigma_sq, int128 ut_sq);
event SetParams(uint8 miningEthUnit, uint32 nestStakedNum1k, uint8 biteFeeRate,
uint8 miningFeeRate, uint8 priceDurationBlock, uint8 maxBiteNestedLevel,
uint8 biteInflateFactor, uint8 biteNestInflateFactor);
// event GovSet(address oldGov, address newGov);
/* ========== GIANT STATE VARIABLE ========== */
struct State {
// TODO: more comments
uint8 miningEthUnit; // = 30 on mainnet;
uint32 nestStakedNum1k; // = 100;
uint8 biteFeeRate; //
uint8 miningFeeRate; // = 10;
uint8 priceDurationBlock; // = 25;
uint8 maxBiteNestedLevel; // = 3;
uint8 biteInflateFactor; // = 2;
uint8 biteNestInflateFactor; // = 2;
uint32 genesisBlock; // = 6236588;
uint128 latestMiningHeight; // latest block number of NEST mining
uint128 minedNestAmount; // the total amount of mined NEST
address _developer_address; // WARNING: DO NOT delete this unused variable
address _NN_address; // WARNING: DO NOT delete this unused variable
address C_NestPool;
address C_NestToken;
address C_NestStaking;
address C_NNRewardPool;
address C_NestQuery;
address C_NestDAO;
uint256[10] _mining_nest_yield_per_block_amount;
uint256[10] _mining_ntoken_yield_per_block_amount;
// A mapping (from token(address) to an array of PriceSheet)
mapping(address => PriceSheet[]) priceSheetList;
// from token(address) to Price
mapping(address => PriceInfo) priceInfo;
// (token-address, block-number) => (ethFee-total, nest/ntoken-mined-total)
mapping(address => mapping(uint256 => uint256)) minedAtHeight;
// WARNING: DO NOT delete these variables, reserved for future use
uint256 _reserved1;
uint256 _reserved2;
uint256 _reserved3;
uint256 _reserved4;
}
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;
import "../lib/SafeMath.sol";
import "../lib/SafeERC20.sol";
import '../lib/TransferHelper.sol';
import "../lib/ABDKMath64x64.sol";
import "../iface/INestPool.sol";
import "../iface/INestStaking.sol";
import "../iface/INToken.sol";
import "../iface/INNRewardPool.sol";
import "../libminingv1/MiningV1Data.sol";
//import "hardhat/console.sol";
/// @title NestMiningV1/MiningV1Calc
/// @author Inf Loop - <inf-loop@nestprotocol.org>
/// @author Paradox - <paradox@nestprotocol.org>
library MiningV1Calc {
using SafeMath for uint256;
/// @dev Average block mining interval, ~ 14s
uint256 constant ETHEREUM_BLOCK_TIMESPAN = 14;
function _calcVola(
// uint256 ethA0,
uint256 tokenA0,
// uint256 ethA1,
uint256 tokenA1,
int128 _sigma_sq,
int128 _ut_sq,
uint256 _interval
)
private
pure
// pure
returns (int128, int128)
{
int128 _ut_sq_2 = ABDKMath64x64.div(_ut_sq,
ABDKMath64x64.fromUInt(_interval.mul(ETHEREUM_BLOCK_TIMESPAN)));
int128 _new_sigma_sq = ABDKMath64x64.add(
ABDKMath64x64.mul(ABDKMath64x64.divu(95, 100), _sigma_sq),
ABDKMath64x64.mul(ABDKMath64x64.divu(5,100), _ut_sq_2));
int128 _new_ut_sq;
_new_ut_sq = ABDKMath64x64.pow(ABDKMath64x64.sub(
ABDKMath64x64.divu(tokenA1, tokenA0),
ABDKMath64x64.fromUInt(1)),
2);
return (_new_sigma_sq, _new_ut_sq);
}
function _calcAvg(uint256 ethA, uint256 tokenA, uint256 _avg)
private
pure
returns(uint256)
{
uint256 _newP = tokenA.div(ethA);
uint256 _newAvg;
if (_avg == 0) {
_newAvg = _newP;
} else {
_newAvg = (_avg.mul(95).div(100)).add(_newP.mul(5).div(100));
// _newAvg = ABDKMath64x64.add(
// ABDKMath64x64.mul(ABDKMath64x64.divu(95, 100), _avg),
// ABDKMath64x64.mul(ABDKMath64x64.divu(5,100), _newP));
}
return _newAvg;
}
function _moveAndCalc(
MiningV1Data.PriceInfo memory p0,
MiningV1Data.PriceSheet[] storage pL,
uint256 priceDurationBlock
)
private
view
returns (MiningV1Data.PriceInfo memory)
{
uint256 i = p0.index + 1;
if (i >= pL.length) {
return (MiningV1Data.PriceInfo(0,0,0,0,0,int128(0),int128(0), uint128(0), 0));
}
uint256 h = uint256(pL[i].height);
if (h + priceDurationBlock >= block.number) {
return (MiningV1Data.PriceInfo(0,0,0,0,0,int128(0),int128(0), uint128(0), 0));
}
uint256 ethA1 = 0;
uint256 tokenA1 = 0;
while (i < pL.length && pL[i].height == h) {
uint256 _remain = uint256(pL[i].remainNum);
if (_remain == 0) {
i = i + 1;
continue; // jump over a bitten sheet
}
ethA1 = ethA1 + _remain;
tokenA1 = tokenA1 + _remain.mul(pL[i].tokenAmountPerEth);
i = i + 1;
}
i = i - 1;
if (ethA1 == 0 || tokenA1 == 0) {
return (MiningV1Data.PriceInfo(
uint32(i), // index
uint32(0), // height
uint32(0), // ethNum
uint32(0), // _reserved
uint32(0), // tokenAmount
int128(0), // volatility_sigma_sq
int128(0), // volatility_ut_sq
uint128(0), // avgTokenAmount
0 // _reserved2
));
}
int128 new_sigma_sq;
int128 new_ut_sq;
{
if (uint256(p0.ethNum) != 0) {
(new_sigma_sq, new_ut_sq) = _calcVola(
uint256(p0.tokenAmount).div(uint256(p0.ethNum)),
uint256(tokenA1).div(uint256(ethA1)),
p0.volatility_sigma_sq, p0.volatility_ut_sq,
h - p0.height);
}
}
uint256 _newAvg = _calcAvg(ethA1, tokenA1, p0.avgTokenAmount);
return(MiningV1Data.PriceInfo(
uint32(i), // index
uint32(h), // height
uint32(ethA1), // ethNum
uint32(0), // _reserved
uint128(tokenA1), // tokenAmount
new_sigma_sq, // volatility_sigma_sq
new_ut_sq, // volatility_ut_sq
uint128(_newAvg), // avgTokenAmount
uint128(0) // _reserved2
));
}
/// @dev The function updates the statistics of price sheets
/// It calculates from priceInfo to the newest that is effective.
/// Different from `_statOneBlock()`, it may cross multiple blocks.
function _stat(MiningV1Data.State storage state, address token)
external
{
MiningV1Data.PriceInfo memory p0 = state.priceInfo[token];
MiningV1Data.PriceSheet[] storage pL = state.priceSheetList[token];
if (pL.length < 2) {
return;
}
if (p0.height == 0) {
MiningV1Data.PriceSheet memory _sheet = pL[0];
p0.ethNum = _sheet.ethNum;
p0.tokenAmount = uint128(uint256(_sheet.tokenAmountPerEth).mul(_sheet.ethNum));
p0.height = _sheet.height;
p0.volatility_sigma_sq = 0;
p0.volatility_ut_sq = 0;
p0.avgTokenAmount = uint128(_sheet.tokenAmountPerEth);
// write back
state.priceInfo[token] = p0;
}
MiningV1Data.PriceInfo memory p1;
// record the gas usage
uint256 startGas = gasleft();
uint256 gasUsed;
while (uint256(p0.index) < pL.length && uint256(p0.height) + state.priceDurationBlock < block.number){
gasUsed = startGas - gasleft();
// NOTE: check gas usage to prevent DOS attacks
if (gasUsed > 1_000_000) {
break;
}
p1 = _moveAndCalc(p0, pL, state.priceDurationBlock);
if (p1.index <= p0.index) { // bootstraping
break;
} else if (p1.ethNum == 0) { // jump cross a block with bitten prices
p0.index = p1.index;
continue;
} else { // calculate one more block
p0 = p1;
}
}
if (p0.index > state.priceInfo[token].index) {
state.priceInfo[token] = p0;
}
return;
}
/// @dev The function updates the statistics of price sheets across only one block.
function _statOneBlock(MiningV1Data.State storage state, address token)
external
{
MiningV1Data.PriceInfo memory p0 = state.priceInfo[token];
MiningV1Data.PriceSheet[] storage pL = state.priceSheetList[token];
if (pL.length < 2) {
return;
}
(MiningV1Data.PriceInfo memory p1) = _moveAndCalc(p0, state.priceSheetList[token], state.priceDurationBlock);
if (p1.index > p0.index && p1.ethNum != 0) {
state.priceInfo[token] = p1;
} else if (p1.index > p0.index && p1.ethNum == 0) {
p0.index = p1.index;
state.priceInfo[token] = p1;
}
return;
}
/// @notice Return a consecutive price list for a token
/// @dev
/// @param token The address of token contract
/// @param num The length of price list
function _priceListOfToken(
MiningV1Data.State storage state,
address token,
uint8 num
)
external
view
returns (uint128[] memory data, uint256 bn)
{
MiningV1Data.PriceSheet[] storage _list = state.priceSheetList[token];
uint256 len = _list.length;
uint256 _index = 0;
data = new uint128[](num * 3);
MiningV1Data.PriceSheet memory _sheet;
uint256 _ethNum;
// loop
uint256 _curr = 0;
uint256 _prev = 0;
for (uint i = 1; i <= len; i++) {
_sheet = _list[len - i];
_curr = uint256(_sheet.height);
if (_prev == 0) {
if (_curr + state.priceDurationBlock < block.number) {
_ethNum = uint256(_sheet.remainNum);
if(_ethNum > 0) {
data[_index] = uint128(_curr + state.priceDurationBlock); // safe math
data[_index + 1] = uint128(_ethNum.mul(1 ether));
data[_index + 2] = uint128(_ethNum.mul(_sheet.tokenAmountPerEth));
bn = _curr + state.priceDurationBlock; // safe math
_prev = _curr;
}
}
} else if (_prev == _curr) {
_ethNum = uint256(_sheet.remainNum);
data[_index + 1] += uint128(_ethNum.mul(1 ether));
data[_index + 2] += uint128(_ethNum.mul(_sheet.tokenAmountPerEth));
} else if (_prev > _curr) {
_ethNum = uint256(_sheet.remainNum);
if(_ethNum > 0){
_index += 3;
if (_index >= uint256(num * 3)) {
break;
}
data[_index] = uint128(_curr + state.priceDurationBlock); // safe math
data[_index + 1] = uint128(_ethNum.mul(1 ether));
data[_index + 2] = uint128(_ethNum.mul(_sheet.tokenAmountPerEth));
_prev = _curr;
}
}
}
// require (data.length == uint256(num * 3), "Incorrect price list length");
}
function _priceOfTokenAtHeight(
MiningV1Data.State storage state,
address token,
uint64 atHeight
)
external
view
returns(uint256 ethAmount, uint256 tokenAmount, uint256 blockNum)
{
require(atHeight <= block.number, "Nest:Mine:!height");
MiningV1Data.PriceSheet[] storage _list = state.priceSheetList[token];
uint256 len = state.priceSheetList[token].length;
MiningV1Data.PriceSheet memory _sheet;
uint256 _ethNum;
if (len == 0) {
return (0, 0, 0);
}
uint256 _first = 0;
uint256 _prev = 0;
for (uint i = 1; i <= len; i++) {
_sheet = _list[len - i];
_first = uint256(_sheet.height);
if (_prev == 0) {
if (_first + state.priceDurationBlock < uint256(atHeight)) {
_ethNum = uint256(_sheet.remainNum);
if (_ethNum == 0) {
continue; // jump over a bitten sheet
}
ethAmount = _ethNum.mul(1 ether);
tokenAmount = _ethNum.mul(_sheet.tokenAmountPerEth);
blockNum = _first + state.priceDurationBlock;
_prev = _first;
}
} else if (_first == _prev) {
_ethNum = uint256(_sheet.remainNum);
ethAmount = ethAmount.add(_ethNum.mul(1 ether));
tokenAmount = tokenAmount.add(_ethNum.mul(_sheet.tokenAmountPerEth));
} else if (_prev > _first) {
break;
}
}
}
function _priceSheet(
MiningV1Data.State storage state,
address token,
uint256 index
)
view external
returns (MiningV1Data.PriceSheetPub memory sheet)
{
uint256 len = state.priceSheetList[token].length;
require (index < len, "Nest:Mine:!index");
MiningV1Data.PriceSheet memory _sheet = state.priceSheetList[token][index];
sheet.miner = _sheet.miner;
sheet.height = _sheet.height;
sheet.ethNum = _sheet.ethNum;
sheet.typ = _sheet.typ;
sheet.state = _sheet.state;
sheet.ethNumBal = _sheet.ethNumBal;
sheet.tokenNumBal = _sheet.tokenNumBal;
}
function unVerifiedSheetList(
MiningV1Data.State storage state,
address token
)
view
public
returns (MiningV1Data.PriceSheetPub2[] memory sheets)
{
MiningV1Data.PriceSheet[] storage _list = state.priceSheetList[token];
uint256 len = _list.length;
uint256 num;
for (uint i = 0; i < len; i++) {
if (_list[len - 1 - i].height + state.priceDurationBlock < block.number) {
break;
}
num += 1;
}
sheets = new MiningV1Data.PriceSheetPub2[](num);
for (uint i = 0; i < num; i++) {
MiningV1Data.PriceSheet memory _sheet = _list[len - 1 - i];
if (uint256(_sheet.height) + state.priceDurationBlock < block.number) {
break;
}
//sheets[i] = _sheet;
sheets[i].miner = _sheet.miner;
sheets[i].height = _sheet.height;
sheets[i].ethNum = _sheet.ethNum;
sheets[i].remainNum = _sheet.remainNum;
sheets[i].level = _sheet.level;
sheets[i].typ = _sheet.typ;
sheets[i].state = _sheet.state;
sheets[i].index = len - 1 - i;
sheets[i].nestNum1k = _sheet.nestNum1k;
sheets[i].tokenAmountPerEth = _sheet.tokenAmountPerEth;
}
}
function unClosedSheetListOf(
MiningV1Data.State storage state,
address miner,
address token,
uint256 fromIndex,
uint256 num)
view
external
returns (MiningV1Data.PriceSheetPub2[] memory sheets)
{
sheets = new MiningV1Data.PriceSheetPub2[](num);
MiningV1Data.PriceSheet[] storage _list = state.priceSheetList[token];
uint256 len = _list.length;
require(fromIndex < len, "Nest:Mine:!from");
for (uint i = 0; i < num; i++) {
if (fromIndex < i) {
break;
}
MiningV1Data.PriceSheet memory _sheet = _list[fromIndex - i];
if (uint256(_sheet.miner) == uint256(miner)
&& (_sheet.state == MiningV1Data.PRICESHEET_STATE_POSTED
|| _sheet.state == MiningV1Data.PRICESHEET_STATE_BITTEN)) {
sheets[i].miner = _sheet.miner;
sheets[i].height = _sheet.height;
sheets[i].ethNum = _sheet.ethNum;
sheets[i].remainNum = _sheet.remainNum;
sheets[i].level = _sheet.level;
sheets[i].typ = _sheet.typ;
sheets[i].state = _sheet.state;
sheets[i].index = fromIndex - i;
sheets[i].nestNum1k = _sheet.nestNum1k;
sheets[i].tokenAmountPerEth = _sheet.tokenAmountPerEth;
}
}
}
function sheetListOf(
MiningV1Data.State storage state,
address miner,
address token,
uint256 fromIndex,
uint256 num
)
view
external
returns (MiningV1Data.PriceSheetPub2[] memory sheets)
{
sheets = new MiningV1Data.PriceSheetPub2[](num);
MiningV1Data.PriceSheet[] storage _list = state.priceSheetList[token];
uint256 len = _list.length;
require(fromIndex < len, "Nest:Mine:!from");
for (uint i = 0; i < num; i++) {
if (fromIndex < i) {
break;
}
MiningV1Data.PriceSheet memory _sheet = _list[fromIndex - i];
if (uint256(_sheet.miner) == uint256(miner)) {
sheets[i].miner = _sheet.miner;
sheets[i].height = _sheet.height;
sheets[i].ethNum = _sheet.ethNum;
sheets[i].remainNum = _sheet.remainNum;
sheets[i].level = _sheet.level;
sheets[i].typ = _sheet.typ;
sheets[i].state = _sheet.state;
sheets[i].index = fromIndex - i;
sheets[i].nestNum1k = _sheet.nestNum1k;
sheets[i].tokenAmountPerEth = _sheet.tokenAmountPerEth;
}
}
}
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;
import "../lib/SafeMath.sol";
import "../lib/SafeERC20.sol";
import '../lib/TransferHelper.sol';
import "../lib/ABDKMath64x64.sol";
import "../iface/INestPool.sol";
import "../iface/INestStaking.sol";
import "../iface/INToken.sol";
import "../iface/INNRewardPool.sol";
import "../libminingv1/MiningV1Data.sol";
//import "hardhat/console.sol";
/// @title NestMiningV1/MiningV1Calc
/// @author Inf Loop - <inf-loop@nestprotocol.org>
/// @author Paradox - <paradox@nestprotocol.org>
library MiningV1Op {
using SafeMath for uint256;
/// @notice Call the function to buy TOKEN/NTOKEN from a posted price sheet
/// @dev bite TOKEN(NTOKEN) by ETH, (+ethNumBal, -tokenNumBal)
/// @param token The address of token(ntoken)
/// @param index The position of the sheet in priceSheetList[token]
/// @param biteNum The amount of bitting (in the unit of ETH), realAmount = biteNum * newTokenAmountPerEth
/// @param newTokenAmountPerEth The new price of token (1 ETH : some TOKEN), here some means newTokenAmountPerEth
function _biteToken(
MiningV1Data.State storage state,
address token,
uint256 index,
uint256 biteNum,
uint256 newTokenAmountPerEth
)
external
{
// check parameters
require(token != address(0x0), "Nest:Mine:(token)=0");
require(newTokenAmountPerEth > 0, "Nest:Mine:(price)=0");
require(biteNum >= state.miningEthUnit && biteNum % state.miningEthUnit == 0, "Nest:Mine:!(bite)");
// check sheet
MiningV1Data.PriceSheet memory _sheet = state.priceSheetList[token][index];
require(uint256(_sheet.height) + state.priceDurationBlock >= block.number, "Nest:Mine:!EFF(sheet)");
require(uint256(_sheet.remainNum) >= biteNum, "Nest:Mine:!(remain)");
// load address of NestPool
INestPool _C_NestPool = INestPool(state.C_NestPool);
// check sheet sate
uint256 _state = uint256(_sheet.state);
require(_state == MiningV1Data.PRICESHEET_STATE_POSTED
|| _state == MiningV1Data.PRICESHEET_STATE_BITTEN, "Nest:Mine:!(state)");
{
// load NTOKEN
address _ntoken = _C_NestPool.getNTokenFromToken(token);
// calculate fee
uint256 _ethFee = biteNum.mul(1 ether).mul(state.biteFeeRate).div(1000);
// save the changes into miner's virtual account
if (msg.value.sub(_ethFee) > 0) {
_C_NestPool.depositEth{value:msg.value.sub(_ethFee)}(address(msg.sender));
}
// pump fee into staking pool
if (_ethFee > 0) {
INestStaking(state.C_NestStaking).addETHReward{value:_ethFee}(_ntoken);
}
}
// post a new price sheet
{
// check bitting conditions
uint256 _newEthNum;
uint256 _newNestNum1k = uint256(_sheet.nestNum1k);
{
uint256 _level = uint256(_sheet.level);
uint256 _newLevel;
// calculate `(_newEthNum, _newNestNum1k, _newLevel)`
if (_level > state.maxBiteNestedLevel && _level < 127) { // bitten sheet, nest doubling
_newEthNum = biteNum;
_newNestNum1k = _newNestNum1k.mul(biteNum.mul(state.biteNestInflateFactor)).div(_sheet.ethNum);
_newLevel = _level + 1;
} else if (_level <= state.maxBiteNestedLevel) { // bitten sheet, eth doubling
_newEthNum = biteNum.mul(state.biteInflateFactor);
_newNestNum1k = _newNestNum1k.mul(biteNum.mul(state.biteNestInflateFactor)).div(_sheet.ethNum);
_newLevel = _level + 1;
}
// freeze NEST
_C_NestPool.freezeNest(address(msg.sender), _newNestNum1k.mul(1000 * 1e18));
// freeze(TOKEN, ETH); or freeeze(ETH) but unfreeze(TOKEN)
if (_newEthNum.mul(newTokenAmountPerEth) < biteNum * _sheet.tokenAmountPerEth) {
uint256 _unfreezetokenAmount;
_unfreezetokenAmount = uint256(_sheet.tokenAmountPerEth).mul(biteNum).sub((uint256(newTokenAmountPerEth)).mul(_newEthNum));
_C_NestPool.unfreezeToken(msg.sender, token, _unfreezetokenAmount);
_C_NestPool.freezeEth(msg.sender, _newEthNum.add(biteNum).mul(1 ether));
} else {
_C_NestPool.freezeEthAndToken(msg.sender, _newEthNum.add(biteNum).mul(1 ether),
token, _newEthNum.mul(newTokenAmountPerEth)
.sub(biteNum * _sheet.tokenAmountPerEth));
}
MiningV1Data.PriceSheet[] storage _sheetOfToken = state.priceSheetList[token];
// append a new price sheet
_sheetOfToken.push(MiningV1Data.PriceSheet(
uint160(msg.sender), // miner
uint32(block.number), // atHeight
uint32(_newEthNum), // ethNum
uint32(_newEthNum), // remainNum
uint8(_newLevel), // level
uint8(_sheet.typ), // typ
uint8(MiningV1Data.PRICESHEET_STATE_POSTED), // state
uint8(0), // _reserved
uint32(_newEthNum), // ethNumBal
uint32(_newEthNum), // tokenNumBal
uint32(_newNestNum1k), // nestNum1k
uint128(newTokenAmountPerEth) // tokenAmountPerEth
));
}
// update the bitten sheet
_sheet.state = MiningV1Data.PRICESHEET_STATE_BITTEN;
_sheet.ethNumBal = uint32(uint256(_sheet.ethNumBal).add(biteNum));
_sheet.tokenNumBal = uint32(uint256(_sheet.tokenNumBal).sub(biteNum));
_sheet.remainNum = uint32(uint256(_sheet.remainNum).sub(biteNum));
state.priceSheetList[token][index] = _sheet;
}
emit MiningV1Data.TokenBought(address(msg.sender), address(token), index, biteNum.mul(1 ether), biteNum.mul(_sheet.tokenAmountPerEth));
return;
}
/// @notice Call the function to buy TOKEN/NTOKEN from a posted price sheet
/// @dev bite TOKEN(NTOKEN) by ETH, (+ethNumBal, -tokenNumBal)
/// @param token The address of token(ntoken)
/// @param index The position of the sheet in priceSheetList[token]
/// @param biteNum The amount of bitting (in the unit of ETH), realAmount = biteNum * newTokenAmountPerEth
/// @param newTokenAmountPerEth The new price of token (1 ETH : some TOKEN), here some means newTokenAmountPerEth
function _biteEth(
MiningV1Data.State storage state,
address token,
uint256 index,
uint256 biteNum,
uint256 newTokenAmountPerEth
)
external
{
// check parameters
require(token != address(0x0), "Nest:Mine:(token)=0");
require(newTokenAmountPerEth > 0, "Nest:Mine:(price)=0");
require(biteNum >= state.miningEthUnit && biteNum % state.miningEthUnit == 0, "Nest:Mine:!(bite)");
MiningV1Data.PriceSheet memory _sheet = state.priceSheetList[token][index];
require(uint256(_sheet.height) + state.priceDurationBlock >= block.number, "Nest:Mine:!EFF(sheet)");
require(uint256(_sheet.remainNum) >= biteNum, "Nest:Mine:!(remain)");
// load NestPool
INestPool _C_NestPool = INestPool(state.C_NestPool);
// check state
uint256 _state = uint256(_sheet.state);
require(_state == MiningV1Data.PRICESHEET_STATE_POSTED
|| _state == MiningV1Data.PRICESHEET_STATE_BITTEN, "Nest:Mine:!(state)");
{
// load NTOKEN
address _ntoken = _C_NestPool.getNTokenFromToken(token);
// calculate fee
uint256 _ethFee = biteNum.mul(1 ether).mul(state.biteFeeRate).div(1000);
// save the changes into miner's virtual account
if (msg.value.sub(_ethFee) > 0) {
_C_NestPool.depositEth{value:msg.value.sub(_ethFee)}(address(msg.sender));
}
// pump fee into NestStaking
INestStaking(state.C_NestStaking).addETHReward{value:_ethFee}(_ntoken);
}
// post a new price sheet
{
// check bitting conditions
uint256 _newEthNum;
uint256 _newNestNum1k = uint256(_sheet.nestNum1k);
{
uint256 _level = uint256(_sheet.level);
uint256 _newLevel;
if (_level > state.maxBiteNestedLevel && _level < 127) { // bitten sheet, nest doubling
_newEthNum = biteNum;
_newNestNum1k = _newNestNum1k.mul(biteNum.mul(state.biteNestInflateFactor)).div(_sheet.ethNum);
_newLevel = _level + 1;
} else if (_level <= state.maxBiteNestedLevel) { // bitten sheet, eth doubling
_newEthNum = biteNum.mul(state.biteInflateFactor);
_newNestNum1k = _newNestNum1k.mul(biteNum.mul(state.biteNestInflateFactor)).div(_sheet.ethNum);
_newLevel = _level + 1;
}
MiningV1Data.PriceSheet[] storage _sheetOfToken = state.priceSheetList[token];
// append a new price sheet
_sheetOfToken.push(MiningV1Data.PriceSheet(
uint160(msg.sender), // miner
uint32(block.number), // atHeight
uint32(_newEthNum), // ethNum
uint32(_newEthNum), // remainNum
uint8(_newLevel), // level
uint8(_sheet.typ), // typ
uint8(MiningV1Data.PRICESHEET_STATE_POSTED), // state
uint8(0), // _reserved
uint32(_newEthNum), // ethNumBal
uint32(_newEthNum), // tokenNumBal
uint32(_newNestNum1k), // nestNum1k
uint128(newTokenAmountPerEth) // tokenAmountPerEth
));
}
// freeze NEST
_C_NestPool.freezeNest(address(msg.sender), _newNestNum1k.mul(1000 * 1e18));
// freeze(TOKEN, ETH)
_C_NestPool.freezeEthAndToken(msg.sender, _newEthNum.sub(biteNum).mul(1 ether),
token, _newEthNum.mul(newTokenAmountPerEth)
.add(biteNum.mul(_sheet.tokenAmountPerEth)));
// update the bitten sheet
_sheet.state = MiningV1Data.PRICESHEET_STATE_BITTEN;
_sheet.ethNumBal = uint32(uint256(_sheet.ethNumBal).sub(biteNum));
_sheet.tokenNumBal = uint32(uint256(_sheet.tokenNumBal).add(biteNum));
_sheet.remainNum = uint32(uint256(_sheet.remainNum).sub(biteNum));
state.priceSheetList[token][index] = _sheet;
}
emit MiningV1Data.TokenSold(address(msg.sender), address(token), index, biteNum.mul(1 ether), biteNum.mul(_sheet.tokenAmountPerEth));
return;
}
/// @notice Close a price sheet of (ETH, USDx) | (ETH, NEST) | (ETH, TOKEN) | (ETH, NTOKEN)
/// @dev Here we allow an empty price sheet (still in VERIFICATION-PERIOD) to be closed
/// @param token The address of TOKEN contract
/// @param index The index of the price sheet w.r.t. `token`
function _close(
MiningV1Data.State storage state,
address token,
uint256 index
)
external
{
// load sheet
MiningV1Data.PriceSheet memory _sheet = state.priceSheetList[token][index];
// check if the sheet is closable
require(uint256(_sheet.height) + state.priceDurationBlock < block.number // safe_math
|| _sheet.remainNum == 0, "Nest:Mine:!(height)");
// check owner
require(address(_sheet.miner) == address(msg.sender), "Nest:Mine:!(miner)");
// check state flag
require(uint256(_sheet.state) != MiningV1Data.PRICESHEET_STATE_CLOSED, "Nest:Mine:!unclosed");
// load ntoken
INestPool _C_NestPool = INestPool(state.C_NestPool);
address _ntoken = _C_NestPool.getNTokenFromToken(token);
// distribute rewards (NEST or NTOKEN)
{
uint256 h = _sheet.height;
if (_sheet.typ == MiningV1Data.PRICESHEET_TYPE_USD && _sheet.level == 0) { // for (USDT, NEST)
uint256 _nestH = uint256(state.minedAtHeight[token][h] / (1 << 128));
uint256 _ethH = uint256(state.minedAtHeight[token][h] % (1 << 128));
uint256 _reward = uint256(_sheet.ethNum).mul(_nestH).div(_ethH);
_C_NestPool.addNest(address(msg.sender), _reward);
} else if (_sheet.typ == MiningV1Data.PRICESHEET_TYPE_TOKEN && _sheet.level == 0) { // for (ERC20, NTOKEN)
uint256 _ntokenH = uint256(state.minedAtHeight[token][h] / (1 << 128));
uint256 _ethH = uint256(state.minedAtHeight[token][h] % (1 << 128));
uint256 _reward = uint256(_sheet.ethNum).mul(_ntokenH).div(_ethH);
_C_NestPool.addNToken(address(msg.sender), _ntoken, _reward);
}
}
// unfreeze the assets withheld by the sheet
{
uint256 _ethAmount = uint256(_sheet.ethNumBal).mul(1 ether);
uint256 _tokenAmount = uint256(_sheet.tokenNumBal).mul(_sheet.tokenAmountPerEth);
uint256 _nestAmount = uint256(_sheet.nestNum1k).mul(1000 * 1e18);
_sheet.ethNumBal = 0;
_sheet.tokenNumBal = 0;
_sheet.nestNum1k = 0;
_C_NestPool.unfreezeEthAndToken(address(msg.sender), _ethAmount, token, _tokenAmount);
_C_NestPool.unfreezeNest(address(msg.sender), _nestAmount);
}
// update the state flag
_sheet.state = MiningV1Data.PRICESHEET_STATE_CLOSED;
// write back
state.priceSheetList[token][index] = _sheet;
// emit an event
emit MiningV1Data.PriceClosed(address(msg.sender), token, index);
}
/// @notice Close a price sheet and withdraw assets for WEB users.
/// @dev Contracts aren't allowed to call it.
/// @param token The address of TOKEN contract
/// @param index The index of the price sheet w.r.t. `token`
function _closeAndWithdraw(
MiningV1Data.State storage state,
address token,
uint256 index
)
external
{
// check sheet if passing verification
MiningV1Data.PriceSheet memory _sheet = state.priceSheetList[token][index];
require(uint256(_sheet.height) + state.priceDurationBlock < block.number // safe_math
|| _sheet.remainNum == 0, "Nest:Mine:!(height)");
// check ownership and state
require(address(_sheet.miner) == address(msg.sender), "Nest:Mine:!(miner)");
require(uint256(_sheet.state) != MiningV1Data.PRICESHEET_STATE_CLOSED, "Nest:Mine:!unclosed");
// get ntoken
INestPool _C_NestPool = INestPool(state.C_NestPool);
address _ntoken = _C_NestPool.getNTokenFromToken(token);
{
uint256 h = uint256(_sheet.height);
if (_sheet.typ == MiningV1Data.PRICESHEET_TYPE_USD && _sheet.level == 0) {
uint256 _nestH = uint256(state.minedAtHeight[token][h] / (1 << 128));
uint256 _ethH = uint256(state.minedAtHeight[token][h] % (1 << 128));
uint256 _reward = uint256(_sheet.ethNum).mul(_nestH).div(_ethH);
_C_NestPool.addNest(address(msg.sender), _reward);
} else if (_sheet.typ == MiningV1Data.PRICESHEET_TYPE_TOKEN && _sheet.level == 0) {
uint256 _ntokenH = uint256(state.minedAtHeight[token][h] / (1 << 128));
uint256 _ethH = uint256(state.minedAtHeight[token][h] % (1 << 128));
uint256 _reward = uint256(_sheet.ethNum).mul(_ntokenH).div(_ethH);
_C_NestPool.addNToken(address(msg.sender), _ntoken, _reward);
}
}
{
uint256 _ethAmount = uint256(_sheet.ethNumBal).mul(1 ether);
uint256 _tokenAmount = uint256(_sheet.tokenNumBal).mul(_sheet.tokenAmountPerEth);
uint256 _nestAmount = uint256(_sheet.nestNum1k).mul(1000 * 1e18);
_sheet.ethNumBal = 0;
_sheet.tokenNumBal = 0;
_sheet.nestNum1k = 0;
_C_NestPool.unfreezeEthAndToken(address(msg.sender), _ethAmount, token, _tokenAmount);
_C_NestPool.unfreezeNest(address(msg.sender), _nestAmount);
_C_NestPool.withdrawEthAndToken(address(msg.sender), _ethAmount, token, _tokenAmount);
_C_NestPool.withdrawNest(address(msg.sender), _nestAmount);
}
/*
- Issue #23:
Uncomment the following code to support withdrawing ethers cached
{
uint256 _ethAmount = _C_NestPool.balanceOfEthInPool(address(msg.sender));
if (_ethAmount > 0) {
_C_NestPool.withdrawEth(address(msg.sender), _ethAmount);
}
}
*/
_sheet.state = MiningV1Data.PRICESHEET_STATE_CLOSED;
state.priceSheetList[token][index] = _sheet;
emit MiningV1Data.PriceClosed(address(msg.sender), token, index);
}
/// @notice Close a batch of price sheets passed VERIFICATION-PHASE
/// @dev Empty sheets but in VERIFICATION-PHASE aren't allowed
/// @param token The address of TOKEN contract
/// @param indices A list of indices of sheets w.r.t. `token`
function _closeList(
MiningV1Data.State storage state,
address token,
uint32[] memory indices)
external
{
uint256 _ethAmount;
uint256 _tokenAmount;
uint256 _nestAmount;
uint256 _reward;
// load storage point to the list of price sheets
MiningV1Data.PriceSheet[] storage prices = state.priceSheetList[token];
// loop
for (uint i=0; i<indices.length; i++) {
// load one sheet
MiningV1Data.PriceSheet memory _sheet = prices[indices[i]];
// check owner
if (uint256(_sheet.miner) != uint256(msg.sender)) {
continue;
}
// check state
if(_sheet.state == MiningV1Data.PRICESHEET_STATE_CLOSED) {
continue;
}
uint256 h = uint256(_sheet.height);
// check if the sheet closable
if (h + state.priceDurationBlock < block.number || _sheet.remainNum == 0) { // safe_math: untainted values
// count up assets in the sheet
_ethAmount = _ethAmount.add(uint256(_sheet.ethNumBal).mul(1 ether));
_tokenAmount = _tokenAmount.add(uint256(_sheet.tokenNumBal).mul(_sheet.tokenAmountPerEth));
_nestAmount = _nestAmount.add(uint256(_sheet.nestNum1k).mul(1000 * 1e18));
// clear bits in the sheet
_sheet.ethNumBal = 0;
_sheet.tokenNumBal = 0;
_sheet.nestNum1k = 0;
// update state flag
_sheet.state = MiningV1Data.PRICESHEET_STATE_CLOSED;
// write back
prices[indices[i]] = _sheet;
// count up the reward
if(_sheet.level == 0 && (_sheet.typ == MiningV1Data.PRICESHEET_TYPE_USD || _sheet.typ == MiningV1Data.PRICESHEET_TYPE_TOKEN)) {
uint256 _ntokenH = uint256(state.minedAtHeight[token][h] >> 128);
uint256 _ethH = uint256(state.minedAtHeight[token][h] << 128 >> 128);
_reward = _reward.add(uint256(_sheet.ethNum).mul(_ntokenH).div(_ethH));
}
emit MiningV1Data.PriceClosed(address(msg.sender), token, indices[i]);
}
}
// load address of NestPool (for gas saving)
INestPool _C_NestPool = INestPool(state.C_NestPool);
// unfreeze assets
if (_ethAmount > 0 || _tokenAmount > 0) {
_C_NestPool.unfreezeEthAndToken(address(msg.sender), _ethAmount, token, _tokenAmount);
}
_C_NestPool.unfreezeNest(address(msg.sender), _nestAmount);
// distribute the rewards
{
uint256 _typ = prices[indices[0]].typ;
if (_typ == MiningV1Data.PRICESHEET_TYPE_USD) {
_C_NestPool.addNest(address(msg.sender), _reward);
} else if (_typ == MiningV1Data.PRICESHEET_TYPE_TOKEN) {
address _ntoken = _C_NestPool.getNTokenFromToken(token);
_C_NestPool.addNToken(address(msg.sender), _ntoken, _reward);
}
}
}
/*
/// @dev This function is only for post dual-price-sheet before upgrading without assets
function _post2Only4Upgrade(
MiningV1Data.State storage state,
address token,
uint256 ethNum,
uint256 tokenAmountPerEth,
uint256 ntokenAmountPerEth
)
external
{
// check parameters
require(ethNum == state.miningEthUnit, "Nest:Mine:!(ethNum)");
require(tokenAmountPerEth > 0 && ntokenAmountPerEth > 0, "Nest:Mine:!(price)");
address _ntoken = INestPool(state.C_NestPool).getNTokenFromToken(token);
// no eth fee, no freezing
// push sheets
{
uint8 typ1;
uint8 typ2;
if (_ntoken == address(state.C_NestToken)) {
typ1 = MiningV1Data.PRICESHEET_TYPE_USD;
typ2 = MiningV1Data.PRICESHEET_TYPE_NEST;
} else {
typ1 = MiningV1Data.PRICESHEET_TYPE_TOKEN;
typ2 = MiningV1Data.PRICESHEET_TYPE_NTOKEN;
}
MiningV1Data.PriceSheet[] storage _sheetToken = state.priceSheetList[token];
// append a new price sheet
_sheetToken.push(MiningV1Data.PriceSheet(
uint160(msg.sender), // miner
uint32(block.number), // atHeight
uint32(ethNum), // ethNum
uint32(ethNum), // remainNum
uint8(0), // level
uint8(typ1), // typ
uint8(MiningV1Data.PRICESHEET_STATE_CLOSED), // state
uint8(0), // _reserved
uint32(ethNum), // ethNumBal
uint32(ethNum), // tokenNumBal
uint32(state.nestStakedNum1k), // nestNum1k
uint128(tokenAmountPerEth) // tokenAmountPerEth
));
MiningV1Data.PriceSheet[] storage _sheetNToken = state.priceSheetList[_ntoken];
// append a new price sheet for ntoken
_sheetNToken.push(MiningV1Data.PriceSheet(
uint160(msg.sender), // miner
uint32(block.number), // atHeight
uint32(ethNum), // ethNum
uint32(ethNum), // remainNum
uint8(0), // level
uint8(typ2), // typ
uint8(MiningV1Data.PRICESHEET_STATE_CLOSED), // state
uint8(0), // _reserved
uint32(ethNum), // ethNumBal
uint32(ethNum), // tokenNumBal
uint32(state.nestStakedNum1k), // nestNum1k
uint128(ntokenAmountPerEth) // tokenAmountPerEth
));
emit MiningV1Data.PricePosted(msg.sender, token, (_sheetToken.length - 1), ethNum.mul(1 ether), tokenAmountPerEth.mul(ethNum));
emit MiningV1Data.PricePosted(msg.sender, _ntoken, (_sheetNToken.length - 1), ethNum.mul(1 ether), ntokenAmountPerEth.mul(ethNum));
}
// no mining
return;
}
*/
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.6.12;
// a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math)
library SafeMath {
function add(uint x, uint y) internal pure returns (uint z) {
require((z = x + y) >= x, 'ds-math-add-overflow');
}
function sub(uint x, uint y) internal pure returns (uint z) {
require((z = x - y) <= x, 'ds-math-sub-underflow');
}
function mul(uint x, uint y) internal pure returns (uint z) {
require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow');
}
function div(uint x, uint y) internal pure returns (uint z) {
require(y > 0, "ds-math-div-zero");
z = x / y;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
}
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.6.12;
import "./Address.sol";
import "./SafeMath.sol";
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(ERC20 token, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(ERC20 token, address from, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(ERC20 token, address spender, uint256 value) internal {
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(ERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(ERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function callOptionalReturn(ERC20 token, bytes memory data) private {
require(address(token).isContract(), "SafeERC20: call to non-contract");
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
interface ERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.6.12;
// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
library TransferHelper {
function safeApprove(address token, address to, uint value) internal {
// bytes4(keccak256(bytes('approve(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');
}
function safeTransfer(address token, address to, uint value) internal {
// bytes4(keccak256(bytes('transfer(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');
}
function safeTransferFrom(address token, address from, address to, uint value) internal {
// bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
}
function safeTransferETH(address to, uint value) internal {
(bool success,) = to.call{value:value}(new bytes(0));
require(success, 'TransferHelper: ETH_TRANSFER_FAILED');
}
}// SPDX-License-Identifier: Copyright © 2019 by ABDK Consulting
/*
* ABDK Math 64.64 Smart Contract Library. Copyright © 2019 by ABDK Consulting.
* Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>
*/
pragma solidity 0.6.12;
/**
* Smart contract library of mathematical functions operating with signed
* 64.64-bit fixed point numbers. Signed 64.64-bit fixed point number is
* basically a simple fraction whose numerator is signed 128-bit integer and
* denominator is 2^64. As long as denominator is always the same, there is no
* need to store it, thus in Solidity signed 64.64-bit fixed point numbers are
* represented by int128 type holding only the numerator.
*/
library ABDKMath64x64 {
/**
* @dev Minimum value signed 64.64-bit fixed point number may have.
*/
int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;
/**
* @dev Maximum value signed 64.64-bit fixed point number may have.
*/
int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
/**
* Convert signed 256-bit integer number into signed 64.64-bit fixed point
* number. Revert on overflow.
*
* @param x signed 256-bit integer number
* @return signed 64.64-bit fixed point number
*/
function fromInt (int256 x) internal pure returns (int128) {
require (x >= -0x8000000000000000 && x <= 0x7FFFFFFFFFFFFFFF);
return int128 (x << 64);
}
/**
* Convert signed 64.64 fixed point number into signed 64-bit integer number
* rounding down.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64-bit integer number
*/
function toInt (int128 x) internal pure returns (int64) {
return int64 (x >> 64);
}
/**
* Convert unsigned 256-bit integer number into signed 64.64-bit fixed point
* number. Revert on overflow.
*
* @param x unsigned 256-bit integer number
* @return signed 64.64-bit fixed point number
*/
function fromUInt (uint256 x) internal pure returns (int128) {
require (x <= 0x7FFFFFFFFFFFFFFF);
return int128 (x << 64);
}
/**
* Convert signed 64.64 fixed point number into unsigned 64-bit integer
* number rounding down. Revert on underflow.
*
* @param x signed 64.64-bit fixed point number
* @return unsigned 64-bit integer number
*/
function toUInt (int128 x) internal pure returns (uint64) {
require (x >= 0);
return uint64 (x >> 64);
}
/**
* Convert signed 128.128 fixed point number into signed 64.64-bit fixed point
* number rounding down. Revert on overflow.
*
* @param x signed 128.128-bin fixed point number
* @return signed 64.64-bit fixed point number
*/
function from128x128 (int256 x) internal pure returns (int128) {
int256 result = x >> 64;
require (result >= MIN_64x64 && result <= MAX_64x64);
return int128 (result);
}
/**
* Convert signed 64.64 fixed point number into signed 128.128 fixed point
* number.
*
* @param x signed 64.64-bit fixed point number
* @return signed 128.128 fixed point number
*/
function to128x128 (int128 x) internal pure returns (int256) {
return int256 (x) << 64;
}
/**
* Calculate x + y. Revert on overflow.
*
* @param x signed 64.64-bit fixed point number
* @param y signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function add (int128 x, int128 y) internal pure returns (int128) {
int256 result = int256(x) + y;
require (result >= MIN_64x64 && result <= MAX_64x64);
return int128 (result);
}
/**
* Calculate x - y. Revert on overflow.
*
* @param x signed 64.64-bit fixed point number
* @param y signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function sub (int128 x, int128 y) internal pure returns (int128) {
int256 result = int256(x) - y;
require (result >= MIN_64x64 && result <= MAX_64x64);
return int128 (result);
}
/**
* Calculate x * y rounding down. Revert on overflow.
*
* @param x signed 64.64-bit fixed point number
* @param y signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function mul (int128 x, int128 y) internal pure returns (int128) {
int256 result = int256(x) * y >> 64;
require (result >= MIN_64x64 && result <= MAX_64x64);
return int128 (result);
}
/**
* Calculate x * y rounding towards zero, where x is signed 64.64 fixed point
* number and y is signed 256-bit integer number. Revert on overflow.
*
* @param x signed 64.64 fixed point number
* @param y signed 256-bit integer number
* @return signed 256-bit integer number
*/
function muli (int128 x, int256 y) internal pure returns (int256) {
if (x == MIN_64x64) {
require (y >= -0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF &&
y <= 0x1000000000000000000000000000000000000000000000000);
return -y << 63;
} else {
bool negativeResult = false;
if (x < 0) {
x = -x;
negativeResult = true;
}
if (y < 0) {
y = -y; // We rely on overflow behavior here
negativeResult = !negativeResult;
}
uint256 absoluteResult = mulu (x, uint256 (y));
if (negativeResult) {
require (absoluteResult <=
0x8000000000000000000000000000000000000000000000000000000000000000);
return -int256 (absoluteResult); // We rely on overflow behavior here
} else {
require (absoluteResult <=
0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
return int256 (absoluteResult);
}
}
}
/**
* Calculate x * y rounding down, where x is signed 64.64 fixed point number
* and y is unsigned 256-bit integer number. Revert on overflow.
*
* @param x signed 64.64 fixed point number
* @param y unsigned 256-bit integer number
* @return unsigned 256-bit integer number
*/
function mulu (int128 x, uint256 y) internal pure returns (uint256) {
if (y == 0) return 0;
require (x >= 0);
uint256 lo = (uint256 (x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;
uint256 hi = uint256 (x) * (y >> 128);
require (hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
hi <<= 64;
require (hi <=
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo);
return hi + lo;
}
/**
* Calculate x / y rounding towards zero. Revert on overflow or when y is
* zero.
*
* @param x signed 64.64-bit fixed point number
* @param y signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function div (int128 x, int128 y) internal pure returns (int128) {
require (y != 0);
int256 result = (int256 (x) << 64) / y;
require (result >= MIN_64x64 && result <= MAX_64x64);
return int128 (result);
}
/**
* Calculate x / y rounding towards zero, where x and y are signed 256-bit
* integer numbers. Revert on overflow or when y is zero.
*
* @param x signed 256-bit integer number
* @param y signed 256-bit integer number
* @return signed 64.64-bit fixed point number
*/
function divi (int256 x, int256 y) internal pure returns (int128) {
require (y != 0);
bool negativeResult = false;
if (x < 0) {
x = -x; // We rely on overflow behavior here
negativeResult = true;
}
if (y < 0) {
y = -y; // We rely on overflow behavior here
negativeResult = !negativeResult;
}
uint128 absoluteResult = divuu (uint256 (x), uint256 (y));
if (negativeResult) {
require (absoluteResult <= 0x80000000000000000000000000000000);
return -int128 (absoluteResult); // We rely on overflow behavior here
} else {
require (absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
return int128 (absoluteResult); // We rely on overflow behavior here
}
}
/**
* Calculate x / y rounding towards zero, where x and y are unsigned 256-bit
* integer numbers. Revert on overflow or when y is zero.
*
* @param x unsigned 256-bit integer number
* @param y unsigned 256-bit integer number
* @return signed 64.64-bit fixed point number
*/
function divu (uint256 x, uint256 y) internal pure returns (int128) {
require (y != 0);
uint128 result = divuu (x, y);
require (result <= uint128 (MAX_64x64));
return int128 (result);
}
/**
* Calculate -x. Revert on overflow.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function neg (int128 x) internal pure returns (int128) {
require (x != MIN_64x64);
return -x;
}
/**
* Calculate |x|. Revert on overflow.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function abs (int128 x) internal pure returns (int128) {
require (x != MIN_64x64);
return x < 0 ? -x : x;
}
/**
* Calculate 1 / x rounding towards zero. Revert on overflow or when x is
* zero.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function inv (int128 x) internal pure returns (int128) {
require (x != 0);
int256 result = int256 (0x100000000000000000000000000000000) / x;
require (result >= MIN_64x64 && result <= MAX_64x64);
return int128 (result);
}
/**
* Calculate arithmetics average of x and y, i.e. (x + y) / 2 rounding down.
*
* @param x signed 64.64-bit fixed point number
* @param y signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function avg (int128 x, int128 y) internal pure returns (int128) {
return int128 ((int256 (x) + int256 (y)) >> 1);
}
/**
* Calculate geometric average of x and y, i.e. sqrt (x * y) rounding down.
* Revert on overflow or in case x * y is negative.
*
* @param x signed 64.64-bit fixed point number
* @param y signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function gavg (int128 x, int128 y) internal pure returns (int128) {
int256 m = int256 (x) * int256 (y);
require (m >= 0);
require (m <
0x4000000000000000000000000000000000000000000000000000000000000000);
return int128 (sqrtu (uint256 (m), uint256 (x) + uint256 (y) >> 1));
}
/**
* Calculate x^y assuming 0^0 is 1, where x is signed 64.64 fixed point number
* and y is unsigned 256-bit integer number. Revert on overflow.
*
* @param x signed 64.64-bit fixed point number
* @param y uint256 value
* @return signed 64.64-bit fixed point number
*/
function pow (int128 x, uint256 y) internal pure returns (int128) {
uint256 absoluteResult;
bool negativeResult = false;
if (x >= 0) {
absoluteResult = powu (uint256 (x) << 63, y);
} else {
// We rely on overflow behavior here
absoluteResult = powu (uint256 (uint128 (-x)) << 63, y);
negativeResult = y & 1 > 0;
}
absoluteResult >>= 63;
if (negativeResult) {
require (absoluteResult <= 0x80000000000000000000000000000000);
return -int128 (absoluteResult); // We rely on overflow behavior here
} else {
require (absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
return int128 (absoluteResult); // We rely on overflow behavior here
}
}
/**
* Calculate sqrt (x) rounding down. Revert if x < 0.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function sqrt (int128 x) internal pure returns (int128) {
require (x >= 0);
return int128 (sqrtu (uint256 (x) << 64, 0x10000000000000000));
}
/**
* Calculate binary logarithm of x. Revert if x <= 0.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function log_2 (int128 x) internal pure returns (int128) {
require (x > 0);
int256 msb = 0;
int256 xc = x;
if (xc >= 0x10000000000000000) { xc >>= 64; msb += 64; }
if (xc >= 0x100000000) { xc >>= 32; msb += 32; }
if (xc >= 0x10000) { xc >>= 16; msb += 16; }
if (xc >= 0x100) { xc >>= 8; msb += 8; }
if (xc >= 0x10) { xc >>= 4; msb += 4; }
if (xc >= 0x4) { xc >>= 2; msb += 2; }
if (xc >= 0x2) msb += 1; // No need to shift xc anymore
int256 result = msb - 64 << 64;
uint256 ux = uint256 (x) << 127 - msb;
for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {
ux *= ux;
uint256 b = ux >> 255;
ux >>= 127 + b;
result += bit * int256 (b);
}
return int128 (result);
}
/**
* Calculate natural logarithm of x. Revert if x <= 0.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function ln (int128 x) internal pure returns (int128) {
require (x > 0);
return int128 (
uint256 (log_2 (x)) * 0xB17217F7D1CF79ABC9E3B39803F2F6AF >> 128);
}
/**
* Calculate binary exponent of x. Revert on overflow.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function exp_2 (int128 x) internal pure returns (int128) {
require (x < 0x400000000000000000); // Overflow
if (x < -0x400000000000000000) return 0; // Underflow
uint256 result = 0x80000000000000000000000000000000;
if (x & 0x8000000000000000 > 0)
result = result * 0x16A09E667F3BCC908B2FB1366EA957D3E >> 128;
if (x & 0x4000000000000000 > 0)
result = result * 0x1306FE0A31B7152DE8D5A46305C85EDEC >> 128;
if (x & 0x2000000000000000 > 0)
result = result * 0x1172B83C7D517ADCDF7C8C50EB14A791F >> 128;
if (x & 0x1000000000000000 > 0)
result = result * 0x10B5586CF9890F6298B92B71842A98363 >> 128;
if (x & 0x800000000000000 > 0)
result = result * 0x1059B0D31585743AE7C548EB68CA417FD >> 128;
if (x & 0x400000000000000 > 0)
result = result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8 >> 128;
if (x & 0x200000000000000 > 0)
result = result * 0x10163DA9FB33356D84A66AE336DCDFA3F >> 128;
if (x & 0x100000000000000 > 0)
result = result * 0x100B1AFA5ABCBED6129AB13EC11DC9543 >> 128;
if (x & 0x80000000000000 > 0)
result = result * 0x10058C86DA1C09EA1FF19D294CF2F679B >> 128;
if (x & 0x40000000000000 > 0)
result = result * 0x1002C605E2E8CEC506D21BFC89A23A00F >> 128;
if (x & 0x20000000000000 > 0)
result = result * 0x100162F3904051FA128BCA9C55C31E5DF >> 128;
if (x & 0x10000000000000 > 0)
result = result * 0x1000B175EFFDC76BA38E31671CA939725 >> 128;
if (x & 0x8000000000000 > 0)
result = result * 0x100058BA01FB9F96D6CACD4B180917C3D >> 128;
if (x & 0x4000000000000 > 0)
result = result * 0x10002C5CC37DA9491D0985C348C68E7B3 >> 128;
if (x & 0x2000000000000 > 0)
result = result * 0x1000162E525EE054754457D5995292026 >> 128;
if (x & 0x1000000000000 > 0)
result = result * 0x10000B17255775C040618BF4A4ADE83FC >> 128;
if (x & 0x800000000000 > 0)
result = result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB >> 128;
if (x & 0x400000000000 > 0)
result = result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9 >> 128;
if (x & 0x200000000000 > 0)
result = result * 0x10000162E43F4F831060E02D839A9D16D >> 128;
if (x & 0x100000000000 > 0)
result = result * 0x100000B1721BCFC99D9F890EA06911763 >> 128;
if (x & 0x80000000000 > 0)
result = result * 0x10000058B90CF1E6D97F9CA14DBCC1628 >> 128;
if (x & 0x40000000000 > 0)
result = result * 0x1000002C5C863B73F016468F6BAC5CA2B >> 128;
if (x & 0x20000000000 > 0)
result = result * 0x100000162E430E5A18F6119E3C02282A5 >> 128;
if (x & 0x10000000000 > 0)
result = result * 0x1000000B1721835514B86E6D96EFD1BFE >> 128;
if (x & 0x8000000000 > 0)
result = result * 0x100000058B90C0B48C6BE5DF846C5B2EF >> 128;
if (x & 0x4000000000 > 0)
result = result * 0x10000002C5C8601CC6B9E94213C72737A >> 128;
if (x & 0x2000000000 > 0)
result = result * 0x1000000162E42FFF037DF38AA2B219F06 >> 128;
if (x & 0x1000000000 > 0)
result = result * 0x10000000B17217FBA9C739AA5819F44F9 >> 128;
if (x & 0x800000000 > 0)
result = result * 0x1000000058B90BFCDEE5ACD3C1CEDC823 >> 128;
if (x & 0x400000000 > 0)
result = result * 0x100000002C5C85FE31F35A6A30DA1BE50 >> 128;
if (x & 0x200000000 > 0)
result = result * 0x10000000162E42FF0999CE3541B9FFFCF >> 128;
if (x & 0x100000000 > 0)
result = result * 0x100000000B17217F80F4EF5AADDA45554 >> 128;
if (x & 0x80000000 > 0)
result = result * 0x10000000058B90BFBF8479BD5A81B51AD >> 128;
if (x & 0x40000000 > 0)
result = result * 0x1000000002C5C85FDF84BD62AE30A74CC >> 128;
if (x & 0x20000000 > 0)
result = result * 0x100000000162E42FEFB2FED257559BDAA >> 128;
if (x & 0x10000000 > 0)
result = result * 0x1000000000B17217F7D5A7716BBA4A9AE >> 128;
if (x & 0x8000000 > 0)
result = result * 0x100000000058B90BFBE9DDBAC5E109CCE >> 128;
if (x & 0x4000000 > 0)
result = result * 0x10000000002C5C85FDF4B15DE6F17EB0D >> 128;
if (x & 0x2000000 > 0)
result = result * 0x1000000000162E42FEFA494F1478FDE05 >> 128;
if (x & 0x1000000 > 0)
result = result * 0x10000000000B17217F7D20CF927C8E94C >> 128;
if (x & 0x800000 > 0)
result = result * 0x1000000000058B90BFBE8F71CB4E4B33D >> 128;
if (x & 0x400000 > 0)
result = result * 0x100000000002C5C85FDF477B662B26945 >> 128;
if (x & 0x200000 > 0)
result = result * 0x10000000000162E42FEFA3AE53369388C >> 128;
if (x & 0x100000 > 0)
result = result * 0x100000000000B17217F7D1D351A389D40 >> 128;
if (x & 0x80000 > 0)
result = result * 0x10000000000058B90BFBE8E8B2D3D4EDE >> 128;
if (x & 0x40000 > 0)
result = result * 0x1000000000002C5C85FDF4741BEA6E77E >> 128;
if (x & 0x20000 > 0)
result = result * 0x100000000000162E42FEFA39FE95583C2 >> 128;
if (x & 0x10000 > 0)
result = result * 0x1000000000000B17217F7D1CFB72B45E1 >> 128;
if (x & 0x8000 > 0)
result = result * 0x100000000000058B90BFBE8E7CC35C3F0 >> 128;
if (x & 0x4000 > 0)
result = result * 0x10000000000002C5C85FDF473E242EA38 >> 128;
if (x & 0x2000 > 0)
result = result * 0x1000000000000162E42FEFA39F02B772C >> 128;
if (x & 0x1000 > 0)
result = result * 0x10000000000000B17217F7D1CF7D83C1A >> 128;
if (x & 0x800 > 0)
result = result * 0x1000000000000058B90BFBE8E7BDCBE2E >> 128;
if (x & 0x400 > 0)
result = result * 0x100000000000002C5C85FDF473DEA871F >> 128;
if (x & 0x200 > 0)
result = result * 0x10000000000000162E42FEFA39EF44D91 >> 128;
if (x & 0x100 > 0)
result = result * 0x100000000000000B17217F7D1CF79E949 >> 128;
if (x & 0x80 > 0)
result = result * 0x10000000000000058B90BFBE8E7BCE544 >> 128;
if (x & 0x40 > 0)
result = result * 0x1000000000000002C5C85FDF473DE6ECA >> 128;
if (x & 0x20 > 0)
result = result * 0x100000000000000162E42FEFA39EF366F >> 128;
if (x & 0x10 > 0)
result = result * 0x1000000000000000B17217F7D1CF79AFA >> 128;
if (x & 0x8 > 0)
result = result * 0x100000000000000058B90BFBE8E7BCD6D >> 128;
if (x & 0x4 > 0)
result = result * 0x10000000000000002C5C85FDF473DE6B2 >> 128;
if (x & 0x2 > 0)
result = result * 0x1000000000000000162E42FEFA39EF358 >> 128;
if (x & 0x1 > 0)
result = result * 0x10000000000000000B17217F7D1CF79AB >> 128;
result >>= 63 - (x >> 64);
require (result <= uint256 (MAX_64x64));
return int128 (result);
}
/**
* Calculate natural exponent of x. Revert on overflow.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function exp (int128 x) internal pure returns (int128) {
require (x < 0x400000000000000000); // Overflow
if (x < -0x400000000000000000) return 0; // Underflow
return exp_2 (
int128 (int256 (x) * 0x171547652B82FE1777D0FFDA0D23A7D12 >> 128));
}
/**
* Calculate x / y rounding towards zero, where x and y are unsigned 256-bit
* integer numbers. Revert on overflow or when y is zero.
*
* @param x unsigned 256-bit integer number
* @param y unsigned 256-bit integer number
* @return unsigned 64.64-bit fixed point number
*/
function divuu (uint256 x, uint256 y) private pure returns (uint128) {
require (y != 0);
uint256 result;
if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
result = (x << 64) / y;
else {
uint256 msb = 192;
uint256 xc = x >> 192;
if (xc >= 0x100000000) { xc >>= 32; msb += 32; }
if (xc >= 0x10000) { xc >>= 16; msb += 16; }
if (xc >= 0x100) { xc >>= 8; msb += 8; }
if (xc >= 0x10) { xc >>= 4; msb += 4; }
if (xc >= 0x4) { xc >>= 2; msb += 2; }
if (xc >= 0x2) msb += 1; // No need to shift xc anymore
result = (x << 255 - msb) / ((y - 1 >> msb - 191) + 1);
require (result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
uint256 hi = result * (y >> 128);
uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
uint256 xh = x >> 192;
uint256 xl = x << 64;
if (xl < lo) xh -= 1;
xl -= lo; // We rely on overflow behavior here
lo = hi << 128;
if (xl < lo) xh -= 1;
xl -= lo; // We rely on overflow behavior here
assert (xh == hi >> 128);
result += xl / y;
}
require (result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
return uint128 (result);
}
/**
* Calculate x^y assuming 0^0 is 1, where x is unsigned 129.127 fixed point
* number and y is unsigned 256-bit integer number. Revert on overflow.
*
* @param x unsigned 129.127-bit fixed point number
* @param y uint256 value
* @return unsigned 129.127-bit fixed point number
*/
function powu (uint256 x, uint256 y) private pure returns (uint256) {
if (y == 0) return 0x80000000000000000000000000000000;
else if (x == 0) return 0;
else {
int256 msb = 0;
uint256 xc = x;
if (xc >= 0x100000000000000000000000000000000) { xc >>= 128; msb += 128; }
if (xc >= 0x10000000000000000) { xc >>= 64; msb += 64; }
if (xc >= 0x100000000) { xc >>= 32; msb += 32; }
if (xc >= 0x10000) { xc >>= 16; msb += 16; }
if (xc >= 0x100) { xc >>= 8; msb += 8; }
if (xc >= 0x10) { xc >>= 4; msb += 4; }
if (xc >= 0x4) { xc >>= 2; msb += 2; }
if (xc >= 0x2) msb += 1; // No need to shift xc anymore
int256 xe = msb - 127;
if (xe > 0) x >>= xe;
else x <<= -xe;
uint256 result = 0x80000000000000000000000000000000;
int256 re = 0;
while (y > 0) {
if (y & 1 > 0) {
result = result * x;
y -= 1;
re += xe;
if (result >=
0x8000000000000000000000000000000000000000000000000000000000000000) {
result >>= 128;
re += 1;
} else result >>= 127;
if (re < -127) return 0; // Underflow
require (re < 128); // Overflow
} else {
x = x * x;
y >>= 1;
xe <<= 1;
if (x >=
0x8000000000000000000000000000000000000000000000000000000000000000) {
x >>= 128;
xe += 1;
} else x >>= 127;
if (xe < -127) return 0; // Underflow
require (xe < 128); // Overflow
}
}
if (re > 0) result <<= re;
else if (re < 0) result >>= -re;
return result;
}
}
/**
* Calculate sqrt (x) rounding down, where x is unsigned 256-bit integer
* number.
*
* @param x unsigned 256-bit integer number
* @return unsigned 128-bit integer number
*/
function sqrtu (uint256 x, uint256 r) private pure returns (uint128) {
if (x == 0) return 0;
else {
require (r > 0);
while (true) {
uint256 rr = x / r;
if (r == rr || r + 1 == rr) return uint128 (r);
else if (r == rr + 1) return uint128 (rr);
r = r + rr + 1 >> 1;
}
}
}
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.6.12;
import "../lib/SafeERC20.sol";
interface INestPool {
// function getNTokenFromToken(address token) view external returns (address);
// function setNTokenToToken(address token, address ntoken) external;
function addNest(address miner, uint256 amount) external;
function addNToken(address contributor, address ntoken, uint256 amount) external;
function depositEth(address miner) external payable;
function depositNToken(address miner, address from, address ntoken, uint256 amount) external;
function freezeEth(address miner, uint256 ethAmount) external;
function unfreezeEth(address miner, uint256 ethAmount) external;
function freezeNest(address miner, uint256 nestAmount) external;
function unfreezeNest(address miner, uint256 nestAmount) external;
function freezeToken(address miner, address token, uint256 tokenAmount) external;
function unfreezeToken(address miner, address token, uint256 tokenAmount) external;
function freezeEthAndToken(address miner, uint256 ethAmount, address token, uint256 tokenAmount) external;
function unfreezeEthAndToken(address miner, uint256 ethAmount, address token, uint256 tokenAmount) external;
function getNTokenFromToken(address token) external view returns (address);
function setNTokenToToken(address token, address ntoken) external;
function withdrawEth(address miner, uint256 ethAmount) external;
function withdrawToken(address miner, address token, uint256 tokenAmount) external;
function withdrawNest(address miner, uint256 amount) external;
function withdrawEthAndToken(address miner, uint256 ethAmount, address token, uint256 tokenAmount) external;
// function withdrawNToken(address miner, address ntoken, uint256 amount) external;
function withdrawNTokenAndTransfer(address miner, address ntoken, uint256 amount, address to) external;
function balanceOfNestInPool(address miner) external view returns (uint256);
function balanceOfEthInPool(address miner) external view returns (uint256);
function balanceOfTokenInPool(address miner, address token) external view returns (uint256);
function addrOfNestToken() external view returns (address);
function addrOfNestMining() external view returns (address);
function addrOfNTokenController() external view returns (address);
function addrOfNNRewardPool() external view returns (address);
function addrOfNNToken() external view returns (address);
function addrOfNestStaking() external view returns (address);
function addrOfNestQuery() external view returns (address);
function addrOfNestDAO() external view returns (address);
function addressOfBurnedNest() external view returns (address);
function setGovernance(address _gov) external;
function governance() external view returns(address);
function initNestLedger(uint256 amount) external;
function drainNest(address to, uint256 amount, address gov) external;
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.6.12;
interface INestStaking {
// Views
/// @dev How many stakingToken (XToken) deposited into to this reward pool (staking pool)
/// @param ntoken The address of NToken
/// @return The total amount of XTokens deposited in this staking pool
function totalStaked(address ntoken) external view returns (uint256);
/// @dev How many stakingToken (XToken) deposited by the target account
/// @param ntoken The address of NToken
/// @param account The target account
/// @return The total amount of XToken deposited in this staking pool
function stakedBalanceOf(address ntoken, address account) external view returns (uint256);
// Mutative
/// @dev Stake/Deposit into the reward pool (staking pool)
/// @param ntoken The address of NToken
/// @param amount The target amount
function stake(address ntoken, uint256 amount) external;
function stakeFromNestPool(address ntoken, uint256 amount) external;
/// @dev Withdraw from the reward pool (staking pool), get the original tokens back
/// @param ntoken The address of NToken
/// @param amount The target amount
function unstake(address ntoken, uint256 amount) external;
/// @dev Claim the reward the user earned
/// @param ntoken The address of NToken
/// @return The amount of ethers as rewards
function claim(address ntoken) external returns (uint256);
/// @dev Add ETH reward to the staking pool
/// @param ntoken The address of NToken
function addETHReward(address ntoken) external payable;
/// @dev Only for governance
function loadContracts() external;
/// @dev Only for governance
function loadGovernance() external;
function pause() external;
function resume() external;
//function setParams(uint8 dividendShareRate) external;
/* ========== EVENTS ========== */
// Events
event RewardAdded(address ntoken, address sender, uint256 reward);
event NTokenStaked(address ntoken, address indexed user, uint256 amount);
event NTokenUnstaked(address ntoken, address indexed user, uint256 amount);
event SavingWithdrawn(address ntoken, address indexed to, uint256 amount);
event RewardClaimed(address ntoken, address indexed user, uint256 reward);
event FlagSet(address gov, uint256 flag);
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.6.12;
interface INTokenLegacy {
function increaseTotal(uint256 value) external;
// the block height where the ntoken was created
function checkBlockInfo() external view returns(uint256 createBlock, uint256 recentlyUsedBlock);
// the owner (auction winner) of the ntoken
function checkBidder() external view returns(address);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;
import "../lib/SafeERC20.sol";
interface INestMining {
struct Params {
uint8 miningEthUnit; // = 10;
uint32 nestStakedNum1k; // = 1;
uint8 biteFeeRate; // = 1;
uint8 miningFeeRate; // = 10;
uint8 priceDurationBlock;
uint8 maxBiteNestedLevel; // = 3;
uint8 biteInflateFactor;
uint8 biteNestInflateFactor;
}
function priceOf(address token) external view returns(uint256 ethAmount, uint256 tokenAmount, uint256 bn);
function priceListOfToken(address token, uint8 num) external view returns(uint128[] memory data, uint256 bn);
// function priceOfTokenAtHeight(address token, uint64 atHeight) external view returns(uint256 ethAmount, uint256 tokenAmount, uint64 bn);
function latestPriceOf(address token) external view returns (uint256 ethAmount, uint256 tokenAmount, uint256 bn);
function priceAvgAndSigmaOf(address token)
external view returns (uint128, uint128, int128, uint32);
function minedNestAmount() external view returns (uint256);
/// @dev Only for governance
function loadContracts() external;
function loadGovernance() external;
function upgrade() external;
function setup(uint32 genesisBlockNumber, uint128 latestMiningHeight, uint128 minedNestTotalAmount, Params calldata initParams) external;
function setParams1(uint128 latestMiningHeight, uint128 minedNestTotalAmount) external;
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.6.12;
interface INestDAO {
function addETHReward(address ntoken) external payable;
function addNestReward(uint256 amount) external;
/// @dev Only for governance
function loadContracts() external;
/// @dev Only for governance
function loadGovernance() external;
/// @dev Only for governance
function start() external;
function initEthLedger(address ntoken, uint256 amount) external;
event NTokenRedeemed(address ntoken, address user, uint256 amount);
event AssetsCollected(address user, uint256 ethAmount, uint256 nestAmount);
event ParamsSetup(address gov, uint256 oldParam, uint256 newParam);
event FlagSet(address gov, uint256 flag);
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.6.12;
interface INToken {
// mint ntoken for value
function mint(uint256 amount, address account) external;
// the block height where the ntoken was created
function checkBlockInfo() external view returns(uint256 createBlock, uint256 recentlyUsedBlock);
// the owner (auction winner) of the ntoken
function checkBidder() external view returns(address);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.6.12;
/// @title NNRewardPool
/// @author Inf Loop - <inf-loop@nestprotocol.org>
/// @author Paradox - <paradox@nestprotocol.org>
interface INNRewardPool {
/* [DEPRECATED]
uint256 constant DEV_REWARD_PERCENTAGE = 5;
uint256 constant NN_REWARD_PERCENTAGE = 15;
uint256 constant MINER_REWARD_PERCENTAGE = 80;
*/
/// @notice Add rewards for Nest-Nodes, only governance or NestMining (contract) are allowed
/// @dev The rewards need to pull from NestPool
/// @param _amount The amount of Nest token as the rewards to each nest-node
function addNNReward(uint256 _amount) external;
/// @notice Claim rewards by Nest-Nodes
/// @dev The rewards need to pull from NestPool
function claimNNReward() external ;
/// @dev The callback function called by NNToken.transfer()
/// @param fromAdd The address of 'from' to transfer
/// @param toAdd The address of 'to' to transfer
function nodeCount(address fromAdd, address toAdd) external;
/// @notice Show the amount of rewards unclaimed
/// @return reward The reward of a NN holder
function unclaimedNNReward() external view returns (uint256 reward);
/// @dev Only for governance
function loadContracts() external;
/// @dev Only for governance
function loadGovernance() external;
/* ========== EVENTS ============== */
/// @notice When rewards are added to the pool
/// @param reward The amount of Nest Token
/// @param allRewards The snapshot of all rewards accumulated
event NNRewardAdded(uint256 reward, uint256 allRewards);
/// @notice When rewards are claimed by nodes
/// @param nnode The address of the nest node
/// @param share The amount of Nest Token claimed by the nest node
event NNRewardClaimed(address nnode, uint256 share);
/// @notice When flag of state is set by governance
/// @param gov The address of the governance
/// @param flag The value of the new flag
event FlagSet(address gov, uint256 flag);
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.6.12;
library Address {
function isContract(address account) internal view returns (bool) {
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
assembly { codehash := extcodehash(account) }
return (codehash != accountHash && codehash != 0x0);
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value:amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
},
"libraries": {
"contracts/libminingv1/MiningV1Calc.sol": {
"MiningV1Calc": "0x265b6c10c606cd1c79545799ebe36bca9ce124a5"
},
"contracts/libminingv1/MiningV1Op.sol": {
"MiningV1Op": "0xfe543efe9bb91b51a046157b73fdf0838833b841"
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"addrOfGovernance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"biteNum","type":"uint256"},{"internalType":"uint256","name":"newTokenAmountPerEth","type":"uint256"}],"name":"biteEth","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"biteNum","type":"uint256"},{"internalType":"uint256","name":"newTokenAmountPerEth","type":"uint256"}],"name":"biteToken","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"close","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"closeAndWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint32[]","name":"indices","type":"uint32[]"}],"name":"closeList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"flag","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"fullPriceSheet","outputs":[{"components":[{"internalType":"uint160","name":"miner","type":"uint160"},{"internalType":"uint32","name":"height","type":"uint32"},{"internalType":"uint32","name":"ethNum","type":"uint32"},{"internalType":"uint32","name":"remainNum","type":"uint32"},{"internalType":"uint8","name":"level","type":"uint8"},{"internalType":"uint8","name":"typ","type":"uint8"},{"internalType":"uint8","name":"state","type":"uint8"},{"internalType":"uint8","name":"_reserved","type":"uint8"},{"internalType":"uint32","name":"ethNumBal","type":"uint32"},{"internalType":"uint32","name":"tokenNumBal","type":"uint32"},{"internalType":"uint32","name":"nestNum1k","type":"uint32"},{"internalType":"uint128","name":"tokenAmountPerEth","type":"uint128"}],"internalType":"struct MiningV1Data.PriceSheet","name":"sheet","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"incVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"NestPool","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"latestMinedHeight","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"latestPriceOf","outputs":[{"internalType":"uint256","name":"ethAmount","type":"uint256"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"internalType":"uint256","name":"blockNum","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"lengthOfPriceSheets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"loadContracts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"loadGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"ntoken","type":"address"}],"name":"mineNToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mineNest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minedNestAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"parameters","outputs":[{"components":[{"internalType":"uint8","name":"miningEthUnit","type":"uint8"},{"internalType":"uint32","name":"nestStakedNum1k","type":"uint32"},{"internalType":"uint8","name":"biteFeeRate","type":"uint8"},{"internalType":"uint8","name":"miningFeeRate","type":"uint8"},{"internalType":"uint8","name":"priceDurationBlock","type":"uint8"},{"internalType":"uint8","name":"maxBiteNestedLevel","type":"uint8"},{"internalType":"uint8","name":"biteInflateFactor","type":"uint8"},{"internalType":"uint8","name":"biteNestInflateFactor","type":"uint8"}],"internalType":"struct NestMiningV1.Params","name":"params","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"ethNum","type":"uint256"},{"internalType":"uint256","name":"tokenAmountPerEth","type":"uint256"}],"name":"post","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"ethNum","type":"uint256"},{"internalType":"uint256","name":"tokenAmountPerEth","type":"uint256"},{"internalType":"uint256","name":"ntokenAmountPerEth","type":"uint256"}],"name":"post2","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"priceAvgAndSigmaOf","outputs":[{"internalType":"uint128","name":"price","type":"uint128"},{"internalType":"uint128","name":"avgPrice","type":"uint128"},{"internalType":"int128","name":"vola","type":"int128"},{"internalType":"uint32","name":"bn","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint8","name":"num","type":"uint8"}],"name":"priceListOfToken","outputs":[{"internalType":"uint128[]","name":"data","type":"uint128[]"},{"internalType":"uint256","name":"bn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"priceOf","outputs":[{"internalType":"uint256","name":"ethAmount","type":"uint256"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"internalType":"uint256","name":"blockNum","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint64","name":"atHeight","type":"uint64"}],"name":"priceOfTokenAtHeight","outputs":[{"internalType":"uint256","name":"ethAmount","type":"uint256"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"internalType":"uint256","name":"bn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"priceSheet","outputs":[{"components":[{"internalType":"uint160","name":"miner","type":"uint160"},{"internalType":"uint32","name":"height","type":"uint32"},{"internalType":"uint32","name":"ethNum","type":"uint32"},{"internalType":"uint8","name":"typ","type":"uint8"},{"internalType":"uint8","name":"state","type":"uint8"},{"internalType":"uint32","name":"ethNumBal","type":"uint32"},{"internalType":"uint32","name":"tokenNumBal","type":"uint32"}],"internalType":"struct MiningV1Data.PriceSheetPub","name":"sheet","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint8","name":"miningEthUnit","type":"uint8"},{"internalType":"uint32","name":"nestStakedNum1k","type":"uint32"},{"internalType":"uint8","name":"biteFeeRate","type":"uint8"},{"internalType":"uint8","name":"miningFeeRate","type":"uint8"},{"internalType":"uint8","name":"priceDurationBlock","type":"uint8"},{"internalType":"uint8","name":"maxBiteNestedLevel","type":"uint8"},{"internalType":"uint8","name":"biteInflateFactor","type":"uint8"},{"internalType":"uint8","name":"biteNestInflateFactor","type":"uint8"}],"internalType":"struct NestMiningV1.Params","name":"newParams","type":"tuple"}],"name":"setParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"latestMiningHeight","type":"uint128"},{"internalType":"uint128","name":"minedNestTotalAmount","type":"uint128"}],"name":"setParams1","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"genesisBlockNumber","type":"uint32"},{"internalType":"uint128","name":"latestMiningHeight","type":"uint128"},{"internalType":"uint128","name":"minedNestTotalAmount","type":"uint128"},{"components":[{"internalType":"uint8","name":"miningEthUnit","type":"uint8"},{"internalType":"uint32","name":"nestStakedNum1k","type":"uint32"},{"internalType":"uint8","name":"biteFeeRate","type":"uint8"},{"internalType":"uint8","name":"miningFeeRate","type":"uint8"},{"internalType":"uint8","name":"priceDurationBlock","type":"uint8"},{"internalType":"uint8","name":"maxBiteNestedLevel","type":"uint8"},{"internalType":"uint8","name":"biteInflateFactor","type":"uint8"},{"internalType":"uint8","name":"biteNestInflateFactor","type":"uint8"}],"internalType":"struct NestMiningV1.Params","name":"initParams","type":"tuple"}],"name":"setup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"miner","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"fromIndex","type":"uint256"},{"internalType":"uint256","name":"num","type":"uint256"}],"name":"sheetListOf","outputs":[{"components":[{"internalType":"uint160","name":"miner","type":"uint160"},{"internalType":"uint32","name":"height","type":"uint32"},{"internalType":"uint32","name":"ethNum","type":"uint32"},{"internalType":"uint32","name":"remainNum","type":"uint32"},{"internalType":"uint8","name":"level","type":"uint8"},{"internalType":"uint8","name":"typ","type":"uint8"},{"internalType":"uint8","name":"state","type":"uint8"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint32","name":"nestNum1k","type":"uint32"},{"internalType":"uint128","name":"tokenAmountPerEth","type":"uint128"}],"internalType":"struct MiningV1Data.PriceSheetPub2[]","name":"sheets","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"stat","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"miner","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"fromIndex","type":"uint256"},{"internalType":"uint256","name":"num","type":"uint256"}],"name":"unClosedSheetListOf","outputs":[{"components":[{"internalType":"uint160","name":"miner","type":"uint160"},{"internalType":"uint32","name":"height","type":"uint32"},{"internalType":"uint32","name":"ethNum","type":"uint32"},{"internalType":"uint32","name":"remainNum","type":"uint32"},{"internalType":"uint8","name":"level","type":"uint8"},{"internalType":"uint8","name":"typ","type":"uint8"},{"internalType":"uint8","name":"state","type":"uint8"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint32","name":"nestNum1k","type":"uint32"},{"internalType":"uint128","name":"tokenAmountPerEth","type":"uint128"}],"internalType":"struct MiningV1Data.PriceSheetPub2[]","name":"sheets","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"unVerifiedSheetList","outputs":[{"components":[{"internalType":"uint160","name":"miner","type":"uint160"},{"internalType":"uint32","name":"height","type":"uint32"},{"internalType":"uint32","name":"ethNum","type":"uint32"},{"internalType":"uint32","name":"remainNum","type":"uint32"},{"internalType":"uint8","name":"level","type":"uint8"},{"internalType":"uint8","name":"typ","type":"uint8"},{"internalType":"uint8","name":"state","type":"uint8"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint32","name":"nestNum1k","type":"uint32"},{"internalType":"uint128","name":"tokenAmountPerEth","type":"uint128"}],"internalType":"struct MiningV1Data.PriceSheetPub2[]","name":"sheets","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"upgrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"ethAmount","type":"uint256"}],"name":"withdrawEth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"ethAmount","type":"uint256"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"withdrawEthAndToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"ethAmount","type":"uint256"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"internalType":"uint256","name":"nestAmount","type":"uint256"}],"name":"withdrawEthAndTokenAndNest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nestAmount","type":"uint256"}],"name":"withdrawNest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
608060405234801561001057600080fd5b5061580180620000216000396000f3fe60806040526004361061023f5760003560e01c80639b0884e91161012e578063c4d66de8116100ab578063e25b667a1161006f578063e25b667a146106a0578063e49280cb146106b3578063e6adb1ab146106d3578063e6ba7f59146106f3578063ea5807f71461071357610246565b8063c4d66de81461060b578063d4422df61461062b578063d55ec6971461064b578063d5a16cc214610660578063dbb159fb1461068057610246565b8063b24b8b26116100f2578063b24b8b2614610541578063b320bd721461056e578063b51c11d81461059d578063b95ed06f146105cb578063c311d049146105eb57610246565b80639b0884e9146104a1578063a33b7384146104c1578063a5006b72146104ee578063a77ac27114610501578063b124bce51461052157610246565b806354fd4d50116101bc5780637bf43d94116101805780637bf43d94146103fa578063890357301461041a578063890eba681461043c5780638e1e280c1461045e5780639264bc731461047157610246565b806354fd4d50146103865780635aa6e675146103a857806361825a75146103bd5780636c94d6ef146103d057806376a162a3146103e557610246565b8063374147b011610203578063374147b0146102ed578063380f22d61461030f5780634267ee791461032f5780634416f0b81461034457806353950e521461037157610246565b8063034fa5161461024b57806309c255c71461026d5780630e49ab30146102985780631c1ab1a1146102b85780632cad4914146102cd57610246565b3661024657005b600080fd5b34801561025757600080fd5b5061026b610266366004614d45565b610733565b005b34801561027957600080fd5b5061028261085b565b60405161028f91906156ad565b60405180910390f35b3480156102a457600080fd5b506102826102b3366004614859565b610905565b3480156102c457600080fd5b50610282610920565b3480156102d957600080fd5b5061026b6102e83660046148d6565b61092f565b3480156102f957600080fd5b50610302610a11565b60405161028f9190614e7a565b34801561031b57600080fd5b5061026b61032a366004614cde565b610a20565b34801561033b57600080fd5b5061026b610ad4565b34801561035057600080fd5b5061036461035f366004614891565b610e12565b60405161028f9190614f26565b34801561037d57600080fd5b5061026b610eb9565b34801561039257600080fd5b5061039b610ee5565b60405161028f91906156cc565b3480156103b457600080fd5b50610302610efa565b61026b6103cb3660046149e7565b610f09565b3480156103dc57600080fd5b5061039b610ff1565b3480156103f157600080fd5b5061026b611007565b34801561040657600080fd5b50610364610415366004614891565b6110af565b34801561042657600080fd5b5061042f6110f9565b60405161028f9190615364565b34801561044857600080fd5b50610451611172565b60405161028f91906156e1565b61026b61046c3660046149e7565b61117b565b34801561047d57600080fd5b5061049161048c366004614859565b61249c565b60405161028f949392919061567c565b3480156104ad57600080fd5b506102826104bc366004614859565b612690565b3480156104cd57600080fd5b506104e16104dc366004614988565b61277e565b60405161028f9190615456565b61026b6104fc3660046149e7565b6128d1565b34801561050d57600080fd5b5061036461051c366004614859565b612919565b34801561052d57600080fd5b5061026b61053c366004614859565b6129b1565b34801561054d57600080fd5b5061056161055c366004614988565b612a1f565b60405161028f91906153ea565b34801561057a57600080fd5b5061058e610589366004614859565b612aba565b60405161028f939291906156b6565b3480156105a957600080fd5b506105bd6105b8366004614a65565b612dd9565b60405161028f929190615020565b3480156105d757600080fd5b5061058e6105e6366004614859565b612eb9565b3480156105f757600080fd5b5061026b610606366004614cde565b613064565b34801561061757600080fd5b5061026b610626366004614859565b6130d6565b34801561063757600080fd5b5061026b610646366004614988565b6131d9565b34801561065757600080fd5b5061026b61321d565b34801561066c57600080fd5b5061026b61067b366004614d0e565b613259565b34801561068c57600080fd5b5061026b61069b366004614bf4565b613313565b61026b6106ae3660046149b3565b61350e565b3480156106bf57600080fd5b5061026b6106ce366004614988565b614068565b3480156106df57600080fd5b5061026b6106ee366004614cb1565b6140ac565b3480156106ff57600080fd5b5061058e61070e366004614a21565b614115565b34801561071f57600080fd5b5061026b61072e366004614dd8565b614220565b600054600160481b900460ff16600114156107695760405162461bcd60e51b8152600401610760906152dc565b60405180910390fd5b6000805460ff60481b1916600160481b17905560055460405163a798e17d60e01b81526001600160a01b039091169063a798e17d906107b2903390889088908890600401614ed8565b600060405180830381600087803b1580156107cc57600080fd5b505af11580156107e0573d6000803e3d6000fd5b5050600554604051633d835e8960e21b81526001600160a01b03909116925063f60d7a2491506108169033908590600401614ebf565b600060405180830381600087803b15801561083057600080fd5b505af1158015610844573d6000803e3d6000fd5b50506000805460ff60481b19169055505050505050565b600154600090819061088e9062249f009061088890439063ffffffff600160581b90910481169061444916565b9061446c565b9050600060098211156108c2575068022b1c8c1227a00000630a519fd04311156108bd57600092505050610902565b6108d4565b600b82600a81106108cf57fe5b015490505b6001546108fd906108f6904390600160781b90046001600160801b0316614449565b829061449e565b925050505b90565b6001600160a01b03166000908152601f602052604090205490565b6002546001600160801b031690565b6109376144d5565b604051630e3e2b6560e31b815273fe543efe9bb91b51a046157b73fdf0838833b841906371f15b2890610973906001908690869060040161558f565b60006040518083038186803b15801561098b57600080fd5b505af415801561099f573d6000803e3d6000fd5b5050604051637b576fc960e01b815273265b6c10c606cd1c79545799ebe36bca9ce124a59250637b576fc991506109dd906001908690600401615549565b60006040518083038186803b1580156109f557600080fd5b505af4158015610a09573d6000803e3d6000fd5b505050505050565b6026546001600160a01b031690565b600054600160481b900460ff1660011415610a4d5760405162461bcd60e51b8152600401610760906152dc565b6000805460ff60481b1916600160481b179055600554604051633d835e8960e21b81526001600160a01b039091169063f60d7a2490610a929033908590600401614ebf565b600060405180830381600087803b158015610aac57600080fd5b505af1158015610ac0573d6000803e3d6000fd5b50506000805460ff60481b19169055505050565b6027546026546001600160a01b039182169116331480610afc5750336001600160a01b038216145b610b185760405162461bcd60e51b8152600401610760906151ad565b602754600580546001600160a01b0319166001600160a01b039283161790819055604080516397dcd0b360e01b8152905191909216916397dcd0b3916004828101926020929190829003018186803b158015610b7357600080fd5b505afa158015610b87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bab9190614875565b600680546001600160a01b0319166001600160a01b03928316179055600554604080516316733a0d60e31b81529051919092169163b399d068916004808301926020929190829003018186803b158015610c0457600080fd5b505afa158015610c18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3c9190614875565b600780546001600160a01b0319166001600160a01b039283161790556005546040805163c2c5c90960e01b81529051919092169163c2c5c909916004808301926020929190829003018186803b158015610c9557600080fd5b505afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd9190614875565b600980546001600160a01b0319166001600160a01b0392831617905560055460408051634dee753360e01b815290519190921691634dee7533916004808301926020929190829003018186803b158015610d2657600080fd5b505afa158015610d3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5e9190614875565b600880546001600160a01b0319166001600160a01b0392831617905560055460408051630a1107d360e41b81529051919092169163a1107d30916004808301926020929190829003018186803b158015610db757600080fd5b505afa158015610dcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610def9190614875565b600a80546001600160a01b0319166001600160a01b039290921691909117905550565b6060610e1c6144d5565b6040516331e0286360e01b815273265b6c10c606cd1c79545799ebe36bca9ce124a5906331e0286390610e5c906001908990899089908990600401615560565b60006040518083038186803b158015610e7457600080fd5b505af4158015610e88573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610eb09190810190614a92565b95945050505050565b610ec16144f6565b6000805468ffffffffffffffff0019166101004367ffffffffffffffff1602179055565b600054610100900467ffffffffffffffff1681565b6026546001600160a01b031681565b610f116144d5565b6040516335413fb560e01b815273fe543efe9bb91b51a046157b73fdf0838833b841906335413fb590610f51906001908890889088908890600401615605565b60006040518083038186803b158015610f6957600080fd5b505af4158015610f7d573d6000803e3d6000fd5b5050604051637b576fc960e01b815273265b6c10c606cd1c79545799ebe36bca9ce124a59250637b576fc99150610fbb906001908890600401615549565b60006040518083038186803b158015610fd357600080fd5b505af4158015610fe7573d6000803e3d6000fd5b5050505050505050565b600154600160781b90046001600160801b031690565b602760009054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b15801561105557600080fd5b505afa158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d9190614875565b602680546001600160a01b0319166001600160a01b0392909216919091179055565b60606110b96144d5565b6040516341850fdb60e11b815273265b6c10c606cd1c79545799ebe36bca9ce124a59063830a1fb690610e5c906001908990899089908990600401615560565b61110161460d565b60015460ff808216835263ffffffff6101008304166020840152600160281b820481166040840152600160301b820481166060840152600160381b820481166080840152600160401b8204811660a0840152600160481b8204811660c0840152600160501b9091041660e082015290565b60005460ff1681565b6111836144d5565b60015460ff1683146111a75760405162461bcd60e51b8152600401610760906150cd565b6000821180156111b75750600081115b6111d35760405162461bcd60e51b8152600401610760906150fa565b6005546040516372956b6960e01b81526000916001600160a01b0316906372956b6990611204908890600401614e7a565b60206040518083038186803b15801561121c57600080fd5b505afa158015611230573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112549190614875565b9050846001600160a01b0316816001600160a01b03161415801561128057506001600160a01b03811615155b61129c5760405162461bcd60e51b81526004016107609061522f565b6001546000906112d3906127109061088890670de0b6b3a7640000906112cd908a90600160301b900460ff1661449e565b9061449e565b6005549091506001600160a01b031660006112ee3484614449565b111561135d576001600160a01b03811663ad9d4ba361130d3485614449565b336040518363ffffffff1660e01b815260040161132a9190614e7a565b6000604051808303818588803b15801561134357600080fd5b505af1158015611357573d6000803e3d6000fd5b50505050505b600754600a546006546001600160a01b0392831692918216918681169116141561146b576001600160a01b03821663daa78c0f6113a0606461088888605061449e565b876040518363ffffffff1660e01b81526004016113bd9190614e7a565b6000604051808303818588803b1580156113d657600080fd5b505af11580156113ea573d6000803e3d6000fd5b5050505050806001600160a01b031663daa78c0f611417606461088860148961449e90919063ffffffff16565b876040518363ffffffff1660e01b81526004016114349190614e7a565b6000604051808303818588803b15801561144d57600080fd5b505af1158015611461573d6000803e3d6000fd5b50505050506115d8565b6001600160a01b03821663daa78c0f61148a606461088888603c61449e565b876040518363ffffffff1660e01b81526004016114a79190614e7a565b6000604051808303818588803b1580156114c057600080fd5b505af11580156114d4573d6000803e3d6000fd5b5050505050806001600160a01b031663daa78c0f611501606461088860148961449e90919063ffffffff16565b876040518363ffffffff1660e01b815260040161151e9190614e7a565b6000604051808303818588803b15801561153757600080fd5b505af115801561154b573d6000803e3d6000fd5b5050505050806001600160a01b031663daa78c0f611578606461088860148961449e90919063ffffffff16565b6006546040516001600160e01b031960e085901b1681526115a5916001600160a01b031690600401614e7a565b6000604051808303818588803b1580156115be57600080fd5b505af11580156115d2573d6000803e3d6000fd5b50505050505b6001600160a01b0383166361025502336115fa8b670de0b6b3a764000061449e565b8c6116058c8e61449e565b6040518563ffffffff1660e01b81526004016116249493929190614ed8565b600060405180830381600087803b15801561163e57600080fd5b505af1158015611652573d6000803e3d6000fd5b5050506001600160a01b03841690506361025502336116798b670de0b6b3a764000061449e565b886116848b8e61449e565b6040518563ffffffff1660e01b81526004016116a39493929190614ed8565b600060405180830381600087803b1580156116bd57600080fd5b505af11580156116d1573d6000803e3d6000fd5b50506001546001600160a01b0386169250632dc8decd9150339061171590683635c9adc5dea00000906112cd9063ffffffff61010090910481169060029061449e16565b6040518363ffffffff1660e01b8152600401611732929190614ebf565b600060405180830381600087803b15801561174c57600080fd5b505af1158015611760573d6000803e3d6000fd5b5050600654600095508594506001600160a01b038881169116141592506117909150505750600190506002611798565b506003905060045b60006001601e0160008a6001600160a01b03166001600160a01b03168152602001908152602001600020905080604051806101800160405280336001600160a01b031681526020014363ffffffff1681526020018a63ffffffff1681526020018a63ffffffff168152602001600060ff1681526020018560ff168152602001600160ff168152602001600060ff1681526020018a63ffffffff1681526020018a63ffffffff168152602001600160000160019054906101000a900463ffffffff1663ffffffff168152602001896001600160801b0316815250908060018154018082558091505060019003906000526020600020906002020160009091909190915060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160186101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160006101000a81548160ff021916908360ff16021790555060a08201518160010160016101000a81548160ff021916908360ff16021790555060c08201518160010160026101000a81548160ff021916908360ff16021790555060e08201518160010160036101000a81548160ff021916908360ff1602179055506101008201518160010160046101000a81548163ffffffff021916908363ffffffff1602179055506101208201518160010160086101000a81548163ffffffff021916908363ffffffff16021790555061014082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160106101000a8154816001600160801b0302191690836001600160801b03160217905550505060006001601e016000876001600160a01b03166001600160a01b03168152602001908152602001600020905080604051806101800160405280336001600160a01b031681526020014363ffffffff1681526020018b63ffffffff1681526020018b63ffffffff168152602001600060ff1681526020018560ff168152602001600160ff168152602001600060ff1681526020018b63ffffffff1681526020018b63ffffffff168152602001600160000160019054906101000a900463ffffffff1663ffffffff168152602001896001600160801b0316815250908060018154018082558091505060019003906000526020600020906002020160009091909190915060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160186101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160006101000a81548160ff021916908360ff16021790555060a08201518160010160016101000a81548160ff021916908360ff16021790555060c08201518160010160026101000a81548160ff021916908360ff16021790555060e08201518160010160036101000a81548160ff021916908360ff1602179055506101008201518160010160046101000a81548163ffffffff021916908363ffffffff1602179055506101208201518160010160086101000a81548163ffffffff021916908363ffffffff16021790555061014082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160106101000a8154816001600160801b0302191690836001600160801b0316021790555050507fee7aa1809348e0f32177d04baf37df86a10ef3337729271eeff50db46e199190338b6001858054905003611d7e670de0b6b3a76400008e61449e90919063ffffffff16565b611d888d8f61449e565b604051611d99959493929190614e8e565b60405180910390a180547fee7aa1809348e0f32177d04baf37df86a10ef3337729271eeff50db46e199190903390889060001901611ddf8d670de0b6b3a764000061449e565b611de98c8f61449e565b604051611dfa959493929190614e8e565b60405180910390a150506006546001600160a01b038581169116141591506120de9050576001600160a01b0386166000908152602160209081526040808320438452909152902054608081901c6001600160801b0382168161209d576000611e6061085b565b60018054600160781b600160f81b0319164363ffffffff908116600160781b0291909117909155600280546001600160801b031981166001600160801b039182168501909116179055909150611ec29060649061088890849060509061449e16565b6005546008549194506001600160a01b0390811691635c3a6cf29116611eee606461088886600f61449e565b6040518363ffffffff1660e01b8152600401611f0b929190614ebf565b600060405180830381600087803b158015611f2557600080fd5b505af1158015611f39573d6000803e3d6000fd5b50506008546001600160a01b0316915063ccaaf98b9050611f60606461088885600f61449e565b6040518263ffffffff1660e01b8152600401611f7c91906156ad565b600060405180830381600087803b158015611f9657600080fd5b505af1158015611faa573d6000803e3d6000fd5b505060058054600a546001600160a01b039182169450635c3a6cf293501690611fdb9060649061088890879061449e565b6040518363ffffffff1660e01b8152600401611ff8929190614ebf565b600060405180830381600087803b15801561201257600080fd5b505af1158015612026573d6000803e3d6000fd5b5050600a546001600160a01b03169150630c202bf7905061204d606461088885600561449e565b6040518263ffffffff1660e01b815260040161206991906156ad565b600060405180830381600087803b15801561208357600080fd5b505af1158015612097573d6000803e3d6000fd5b50505050505b6120a78189614520565b6001600160a01b038a1660009081526021602090815260408083204384529091529020600160801b90930201909155506123c09050565b6001600160a01b0386166000908152602160209081526040808320438452909152902054608081901c6001600160801b0382168161238457600061212186612690565b90506000866001600160a01b03166328e6a33f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561215e57600080fd5b505afa158015612172573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121969190614875565b6005549091506001600160a01b038083169116141561221d576005546040516394bf804d60e01b815292945084926001600160a01b03808a16926394bf804d926121e69287921690600401615549565b600060405180830381600087803b15801561220057600080fd5b505af1158015612214573d6000803e3d6000fd5b50505050612381565b6040516381fa543160e01b81526001600160a01b038816906381fa5431906122499085906004016156ad565b600060405180830381600087803b15801561226357600080fd5b505af1158015612277573d6000803e3d6000fd5b505060055460405163a9059cbb60e01b81526001600160a01b03808c16945063a9059cbb93506122ad9216908690600401614ebf565b602060405180830381600087803b1580156122c757600080fd5b505af11580156122db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ff9190614bd4565b50612310606461088884605f61449e565b6005549094506001600160a01b03166361bced9d82896123308689614449565b6040518463ffffffff1660e01b815260040161234e93929190614f02565b600060405180830381600087803b15801561236857600080fd5b505af115801561237c573d6000803e3d6000fd5b505050505b50505b61238e8189614520565b6001600160a01b038a1660009081526021602090815260408083204384529091529020600160801b9093020190915550505b604051637b576fc960e01b815273265b6c10c606cd1c79545799ebe36bca9ce124a590637b576fc9906123fa906001908a90600401615549565b60006040518083038186803b15801561241257600080fd5b505af4158015612426573d6000803e3d6000fd5b5050604051637b576fc960e01b815273265b6c10c606cd1c79545799ebe36bca9ce124a59250637b576fc99150612464906001908690600401615549565b60006040518083038186803b15801561247c57600080fd5b505af4158015612490573d6000803e3d6000fd5b50505050505050505050565b6000808080333214806124b95750600a546001600160a01b031633145b806124ce57506007546001600160a01b031633145b806124e357506008546001600160a01b031633145b806124f857506009546001600160a01b031633145b6125145760405162461bcd60e51b815260040161076090615313565b61251c614651565b506001600160a01b03851660009081526020808052604091829020825161012081018452815463ffffffff808216835264010000000082048116948301859052600160401b8204811695830195909552600160601b810490941660608201526001600160801b03600160801b94859004811660808301526001830154600f81810b810b810b60a085015290869004810b810b900b60c083015260029092015480831660e083015293909304166101008301526125ea5760405162461bcd60e51b8152600401610760906150a0565b6125ff6125fa8260a00151614543565b61457f565b925061262b816040015163ffffffff1682608001516001600160801b031661446c90919063ffffffff16565b60e08201516001546020840151929750909550600160381b900460ff160191506001600160801b0385161580159061266c57506000846001600160801b0316115b6126885760405162461bcd60e51b81526004016107609061525c565b509193509193565b6000806000836001600160a01b03166392c088716040518163ffffffff1660e01b8152600401604080518083038186803b1580156126cd57600080fd5b505afa1580156126e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127059190614d6c565b9092509050600061271d62249f006108884386614449565b905060006009821115612739575067058d15e17628000061274b565b601582600a811061274657fe5b015490505b60006127574385614449565b90506064811115612766575060645b6000612772838361449e565b98975050505050505050565b61278661469d565b61278e6144d5565b6001600160a01b0383166000908152601f60205260409020548083106127c65760405162461bcd60e51b8152600401610760906151d8565b6001600160a01b0384166000908152601f602052604090208054849081106127ea57fe5b6000918252602091829020604080516101808101825260029390930290910180546001600160a01b0381168452600160a01b810463ffffffff90811695850195909552600160c01b8104851692840192909252600160e01b909104831660608301526001015460ff8082166080840152610100808304821660a0850152620100008304821660c08501526301000000830490911660e08401526401000000008204841690830152600160401b81048316610120830152600160601b8104909216610140820152600160801b9091046001600160801b03166101608201529150505b92915050565b6128d96144d5565b604051630d26201760e31b815273fe543efe9bb91b51a046157b73fdf0838833b8419063693100b890610f51906001908890889088908890600401615605565b60606129236144d5565b6040516306d8420960e21b815273265b6c10c606cd1c79545799ebe36bca9ce124a590631b6108249061295d906001908690600401615549565b60006040518083038186803b15801561297557600080fd5b505af4158015612989573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526128cb9190810190614a92565b604051637b576fc960e01b815273265b6c10c606cd1c79545799ebe36bca9ce124a590637b576fc9906129eb906001908590600401615549565b60006040518083038186803b158015612a0357600080fd5b505af4158015612a17573d6000803e3d6000fd5b505050505b50565b612a27614701565b604051631182622760e21b815273265b6c10c606cd1c79545799ebe36bca9ce124a590634609889c90612a6390600190879087906004016155e6565b60e06040518083038186803b158015612a7b57600080fd5b505af4158015612a8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ab39190614c10565b9392505050565b6000808033321480612ad65750600a546001600160a01b031633145b80612aeb57506007546001600160a01b031633145b80612b0057506008546001600160a01b031633145b80612b1557506009546001600160a01b031633145b612b315760405162461bcd60e51b815260040161076090615313565b6001600160a01b0384166000908152601f6020526040812080549091612b5561469d565b82612b725760405162461bcd60e51b81526004016107609061525c565b600060015b848111612d8f578581860381548110612b8c57fe5b6000918252602091829020604080516101808101825260029390930290910180546001600160a01b0381168452600160a01b810463ffffffff90811695850195909552600160c01b8104851692840192909252600160e01b909104831660608301526001015460ff8082166080840152610100808304821660a0850152620100008304821660c08501526301000000830490911660e08401526401000000008204841690830152600160401b81048316610120830152600160601b8104909216610140820152600160801b9091046001600160801b0316610160820152925081158015612c99575043600160000160079054906101000a900460ff1660ff16846020015163ffffffff1601105b15612d0157606083015163ffffffff16935083612cb557612d87565b826020015163ffffffff169150612ce38361016001516001600160801b03168561449e90919063ffffffff16565b9750612cf784670de0b6b3a764000061449e565b9850819650612d87565b826020015163ffffffff16821415612d7057826060015163ffffffff169350612d4b612d448461016001516001600160801b03168661449e90919063ffffffff16565b8990614520565b9750612d69612d6285670de0b6b3a764000061449e565b8a90614520565b9850612d87565b826020015163ffffffff16821115612d8757612d8f565b600101612b77565b50600154600160381b900460ff1695909501948715801590612db15750600087115b612dcd5760405162461bcd60e51b81526004016107609061525c565b50505050509193909250565b6009546060906000906001600160a01b031633321480612e015750336001600160a01b038216145b612e1d5760405162461bcd60e51b815260040161076090615202565b6040516353b847a960e01b815273265b6c10c606cd1c79545799ebe36bca9ce124a5906353b847a990612e59906001908990899060040161565a565b60006040518083038186803b158015612e7157600080fd5b505af4158015612e85573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612ead9190810190614b31565b92509250509250929050565b600954600090819081906001600160a01b031633321480612ee25750336001600160a01b038216145b612efe5760405162461bcd60e51b815260040161076090615202565b612f06614651565b506001600160a01b03851660009081526020808052604091829020825161012081018452815463ffffffff808216835264010000000082048116948301859052600160401b8204811695830195909552600160601b810490941660608201526001600160801b03600160801b94859004811660808301526001830154600f81810b810b810b60a085015290869004810b810b900b60c083015260029092015480831660e08301529390930416610100830152612fd45760405162461bcd60e51b8152600401610760906150a0565b612ff9670de0b6b3a7640000826040015163ffffffff1661449e90919063ffffffff16565b945080608001516001600160801b03169350600160000160079054906101000a900460ff1660ff1681602001510163ffffffff16925060008511801561303f5750600084115b61305b5760405162461bcd60e51b81526004016107609061525c565b50509193909250565b600054600160481b900460ff16600114156130915760405162461bcd60e51b8152600401610760906152dc565b6000805460ff60481b1916600160481b1790556005546040516306e6a46960e21b81526001600160a01b0390911690631b9a91a490610a929033908590600401614ebf565b60005460ff16156130f95760405162461bcd60e51b815260040161076090615289565b6815af1d78b58c40000060005b600a8110156131395781600b82600a811061311d57fe5b015561312f606461088884605061449e565b9150600101613106565b50673782dace9d900000905060005b600a81101561317b5781601582600a811061315f57fe5b0155613171606461088884605061449e565b9150600101613148565b505060268054336001600160a01b03199182161790915560008054602780549093166001600160a01b03949094169390931790915568ffffffffffffffff00199091166101004367ffffffffffffffff16021760ff19166001179055565b6131e16144d5565b604051633ebf3e8560e21b815273fe543efe9bb91b51a046157b73fdf0838833b8419063fafcfa149061097390600190869086906004016155e6565b6132256144f6565b60005460ff1660021461324a5760405162461bcd60e51b815260040161076090615289565b6000805460ff19166003179055565b600054600160481b900460ff16600114156132865760405162461bcd60e51b8152600401610760906152dc565b6000805460ff60481b1916600160481b17905560055460405163a798e17d60e01b81526001600160a01b039091169063a798e17d906132cf903390879087908790600401614ed8565b600060405180830381600087803b1580156132e957600080fd5b505af11580156132fd573d6000803e3d6000fd5b50506000805460ff60481b191690555050505050565b61331b6144f6565b6133286020820182614e33565b6001805460ff191660ff9290921691909117905561334c6040820160208301614dbc565b6001805463ffffffff929092166101000264ffffffff001990921691909117905561337d6060820160408301614e33565b6001805460ff92909216600160281b0265ff0000000000199092169190911790556133ae6080820160608301614e33565b6001805460ff92909216600160301b0266ff000000000000199092169190911790556133e060a0820160808301614e33565b6001805460ff92909216600160381b0260ff60381b1990921691909117905561340f60c0820160a08301614e33565b6001805460ff92909216600160401b0260ff60401b1990921691909117905561343e60e0820160c08301614e33565b6001805460ff92909216600160481b0260ff60481b1990921691909117905561346e610100820160e08301614e33565b6001805460ff60501b1916600160501b60ff938416810291909117918290556040517fd52ea55597dda83c654fca3762be1b95778ce32b5d67b2ddc77f14e4c5f778ce936135039380821693610100820463ffffffff1693600160281b8304841693600160301b8404811693600160381b8104821693600160401b8204831693600160481b83048416939190920416906156ef565b60405180910390a150565b6135166144d5565b60015460ff16821461353a5760405162461bcd60e51b8152600401610760906150cd565b6000811161355a5760405162461bcd60e51b8152600401610760906150fa565b6005546040516372956b6960e01b81526001600160a01b039091169060009082906372956b699061358f908890600401614e7a565b60206040518083038186803b1580156135a757600080fd5b505afa1580156135bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135df9190614875565b90506001600160a01b0381161580159061360757506006546001600160a01b03828116911614155b80156136255750806001600160a01b0316856001600160a01b031614155b6136415760405162461bcd60e51b81526004016107609061522f565b6a0422ca8b0a00a425000000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561368657600080fd5b505afa15801561369a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136be9190614cf6565b106136db5760405162461bcd60e51b815260040161076090615154565b60015460009061370c906127109061088890670de0b6b3a7640000906112cd908a90600160301b900460ff1661449e565b9050600061371a3483614449565b1115613789576001600160a01b03831663ad9d4ba36137393484614449565b336040518363ffffffff1660e01b81526004016137569190614e7a565b6000604051808303818588803b15801561376f57600080fd5b505af1158015613783573d6000803e3d6000fd5b50505050505b600754600a546001600160a01b0391821691168163daa78c0f6137b2606461088887603c61449e565b866040518363ffffffff1660e01b81526004016137cf9190614e7a565b6000604051808303818588803b1580156137e857600080fd5b505af11580156137fc573d6000803e3d6000fd5b5050505050806001600160a01b031663daa78c0f613829606461088860148861449e90919063ffffffff16565b866040518363ffffffff1660e01b81526004016138469190614e7a565b6000604051808303818588803b15801561385f57600080fd5b505af1158015613873573d6000803e3d6000fd5b5050505050806001600160a01b031663daa78c0f6138a0606461088860148861449e90919063ffffffff16565b6006546040516001600160e01b031960e085901b1681526138cd916001600160a01b031690600401614e7a565b6000604051808303818588803b1580156138e657600080fd5b505af11580156138fa573d6000803e3d6000fd5b5050505050846001600160a01b031663610255023361392a670de0b6b3a76400008b61449e90919063ffffffff16565b8b6139358b8d61449e565b6040518563ffffffff1660e01b81526004016139549493929190614ed8565b600060405180830381600087803b15801561396e57600080fd5b505af1158015613982573d6000803e3d6000fd5b50506001546001600160a01b0388169250632dc8decd915033906139bf9063ffffffff610100909104811690683635c9adc5dea000009061449e16565b6040518363ffffffff1660e01b81526004016139dc929190614ebf565b600060405180830381600087803b1580156139f657600080fd5b505af1158015613a0a573d6000803e3d6000fd5b50505050505060006001601e016000886001600160a01b03166001600160a01b03168152602001908152602001600020905080604051806101800160405280336001600160a01b031681526020014363ffffffff1681526020018863ffffffff1681526020018863ffffffff168152602001600060ff168152602001600360ff168152602001600160ff168152602001600060ff1681526020018863ffffffff1681526020018863ffffffff168152602001600160000160019054906101000a900463ffffffff1663ffffffff168152602001876001600160801b0316815250908060018154018082558091505060019003906000526020600020906002020160009091909190915060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160186101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160006101000a81548160ff021916908360ff16021790555060a08201518160010160016101000a81548160ff021916908360ff16021790555060c08201518160010160026101000a81548160ff021916908360ff16021790555060e08201518160010160036101000a81548160ff021916908360ff1602179055506101008201518160010160046101000a81548163ffffffff021916908363ffffffff1602179055506101208201518160010160086101000a81548163ffffffff021916908363ffffffff16021790555061014082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160106101000a8154816001600160801b0302191690836001600160801b0316021790555050507fee7aa1809348e0f32177d04baf37df86a10ef3337729271eeff50db46e19919033886001848054905003613d27670de0b6b3a76400008b61449e90919063ffffffff16565b613d318a8c61449e565b604051613d42959493929190614e8e565b60405180910390a1506001600160a01b0386166000908152602160209081526040808320438452909152902054608081901c6001600160801b03821681613ff1576000613d8e86612690565b90506000866001600160a01b03166328e6a33f6040518163ffffffff1660e01b815260040160206040518083038186803b158015613dcb57600080fd5b505afa158015613ddf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e039190614875565b6005549091506001600160a01b0380831691161415613e8a576005546040516394bf804d60e01b815292945084926001600160a01b03808a16926394bf804d92613e539287921690600401615549565b600060405180830381600087803b158015613e6d57600080fd5b505af1158015613e81573d6000803e3d6000fd5b50505050613fee565b613e9a606461088884605f61449e565b6040516381fa543160e01b81529094506001600160a01b038816906381fa543190613ec99085906004016156ad565b600060405180830381600087803b158015613ee357600080fd5b505af1158015613ef7573d6000803e3d6000fd5b505060055460405163a9059cbb60e01b81526001600160a01b03808c16945063a9059cbb9350613f2d9216908690600401614ebf565b602060405180830381600087803b158015613f4757600080fd5b505af1158015613f5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f7f9190614bd4565b506005546001600160a01b03166361bced9d8289613f9d8689614449565b6040518463ffffffff1660e01b8152600401613fbb93929190614f02565b600060405180830381600087803b158015613fd557600080fd5b505af1158015613fe9573d6000803e3d6000fd5b505050505b50505b613ffb8189614520565b6001600160a01b038a16600090815260216020908152604080832043845290915290819020600160801b9094029091019092555051637b576fc960e01b815273265b6c10c606cd1c79545799ebe36bca9ce124a59150637b576fc990612464906001908a90600401615549565b6140706144d5565b604051638f2daafb60e01b815273fe543efe9bb91b51a046157b73fdf0838833b84190638f2daafb9061097390600190869086906004016155e6565b6140b46144f6565b60005460ff166002146140d95760405162461bcd60e51b815260040161076090615289565b60018054600160781b600160f81b031916600160781b6001600160801b0394851602179055600280546001600160801b03191691909216179055565b600954600090819081906001600160a01b03163332148061413e5750336001600160a01b038216145b61415a5760405162461bcd60e51b815260040161076090615202565b604051630da947f160e21b815273265b6c10c606cd1c79545799ebe36bca9ce124a5906336a51fc490614196906001908a908a90600401615631565b60606040518083038186803b1580156141ae57600080fd5b505af41580156141c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141e69190614d8f565b9195509350915083158015906141fc5750600083115b6142185760405162461bcd60e51b81526004016107609061525c565b509250925092565b6142286144f6565b60005460ff1660011461424d5760405162461bcd60e51b815260040161076090615289565b61425a6020820182614e33565b6001805460ff191660ff9290921691909117905561427e6040820160208301614dbc565b6001805463ffffffff929092166101000264ffffffff00199092169190911790556142af6060820160408301614e33565b6001805460ff92909216600160281b0265ff0000000000199092169190911790556142e06080820160608301614e33565b6001805460ff92909216600160301b0266ff0000000000001990921691909117905561431260a0820160808301614e33565b6001805460ff92909216600160381b0260ff60381b1990921691909117905561434160c0820160a08301614e33565b6001805460ff92909216600160401b0260ff60401b1990921691909117905561437060e0820160c08301614e33565b6001805460ff92909216600160481b0260ff60481b199092169190911790556143a0610100820160e08301614e33565b60018054600280546001600160801b0319166001600160801b0396871617815560ff60501b19909116600160501b60ff949094169390930292909217600160781b600160f81b031916600160781b95909416949094029290921763ffffffff60581b1916600160581b63ffffffff9590951694909402939093179091556000805468ffffffffffffffff0019166101004367ffffffffffffffff16021760ff1916909117905550565b808203828111156128cb5760405162461bcd60e51b815260040161076090615071565b600080821161448d5760405162461bcd60e51b8152600401610760906152b2565b81838161449657fe5b049392505050565b60008115806144b9575050808202828282816144b657fe5b04145b6128cb5760405162461bcd60e51b815260040161076090615126565b3332146144f45760405162461bcd60e51b815260040161076090615202565b565b6026546001600160a01b031633146144f45760405162461bcd60e51b81526004016107609061533c565b808201828110156128cb5760405162461bcd60e51b81526004016107609061517f565b6000600f82900b6f7fffffffffffffffffffffffffffffff19141561456757600080fd5b600082600f0b1261457857816128cb565b5060000390565b60008082600f0b121561459157600080fd5b6128cb604083600f0b901b600160401b6000826145b0575060006128cb565b600082116145bd57600080fd5b60008284816145c857fe5b049050808314806145db57508083600101145b156145e957829150506128cb565b806001018314156145fb5790506128cb565b6001818401600101901c9250506145bd565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915290565b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081019190915290565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810182905261016081019190915290565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b6000610100828403121561474f578081fd5b50919050565b6000610140808385031215614768578182fd5b61477181615739565b91505061477e838361482d565b815261478d8360208401614843565b602082015261479f8360408401614843565b60408201526147b18360608401614843565b60608201526147c3836080840161484e565b60808201526147d58360a0840161484e565b60a08201526147e78360c0840161484e565b60c082015260e082015160e082015261010061480584828501614843565b9082015261012061481884848301614822565b9082015292915050565b80516128cb81615795565b80516128cb81615780565b80356128cb816157aa565b80516128cb816157aa565b80516128cb816157bc565b60006020828403121561486a578081fd5b8135612ab381615780565b600060208284031215614886578081fd5b8151612ab381615780565b600080600080608085870312156148a6578283fd5b84356148b181615780565b935060208501356148c181615780565b93969395505050506040820135916060013590565b600080604083850312156148e8578182fd5b82356148f381615780565b915060208381013567ffffffffffffffff81111561490f578283fd5b8401601f8101861361491f578283fd5b803561493261492d82615760565b615739565b81815283810190838501858402850186018a101561494e578687fd5b8694505b83851015614978576149648a82614838565b835260019490940193918501918501614952565b5080955050505050509250929050565b6000806040838503121561499a578182fd5b82356149a581615780565b946020939093013593505050565b6000806000606084860312156149c7578081fd5b83356149d281615780565b95602085013595506040909401359392505050565b600080600080608085870312156149fc578182fd5b8435614a0781615780565b966020860135965060408601359560600135945092505050565b60008060408385031215614a33578182fd5b8235614a3e81615780565b9150602083013567ffffffffffffffff81168114614a5a578182fd5b809150509250929050565b60008060408385031215614a77578182fd5b8235614a8281615780565b91506020830135614a5a816157bc565b60006020808385031215614aa4578182fd5b825167ffffffffffffffff811115614aba578283fd5b8301601f81018513614aca578283fd5b8051614ad861492d82615760565b81815283810190838501610140808502860187018a1015614af7578788fd5b8795505b84861015614b2357614b0d8a83614755565b8452600195909501949286019290810190614afb565b509098975050505050505050565b60008060408385031215614b43578182fd5b825167ffffffffffffffff811115614b59578283fd5b8301601f81018513614b69578283fd5b8051614b7761492d82615760565b808282526020808301925080850189828387028801011115614b97578788fd5b8795505b84861015614bc2578051614bae81615795565b845260019590950194928101928101614b9b565b50969096015195979596505050505050565b600060208284031215614be5578081fd5b81518015158114612ab3578182fd5b60006101008284031215614c06578081fd5b612ab3838361473d565b600060e08284031215614c21578081fd5b614c2b60e0615739565b8251614c3681615780565b81526020830151614c46816157aa565b60208201526040830151614c59816157aa565b60408201526060830151614c6c816157bc565b60608201526080830151614c7f816157bc565b608082015260a0830151614c92816157aa565b60a082015260c0830151614ca5816157aa565b60c08201529392505050565b60008060408385031215614cc3578182fd5b8235614cce81615795565b91506020830135614a5a81615795565b600060208284031215614cef578081fd5b5035919050565b600060208284031215614d07578081fd5b5051919050565b600080600060608486031215614d22578081fd5b833592506020840135614d3481615780565b929592945050506040919091013590565b60008060008060808587031215614d5a578182fd5b8435935060208501356148c181615780565b60008060408385031215614d7e578182fd5b505080516020909101519092909150565b600080600060608486031215614da3578081fd5b8351925060208401519150604084015190509250925092565b600060208284031215614dcd578081fd5b8135612ab3816157aa565b6000806000806101608587031215614dee578182fd5b8435614df9816157aa565b93506020850135614e0981615795565b92506040850135614e1981615795565b9150614e28866060870161473d565b905092959194509250565b600060208284031215614e44578081fd5b8135612ab3816157bc565b6001600160801b03169052565b6001600160a01b03169052565b63ffffffff169052565b60ff169052565b6001600160a01b0391909116815260200190565b6001600160a01b03958616815293909416602084015260408301919091526060820152608081019190915260a00190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039485168152602081019390935292166040820152606081019190915260800190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b602080825282518282018190526000919060409081850190868401855b82811015615013578151614f58858251614e5c565b86810151614f6888870182614e69565b5085810151614f7987870182614e69565b50606080820151614f8c82880182614e69565b5050608080820151614fa082880182614e73565b505060a080820151614fb482880182614e73565b505060c080820151614fc882880182614e73565b505060e0818101519086015261010080820151614fe782880182614e69565b50506101209081015190614ffd86820183614e4f565b5050610140939093019290850190600101614f43565b5091979650505050505050565b604080825283519082018190526000906020906060840190828701845b828110156150625781516001600160801b03168452928401929084019060010161503d565b50505092019290925292915050565b60208082526015908201527464732d6d6174682d7375622d756e646572666c6f7760581b604082015260600190565b6020808252601390820152724e6573743a4d696e653a4e4f2870726963652960681b604082015260600190565b6020808252601390820152724e6573743a4d696e653a21286574684e756d2960681b604082015260600190565b6020808252601290820152714e6573743a4d696e653a212870726963652960701b604082015260600190565b60208082526014908201527364732d6d6174682d6d756c2d6f766572666c6f7760601b604082015260600190565b6020808252601190820152702732b9ba1d26b4b7329d10b73a37b5b2b760791b604082015260600190565b60208082526014908201527364732d6d6174682d6164642d6f766572666c6f7760601b604082015260600190565b6020808252601190820152702732b9ba1d26b4b7329d10b9b2b73232b960791b604082015260600190565b60208082526010908201526f4e6573743a4d696e653a3e286c656e2960801b604082015260600190565b6020808252601390820152724e6573743a4d696e653a636f6e74726163742160681b604082015260600190565b6020808252601390820152724e6573743a4d696e653a21286e746f6b656e2960681b604082015260600190565b6020808252601390820152724e6573743a4d696e653a6e6f2870726963652960681b604082015260600190565b6020808252600f908201526e4e6573743a4d696e653a21666c616760881b604082015260600190565b60208082526010908201526f64732d6d6174682d6469762d7a65726f60801b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252600f908201526e09ccae6e8749ad2dcca744282eae8d608b1b604082015260600190565b6020808252600e908201526d2732b9ba1d26b4b7329d10a3a7ab60911b604082015260600190565b60006101008201905060ff835116825263ffffffff602084015116602083015260ff604084015116604083015260ff606084015116606083015260ff608084015116608083015260a08301516153bd60a0840182614e73565b5060c08301516153d060c0840182614e73565b5060e08301516153e360e0840182614e73565b5092915050565b600060e08201905060018060a01b038351168252602083015163ffffffff808216602085015280604086015116604085015260ff606086015116606085015260ff60808601511660808501528060a08601511660a08501528060c08601511660c0850152505092915050565b60006101808201905061546a828451614e5c565b602083015161547c6020840182614e69565b50604083015161548f6040840182614e69565b5060608301516154a26060840182614e69565b5060808301516154b56080840182614e73565b5060a08301516154c860a0840182614e73565b5060c08301516154db60c0840182614e73565b5060e08301516154ee60e0840182614e73565b506101008084015161550282850182614e69565b50506101208084015161551782850182614e69565b50506101408084015161552c82850182614e69565b50506101608084015161554182850182614e4f565b505092915050565b9182526001600160a01b0316602082015260400190565b9485526001600160a01b0393841660208601529190921660408401526060830191909152608082015260a00190565b8381526001600160a01b0383166020808301919091526060604083018190528351908301819052600091848101916080850190845b81811015614b2357845163ffffffff16835293830193918301916001016155c4565b9283526001600160a01b03919091166020830152604082015260600190565b9485526001600160a01b0393909316602085015260408401919091526060830152608082015260a00190565b9283526001600160a01b0391909116602083015267ffffffffffffffff16604082015260600190565b9283526001600160a01b0391909116602083015260ff16604082015260600190565b6001600160801b039485168152929093166020830152600f0b604082015263ffffffff909116606082015260800190565b90815260200190565b9283526020830191909152604082015260600190565b67ffffffffffffffff91909116815260200190565b60ff91909116815260200190565b60ff988916815263ffffffff979097166020880152948716604087015292861660608601529085166080850152841660a0840152831660c083015290911660e08201526101000190565b60405181810167ffffffffffffffff8111828210171561575857600080fd5b604052919050565b600067ffffffffffffffff821115615776578081fd5b5060209081020190565b6001600160a01b0381168114612a1c57600080fd5b6001600160801b0381168114612a1c57600080fd5b63ffffffff81168114612a1c57600080fd5b60ff81168114612a1c57600080fdfea2646970667358221220d93eef17cc519ed96e943ab106845bf42eba3c315bd881f3d3980f522e5e09e864736f6c634300060c0033
Deployed Bytecode
0x60806040526004361061023f5760003560e01c80639b0884e91161012e578063c4d66de8116100ab578063e25b667a1161006f578063e25b667a146106a0578063e49280cb146106b3578063e6adb1ab146106d3578063e6ba7f59146106f3578063ea5807f71461071357610246565b8063c4d66de81461060b578063d4422df61461062b578063d55ec6971461064b578063d5a16cc214610660578063dbb159fb1461068057610246565b8063b24b8b26116100f2578063b24b8b2614610541578063b320bd721461056e578063b51c11d81461059d578063b95ed06f146105cb578063c311d049146105eb57610246565b80639b0884e9146104a1578063a33b7384146104c1578063a5006b72146104ee578063a77ac27114610501578063b124bce51461052157610246565b806354fd4d50116101bc5780637bf43d94116101805780637bf43d94146103fa578063890357301461041a578063890eba681461043c5780638e1e280c1461045e5780639264bc731461047157610246565b806354fd4d50146103865780635aa6e675146103a857806361825a75146103bd5780636c94d6ef146103d057806376a162a3146103e557610246565b8063374147b011610203578063374147b0146102ed578063380f22d61461030f5780634267ee791461032f5780634416f0b81461034457806353950e521461037157610246565b8063034fa5161461024b57806309c255c71461026d5780630e49ab30146102985780631c1ab1a1146102b85780632cad4914146102cd57610246565b3661024657005b600080fd5b34801561025757600080fd5b5061026b610266366004614d45565b610733565b005b34801561027957600080fd5b5061028261085b565b60405161028f91906156ad565b60405180910390f35b3480156102a457600080fd5b506102826102b3366004614859565b610905565b3480156102c457600080fd5b50610282610920565b3480156102d957600080fd5b5061026b6102e83660046148d6565b61092f565b3480156102f957600080fd5b50610302610a11565b60405161028f9190614e7a565b34801561031b57600080fd5b5061026b61032a366004614cde565b610a20565b34801561033b57600080fd5b5061026b610ad4565b34801561035057600080fd5b5061036461035f366004614891565b610e12565b60405161028f9190614f26565b34801561037d57600080fd5b5061026b610eb9565b34801561039257600080fd5b5061039b610ee5565b60405161028f91906156cc565b3480156103b457600080fd5b50610302610efa565b61026b6103cb3660046149e7565b610f09565b3480156103dc57600080fd5b5061039b610ff1565b3480156103f157600080fd5b5061026b611007565b34801561040657600080fd5b50610364610415366004614891565b6110af565b34801561042657600080fd5b5061042f6110f9565b60405161028f9190615364565b34801561044857600080fd5b50610451611172565b60405161028f91906156e1565b61026b61046c3660046149e7565b61117b565b34801561047d57600080fd5b5061049161048c366004614859565b61249c565b60405161028f949392919061567c565b3480156104ad57600080fd5b506102826104bc366004614859565b612690565b3480156104cd57600080fd5b506104e16104dc366004614988565b61277e565b60405161028f9190615456565b61026b6104fc3660046149e7565b6128d1565b34801561050d57600080fd5b5061036461051c366004614859565b612919565b34801561052d57600080fd5b5061026b61053c366004614859565b6129b1565b34801561054d57600080fd5b5061056161055c366004614988565b612a1f565b60405161028f91906153ea565b34801561057a57600080fd5b5061058e610589366004614859565b612aba565b60405161028f939291906156b6565b3480156105a957600080fd5b506105bd6105b8366004614a65565b612dd9565b60405161028f929190615020565b3480156105d757600080fd5b5061058e6105e6366004614859565b612eb9565b3480156105f757600080fd5b5061026b610606366004614cde565b613064565b34801561061757600080fd5b5061026b610626366004614859565b6130d6565b34801561063757600080fd5b5061026b610646366004614988565b6131d9565b34801561065757600080fd5b5061026b61321d565b34801561066c57600080fd5b5061026b61067b366004614d0e565b613259565b34801561068c57600080fd5b5061026b61069b366004614bf4565b613313565b61026b6106ae3660046149b3565b61350e565b3480156106bf57600080fd5b5061026b6106ce366004614988565b614068565b3480156106df57600080fd5b5061026b6106ee366004614cb1565b6140ac565b3480156106ff57600080fd5b5061058e61070e366004614a21565b614115565b34801561071f57600080fd5b5061026b61072e366004614dd8565b614220565b600054600160481b900460ff16600114156107695760405162461bcd60e51b8152600401610760906152dc565b60405180910390fd5b6000805460ff60481b1916600160481b17905560055460405163a798e17d60e01b81526001600160a01b039091169063a798e17d906107b2903390889088908890600401614ed8565b600060405180830381600087803b1580156107cc57600080fd5b505af11580156107e0573d6000803e3d6000fd5b5050600554604051633d835e8960e21b81526001600160a01b03909116925063f60d7a2491506108169033908590600401614ebf565b600060405180830381600087803b15801561083057600080fd5b505af1158015610844573d6000803e3d6000fd5b50506000805460ff60481b19169055505050505050565b600154600090819061088e9062249f009061088890439063ffffffff600160581b90910481169061444916565b9061446c565b9050600060098211156108c2575068022b1c8c1227a00000630a519fd04311156108bd57600092505050610902565b6108d4565b600b82600a81106108cf57fe5b015490505b6001546108fd906108f6904390600160781b90046001600160801b0316614449565b829061449e565b925050505b90565b6001600160a01b03166000908152601f602052604090205490565b6002546001600160801b031690565b6109376144d5565b604051630e3e2b6560e31b815273fe543efe9bb91b51a046157b73fdf0838833b841906371f15b2890610973906001908690869060040161558f565b60006040518083038186803b15801561098b57600080fd5b505af415801561099f573d6000803e3d6000fd5b5050604051637b576fc960e01b815273265b6c10c606cd1c79545799ebe36bca9ce124a59250637b576fc991506109dd906001908690600401615549565b60006040518083038186803b1580156109f557600080fd5b505af4158015610a09573d6000803e3d6000fd5b505050505050565b6026546001600160a01b031690565b600054600160481b900460ff1660011415610a4d5760405162461bcd60e51b8152600401610760906152dc565b6000805460ff60481b1916600160481b179055600554604051633d835e8960e21b81526001600160a01b039091169063f60d7a2490610a929033908590600401614ebf565b600060405180830381600087803b158015610aac57600080fd5b505af1158015610ac0573d6000803e3d6000fd5b50506000805460ff60481b19169055505050565b6027546026546001600160a01b039182169116331480610afc5750336001600160a01b038216145b610b185760405162461bcd60e51b8152600401610760906151ad565b602754600580546001600160a01b0319166001600160a01b039283161790819055604080516397dcd0b360e01b8152905191909216916397dcd0b3916004828101926020929190829003018186803b158015610b7357600080fd5b505afa158015610b87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bab9190614875565b600680546001600160a01b0319166001600160a01b03928316179055600554604080516316733a0d60e31b81529051919092169163b399d068916004808301926020929190829003018186803b158015610c0457600080fd5b505afa158015610c18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3c9190614875565b600780546001600160a01b0319166001600160a01b039283161790556005546040805163c2c5c90960e01b81529051919092169163c2c5c909916004808301926020929190829003018186803b158015610c9557600080fd5b505afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd9190614875565b600980546001600160a01b0319166001600160a01b0392831617905560055460408051634dee753360e01b815290519190921691634dee7533916004808301926020929190829003018186803b158015610d2657600080fd5b505afa158015610d3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5e9190614875565b600880546001600160a01b0319166001600160a01b0392831617905560055460408051630a1107d360e41b81529051919092169163a1107d30916004808301926020929190829003018186803b158015610db757600080fd5b505afa158015610dcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610def9190614875565b600a80546001600160a01b0319166001600160a01b039290921691909117905550565b6060610e1c6144d5565b6040516331e0286360e01b815273265b6c10c606cd1c79545799ebe36bca9ce124a5906331e0286390610e5c906001908990899089908990600401615560565b60006040518083038186803b158015610e7457600080fd5b505af4158015610e88573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610eb09190810190614a92565b95945050505050565b610ec16144f6565b6000805468ffffffffffffffff0019166101004367ffffffffffffffff1602179055565b600054610100900467ffffffffffffffff1681565b6026546001600160a01b031681565b610f116144d5565b6040516335413fb560e01b815273fe543efe9bb91b51a046157b73fdf0838833b841906335413fb590610f51906001908890889088908890600401615605565b60006040518083038186803b158015610f6957600080fd5b505af4158015610f7d573d6000803e3d6000fd5b5050604051637b576fc960e01b815273265b6c10c606cd1c79545799ebe36bca9ce124a59250637b576fc99150610fbb906001908890600401615549565b60006040518083038186803b158015610fd357600080fd5b505af4158015610fe7573d6000803e3d6000fd5b5050505050505050565b600154600160781b90046001600160801b031690565b602760009054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b15801561105557600080fd5b505afa158015611069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108d9190614875565b602680546001600160a01b0319166001600160a01b0392909216919091179055565b60606110b96144d5565b6040516341850fdb60e11b815273265b6c10c606cd1c79545799ebe36bca9ce124a59063830a1fb690610e5c906001908990899089908990600401615560565b61110161460d565b60015460ff808216835263ffffffff6101008304166020840152600160281b820481166040840152600160301b820481166060840152600160381b820481166080840152600160401b8204811660a0840152600160481b8204811660c0840152600160501b9091041660e082015290565b60005460ff1681565b6111836144d5565b60015460ff1683146111a75760405162461bcd60e51b8152600401610760906150cd565b6000821180156111b75750600081115b6111d35760405162461bcd60e51b8152600401610760906150fa565b6005546040516372956b6960e01b81526000916001600160a01b0316906372956b6990611204908890600401614e7a565b60206040518083038186803b15801561121c57600080fd5b505afa158015611230573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112549190614875565b9050846001600160a01b0316816001600160a01b03161415801561128057506001600160a01b03811615155b61129c5760405162461bcd60e51b81526004016107609061522f565b6001546000906112d3906127109061088890670de0b6b3a7640000906112cd908a90600160301b900460ff1661449e565b9061449e565b6005549091506001600160a01b031660006112ee3484614449565b111561135d576001600160a01b03811663ad9d4ba361130d3485614449565b336040518363ffffffff1660e01b815260040161132a9190614e7a565b6000604051808303818588803b15801561134357600080fd5b505af1158015611357573d6000803e3d6000fd5b50505050505b600754600a546006546001600160a01b0392831692918216918681169116141561146b576001600160a01b03821663daa78c0f6113a0606461088888605061449e565b876040518363ffffffff1660e01b81526004016113bd9190614e7a565b6000604051808303818588803b1580156113d657600080fd5b505af11580156113ea573d6000803e3d6000fd5b5050505050806001600160a01b031663daa78c0f611417606461088860148961449e90919063ffffffff16565b876040518363ffffffff1660e01b81526004016114349190614e7a565b6000604051808303818588803b15801561144d57600080fd5b505af1158015611461573d6000803e3d6000fd5b50505050506115d8565b6001600160a01b03821663daa78c0f61148a606461088888603c61449e565b876040518363ffffffff1660e01b81526004016114a79190614e7a565b6000604051808303818588803b1580156114c057600080fd5b505af11580156114d4573d6000803e3d6000fd5b5050505050806001600160a01b031663daa78c0f611501606461088860148961449e90919063ffffffff16565b876040518363ffffffff1660e01b815260040161151e9190614e7a565b6000604051808303818588803b15801561153757600080fd5b505af115801561154b573d6000803e3d6000fd5b5050505050806001600160a01b031663daa78c0f611578606461088860148961449e90919063ffffffff16565b6006546040516001600160e01b031960e085901b1681526115a5916001600160a01b031690600401614e7a565b6000604051808303818588803b1580156115be57600080fd5b505af11580156115d2573d6000803e3d6000fd5b50505050505b6001600160a01b0383166361025502336115fa8b670de0b6b3a764000061449e565b8c6116058c8e61449e565b6040518563ffffffff1660e01b81526004016116249493929190614ed8565b600060405180830381600087803b15801561163e57600080fd5b505af1158015611652573d6000803e3d6000fd5b5050506001600160a01b03841690506361025502336116798b670de0b6b3a764000061449e565b886116848b8e61449e565b6040518563ffffffff1660e01b81526004016116a39493929190614ed8565b600060405180830381600087803b1580156116bd57600080fd5b505af11580156116d1573d6000803e3d6000fd5b50506001546001600160a01b0386169250632dc8decd9150339061171590683635c9adc5dea00000906112cd9063ffffffff61010090910481169060029061449e16565b6040518363ffffffff1660e01b8152600401611732929190614ebf565b600060405180830381600087803b15801561174c57600080fd5b505af1158015611760573d6000803e3d6000fd5b5050600654600095508594506001600160a01b038881169116141592506117909150505750600190506002611798565b506003905060045b60006001601e0160008a6001600160a01b03166001600160a01b03168152602001908152602001600020905080604051806101800160405280336001600160a01b031681526020014363ffffffff1681526020018a63ffffffff1681526020018a63ffffffff168152602001600060ff1681526020018560ff168152602001600160ff168152602001600060ff1681526020018a63ffffffff1681526020018a63ffffffff168152602001600160000160019054906101000a900463ffffffff1663ffffffff168152602001896001600160801b0316815250908060018154018082558091505060019003906000526020600020906002020160009091909190915060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160186101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160006101000a81548160ff021916908360ff16021790555060a08201518160010160016101000a81548160ff021916908360ff16021790555060c08201518160010160026101000a81548160ff021916908360ff16021790555060e08201518160010160036101000a81548160ff021916908360ff1602179055506101008201518160010160046101000a81548163ffffffff021916908363ffffffff1602179055506101208201518160010160086101000a81548163ffffffff021916908363ffffffff16021790555061014082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160106101000a8154816001600160801b0302191690836001600160801b03160217905550505060006001601e016000876001600160a01b03166001600160a01b03168152602001908152602001600020905080604051806101800160405280336001600160a01b031681526020014363ffffffff1681526020018b63ffffffff1681526020018b63ffffffff168152602001600060ff1681526020018560ff168152602001600160ff168152602001600060ff1681526020018b63ffffffff1681526020018b63ffffffff168152602001600160000160019054906101000a900463ffffffff1663ffffffff168152602001896001600160801b0316815250908060018154018082558091505060019003906000526020600020906002020160009091909190915060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160186101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160006101000a81548160ff021916908360ff16021790555060a08201518160010160016101000a81548160ff021916908360ff16021790555060c08201518160010160026101000a81548160ff021916908360ff16021790555060e08201518160010160036101000a81548160ff021916908360ff1602179055506101008201518160010160046101000a81548163ffffffff021916908363ffffffff1602179055506101208201518160010160086101000a81548163ffffffff021916908363ffffffff16021790555061014082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160106101000a8154816001600160801b0302191690836001600160801b0316021790555050507fee7aa1809348e0f32177d04baf37df86a10ef3337729271eeff50db46e199190338b6001858054905003611d7e670de0b6b3a76400008e61449e90919063ffffffff16565b611d888d8f61449e565b604051611d99959493929190614e8e565b60405180910390a180547fee7aa1809348e0f32177d04baf37df86a10ef3337729271eeff50db46e199190903390889060001901611ddf8d670de0b6b3a764000061449e565b611de98c8f61449e565b604051611dfa959493929190614e8e565b60405180910390a150506006546001600160a01b038581169116141591506120de9050576001600160a01b0386166000908152602160209081526040808320438452909152902054608081901c6001600160801b0382168161209d576000611e6061085b565b60018054600160781b600160f81b0319164363ffffffff908116600160781b0291909117909155600280546001600160801b031981166001600160801b039182168501909116179055909150611ec29060649061088890849060509061449e16565b6005546008549194506001600160a01b0390811691635c3a6cf29116611eee606461088886600f61449e565b6040518363ffffffff1660e01b8152600401611f0b929190614ebf565b600060405180830381600087803b158015611f2557600080fd5b505af1158015611f39573d6000803e3d6000fd5b50506008546001600160a01b0316915063ccaaf98b9050611f60606461088885600f61449e565b6040518263ffffffff1660e01b8152600401611f7c91906156ad565b600060405180830381600087803b158015611f9657600080fd5b505af1158015611faa573d6000803e3d6000fd5b505060058054600a546001600160a01b039182169450635c3a6cf293501690611fdb9060649061088890879061449e565b6040518363ffffffff1660e01b8152600401611ff8929190614ebf565b600060405180830381600087803b15801561201257600080fd5b505af1158015612026573d6000803e3d6000fd5b5050600a546001600160a01b03169150630c202bf7905061204d606461088885600561449e565b6040518263ffffffff1660e01b815260040161206991906156ad565b600060405180830381600087803b15801561208357600080fd5b505af1158015612097573d6000803e3d6000fd5b50505050505b6120a78189614520565b6001600160a01b038a1660009081526021602090815260408083204384529091529020600160801b90930201909155506123c09050565b6001600160a01b0386166000908152602160209081526040808320438452909152902054608081901c6001600160801b0382168161238457600061212186612690565b90506000866001600160a01b03166328e6a33f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561215e57600080fd5b505afa158015612172573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121969190614875565b6005549091506001600160a01b038083169116141561221d576005546040516394bf804d60e01b815292945084926001600160a01b03808a16926394bf804d926121e69287921690600401615549565b600060405180830381600087803b15801561220057600080fd5b505af1158015612214573d6000803e3d6000fd5b50505050612381565b6040516381fa543160e01b81526001600160a01b038816906381fa5431906122499085906004016156ad565b600060405180830381600087803b15801561226357600080fd5b505af1158015612277573d6000803e3d6000fd5b505060055460405163a9059cbb60e01b81526001600160a01b03808c16945063a9059cbb93506122ad9216908690600401614ebf565b602060405180830381600087803b1580156122c757600080fd5b505af11580156122db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ff9190614bd4565b50612310606461088884605f61449e565b6005549094506001600160a01b03166361bced9d82896123308689614449565b6040518463ffffffff1660e01b815260040161234e93929190614f02565b600060405180830381600087803b15801561236857600080fd5b505af115801561237c573d6000803e3d6000fd5b505050505b50505b61238e8189614520565b6001600160a01b038a1660009081526021602090815260408083204384529091529020600160801b9093020190915550505b604051637b576fc960e01b815273265b6c10c606cd1c79545799ebe36bca9ce124a590637b576fc9906123fa906001908a90600401615549565b60006040518083038186803b15801561241257600080fd5b505af4158015612426573d6000803e3d6000fd5b5050604051637b576fc960e01b815273265b6c10c606cd1c79545799ebe36bca9ce124a59250637b576fc99150612464906001908690600401615549565b60006040518083038186803b15801561247c57600080fd5b505af4158015612490573d6000803e3d6000fd5b50505050505050505050565b6000808080333214806124b95750600a546001600160a01b031633145b806124ce57506007546001600160a01b031633145b806124e357506008546001600160a01b031633145b806124f857506009546001600160a01b031633145b6125145760405162461bcd60e51b815260040161076090615313565b61251c614651565b506001600160a01b03851660009081526020808052604091829020825161012081018452815463ffffffff808216835264010000000082048116948301859052600160401b8204811695830195909552600160601b810490941660608201526001600160801b03600160801b94859004811660808301526001830154600f81810b810b810b60a085015290869004810b810b900b60c083015260029092015480831660e083015293909304166101008301526125ea5760405162461bcd60e51b8152600401610760906150a0565b6125ff6125fa8260a00151614543565b61457f565b925061262b816040015163ffffffff1682608001516001600160801b031661446c90919063ffffffff16565b60e08201516001546020840151929750909550600160381b900460ff160191506001600160801b0385161580159061266c57506000846001600160801b0316115b6126885760405162461bcd60e51b81526004016107609061525c565b509193509193565b6000806000836001600160a01b03166392c088716040518163ffffffff1660e01b8152600401604080518083038186803b1580156126cd57600080fd5b505afa1580156126e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127059190614d6c565b9092509050600061271d62249f006108884386614449565b905060006009821115612739575067058d15e17628000061274b565b601582600a811061274657fe5b015490505b60006127574385614449565b90506064811115612766575060645b6000612772838361449e565b98975050505050505050565b61278661469d565b61278e6144d5565b6001600160a01b0383166000908152601f60205260409020548083106127c65760405162461bcd60e51b8152600401610760906151d8565b6001600160a01b0384166000908152601f602052604090208054849081106127ea57fe5b6000918252602091829020604080516101808101825260029390930290910180546001600160a01b0381168452600160a01b810463ffffffff90811695850195909552600160c01b8104851692840192909252600160e01b909104831660608301526001015460ff8082166080840152610100808304821660a0850152620100008304821660c08501526301000000830490911660e08401526401000000008204841690830152600160401b81048316610120830152600160601b8104909216610140820152600160801b9091046001600160801b03166101608201529150505b92915050565b6128d96144d5565b604051630d26201760e31b815273fe543efe9bb91b51a046157b73fdf0838833b8419063693100b890610f51906001908890889088908890600401615605565b60606129236144d5565b6040516306d8420960e21b815273265b6c10c606cd1c79545799ebe36bca9ce124a590631b6108249061295d906001908690600401615549565b60006040518083038186803b15801561297557600080fd5b505af4158015612989573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526128cb9190810190614a92565b604051637b576fc960e01b815273265b6c10c606cd1c79545799ebe36bca9ce124a590637b576fc9906129eb906001908590600401615549565b60006040518083038186803b158015612a0357600080fd5b505af4158015612a17573d6000803e3d6000fd5b505050505b50565b612a27614701565b604051631182622760e21b815273265b6c10c606cd1c79545799ebe36bca9ce124a590634609889c90612a6390600190879087906004016155e6565b60e06040518083038186803b158015612a7b57600080fd5b505af4158015612a8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ab39190614c10565b9392505050565b6000808033321480612ad65750600a546001600160a01b031633145b80612aeb57506007546001600160a01b031633145b80612b0057506008546001600160a01b031633145b80612b1557506009546001600160a01b031633145b612b315760405162461bcd60e51b815260040161076090615313565b6001600160a01b0384166000908152601f6020526040812080549091612b5561469d565b82612b725760405162461bcd60e51b81526004016107609061525c565b600060015b848111612d8f578581860381548110612b8c57fe5b6000918252602091829020604080516101808101825260029390930290910180546001600160a01b0381168452600160a01b810463ffffffff90811695850195909552600160c01b8104851692840192909252600160e01b909104831660608301526001015460ff8082166080840152610100808304821660a0850152620100008304821660c08501526301000000830490911660e08401526401000000008204841690830152600160401b81048316610120830152600160601b8104909216610140820152600160801b9091046001600160801b0316610160820152925081158015612c99575043600160000160079054906101000a900460ff1660ff16846020015163ffffffff1601105b15612d0157606083015163ffffffff16935083612cb557612d87565b826020015163ffffffff169150612ce38361016001516001600160801b03168561449e90919063ffffffff16565b9750612cf784670de0b6b3a764000061449e565b9850819650612d87565b826020015163ffffffff16821415612d7057826060015163ffffffff169350612d4b612d448461016001516001600160801b03168661449e90919063ffffffff16565b8990614520565b9750612d69612d6285670de0b6b3a764000061449e565b8a90614520565b9850612d87565b826020015163ffffffff16821115612d8757612d8f565b600101612b77565b50600154600160381b900460ff1695909501948715801590612db15750600087115b612dcd5760405162461bcd60e51b81526004016107609061525c565b50505050509193909250565b6009546060906000906001600160a01b031633321480612e015750336001600160a01b038216145b612e1d5760405162461bcd60e51b815260040161076090615202565b6040516353b847a960e01b815273265b6c10c606cd1c79545799ebe36bca9ce124a5906353b847a990612e59906001908990899060040161565a565b60006040518083038186803b158015612e7157600080fd5b505af4158015612e85573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612ead9190810190614b31565b92509250509250929050565b600954600090819081906001600160a01b031633321480612ee25750336001600160a01b038216145b612efe5760405162461bcd60e51b815260040161076090615202565b612f06614651565b506001600160a01b03851660009081526020808052604091829020825161012081018452815463ffffffff808216835264010000000082048116948301859052600160401b8204811695830195909552600160601b810490941660608201526001600160801b03600160801b94859004811660808301526001830154600f81810b810b810b60a085015290869004810b810b900b60c083015260029092015480831660e08301529390930416610100830152612fd45760405162461bcd60e51b8152600401610760906150a0565b612ff9670de0b6b3a7640000826040015163ffffffff1661449e90919063ffffffff16565b945080608001516001600160801b03169350600160000160079054906101000a900460ff1660ff1681602001510163ffffffff16925060008511801561303f5750600084115b61305b5760405162461bcd60e51b81526004016107609061525c565b50509193909250565b600054600160481b900460ff16600114156130915760405162461bcd60e51b8152600401610760906152dc565b6000805460ff60481b1916600160481b1790556005546040516306e6a46960e21b81526001600160a01b0390911690631b9a91a490610a929033908590600401614ebf565b60005460ff16156130f95760405162461bcd60e51b815260040161076090615289565b6815af1d78b58c40000060005b600a8110156131395781600b82600a811061311d57fe5b015561312f606461088884605061449e565b9150600101613106565b50673782dace9d900000905060005b600a81101561317b5781601582600a811061315f57fe5b0155613171606461088884605061449e565b9150600101613148565b505060268054336001600160a01b03199182161790915560008054602780549093166001600160a01b03949094169390931790915568ffffffffffffffff00199091166101004367ffffffffffffffff16021760ff19166001179055565b6131e16144d5565b604051633ebf3e8560e21b815273fe543efe9bb91b51a046157b73fdf0838833b8419063fafcfa149061097390600190869086906004016155e6565b6132256144f6565b60005460ff1660021461324a5760405162461bcd60e51b815260040161076090615289565b6000805460ff19166003179055565b600054600160481b900460ff16600114156132865760405162461bcd60e51b8152600401610760906152dc565b6000805460ff60481b1916600160481b17905560055460405163a798e17d60e01b81526001600160a01b039091169063a798e17d906132cf903390879087908790600401614ed8565b600060405180830381600087803b1580156132e957600080fd5b505af11580156132fd573d6000803e3d6000fd5b50506000805460ff60481b191690555050505050565b61331b6144f6565b6133286020820182614e33565b6001805460ff191660ff9290921691909117905561334c6040820160208301614dbc565b6001805463ffffffff929092166101000264ffffffff001990921691909117905561337d6060820160408301614e33565b6001805460ff92909216600160281b0265ff0000000000199092169190911790556133ae6080820160608301614e33565b6001805460ff92909216600160301b0266ff000000000000199092169190911790556133e060a0820160808301614e33565b6001805460ff92909216600160381b0260ff60381b1990921691909117905561340f60c0820160a08301614e33565b6001805460ff92909216600160401b0260ff60401b1990921691909117905561343e60e0820160c08301614e33565b6001805460ff92909216600160481b0260ff60481b1990921691909117905561346e610100820160e08301614e33565b6001805460ff60501b1916600160501b60ff938416810291909117918290556040517fd52ea55597dda83c654fca3762be1b95778ce32b5d67b2ddc77f14e4c5f778ce936135039380821693610100820463ffffffff1693600160281b8304841693600160301b8404811693600160381b8104821693600160401b8204831693600160481b83048416939190920416906156ef565b60405180910390a150565b6135166144d5565b60015460ff16821461353a5760405162461bcd60e51b8152600401610760906150cd565b6000811161355a5760405162461bcd60e51b8152600401610760906150fa565b6005546040516372956b6960e01b81526001600160a01b039091169060009082906372956b699061358f908890600401614e7a565b60206040518083038186803b1580156135a757600080fd5b505afa1580156135bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135df9190614875565b90506001600160a01b0381161580159061360757506006546001600160a01b03828116911614155b80156136255750806001600160a01b0316856001600160a01b031614155b6136415760405162461bcd60e51b81526004016107609061522f565b6a0422ca8b0a00a425000000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561368657600080fd5b505afa15801561369a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136be9190614cf6565b106136db5760405162461bcd60e51b815260040161076090615154565b60015460009061370c906127109061088890670de0b6b3a7640000906112cd908a90600160301b900460ff1661449e565b9050600061371a3483614449565b1115613789576001600160a01b03831663ad9d4ba36137393484614449565b336040518363ffffffff1660e01b81526004016137569190614e7a565b6000604051808303818588803b15801561376f57600080fd5b505af1158015613783573d6000803e3d6000fd5b50505050505b600754600a546001600160a01b0391821691168163daa78c0f6137b2606461088887603c61449e565b866040518363ffffffff1660e01b81526004016137cf9190614e7a565b6000604051808303818588803b1580156137e857600080fd5b505af11580156137fc573d6000803e3d6000fd5b5050505050806001600160a01b031663daa78c0f613829606461088860148861449e90919063ffffffff16565b866040518363ffffffff1660e01b81526004016138469190614e7a565b6000604051808303818588803b15801561385f57600080fd5b505af1158015613873573d6000803e3d6000fd5b5050505050806001600160a01b031663daa78c0f6138a0606461088860148861449e90919063ffffffff16565b6006546040516001600160e01b031960e085901b1681526138cd916001600160a01b031690600401614e7a565b6000604051808303818588803b1580156138e657600080fd5b505af11580156138fa573d6000803e3d6000fd5b5050505050846001600160a01b031663610255023361392a670de0b6b3a76400008b61449e90919063ffffffff16565b8b6139358b8d61449e565b6040518563ffffffff1660e01b81526004016139549493929190614ed8565b600060405180830381600087803b15801561396e57600080fd5b505af1158015613982573d6000803e3d6000fd5b50506001546001600160a01b0388169250632dc8decd915033906139bf9063ffffffff610100909104811690683635c9adc5dea000009061449e16565b6040518363ffffffff1660e01b81526004016139dc929190614ebf565b600060405180830381600087803b1580156139f657600080fd5b505af1158015613a0a573d6000803e3d6000fd5b50505050505060006001601e016000886001600160a01b03166001600160a01b03168152602001908152602001600020905080604051806101800160405280336001600160a01b031681526020014363ffffffff1681526020018863ffffffff1681526020018863ffffffff168152602001600060ff168152602001600360ff168152602001600160ff168152602001600060ff1681526020018863ffffffff1681526020018863ffffffff168152602001600160000160019054906101000a900463ffffffff1663ffffffff168152602001876001600160801b0316815250908060018154018082558091505060019003906000526020600020906002020160009091909190915060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160186101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160006101000a81548160ff021916908360ff16021790555060a08201518160010160016101000a81548160ff021916908360ff16021790555060c08201518160010160026101000a81548160ff021916908360ff16021790555060e08201518160010160036101000a81548160ff021916908360ff1602179055506101008201518160010160046101000a81548163ffffffff021916908363ffffffff1602179055506101208201518160010160086101000a81548163ffffffff021916908363ffffffff16021790555061014082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160106101000a8154816001600160801b0302191690836001600160801b0316021790555050507fee7aa1809348e0f32177d04baf37df86a10ef3337729271eeff50db46e19919033886001848054905003613d27670de0b6b3a76400008b61449e90919063ffffffff16565b613d318a8c61449e565b604051613d42959493929190614e8e565b60405180910390a1506001600160a01b0386166000908152602160209081526040808320438452909152902054608081901c6001600160801b03821681613ff1576000613d8e86612690565b90506000866001600160a01b03166328e6a33f6040518163ffffffff1660e01b815260040160206040518083038186803b158015613dcb57600080fd5b505afa158015613ddf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e039190614875565b6005549091506001600160a01b0380831691161415613e8a576005546040516394bf804d60e01b815292945084926001600160a01b03808a16926394bf804d92613e539287921690600401615549565b600060405180830381600087803b158015613e6d57600080fd5b505af1158015613e81573d6000803e3d6000fd5b50505050613fee565b613e9a606461088884605f61449e565b6040516381fa543160e01b81529094506001600160a01b038816906381fa543190613ec99085906004016156ad565b600060405180830381600087803b158015613ee357600080fd5b505af1158015613ef7573d6000803e3d6000fd5b505060055460405163a9059cbb60e01b81526001600160a01b03808c16945063a9059cbb9350613f2d9216908690600401614ebf565b602060405180830381600087803b158015613f4757600080fd5b505af1158015613f5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f7f9190614bd4565b506005546001600160a01b03166361bced9d8289613f9d8689614449565b6040518463ffffffff1660e01b8152600401613fbb93929190614f02565b600060405180830381600087803b158015613fd557600080fd5b505af1158015613fe9573d6000803e3d6000fd5b505050505b50505b613ffb8189614520565b6001600160a01b038a16600090815260216020908152604080832043845290915290819020600160801b9094029091019092555051637b576fc960e01b815273265b6c10c606cd1c79545799ebe36bca9ce124a59150637b576fc990612464906001908a90600401615549565b6140706144d5565b604051638f2daafb60e01b815273fe543efe9bb91b51a046157b73fdf0838833b84190638f2daafb9061097390600190869086906004016155e6565b6140b46144f6565b60005460ff166002146140d95760405162461bcd60e51b815260040161076090615289565b60018054600160781b600160f81b031916600160781b6001600160801b0394851602179055600280546001600160801b03191691909216179055565b600954600090819081906001600160a01b03163332148061413e5750336001600160a01b038216145b61415a5760405162461bcd60e51b815260040161076090615202565b604051630da947f160e21b815273265b6c10c606cd1c79545799ebe36bca9ce124a5906336a51fc490614196906001908a908a90600401615631565b60606040518083038186803b1580156141ae57600080fd5b505af41580156141c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141e69190614d8f565b9195509350915083158015906141fc5750600083115b6142185760405162461bcd60e51b81526004016107609061525c565b509250925092565b6142286144f6565b60005460ff1660011461424d5760405162461bcd60e51b815260040161076090615289565b61425a6020820182614e33565b6001805460ff191660ff9290921691909117905561427e6040820160208301614dbc565b6001805463ffffffff929092166101000264ffffffff00199092169190911790556142af6060820160408301614e33565b6001805460ff92909216600160281b0265ff0000000000199092169190911790556142e06080820160608301614e33565b6001805460ff92909216600160301b0266ff0000000000001990921691909117905561431260a0820160808301614e33565b6001805460ff92909216600160381b0260ff60381b1990921691909117905561434160c0820160a08301614e33565b6001805460ff92909216600160401b0260ff60401b1990921691909117905561437060e0820160c08301614e33565b6001805460ff92909216600160481b0260ff60481b199092169190911790556143a0610100820160e08301614e33565b60018054600280546001600160801b0319166001600160801b0396871617815560ff60501b19909116600160501b60ff949094169390930292909217600160781b600160f81b031916600160781b95909416949094029290921763ffffffff60581b1916600160581b63ffffffff9590951694909402939093179091556000805468ffffffffffffffff0019166101004367ffffffffffffffff16021760ff1916909117905550565b808203828111156128cb5760405162461bcd60e51b815260040161076090615071565b600080821161448d5760405162461bcd60e51b8152600401610760906152b2565b81838161449657fe5b049392505050565b60008115806144b9575050808202828282816144b657fe5b04145b6128cb5760405162461bcd60e51b815260040161076090615126565b3332146144f45760405162461bcd60e51b815260040161076090615202565b565b6026546001600160a01b031633146144f45760405162461bcd60e51b81526004016107609061533c565b808201828110156128cb5760405162461bcd60e51b81526004016107609061517f565b6000600f82900b6f7fffffffffffffffffffffffffffffff19141561456757600080fd5b600082600f0b1261457857816128cb565b5060000390565b60008082600f0b121561459157600080fd5b6128cb604083600f0b901b600160401b6000826145b0575060006128cb565b600082116145bd57600080fd5b60008284816145c857fe5b049050808314806145db57508083600101145b156145e957829150506128cb565b806001018314156145fb5790506128cb565b6001818401600101901c9250506145bd565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915290565b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081019190915290565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810182905261016081019190915290565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b6000610100828403121561474f578081fd5b50919050565b6000610140808385031215614768578182fd5b61477181615739565b91505061477e838361482d565b815261478d8360208401614843565b602082015261479f8360408401614843565b60408201526147b18360608401614843565b60608201526147c3836080840161484e565b60808201526147d58360a0840161484e565b60a08201526147e78360c0840161484e565b60c082015260e082015160e082015261010061480584828501614843565b9082015261012061481884848301614822565b9082015292915050565b80516128cb81615795565b80516128cb81615780565b80356128cb816157aa565b80516128cb816157aa565b80516128cb816157bc565b60006020828403121561486a578081fd5b8135612ab381615780565b600060208284031215614886578081fd5b8151612ab381615780565b600080600080608085870312156148a6578283fd5b84356148b181615780565b935060208501356148c181615780565b93969395505050506040820135916060013590565b600080604083850312156148e8578182fd5b82356148f381615780565b915060208381013567ffffffffffffffff81111561490f578283fd5b8401601f8101861361491f578283fd5b803561493261492d82615760565b615739565b81815283810190838501858402850186018a101561494e578687fd5b8694505b83851015614978576149648a82614838565b835260019490940193918501918501614952565b5080955050505050509250929050565b6000806040838503121561499a578182fd5b82356149a581615780565b946020939093013593505050565b6000806000606084860312156149c7578081fd5b83356149d281615780565b95602085013595506040909401359392505050565b600080600080608085870312156149fc578182fd5b8435614a0781615780565b966020860135965060408601359560600135945092505050565b60008060408385031215614a33578182fd5b8235614a3e81615780565b9150602083013567ffffffffffffffff81168114614a5a578182fd5b809150509250929050565b60008060408385031215614a77578182fd5b8235614a8281615780565b91506020830135614a5a816157bc565b60006020808385031215614aa4578182fd5b825167ffffffffffffffff811115614aba578283fd5b8301601f81018513614aca578283fd5b8051614ad861492d82615760565b81815283810190838501610140808502860187018a1015614af7578788fd5b8795505b84861015614b2357614b0d8a83614755565b8452600195909501949286019290810190614afb565b509098975050505050505050565b60008060408385031215614b43578182fd5b825167ffffffffffffffff811115614b59578283fd5b8301601f81018513614b69578283fd5b8051614b7761492d82615760565b808282526020808301925080850189828387028801011115614b97578788fd5b8795505b84861015614bc2578051614bae81615795565b845260019590950194928101928101614b9b565b50969096015195979596505050505050565b600060208284031215614be5578081fd5b81518015158114612ab3578182fd5b60006101008284031215614c06578081fd5b612ab3838361473d565b600060e08284031215614c21578081fd5b614c2b60e0615739565b8251614c3681615780565b81526020830151614c46816157aa565b60208201526040830151614c59816157aa565b60408201526060830151614c6c816157bc565b60608201526080830151614c7f816157bc565b608082015260a0830151614c92816157aa565b60a082015260c0830151614ca5816157aa565b60c08201529392505050565b60008060408385031215614cc3578182fd5b8235614cce81615795565b91506020830135614a5a81615795565b600060208284031215614cef578081fd5b5035919050565b600060208284031215614d07578081fd5b5051919050565b600080600060608486031215614d22578081fd5b833592506020840135614d3481615780565b929592945050506040919091013590565b60008060008060808587031215614d5a578182fd5b8435935060208501356148c181615780565b60008060408385031215614d7e578182fd5b505080516020909101519092909150565b600080600060608486031215614da3578081fd5b8351925060208401519150604084015190509250925092565b600060208284031215614dcd578081fd5b8135612ab3816157aa565b6000806000806101608587031215614dee578182fd5b8435614df9816157aa565b93506020850135614e0981615795565b92506040850135614e1981615795565b9150614e28866060870161473d565b905092959194509250565b600060208284031215614e44578081fd5b8135612ab3816157bc565b6001600160801b03169052565b6001600160a01b03169052565b63ffffffff169052565b60ff169052565b6001600160a01b0391909116815260200190565b6001600160a01b03958616815293909416602084015260408301919091526060820152608081019190915260a00190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039485168152602081019390935292166040820152606081019190915260800190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b602080825282518282018190526000919060409081850190868401855b82811015615013578151614f58858251614e5c565b86810151614f6888870182614e69565b5085810151614f7987870182614e69565b50606080820151614f8c82880182614e69565b5050608080820151614fa082880182614e73565b505060a080820151614fb482880182614e73565b505060c080820151614fc882880182614e73565b505060e0818101519086015261010080820151614fe782880182614e69565b50506101209081015190614ffd86820183614e4f565b5050610140939093019290850190600101614f43565b5091979650505050505050565b604080825283519082018190526000906020906060840190828701845b828110156150625781516001600160801b03168452928401929084019060010161503d565b50505092019290925292915050565b60208082526015908201527464732d6d6174682d7375622d756e646572666c6f7760581b604082015260600190565b6020808252601390820152724e6573743a4d696e653a4e4f2870726963652960681b604082015260600190565b6020808252601390820152724e6573743a4d696e653a21286574684e756d2960681b604082015260600190565b6020808252601290820152714e6573743a4d696e653a212870726963652960701b604082015260600190565b60208082526014908201527364732d6d6174682d6d756c2d6f766572666c6f7760601b604082015260600190565b6020808252601190820152702732b9ba1d26b4b7329d10b73a37b5b2b760791b604082015260600190565b60208082526014908201527364732d6d6174682d6164642d6f766572666c6f7760601b604082015260600190565b6020808252601190820152702732b9ba1d26b4b7329d10b9b2b73232b960791b604082015260600190565b60208082526010908201526f4e6573743a4d696e653a3e286c656e2960801b604082015260600190565b6020808252601390820152724e6573743a4d696e653a636f6e74726163742160681b604082015260600190565b6020808252601390820152724e6573743a4d696e653a21286e746f6b656e2960681b604082015260600190565b6020808252601390820152724e6573743a4d696e653a6e6f2870726963652960681b604082015260600190565b6020808252600f908201526e4e6573743a4d696e653a21666c616760881b604082015260600190565b60208082526010908201526f64732d6d6174682d6469762d7a65726f60801b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252600f908201526e09ccae6e8749ad2dcca744282eae8d608b1b604082015260600190565b6020808252600e908201526d2732b9ba1d26b4b7329d10a3a7ab60911b604082015260600190565b60006101008201905060ff835116825263ffffffff602084015116602083015260ff604084015116604083015260ff606084015116606083015260ff608084015116608083015260a08301516153bd60a0840182614e73565b5060c08301516153d060c0840182614e73565b5060e08301516153e360e0840182614e73565b5092915050565b600060e08201905060018060a01b038351168252602083015163ffffffff808216602085015280604086015116604085015260ff606086015116606085015260ff60808601511660808501528060a08601511660a08501528060c08601511660c0850152505092915050565b60006101808201905061546a828451614e5c565b602083015161547c6020840182614e69565b50604083015161548f6040840182614e69565b5060608301516154a26060840182614e69565b5060808301516154b56080840182614e73565b5060a08301516154c860a0840182614e73565b5060c08301516154db60c0840182614e73565b5060e08301516154ee60e0840182614e73565b506101008084015161550282850182614e69565b50506101208084015161551782850182614e69565b50506101408084015161552c82850182614e69565b50506101608084015161554182850182614e4f565b505092915050565b9182526001600160a01b0316602082015260400190565b9485526001600160a01b0393841660208601529190921660408401526060830191909152608082015260a00190565b8381526001600160a01b0383166020808301919091526060604083018190528351908301819052600091848101916080850190845b81811015614b2357845163ffffffff16835293830193918301916001016155c4565b9283526001600160a01b03919091166020830152604082015260600190565b9485526001600160a01b0393909316602085015260408401919091526060830152608082015260a00190565b9283526001600160a01b0391909116602083015267ffffffffffffffff16604082015260600190565b9283526001600160a01b0391909116602083015260ff16604082015260600190565b6001600160801b039485168152929093166020830152600f0b604082015263ffffffff909116606082015260800190565b90815260200190565b9283526020830191909152604082015260600190565b67ffffffffffffffff91909116815260200190565b60ff91909116815260200190565b60ff988916815263ffffffff979097166020880152948716604087015292861660608601529085166080850152841660a0840152831660c083015290911660e08201526101000190565b60405181810167ffffffffffffffff8111828210171561575857600080fd5b604052919050565b600067ffffffffffffffff821115615776578081fd5b5060209081020190565b6001600160a01b0381168114612a1c57600080fd5b6001600160801b0381168114612a1c57600080fd5b63ffffffff81168114612a1c57600080fd5b60ff81168114612a1c57600080fdfea2646970667358221220d93eef17cc519ed96e943ab106845bf42eba3c315bd881f3d3980f522e5e09e864736f6c634300060c0033
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.