Transaction Hash:
Block:
11454900 at Dec-15-2020 02:26:14 AM +UTC
Transaction Fee:
0.007289105043918045 ETH
$13.76
Gas Used:
76,047 Gas / 95.850001235 Gwei
Emitted Events:
94 |
HBTCToken.Transfer( from=[Receiver] Nest_NToken_OfferMain, to=[Sender] 0x9fec61245a720fd9f3f686f0f86e2b2b4b0f775e, value=305370000000000030 )
|
95 |
Nest_NToken.Transfer( from=[Receiver] Nest_NToken_OfferMain, to=[Sender] 0x9fec61245a720fd9f3f686f0f86e2b2b4b0f775e, value=76000000000000000000 )
|
96 |
Nest_NToken_OfferMain.MiningLog( blockNum=11454873, tokenAddress=HBTCToken, offerTimes=100000000000000000 )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x1542E790...E7794EEf4 | 70 Eth | 60 Eth | 10 | ||
0x1F832091...611225d46 | |||||
0x8565fC13...c458842ce
Miner
| 3.248777885324889843 Eth | 3.256066990368807888 Eth | 0.007289105043918045 | ||
0x9FEC6124...b4B0F775e |
1.60430729386449798 Eth
Nonce: 1442
|
11.597018188820579935 Eth
Nonce: 1443
| 9.992710894956081955 | ||
0xC728693d...28426eefd |
Execution Trace
Nest_NToken_OfferMain.turnOut( contractAddress=0x000000000000000000000000000000000000E6f2 )
- ETH 10
0x9fec61245a720fd9f3f686f0f86e2b2b4b0f775e.CALL( )
HBTCToken.transfer( to=0x9FEC61245A720Fd9F3f686F0f86e2B2b4B0F775e, value=305370000000000030 ) => ( True )
0xe57c8c5ab4eb4f117dfba282e000ee1968fbae4b.7ea56078( )
-
HBTCStorage.balanceOf( account=0x1542E790a742333EA6A2F171c5d07A2E7794EEf4 ) => ( 610510000000000030 )
-
HBTCStorage.balanceOf( account=0x9FEC61245A720Fd9F3f686F0f86e2B2b4B0F775e ) => ( 368800479999999930 )
-
0x898b3f52b7aa863bc9e033491fb7c3fd4772f981.a293d1e8( )
-
0x898b3f52b7aa863bc9e033491fb7c3fd4772f981.e6cb9013( )
-
HBTCStorage.setBalance( account=0x1542E790a742333EA6A2F171c5d07A2E7794EEf4, amount=305140000000000000 )
-
HBTCStorage.setBalance( account=0x9FEC61245A720Fd9F3f686F0f86e2B2b4B0F775e, amount=674170479999999960 )
-
-
Nest_NToken_TokenMapping.checkTokenMapping( token=0x0316EB71485b0Ab14103307bf65a021042c6d380 ) => ( 0x1F832091fAf289Ed4f50FE7418cFbD2611225d46 )
-
Nest_NToken.transfer( to=0x9FEC61245A720Fd9F3f686F0f86e2B2b4B0F775e, value=76000000000000000000 ) => ( True )
turnOut[Nest_NToken_OfferMain (ln:185)]
toIndex[Nest_NToken_OfferMain (ln:187)]
checkContractState[Nest_NToken_OfferMain (ln:189)]
repayEth[Nest_NToken_OfferMain (ln:194)]
make_payable[Nest_NToken_OfferMain (ln:409)]
transfer[Nest_NToken_OfferMain (ln:410)]
safeTransfer[Nest_NToken_OfferMain (ln:200)]
File 1 of 5: Nest_NToken_OfferMain
File 2 of 5: HBTCToken
File 3 of 5: Nest_NToken
File 4 of 5: HBTCStorage
File 5 of 5: Nest_NToken_TokenMapping
/** *Submitted for verification at Etherscan.io on 2020-08-11 */ pragma solidity 0.6.0; /** * @title Offering contract * @dev Offering logic and mining logic */ contract Nest_NToken_OfferMain { using SafeMath for uint256; using address_make_payable for address; using SafeERC20 for ERC20; // Offering data structure struct Nest_NToken_OfferPriceData { // The unique identifier is determined by the position of the offer in the array, and is converted to each other through a fixed algorithm (toindex(), toaddress()) address owner; // Offering owner bool deviate; // Whether it deviates address tokenAddress; // The erc20 contract address of the target offer token uint256 ethAmount; // The ETH amount in the offer list uint256 tokenAmount; // The token amount in the offer list uint256 dealEthAmount; // The remaining number of tradable ETH uint256 dealTokenAmount; // The remaining number of tradable tokens uint256 blockNum; // The block number where the offer is located uint256 serviceCharge; // The fee for mining // Determine whether the asset has been collected by judging that ethamount, tokenamount, and servicecharge are all 0 } Nest_NToken_OfferPriceData [] _prices; // Array used to save offers Nest_3_VoteFactory _voteFactory; // Voting contract Nest_3_OfferPrice _offerPrice; // Price contract Nest_NToken_TokenMapping _tokenMapping; // NToken mapping contract ERC20 _nestToken; // nestToken Nest_3_Abonus _abonus; // Bonus pool uint256 _miningETH = 10; // Offering mining fee ratio uint256 _tranEth = 1; // Taker fee ratio uint256 _tranAddition = 2; // Additional transaction multiple uint256 _leastEth = 10 ether; // Minimum offer of ETH uint256 _offerSpan = 10 ether; // ETH Offering span uint256 _deviate = 10; // Price deviation - 10% uint256 _deviationFromScale = 10; // Deviation from asset scale uint256 _ownerMining = 5; // Creator ratio uint256 _afterMiningAmount = 0.4 ether; // Stable period mining amount uint32 _blockLimit = 25; // Block interval upper limit uint256 _blockAttenuation = 2400000; // Block decay interval mapping(uint256 => mapping(address => uint256)) _blockOfferAmount; // Block offer times - block number=>token address=>offer fee mapping(uint256 => mapping(address => uint256)) _blockMining; // Offering block mining amount - block number=>token address=>mining amount uint256[10] _attenuationAmount; // Mining decay list // Log token contract address event OfferTokenContractAddress(address contractAddress); // Log offering contract, token address, amount of ETH, amount of ERC20, delayed block, mining fee event OfferContractAddress(address contractAddress, address tokenAddress, uint256 ethAmount, uint256 erc20Amount, uint256 continued,uint256 mining); // Log transaction sender, transaction token, transaction amount, purchase token address, purchase token amount, transaction offering contract address, transaction user address event OfferTran(address tranSender, address tranToken, uint256 tranAmount,address otherToken, uint256 otherAmount, address tradedContract, address tradedOwner); // Log current block, current block mined amount, token address event OreDrawingLog(uint256 nowBlock, uint256 blockAmount, address tokenAddress); // Log offering block, token address, token offered times event MiningLog(uint256 blockNum, address tokenAddress, uint256 offerTimes); /** * Initialization method * @param voteFactory Voting contract address **/ constructor (address voteFactory) public { Nest_3_VoteFactory voteFactoryMap = Nest_3_VoteFactory(address(voteFactory)); _voteFactory = voteFactoryMap; _offerPrice = Nest_3_OfferPrice(address(voteFactoryMap.checkAddress("nest.v3.offerPrice"))); _nestToken = ERC20(voteFactoryMap.checkAddress("nest")); _abonus = Nest_3_Abonus(voteFactoryMap.checkAddress("nest.v3.abonus")); _tokenMapping = Nest_NToken_TokenMapping(address(voteFactoryMap.checkAddress("nest.nToken.tokenMapping"))); uint256 blockAmount = 4 ether; for (uint256 i = 0; i < 10; i ++) { _attenuationAmount[i] = blockAmount; blockAmount = blockAmount.mul(8).div(10); } } /** * Reset voting contract method * @param voteFactory Voting contract address **/ function changeMapping(address voteFactory) public onlyOwner { Nest_3_VoteFactory voteFactoryMap = Nest_3_VoteFactory(address(voteFactory)); _voteFactory = voteFactoryMap; _offerPrice = Nest_3_OfferPrice(address(voteFactoryMap.checkAddress("nest.v3.offerPrice"))); _nestToken = ERC20(voteFactoryMap.checkAddress("nest")); _abonus = Nest_3_Abonus(voteFactoryMap.checkAddress("nest.v3.abonus")); _tokenMapping = Nest_NToken_TokenMapping(address(voteFactoryMap.checkAddress("nest.nToken.tokenMapping"))); } /** * Offering method * @param ethAmount ETH amount * @param erc20Amount Erc20 token amount * @param erc20Address Erc20 token address **/ function offer(uint256 ethAmount, uint256 erc20Amount, address erc20Address) public payable { require(address(msg.sender) == address(tx.origin), "It can't be a contract"); address nTokenAddress = _tokenMapping.checkTokenMapping(erc20Address); require(nTokenAddress != address(0x0)); // Judge whether the price deviates uint256 ethMining; bool isDeviate = comparativePrice(ethAmount,erc20Amount,erc20Address); if (isDeviate) { require(ethAmount >= _leastEth.mul(_deviationFromScale), "EthAmount needs to be no less than 10 times of the minimum scale"); ethMining = _leastEth.mul(_miningETH).div(1000); } else { ethMining = ethAmount.mul(_miningETH).div(1000); } require(msg.value >= ethAmount.add(ethMining), "msg.value needs to be equal to the quoted eth quantity plus Mining handling fee"); uint256 subValue = msg.value.sub(ethAmount.add(ethMining)); if (subValue > 0) { repayEth(address(msg.sender), subValue); } // Create an offer createOffer(ethAmount, erc20Amount, erc20Address,isDeviate, ethMining); // Transfer in offer asset - erc20 to this contract ERC20(erc20Address).safeTransferFrom(address(msg.sender), address(this), erc20Amount); _abonus.switchToEthForNTokenOffer.value(ethMining)(nTokenAddress); // Mining if (_blockOfferAmount[block.number][erc20Address] == 0) { uint256 miningAmount = oreDrawing(nTokenAddress); Nest_NToken nToken = Nest_NToken(nTokenAddress); nToken.transfer(nToken.checkBidder(), miningAmount.mul(_ownerMining).div(100)); _blockMining[block.number][erc20Address] = miningAmount.sub(miningAmount.mul(_ownerMining).div(100)); } _blockOfferAmount[block.number][erc20Address] = _blockOfferAmount[block.number][erc20Address].add(ethMining); } /** * @dev Create offer * @param ethAmount Offering ETH amount * @param erc20Amount Offering erc20 amount * @param erc20Address Offering erc20 address **/ function createOffer(uint256 ethAmount, uint256 erc20Amount, address erc20Address, bool isDeviate, uint256 mining) private { // Check offer conditions require(ethAmount >= _leastEth, "Eth scale is smaller than the minimum scale"); require(ethAmount % _offerSpan == 0, "Non compliant asset span"); require(erc20Amount % (ethAmount.div(_offerSpan)) == 0, "Asset quantity is not divided"); require(erc20Amount > 0); // Create offering contract emit OfferContractAddress(toAddress(_prices.length), address(erc20Address), ethAmount, erc20Amount,_blockLimit,mining); _prices.push(Nest_NToken_OfferPriceData( msg.sender, isDeviate, erc20Address, ethAmount, erc20Amount, ethAmount, erc20Amount, block.number, mining )); // Record price _offerPrice.addPrice(ethAmount, erc20Amount, block.number.add(_blockLimit), erc20Address, address(msg.sender)); } // Convert offer address into index in offer array function toIndex(address contractAddress) public pure returns(uint256) { return uint256(contractAddress); } // Convert index in offer array into offer address function toAddress(uint256 index) public pure returns(address) { return address(index); } /** * Withdraw offer assets * @param contractAddress Offer address **/ function turnOut(address contractAddress) public { require(address(msg.sender) == address(tx.origin), "It can't be a contract"); uint256 index = toIndex(contractAddress); Nest_NToken_OfferPriceData storage offerPriceData = _prices[index]; require(checkContractState(offerPriceData.blockNum) == 1, "Offer status error"); // Withdraw ETH if (offerPriceData.ethAmount > 0) { uint256 payEth = offerPriceData.ethAmount; offerPriceData.ethAmount = 0; repayEth(offerPriceData.owner, payEth); } // Withdraw erc20 if (offerPriceData.tokenAmount > 0) { uint256 payErc = offerPriceData.tokenAmount; offerPriceData.tokenAmount = 0; ERC20(address(offerPriceData.tokenAddress)).safeTransfer(address(offerPriceData.owner), payErc); } // Mining settlement if (offerPriceData.serviceCharge > 0) { mining(offerPriceData.blockNum, offerPriceData.tokenAddress, offerPriceData.serviceCharge, offerPriceData.owner); offerPriceData.serviceCharge = 0; } } /** * @dev Taker order - pay ETH and buy erc20 * @param ethAmount The amount of ETH of this offer * @param tokenAmount The amount of erc20 of this offer * @param contractAddress The target offer address * @param tranEthAmount The amount of ETH of taker order * @param tranTokenAmount The amount of erc20 of taker order * @param tranTokenAddress The erc20 address of taker order */ function sendEthBuyErc(uint256 ethAmount, uint256 tokenAmount, address contractAddress, uint256 tranEthAmount, uint256 tranTokenAmount, address tranTokenAddress) public payable { require(address(msg.sender) == address(tx.origin), "It can't be a contract"); uint256 serviceCharge = tranEthAmount.mul(_tranEth).div(1000); require(msg.value == ethAmount.add(tranEthAmount).add(serviceCharge), "msg.value needs to be equal to the quotation eth quantity plus transaction eth plus"); require(tranEthAmount % _offerSpan == 0, "Transaction size does not meet asset span"); // Get the offer data structure uint256 index = toIndex(contractAddress); Nest_NToken_OfferPriceData memory offerPriceData = _prices[index]; // Check the price, compare the current offer to the last effective price bool thisDeviate = comparativePrice(ethAmount,tokenAmount,tranTokenAddress); bool isDeviate; if (offerPriceData.deviate == true) { isDeviate = true; } else { isDeviate = thisDeviate; } // Limit the taker order only be twice the amount of the offer to prevent large-amount attacks if (offerPriceData.deviate) { // The taker order deviates x2 require(ethAmount >= tranEthAmount.mul(_tranAddition), "EthAmount needs to be no less than 2 times of transaction scale"); } else { if (isDeviate) { // If the taken offer is normal and the taker order deviates x10 require(ethAmount >= tranEthAmount.mul(_deviationFromScale), "EthAmount needs to be no less than 10 times of transaction scale"); } else { // If the taken offer is normal and the taker order is normal x2 require(ethAmount >= tranEthAmount.mul(_tranAddition), "EthAmount needs to be no less than 2 times of transaction scale"); } } // Check whether the conditions for taker order are satisfied require(checkContractState(offerPriceData.blockNum) == 0, "Offer status error"); require(offerPriceData.dealEthAmount >= tranEthAmount, "Insufficient trading eth"); require(offerPriceData.dealTokenAmount >= tranTokenAmount, "Insufficient trading token"); require(offerPriceData.tokenAddress == tranTokenAddress, "Wrong token address"); require(tranTokenAmount == offerPriceData.dealTokenAmount * tranEthAmount / offerPriceData.dealEthAmount, "Wrong token amount"); // Update the offer information offerPriceData.ethAmount = offerPriceData.ethAmount.add(tranEthAmount); offerPriceData.tokenAmount = offerPriceData.tokenAmount.sub(tranTokenAmount); offerPriceData.dealEthAmount = offerPriceData.dealEthAmount.sub(tranEthAmount); offerPriceData.dealTokenAmount = offerPriceData.dealTokenAmount.sub(tranTokenAmount); _prices[index] = offerPriceData; // Create a new offer createOffer(ethAmount, tokenAmount, tranTokenAddress, isDeviate, 0); // Transfer in erc20 + offer asset to this contract if (tokenAmount > tranTokenAmount) { ERC20(tranTokenAddress).safeTransferFrom(address(msg.sender), address(this), tokenAmount.sub(tranTokenAmount)); } else { ERC20(tranTokenAddress).safeTransfer(address(msg.sender), tranTokenAmount.sub(tokenAmount)); } // Modify price _offerPrice.changePrice(tranEthAmount, tranTokenAmount, tranTokenAddress, offerPriceData.blockNum.add(_blockLimit)); emit OfferTran(address(msg.sender), address(0x0), tranEthAmount, address(tranTokenAddress), tranTokenAmount, contractAddress, offerPriceData.owner); // Transfer fee if (serviceCharge > 0) { address nTokenAddress = _tokenMapping.checkTokenMapping(tranTokenAddress); _abonus.switchToEth.value(serviceCharge)(nTokenAddress); } } /** * @dev Taker order - pay erc20 and buy ETH * @param ethAmount The amount of ETH of this offer * @param tokenAmount The amount of erc20 of this offer * @param contractAddress The target offer address * @param tranEthAmount The amount of ETH of taker order * @param tranTokenAmount The amount of erc20 of taker order * @param tranTokenAddress The erc20 address of taker order */ function sendErcBuyEth(uint256 ethAmount, uint256 tokenAmount, address contractAddress, uint256 tranEthAmount, uint256 tranTokenAmount, address tranTokenAddress) public payable { require(address(msg.sender) == address(tx.origin), "It can't be a contract"); uint256 serviceCharge = tranEthAmount.mul(_tranEth).div(1000); require(msg.value == ethAmount.sub(tranEthAmount).add(serviceCharge), "msg.value needs to be equal to the quoted eth quantity plus transaction handling fee"); require(tranEthAmount % _offerSpan == 0, "Transaction size does not meet asset span"); // Get the offer data structure uint256 index = toIndex(contractAddress); Nest_NToken_OfferPriceData memory offerPriceData = _prices[index]; // Check the price, compare the current offer to the last effective price bool thisDeviate = comparativePrice(ethAmount,tokenAmount,tranTokenAddress); bool isDeviate; if (offerPriceData.deviate == true) { isDeviate = true; } else { isDeviate = thisDeviate; } // Limit the taker order only be twice the amount of the offer to prevent large-amount attacks if (offerPriceData.deviate) { // The taker order deviates x2 require(ethAmount >= tranEthAmount.mul(_tranAddition), "EthAmount needs to be no less than 2 times of transaction scale"); } else { if (isDeviate) { // If the taken offer is normal and the taker order deviates x10 require(ethAmount >= tranEthAmount.mul(_deviationFromScale), "EthAmount needs to be no less than 10 times of transaction scale"); } else { // If the taken offer is normal and the taker order is normal x2 require(ethAmount >= tranEthAmount.mul(_tranAddition), "EthAmount needs to be no less than 2 times of transaction scale"); } } // Check whether the conditions for taker order are satisfied require(checkContractState(offerPriceData.blockNum) == 0, "Offer status error"); require(offerPriceData.dealEthAmount >= tranEthAmount, "Insufficient trading eth"); require(offerPriceData.dealTokenAmount >= tranTokenAmount, "Insufficient trading token"); require(offerPriceData.tokenAddress == tranTokenAddress, "Wrong token address"); require(tranTokenAmount == offerPriceData.dealTokenAmount * tranEthAmount / offerPriceData.dealEthAmount, "Wrong token amount"); // Update the offer information offerPriceData.ethAmount = offerPriceData.ethAmount.sub(tranEthAmount); offerPriceData.tokenAmount = offerPriceData.tokenAmount.add(tranTokenAmount); offerPriceData.dealEthAmount = offerPriceData.dealEthAmount.sub(tranEthAmount); offerPriceData.dealTokenAmount = offerPriceData.dealTokenAmount.sub(tranTokenAmount); _prices[index] = offerPriceData; // Create a new offer createOffer(ethAmount, tokenAmount, tranTokenAddress, isDeviate, 0); // Transfer in erc20 + offer asset to this contract ERC20(tranTokenAddress).safeTransferFrom(address(msg.sender), address(this), tranTokenAmount.add(tokenAmount)); // Modify price _offerPrice.changePrice(tranEthAmount, tranTokenAmount, tranTokenAddress, offerPriceData.blockNum.add(_blockLimit)); emit OfferTran(address(msg.sender), address(tranTokenAddress), tranTokenAmount, address(0x0), tranEthAmount, contractAddress, offerPriceData.owner); // Transfer fee if (serviceCharge > 0) { address nTokenAddress = _tokenMapping.checkTokenMapping(tranTokenAddress); _abonus.switchToEth.value(serviceCharge)(nTokenAddress); } } /** * Offering mining * @param ntoken NToken address **/ function oreDrawing(address ntoken) private returns(uint256) { Nest_NToken miningToken = Nest_NToken(ntoken); (uint256 createBlock, uint256 recentlyUsedBlock) = miningToken.checkBlockInfo(); uint256 attenuationPointNow = block.number.sub(createBlock).div(_blockAttenuation); uint256 miningAmount = 0; uint256 attenuation; if (attenuationPointNow > 9) { attenuation = _afterMiningAmount; } else { attenuation = _attenuationAmount[attenuationPointNow]; } miningAmount = attenuation.mul(block.number.sub(recentlyUsedBlock)); miningToken.increaseTotal(miningAmount); emit OreDrawingLog(block.number, miningAmount, ntoken); return miningAmount; } /** * Retrieve mining * @param token Token address **/ function mining(uint256 blockNum, address token, uint256 serviceCharge, address owner) private returns(uint256) { // Block mining amount*offer fee/block offer fee uint256 miningAmount = _blockMining[blockNum][token].mul(serviceCharge).div(_blockOfferAmount[blockNum][token]); // Transfer NToken Nest_NToken nToken = Nest_NToken(address(_tokenMapping.checkTokenMapping(token))); require(nToken.transfer(address(owner), miningAmount), "Transfer failure"); emit MiningLog(blockNum, token,_blockOfferAmount[blockNum][token]); return miningAmount; } // Compare order prices function comparativePrice(uint256 myEthValue, uint256 myTokenValue, address token) private view returns(bool) { (uint256 frontEthValue, uint256 frontTokenValue) = _offerPrice.updateAndCheckPricePrivate(token); if (frontEthValue == 0 || frontTokenValue == 0) { return false; } uint256 maxTokenAmount = myEthValue.mul(frontTokenValue).mul(uint256(100).add(_deviate)).div(frontEthValue.mul(100)); if (myTokenValue <= maxTokenAmount) { uint256 minTokenAmount = myEthValue.mul(frontTokenValue).mul(uint256(100).sub(_deviate)).div(frontEthValue.mul(100)); if (myTokenValue >= minTokenAmount) { return false; } } return true; } // Check contract status function checkContractState(uint256 createBlock) public view returns (uint256) { if (block.number.sub(createBlock) > _blockLimit) { return 1; } return 0; } // Transfer ETH function repayEth(address accountAddress, uint256 asset) private { address payable addr = accountAddress.make_payable(); addr.transfer(asset); } // View the upper limit of the block interval function checkBlockLimit() public view returns(uint256) { return _blockLimit; } // View taker fee ratio function checkTranEth() public view returns (uint256) { return _tranEth; } // View additional transaction multiple function checkTranAddition() public view returns(uint256) { return _tranAddition; } // View minimum offering ETH function checkleastEth() public view returns(uint256) { return _leastEth; } // View offering ETH span function checkOfferSpan() public view returns(uint256) { return _offerSpan; } // View block offering amount function checkBlockOfferAmount(uint256 blockNum, address token) public view returns (uint256) { return _blockOfferAmount[blockNum][token]; } // View offering block mining amount function checkBlockMining(uint256 blockNum, address token) public view returns (uint256) { return _blockMining[blockNum][token]; } // View offering mining amount function checkOfferMining(uint256 blockNum, address token, uint256 serviceCharge) public view returns (uint256) { if (serviceCharge == 0) { return 0; } else { return _blockMining[blockNum][token].mul(serviceCharge).div(_blockOfferAmount[blockNum][token]); } } // View the owner allocation ratio function checkOwnerMining() public view returns(uint256) { return _ownerMining; } // View the mining decay function checkAttenuationAmount(uint256 num) public view returns(uint256) { return _attenuationAmount[num]; } // Modify taker order fee ratio function changeTranEth(uint256 num) public onlyOwner { _tranEth = num; } // Modify block interval upper limit function changeBlockLimit(uint32 num) public onlyOwner { _blockLimit = num; } // Modify additional transaction multiple function changeTranAddition(uint256 num) public onlyOwner { require(num > 0, "Parameter needs to be greater than 0"); _tranAddition = num; } // Modify minimum offering ETH function changeLeastEth(uint256 num) public onlyOwner { require(num > 0, "Parameter needs to be greater than 0"); _leastEth = num; } // Modify offering ETH span function changeOfferSpan(uint256 num) public onlyOwner { require(num > 0, "Parameter needs to be greater than 0"); _offerSpan = num; } // Modify price deviation function changekDeviate(uint256 num) public onlyOwner { _deviate = num; } // Modify the deviation from scale function changeDeviationFromScale(uint256 num) public onlyOwner { _deviationFromScale = num; } // Modify the owner allocation ratio function changeOwnerMining(uint256 num) public onlyOwner { _ownerMining = num; } // Modify the mining decay function changeAttenuationAmount(uint256 firstAmount, uint256 top, uint256 bottom) public onlyOwner { uint256 blockAmount = firstAmount; for (uint256 i = 0; i < 10; i ++) { _attenuationAmount[i] = blockAmount; blockAmount = blockAmount.mul(top).div(bottom); } } // Vote administrators only modifier onlyOwner(){ require(_voteFactory.checkOwners(msg.sender), "No authority"); _; } /** * Get the number of offers stored in the offer array * @return The number of offers stored in the offer array **/ function getPriceCount() view public returns (uint256) { return _prices.length; } /** * Get offer information according to the index * @param priceIndex Offer index * @return Offer information **/ function getPrice(uint256 priceIndex) view public returns (string memory) { // The buffer array used to generate the result string bytes memory buf = new bytes(500000); uint256 index = 0; index = writeOfferPriceData(priceIndex, _prices[priceIndex], buf, index); // Generate the result string and return bytes memory str = new bytes(index); while(index-- > 0) { str[index] = buf[index]; } return string(str); } /** * Search the contract address list of the target account (reverse order) * @param start Search forward from the index corresponding to the given contract address (not including the record corresponding to start address) * @param count Maximum number of records to return * @param maxFindCount The max index to search * @param owner Target account address * @return Separate the offer records with symbols. use , to divide fields: * uuid,owner,tokenAddress,ethAmount,tokenAmount,dealEthAmount,dealTokenAmount,blockNum,serviceCharge **/ function find(address start, uint256 count, uint256 maxFindCount, address owner) view public returns (string memory) { // Buffer array used to generate result string bytes memory buf = new bytes(500000); uint256 index = 0; // Calculate search interval i and end uint256 i = _prices.length; uint256 end = 0; if (start != address(0)) { i = toIndex(start); } if (i > maxFindCount) { end = i - maxFindCount; } // Loop search, write qualified records into buffer while (count > 0 && i-- > end) { Nest_NToken_OfferPriceData memory price = _prices[i]; if (price.owner == owner) { --count; index = writeOfferPriceData(i, price, buf, index); } } // Generate result string and return bytes memory str = new bytes(index); while(index-- > 0) { str[index] = buf[index]; } return string(str); } /** * Get the list of offers by page * @param offset Skip the first offset records * @param count Maximum number of records to return * @param order Sort rules. 0 means reverse order, non-zero means positive order * @return Separate the offer records with symbols. use , to divide fields: * uuid,owner,tokenAddress,ethAmount,tokenAmount,dealEthAmount,dealTokenAmount,blockNum,serviceCharge **/ function list(uint256 offset, uint256 count, uint256 order) view public returns (string memory) { // Buffer array used to generate result string bytes memory buf = new bytes(500000); uint256 index = 0; // Find search interval i and end uint256 i = 0; uint256 end = 0; if (order == 0) { // Reverse order, in default // Calculate search interval i and end if (offset < _prices.length) { i = _prices.length - offset; } if (count < i) { end = i - count; } // Write records in the target interval into the buffer while (i-- > end) { index = writeOfferPriceData(i, _prices[i], buf, index); } } else { // Ascending order // Calculate the search interval i and end if (offset < _prices.length) { i = offset; } else { i = _prices.length; } end = i + count; if(end > _prices.length) { end = _prices.length; } // Write the records in the target interval into the buffer while (i < end) { index = writeOfferPriceData(i, _prices[i], buf, index); ++i; } } // Generate the result string and return bytes memory str = new bytes(index); while(index-- > 0) { str[index] = buf[index]; } return string(str); } // Write the offer data into the buffer and return the buffer index function writeOfferPriceData(uint256 priceIndex, Nest_NToken_OfferPriceData memory price, bytes memory buf, uint256 index) pure private returns (uint256) { index = writeAddress(toAddress(priceIndex), buf, index); buf[index++] = byte(uint8(44)); index = writeAddress(price.owner, buf, index); buf[index++] = byte(uint8(44)); index = writeAddress(price.tokenAddress, buf, index); buf[index++] = byte(uint8(44)); index = writeUInt(price.ethAmount, buf, index); buf[index++] = byte(uint8(44)); index = writeUInt(price.tokenAmount, buf, index); buf[index++] = byte(uint8(44)); index = writeUInt(price.dealEthAmount, buf, index); buf[index++] = byte(uint8(44)); index = writeUInt(price.dealTokenAmount, buf, index); buf[index++] = byte(uint8(44)); index = writeUInt(price.blockNum, buf, index); buf[index++] = byte(uint8(44)); index = writeUInt(price.serviceCharge, buf, index); buf[index++] = byte(uint8(44)); return index; } // Convert integer to string in decimal form, write the string into the buffer, and return the buffer index function writeUInt(uint256 iv, bytes memory buf, uint256 index) pure public returns (uint256) { uint256 i = index; do { buf[index++] = byte(uint8(iv % 10 +48)); iv /= 10; } while (iv > 0); for (uint256 j = index; j > i; ++i) { byte t = buf[i]; buf[i] = buf[--j]; buf[j] = t; } return index; } // Convert the address to a hexadecimal string and write it into the buffer, and return the buffer index function writeAddress(address addr, bytes memory buf, uint256 index) pure private returns (uint256) { uint256 iv = uint256(addr); uint256 i = index + 40; do { uint256 w = iv % 16; if(w < 10) { buf[index++] = byte(uint8(w +48)); } else { buf[index++] = byte(uint8(w +87)); } iv /= 16; } while (index < i); i -= 40; for (uint256 j = index; j > i; ++i) { byte t = buf[i]; buf[i] = buf[--j]; buf[j] = t; } return index; } } // Price contract interface Nest_3_OfferPrice { // Add price data function addPrice(uint256 ethAmount, uint256 tokenAmount, uint256 endBlock, address tokenAddress, address offerOwner) external; // Modify price function changePrice(uint256 ethAmount, uint256 tokenAmount, address tokenAddress, uint256 endBlock) external; function updateAndCheckPricePrivate(address tokenAddress) external view returns(uint256 ethAmount, uint256 erc20Amount); } // Voting contract interface Nest_3_VoteFactory { // Check address function checkAddress(string calldata name) external view returns (address contractAddress); // Check whether an administrator function checkOwners(address man) external view returns (bool); } // NToken contract interface Nest_NToken { // Additional issuance function increaseTotal(uint256 value) external; // Check mining information function checkBlockInfo() external view returns(uint256 createBlock, uint256 recentlyUsedBlock); // Check creator 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); } // NToken mapping contract interface Nest_NToken_TokenMapping { // Check token mapping function checkTokenMapping(address token) external view returns (address); } // Bonus pool contract interface Nest_3_Abonus { function switchToEth(address token) external payable; function switchToEthForNTokenOffer(address token) external payable; } library SafeMath { function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); uint256 c = a / b; return c; } function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } library address_make_payable { function make_payable(address x) internal pure returns (address payable) { return address(uint160(x)); } } 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, "SafeERC20: decreased allowance below zero"); 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); } 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"); } }
File 2 of 5: HBTCToken
{"Container.sol":{"content":"pragma solidity ^0.5.11;\n\ncontract Container{\n struct Item{\n uint256 itemType;\n uint256 status;\n address[] addresses;\n }\n uint256 MaxItemAdressNum = 255;\n\n mapping (bytes32 =\u003e Item) private container;\n\n function itemAddressExists(bytes32 id, address oneAddress) internal view returns(bool){\n for(uint256 i = 0; i \u003c container[id].addresses.length; i++){\n if(container[id].addresses[i] == oneAddress)\n return true;\n }\n return false;\n }\n function getItemAddresses(bytes32 id) internal view returns(address[] memory){\n return container[id].addresses;\n }\n\n function getItemInfo(bytes32 id) internal view returns(uint256, uint256, uint256){\n return (container[id].itemType, container[id].status, container[id].addresses.length);\n }\n\n function getItemAddressCount(bytes32 id) internal view returns(uint256){\n return container[id].addresses.length;\n }\n\n function setItemInfo(bytes32 id, uint256 itemType, uint256 status) internal{\n container[id].itemType = itemType;\n container[id].status = status;\n }\n\n function addItemAddress(bytes32 id, address oneAddress) internal{\n require(!itemAddressExists(id, oneAddress), \"dup address added\");\n require(container[id].addresses.length \u003c MaxItemAdressNum, \"too many addresses\");\n container[id].addresses.push(oneAddress);\n }\n function removeItemAddresses(bytes32 id) internal{\n container[id].addresses.length = 0;\n }\n\n function removeOneItemAddress(bytes32 id, address oneAddress) internal{\n for(uint256 i = 0; i \u003c container[id].addresses.length; i++){\n if(container[id].addresses[i] == oneAddress){\n container[id].addresses[i] = container[id].addresses[container[id].addresses.length - 1];\n container[id].addresses.length--;\n return;\n }\n }\n revert(\"not exist address\");\n }\n\n function removeItem(bytes32 id) internal{\n delete container[id];\n }\n\n function replaceItemAddress(bytes32 id, address oneAddress, address anotherAddress) internal{\n require(!itemAddressExists(id,anotherAddress),\"dup address added\");\n for(uint256 i = 0; i \u003c container[id].addresses.length; i++){\n if(container[id].addresses[i] == oneAddress){\n container[id].addresses[i] = anotherAddress;\n return;\n }\n }\n revert(\"not exist address\");\n }\n}"},"HBTCAdmin.sol":{"content":"pragma solidity ^0.5.11;\n\nimport \"./Container.sol\";\n\ncontract HBTCAdmin is Container{\n\n bytes32 internal constant OWNERHASH = 0x02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0;\n bytes32 internal constant OPERATORHASH = 0x46a52cf33029de9f84853745a87af28464c80bf0346df1b32e205fc73319f622;\n bytes32 internal constant PAUSERHASH = 0x0cc58340b26c619cd4edc70f833d3f4d9d26f3ae7d5ef2965f81fe5495049a4f;\n bytes32 internal constant STOREHASH = 0xe41d88711b08bdcd7556c5d2d24e0da6fa1f614cf2055f4d7e10206017cd1680;\n bytes32 internal constant LOGICHASH = 0x397bc5b97f629151e68146caedba62f10b47e426b38db589771a288c0861f182;\n uint256 internal constant MAXUSERNUM = 255;\n bytes32[] private classHashArray;\n\n uint256 internal ownerRequireNum;\n uint256 internal operatorRequireNum;\n\n event AdminChanged(string TaskType, string class, address oldAddress, address newAddress);\n event AdminRequiredNumChanged(string TaskType, string class, uint256 previousNum, uint256 requiredNum);\n event AdminTaskDropped(bytes32 taskHash);\n\n function initAdmin(address owner0, address owner1, address owner2) internal{\n addItemAddress(OWNERHASH, owner0);\n addItemAddress(OWNERHASH, owner1);\n addItemAddress(OWNERHASH, owner2);\n addItemAddress(LOGICHASH, address(0x0));\n addItemAddress(STOREHASH, address(0x1));\n\n classHashArray.push(OWNERHASH);\n classHashArray.push(OPERATORHASH);\n classHashArray.push(PAUSERHASH);\n classHashArray.push(STOREHASH);\n classHashArray.push(LOGICHASH);\n ownerRequireNum = 2;\n operatorRequireNum = 2;\n }\n\n function classHashExist(bytes32 aHash) private view returns(bool){\n for(uint256 i = 0; i \u003c classHashArray.length; i++)\n if(classHashArray[i] == aHash) return true;\n return false;\n }\n function getAdminAddresses(string memory class) public view returns(address[] memory) {\n bytes32 classHash = getClassHash(class);\n return getItemAddresses(classHash);\n }\n function getOwnerRequiredNum() public view returns(uint256){\n return ownerRequireNum;\n }\n function getOperatorRequiredNum() public view returns(uint256){\n return operatorRequireNum;\n }\n\n function resetRequiredNum(string memory class, uint256 requiredNum)\n public onlyOwner returns(bool){\n bytes32 classHash = getClassHash(class);\n require((classHash == OPERATORHASH) || (classHash == OWNERHASH),\"wrong class\");\n if (classHash == OWNERHASH)\n require(requiredNum \u003c= getItemAddressCount(OWNERHASH),\"num larger than existed owners\");\n\n bytes32 taskHash = keccak256(abi.encodePacked(\"resetRequiredNum\", class, requiredNum));\n addItemAddress(taskHash, msg.sender);\n\n if(getItemAddressCount(taskHash) \u003e= ownerRequireNum){\n removeItem(taskHash);\n uint256 previousNum = 0;\n if (classHash == OWNERHASH){\n previousNum = ownerRequireNum;\n ownerRequireNum = requiredNum;\n }\n else if(classHash == OPERATORHASH){\n previousNum = operatorRequireNum;\n operatorRequireNum = requiredNum;\n }else{\n revert(\"wrong class\");\n }\n emit AdminRequiredNumChanged(\"resetRequiredNum\", class, previousNum, requiredNum);\n }\n return true;\n }\n\n\n function modifyAddress(string memory class, address oldAddress, address newAddress)\n internal onlyOwner returns(bool){\n bytes32 classHash = getClassHash(class);\n require(!itemAddressExists(classHash,newAddress),\"address existed already\");\n require(itemAddressExists(classHash,oldAddress),\"address not existed\");\n bytes32 taskHash = keccak256(abi.encodePacked(\"modifyAddress\", class, oldAddress, newAddress));\n addItemAddress(taskHash, msg.sender);\n if(getItemAddressCount(taskHash) \u003e= ownerRequireNum){\n replaceItemAddress(classHash, oldAddress, newAddress);\n emit AdminChanged(\"modifyAddress\", class, oldAddress, newAddress);\n removeItem(taskHash);\n return true;\n }\n return false;\n }\n\n function getClassHash(string memory class) private view returns (bytes32){\n bytes32 classHash = keccak256(abi.encodePacked(class));\n require(classHashExist(classHash), \"invalid class\");\n return classHash;\n }\n\n function dropAddress(string memory class, address oneAddress)\n public onlyOwner returns(bool){\n bytes32 classHash = getClassHash(class);\n require(classHash != STOREHASH \u0026\u0026 classHash != LOGICHASH, \"wrong class\");\n require(itemAddressExists(classHash, oneAddress), \"no such address exist\");\n\n if(classHash == OWNERHASH)\n require(getItemAddressCount(classHash) \u003e ownerRequireNum, \"insuffience addresses\");\n\n bytes32 taskHash = keccak256(abi.encodePacked(\"dropAddress\", class, oneAddress));\n addItemAddress(taskHash, msg.sender);\n if(getItemAddressCount(taskHash) \u003e= ownerRequireNum){\n removeOneItemAddress(classHash, oneAddress);\n emit AdminChanged(\"dropAddress\", class, oneAddress, oneAddress);\n removeItem(taskHash);\n return true;\n }\n return false;\n\n }\n\n function addAddress(string memory class, address oneAddress)\n public onlyOwner returns(bool){\n bytes32 classHash = getClassHash(class);\n require(classHash != STOREHASH \u0026\u0026 classHash != LOGICHASH, \"wrong class\");\n require(!itemAddressExists(classHash,oneAddress),\"address existed already\");\n\n bytes32 taskHash = keccak256(abi.encodePacked(\"addAddress\", class, oneAddress));\n addItemAddress(taskHash, msg.sender);\n if(getItemAddressCount(taskHash) \u003e= ownerRequireNum){\n addItemAddress(classHash, oneAddress);\n emit AdminChanged(\"addAddress\", class, oneAddress, oneAddress);\n removeItem(taskHash);\n return true;\n }\n return false;\n }\n\n\n function dropTask(bytes32 taskHash)\n public onlyOwner returns (bool){\n removeItem(taskHash);\n emit AdminTaskDropped(taskHash);\n return true;\n }\n\n modifier onlyOwner() {\n require(itemAddressExists(OWNERHASH, msg.sender), \"only use owner to call\");\n _;\n }\n\n}"},"HBTCLogic.sol":{"content":"pragma solidity ^0.5.11;\n\nimport \"./SafeMath.sol\";\nimport \"./HBTCStorage.sol\";\n\ncontract HBTCLogic {\n\n using SafeMath for uint256;\n\n string public constant name = \"HBTCLogic\";\n\n uint256 public constant TASKINIT = 0;\n uint256 public constant TASKPROCESSING = 1;\n uint256 public constant TASKCANCELLED = 2;\n uint256 public constant TASKDONE = 3;\n uint256 public constant MINTTASK = 1;\n uint256 public constant BURNTASK = 2;\n\n address private caller;\n HBTCStorage private store;\n\n constructor(address aCaller) public{\n caller = aCaller;\n }\n\n modifier onlyCaller(){\n require(msg.sender == caller, \"only main contract can call\");\n _;\n }\n\n function mintLogic(uint256 value,address to,string calldata proof,\n bytes32 taskHash, address supportAddress, uint256 requireNum)\n external onlyCaller returns(uint256){\n require(to != address(0), \"cannot be burned from zero address\");\n require(value \u003e 0, \"value need \u003e 0\");\n require(taskHash == keccak256((abi.encodePacked(to,value,proof))),\"taskHash is wrong\");\n uint256 status = supportTask(MINTTASK, taskHash, supportAddress, requireNum);\n\n if( status == TASKDONE){\n uint256 totalSupply = store.getTotalSupply();\n uint256 balanceTo = store.balanceOf(to);\n balanceTo = balanceTo.safeAdd(value);\n totalSupply = totalSupply.safeAdd(value);\n store.setBalance(to,balanceTo);\n store.setTotalSupply(totalSupply);\n }\n return status;\n }\n\n function burnLogic(address from, uint256 value,string calldata btcAddress,\n string calldata proof,bytes32 taskHash, address supportAddress, uint256 requireNum)\n external onlyCaller returns(uint256){\n\n uint256 balance = store.balanceOf(from);\n require(balance \u003e= value,\"sender address not have enough HBTC\");\n require(value \u003e 0, \"value need \u003e 0\");\n require(taskHash == keccak256((abi.encodePacked(from,value,btcAddress,proof))),\"taskHash is wrong\");\n uint256 status = supportTask(BURNTASK, taskHash, supportAddress, requireNum);\n\n if ( status == TASKDONE ){\n uint256 totalSupply = store.getTotalSupply();\n totalSupply = totalSupply.safeSub(value);\n balance = balance.safeSub(value);\n store.setBalance(from,balance);\n store.setTotalSupply(totalSupply);\n\n }\n return status;\n }\n\n function transferLogic(address sender,address to,uint256 value) external onlyCaller returns(bool) {\n require(to != address(0), \"cannot transfer to address zero\");\n require(sender != to, \"sender need != to\");\n require(value \u003e 0, \"value need \u003e 0\");\n require(address(store) != address(0), \"dataStore address error\");\n\n uint256 balanceFrom = store.balanceOf(sender);\n uint256 balanceTo = store.balanceOf(to);\n require(value \u003c= balanceFrom, \"insufficient funds\");\n balanceFrom = balanceFrom.safeSub(value);\n balanceTo = balanceTo.safeAdd(value);\n store.setBalance(sender,balanceFrom);\n store.setBalance(to,balanceTo);\n return true;\n }\n\n function transferFromLogic(address sender,address from,address to,uint256 value) external onlyCaller returns(bool) {\n require(from != address(0), \"cannot transfer from address zero\");\n require(to != address(0), \"cannot transfer to address zero\");\n require(value \u003e 0, \"can not tranfer zero Token\");\n require(from!=to,\"from and to can not be be the same \");\n require(address(store) != address(0), \"dataStore address error\");\n\n uint256 balanceFrom = store.balanceOf(from);\n uint256 balanceTo = store.balanceOf(to);\n uint256 allowedvalue = store.getAllowed(from,sender);\n\n require(value \u003c= allowedvalue, \"insufficient allowance\");\n require(value \u003c= balanceFrom, \"insufficient funds\");\n\n balanceFrom = balanceFrom.safeSub(value);\n balanceTo = balanceTo.safeAdd(value);\n allowedvalue = allowedvalue.safeSub(value);\n\n store.setBalance(from,balanceFrom);\n store.setBalance(to,balanceTo);\n store.setAllowed(from,sender,allowedvalue);\n return true;\n }\n\n function approveLogic(address sender,address spender,uint256 value) external onlyCaller returns(bool success){\n require(spender != address(0), \"spender address zero\");\n require(value \u003e 0, \"value need \u003e 0\");\n require(address(store) != address(0), \"dataStore address error\");\n\n store.setAllowed(sender,spender,value);\n return true;\n }\n\n function resetStoreLogic(address storeAddress) external onlyCaller {\n store = HBTCStorage(storeAddress);\n }\n\n function getTotalSupply() public view returns (uint256 supply) {\n return store.getTotalSupply();\n }\n\n function balanceOf(address owner) public view returns (uint256 balance) {\n return store.balanceOf(owner);\n }\n\n function getAllowed(address owner, address spender) public view returns (uint256 remaining){\n return store.getAllowed(owner,spender);\n }\n\n function getStoreAddress() public view returns(address){\n return address(store);\n }\n\n function supportTask(uint256 taskType, bytes32 taskHash, address oneAddress, uint256 requireNum) private returns(uint256){\n require(!store.supporterExists(taskHash, oneAddress), \"supporter already exists\");\n (uint256 theTaskType,uint256 theTaskStatus,uint256 theSupporterNum) = store.getTaskInfo(taskHash);\n require(theTaskStatus \u003c TASKDONE, \"wrong status\");\n\n if (theTaskStatus != TASKINIT)\n require(theTaskType == taskType, \"task type not match\");\n store.addSupporter(taskHash, oneAddress);\n theSupporterNum++;\n if(theSupporterNum \u003e= requireNum)\n theTaskStatus = TASKDONE;\n else\n theTaskStatus = TASKPROCESSING;\n store.setTaskInfo(taskHash, taskType, theTaskStatus);\n return theTaskStatus;\n }\n\n function cancelTask(bytes32 taskHash) external onlyCaller returns(uint256){\n (uint256 theTaskType,uint256 theTaskStatus,uint256 theSupporterNum) = store.getTaskInfo(taskHash);\n require(theTaskStatus == TASKPROCESSING, \"wrong status\");\n if(theSupporterNum \u003e 0) store.removeAllSupporter(taskHash);\n theTaskStatus = TASKCANCELLED;\n store.setTaskInfo(taskHash, theTaskType, theTaskStatus);\n return theTaskStatus;\n }\n}"},"HBTCStorage.sol":{"content":"pragma solidity ^0.5.11;\n\nimport \"./Container.sol\";\n\ncontract HBTCStorage is Container{\n\n string public constant name = \"HBTCStorage\";\n\n address private caller;\n\n constructor(address aCaller) public{\n totalSupply = 0;\n caller = aCaller;\n }\n uint256 public totalSupply;\n\n mapping (address =\u003e uint256) private balances;\n\n mapping (address =\u003e mapping (address =\u003e uint256)) private allowed;\n\n function supporterExists(bytes32 taskHash, address user) public view returns(bool){\n return itemAddressExists(taskHash, user);\n }\n\n function setTaskInfo(bytes32 taskHash, uint256 taskType, uint256 status) external onlyCaller{\n setItemInfo(taskHash, taskType, status);\n }\n\n function getTaskInfo(bytes32 taskHash) public view returns(uint256, uint256, uint256){\n return getItemInfo(taskHash);\n }\n\n function addSupporter(bytes32 taskHash, address oneAddress) external onlyCaller{\n addItemAddress(taskHash, oneAddress);\n }\n\n function removeAllSupporter(bytes32 taskHash) external onlyCaller{\n removeItemAddresses(taskHash);\n }\n\n modifier onlyCaller() {\n require(msg.sender == caller, \"only use main main contract to call\");\n _;\n }\n\n function getTotalSupply() external view returns(uint256) {\n return totalSupply;\n }\n\n function setTotalSupply(uint256 amount) external onlyCaller {\n totalSupply = amount;\n }\n\n function balanceOf(address account) external view returns(uint256) {\n return balances[account];\n }\n\n function setBalance(address account,uint256 amount) external onlyCaller {\n require(account != address(0),\"account address error\");\n balances[account] = amount;\n }\n\n function getAllowed(address owner,address spender) external view returns(uint256) {\n return allowed[owner][spender];\n }\n\n function setAllowed(address owner,address spender,uint256 amount) external onlyCaller {\n require(owner != address(0),\"owner address error\");\n require(spender != address(0),\"spender address error\");\n require(amount \u003c= balances[owner], \"owner balance need \u003e= amount\");\n allowed[owner][spender] = amount;\n }\n}"},"HBTCToken.sol":{"content":"pragma solidity ^0.5.11;\n\nimport \"./IERC20Token.sol\";\nimport \"./HBTCAdmin.sol\";\nimport \"./HBTCLogic.sol\";\nimport \"./HBTCStorage.sol\";\nimport \"./Pausable.sol\";\n\ncontract HBTCToken is IERC20Token,Pausable, HBTCAdmin{\n string public constant name = \"Huobi BTC\";\n\n string public constant symbol = \"HBTC\";\n\n uint8 public constant decimals = 18;\n\n HBTCLogic private logic;\n\n event Burning(address indexed from, uint256 value, string proof, string btcAddress, address burner);\n event Burned(address indexed from, uint256 value, string proof, string btcAddress);\n event Minting(address indexed to, uint256 value, string proof, address minter);\n event Minted(address indexed to, uint256 value, string proof);\n\n constructor(address owner0, address owner1, address owner2) public{\n initAdmin(owner0, owner1, owner2);\n }\n\n\n function totalSupply() public view returns (uint256 supply) {\n return logic.getTotalSupply();\n }\n\n function balanceOf(address owner) public view returns (uint256 balance) {\n return logic.balanceOf(owner);\n }\n\n function mint(address to, uint256 value, string memory proof,bytes32 taskHash) public whenNotPaused returns(bool){\n require(itemAddressExists(OPERATORHASH, msg.sender), \"wrong operator\");\n uint256 status = logic.mintLogic(value,to,proof,taskHash, msg.sender, operatorRequireNum);\n if (status == 1){\n emit Minting(to, value, proof, msg.sender);\n }else if (status == 3) {\n emit Minting(to, value, proof, msg.sender);\n emit Minted(to, value, proof);\n emit Transfer(address(0x0),to,value);\n }\n return true;\n }\n\n\n function burn(address from,uint256 value,string memory btcAddress,string memory proof, bytes32 taskHash)\n public whenNotPaused returns(bool){\n require(itemAddressExists(OPERATORHASH, msg.sender), \"wrong operator\");\n uint256 status = logic.burnLogic(from,value,btcAddress,proof,taskHash, msg.sender, operatorRequireNum);\n if (status == 1){\n emit Burning(from, value, proof,btcAddress, msg.sender);\n }else if (status == 3) {\n emit Burning(from, value, proof,btcAddress, msg.sender);\n emit Burned(from, value, proof,btcAddress);\n emit Transfer(from, address(0x0),value);\n }\n return true;\n }\n\n function cancelTask(bytes32 taskHash) public returns(uint256){\n require(itemAddressExists(OPERATORHASH, msg.sender), \"wrong operator\");\n return logic.cancelTask(taskHash);\n }\n\n function transfer(address to, uint256 value) public whenNotPaused returns (bool) {\n bool flag = logic.transferLogic(msg.sender,to,value);\n require(flag, \"transfer failed\");\n emit Transfer(msg.sender,to,value);\n return true;\n }\n\n function transferFrom(address from, address to, uint256 value) public whenNotPaused returns (bool){\n bool flag = logic.transferFromLogic(msg.sender,from,to,value);\n require(flag,\"transferFrom failed\");\n emit Transfer(from, to, value);\n return true;\n }\n\n\n function approve(address spender, uint256 value) public whenNotPaused returns (bool){\n bool flag = logic.approveLogic(msg.sender,spender,value);\n require(flag, \"approve failed\");\n emit Approval(msg.sender, spender, value);\n return true;\n }\n\n function allowance(address owner, address spender) public view returns (uint256 remaining){\n return logic.getAllowed(owner,spender);\n }\n\n function modifyAdminAddress(string memory class, address oldAddress, address newAddress) public whenPaused{\n require(newAddress != address(0x0), \"wrong address\");\n bool flag = modifyAddress(class, oldAddress, newAddress);\n if(flag){\n bytes32 classHash = keccak256(abi.encodePacked(class));\n if(classHash == LOGICHASH){\n logic = HBTCLogic(newAddress);\n }else if(classHash == STOREHASH){\n logic.resetStoreLogic(newAddress);\n }\n }\n }\n\n function getLogicAddress() public view returns(address){\n return address(logic);\n }\n\n function getStoreAddress() public view returns(address){\n return logic.getStoreAddress();\n }\n\n function pause() public{\n require(itemAddressExists(PAUSERHASH, msg.sender), \"wrong user to pauser\");\n doPause();\n }\n\n}"},"IERC20Token.sol":{"content":"pragma solidity ^0.5.11;\n\ncontract IERC20Token {\n function totalSupply() public view returns (uint256 supply);\n /// @param owner The address from which the balance will be retrieved\n /// @return The balance\n //solium-disable security/enforce-explicit-visibility\n function balanceOf(address owner) public view returns (uint256 balance);\n\n /// @notice send `value` token to `to` from `msg.sender`\n /// @param to The address of the recipient\n /// @param value The amount of token to be transferred\n /// @return Whether the transfer was successful or not\n function transfer(address to, uint256 value) public returns (bool success);\n\n /// @notice send `value` token to `to` from `from` on the condition it is approved by `from`\n /// @param from The address of the sender\n /// @param to The address of the recipient\n /// @param value The amount of token to be transferred\n /// @return Whether the transfer was successful or not\n function transferFrom(address from, address to, uint256 value) public returns (bool success);\n\n /// @notice `msg.sender` approves `spender` to spend `value` tokens\n /// @param spender The address of the account able to transfer the tokens\n /// @param value The amount of tokens to be approved for transfer\n /// @return Whether the approval was successful or not\n function approve(address spender, uint256 value) public returns (bool success);\n\n /// @param owner The address of the account owning tokens\n /// @param spender The address of the account able to transfer the tokens\n /// @return Amount of remaining tokens allowed to spent\n function allowance(address owner, address spender) public view returns (uint256 remaining);\n\n event Transfer(address indexed from, address indexed to, uint256 value);\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n}"},"Migrations.sol":{"content":"pragma solidity \u003e=0.4.21 \u003c0.6.0;\n\ncontract Migrations {\n address public owner;\n uint public last_completed_migration;\n\n constructor() public {\n owner = msg.sender;\n }\n\n modifier restricted() {\n if (msg.sender == owner) _;\n }\n\n function setCompleted(uint completed) public restricted {\n last_completed_migration = completed;\n }\n\n function upgrade(address new_address) public restricted {\n Migrations upgraded = Migrations(new_address);\n upgraded.setCompleted(last_completed_migration);\n }\n}\n"},"Pausable.sol":{"content":"pragma solidity ^0.5.11;\n\ncontract Pausable {\n\n bool private pauseState = true;\n\n event PauseChangedTo(bool pauseState);\n\n function doPause() internal {\n pauseState = !pauseState;\n emit PauseChangedTo(pauseState);\n }\n\n function isPaused() public view returns (bool) {\n return pauseState;\n }\n\n modifier whenPaused() {\n require(pauseState, \"it is not paused now\");\n _;\n }\n\n modifier whenNotPaused() {\n require(!pauseState, \"it is paused now\");\n _;\n }\n\n}"},"SafeMath.sol":{"content":"// solium-disable linebreak-style\r\npragma solidity ^0.5.11;\r\n\r\nlibrary SafeMath {\r\n function safeAdd(uint a, uint b) public pure returns (uint c) {\r\n c = a + b;\r\n require(c \u003e= a,\"\");\r\n }\r\n function safeSub(uint a, uint b) public pure returns (uint c) {\r\n require(b \u003c= a,\"\");\r\n c = a - b;\r\n }\r\n function safeMul(uint a, uint b) public pure returns (uint c) {\r\n c = a * b;\r\n require(a == 0 || c / a == b,\"\");\r\n }\r\n function safeDiv(uint a, uint b) public pure returns (uint c) {\r\n require(b \u003e 0,\"\");\r\n c = a / b;\r\n }\r\n}"}}
File 3 of 5: Nest_NToken
pragma solidity 0.6.0; library SafeMath { function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); uint256 c = a / b; return c; } function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } // voting contract interface Nest_3_VoteFactory { // Check address function checkAddress(string calldata name) external view returns (address contractAddress); // check whether the administrator function checkOwners(address man) external view returns (bool); } /** * @title NToken contract * @dev Include standard erc20 method, mining method, and mining data */ interface IERC20 { function totalSupply() external view returns (uint256); function balanceOf(address who) external view returns (uint256); function allowance(address owner, address spender) external view returns (uint256); function transfer(address to, uint256 value) external returns (bool); function approve(address spender, uint256 value) external returns (bool); function transferFrom(address from, address to, uint256 value) external returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); } contract Nest_NToken is IERC20 { using SafeMath for uint256; mapping (address => uint256) private _balances; // Balance ledger mapping (address => mapping (address => uint256)) private _allowed; // Approval ledger uint256 private _totalSupply = 0 ether; // Total supply string public name; // Token name string public symbol; // Token symbol uint8 public decimals = 18; // Precision uint256 public _createBlock; // Create block number uint256 public _recentlyUsedBlock; // Recently used block number Nest_3_VoteFactory _voteFactory; // Voting factory contract address _bidder; // Owner /** * @dev Initialization method * @param _name Token name * @param _symbol Token symbol * @param voteFactory Voting factory contract address * @param bidder Successful bidder address */ constructor (string memory _name, string memory _symbol, address voteFactory, address bidder) public { name = _name; symbol = _symbol; _createBlock = block.number; _recentlyUsedBlock = block.number; _voteFactory = Nest_3_VoteFactory(address(voteFactory)); _bidder = bidder; } /** * @dev Reset voting contract method * @param voteFactory Voting contract address */ function changeMapping (address voteFactory) public onlyOwner { _voteFactory = Nest_3_VoteFactory(address(voteFactory)); } /** * @dev Additional issuance * @param value Additional issuance amount */ function increaseTotal(uint256 value) public { address offerMain = address(_voteFactory.checkAddress("nest.nToken.offerMain")); require(address(msg.sender) == offerMain, "No authority"); _balances[offerMain] = _balances[offerMain].add(value); _totalSupply = _totalSupply.add(value); _recentlyUsedBlock = block.number; } /** * @dev Check the total amount of tokens * @return Total supply */ function totalSupply() override public view returns (uint256) { return _totalSupply; } /** * @dev Check address balance * @param owner Address to be checked * @return Return the balance of the corresponding address */ function balanceOf(address owner) override public view returns (uint256) { return _balances[owner]; } /** * @dev Check block information * @return createBlock Initial block number * @return recentlyUsedBlock Recently mined and issued block */ function checkBlockInfo() public view returns(uint256 createBlock, uint256 recentlyUsedBlock) { return (_createBlock, _recentlyUsedBlock); } /** * @dev Check owner's approved allowance to the spender * @param owner Approving address * @param spender Approved address * @return Approved amount */ function allowance(address owner, address spender) override public view returns (uint256) { return _allowed[owner][spender]; } /** * @dev Transfer method * @param to Transfer target * @param value Transfer amount * @return Whether the transfer is successful */ function transfer(address to, uint256 value) override public returns (bool) { _transfer(msg.sender, to, value); return true; } /** * @dev Approval method * @param spender Approval target * @param value Approval amount * @return Whether the approval is successful */ function approve(address spender, uint256 value) override public returns (bool) { require(spender != address(0)); _allowed[msg.sender][spender] = value; emit Approval(msg.sender, spender, value); return true; } /** * @dev Transfer tokens when approved * @param from Transfer-out account address * @param to Transfer-in account address * @param value Transfer amount * @return Whether approved transfer is successful */ function transferFrom(address from, address to, uint256 value) override public returns (bool) { _allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value); _transfer(from, to, value); emit Approval(from, msg.sender, _allowed[from][msg.sender]); return true; } /** * @dev Increase the allowance * @param spender Approval target * @param addedValue Amount to increase * @return whether increase is successful */ function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { require(spender != address(0)); _allowed[msg.sender][spender] = _allowed[msg.sender][spender].add(addedValue); emit Approval(msg.sender, spender, _allowed[msg.sender][spender]); return true; } /** * @dev Decrease the allowance * @param spender Approval target * @param subtractedValue Amount to decrease * @return Whether decrease is successful */ function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { require(spender != address(0)); _allowed[msg.sender][spender] = _allowed[msg.sender][spender].sub(subtractedValue); emit Approval(msg.sender, spender, _allowed[msg.sender][spender]); return true; } /** * @dev Transfer method * @param to Transfer target * @param value Transfer amount */ function _transfer(address from, address to, uint256 value) internal { _balances[from] = _balances[from].sub(value); _balances[to] = _balances[to].add(value); emit Transfer(from, to, value); } /** * @dev Check the creator * @return Creator address */ function checkBidder() public view returns(address) { return _bidder; } /** * @dev Transfer creator * @param bidder New creator address */ function changeBidder(address bidder) public { require(address(msg.sender) == _bidder); _bidder = bidder; } // Administrator only modifier onlyOwner(){ require(_voteFactory.checkOwners(msg.sender)); _; } }
File 4 of 5: HBTCStorage
{"Container.sol":{"content":"pragma solidity ^0.5.11;\n\ncontract Container{\n struct Item{\n uint256 itemType;\n uint256 status;\n address[] addresses;\n }\n uint256 MaxItemAdressNum = 255;\n\n mapping (bytes32 =\u003e Item) private container;\n\n function itemAddressExists(bytes32 id, address oneAddress) internal view returns(bool){\n for(uint256 i = 0; i \u003c container[id].addresses.length; i++){\n if(container[id].addresses[i] == oneAddress)\n return true;\n }\n return false;\n }\n function getItemAddresses(bytes32 id) internal view returns(address[] memory){\n return container[id].addresses;\n }\n\n function getItemInfo(bytes32 id) internal view returns(uint256, uint256, uint256){\n return (container[id].itemType, container[id].status, container[id].addresses.length);\n }\n\n function getItemAddressCount(bytes32 id) internal view returns(uint256){\n return container[id].addresses.length;\n }\n\n function setItemInfo(bytes32 id, uint256 itemType, uint256 status) internal{\n container[id].itemType = itemType;\n container[id].status = status;\n }\n\n function addItemAddress(bytes32 id, address oneAddress) internal{\n require(!itemAddressExists(id, oneAddress), \"dup address added\");\n require(container[id].addresses.length \u003c MaxItemAdressNum, \"too many addresses\");\n container[id].addresses.push(oneAddress);\n }\n function removeItemAddresses(bytes32 id) internal{\n container[id].addresses.length = 0;\n }\n\n function removeOneItemAddress(bytes32 id, address oneAddress) internal{\n for(uint256 i = 0; i \u003c container[id].addresses.length; i++){\n if(container[id].addresses[i] == oneAddress){\n container[id].addresses[i] = container[id].addresses[container[id].addresses.length - 1];\n container[id].addresses.length--;\n return;\n }\n }\n revert(\"not exist address\");\n }\n\n function removeItem(bytes32 id) internal{\n delete container[id];\n }\n\n function replaceItemAddress(bytes32 id, address oneAddress, address anotherAddress) internal{\n require(!itemAddressExists(id,anotherAddress),\"dup address added\");\n for(uint256 i = 0; i \u003c container[id].addresses.length; i++){\n if(container[id].addresses[i] == oneAddress){\n container[id].addresses[i] = anotherAddress;\n return;\n }\n }\n revert(\"not exist address\");\n }\n}"},"HBTCStorage.sol":{"content":"pragma solidity ^0.5.11;\n\nimport \"./Container.sol\";\n\ncontract HBTCStorage is Container{\n\n string public constant name = \"HBTCStorage\";\n\n address private caller;\n\n constructor(address aCaller) public{\n totalSupply = 0;\n caller = aCaller;\n }\n uint256 public totalSupply;\n\n mapping (address =\u003e uint256) private balances;\n\n mapping (address =\u003e mapping (address =\u003e uint256)) private allowed;\n\n function supporterExists(bytes32 taskHash, address user) public view returns(bool){\n return itemAddressExists(taskHash, user);\n }\n\n function setTaskInfo(bytes32 taskHash, uint256 taskType, uint256 status) external onlyCaller{\n setItemInfo(taskHash, taskType, status);\n }\n\n function getTaskInfo(bytes32 taskHash) public view returns(uint256, uint256, uint256){\n return getItemInfo(taskHash);\n }\n\n function addSupporter(bytes32 taskHash, address oneAddress) external onlyCaller{\n addItemAddress(taskHash, oneAddress);\n }\n\n function removeAllSupporter(bytes32 taskHash) external onlyCaller{\n removeItemAddresses(taskHash);\n }\n\n modifier onlyCaller() {\n require(msg.sender == caller, \"only use main main contract to call\");\n _;\n }\n\n function getTotalSupply() external view returns(uint256) {\n return totalSupply;\n }\n\n function setTotalSupply(uint256 amount) external onlyCaller {\n totalSupply = amount;\n }\n\n function balanceOf(address account) external view returns(uint256) {\n return balances[account];\n }\n\n function setBalance(address account,uint256 amount) external onlyCaller {\n require(account != address(0),\"account address error\");\n balances[account] = amount;\n }\n\n function getAllowed(address owner,address spender) external view returns(uint256) {\n return allowed[owner][spender];\n }\n\n function setAllowed(address owner,address spender,uint256 amount) external onlyCaller {\n require(owner != address(0),\"owner address error\");\n require(spender != address(0),\"spender address error\");\n allowed[owner][spender] = amount;\n }\n}"}}
File 5 of 5: Nest_NToken_TokenMapping
pragma solidity 0.6.0; /** * @title NToken mapping contract * @dev Add, modify and check offering token mapping */ contract Nest_NToken_TokenMapping { mapping (address => address) _tokenMapping; // Token mapping - offering token => NToken Nest_3_VoteFactory _voteFactory; // Voting contract event TokenMappingLog(address token, address nToken); /** * @dev Initialization method * @param voteFactory Voting contract address */ constructor(address voteFactory) public { _voteFactory = Nest_3_VoteFactory(address(voteFactory)); } /** * @dev Reset voting contract * @param voteFactory voting contract address */ function changeMapping(address voteFactory) public onlyOwner { _voteFactory = Nest_3_VoteFactory(address(voteFactory)); } /** * @dev Add token mapping * @param token Offering token address * @param nToken Mining NToken address */ function addTokenMapping(address token, address nToken) public { require(address(msg.sender) == address(_voteFactory.checkAddress("nest.nToken.tokenAuction")), "No authority"); require(_tokenMapping[token] == address(0x0), "Token already exists"); _tokenMapping[token] = nToken; emit TokenMappingLog(token, nToken); } /** * @dev Change token mapping * @param token Offering token address * @param nToken Mining NToken address */ function changeTokenMapping(address token, address nToken) public onlyOwner { _tokenMapping[token] = nToken; emit TokenMappingLog(token, nToken); } /** * @dev Check token mapping * @param token Offering token address * @return Mining NToken address */ function checkTokenMapping(address token) public view returns (address) { return _tokenMapping[token]; } // Only for administrator modifier onlyOwner(){ require(_voteFactory.checkOwners(msg.sender), "No authority"); _; } } // Voting contract interface Nest_3_VoteFactory { // Check address function checkAddress(string calldata name) external view returns (address contractAddress); // Check whether the administrator function checkOwners(address man) external view returns (bool); }