Transaction Hash:
Block:
11299801 at Nov-21-2020 06:21:31 AM +UTC
Transaction Fee:
0.003002112218904 ETH
$6.11
Gas Used:
104,240 Gas / 28.8000021 Gwei
Emitted Events:
| 64 |
Nest_3_TokenAbonus.GetTokenLog( tokenAddress=0x5E17a41c...E26dc5Fcd, tokenAmount=20360606808402613 )
|
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
| 0x19E1d193...8726e67c5 | |||||
| 0x43121397...e39D44852 | (NEST Protocol: Revenue Pool) | 299.069002382346646861 Eth | 299.048641775538244248 Eth | 0.020360606808402613 | |
| 0x70e952D8...a897696F3 |
7.7765264214993651 Eth
Nonce: 340
|
7.793884916088863713 Eth
Nonce: 341
| 0.017358494589498613 | ||
|
0x829BD824...93333A830
Miner
| (F2Pool Old) | 5,496.600827538089284972 Eth | 5,496.603829650308188972 Eth | 0.003002112218904 |
Execution Trace
Nest_3_TokenAbonus.getAbonus( token=0x5E17a41c59007abC492dB7C4C65B85eE26dc5Fcd )
-
Nest_3_TokenSave.checkAmount( sender=0x70e952D8B2385f646860E271367EB25a897696F3, token=0x5E17a41c59007abC492dB7C4C65B85eE26dc5Fcd ) => ( 431159000000000000000000 ) Nest_3_Abonus.getETH( num=20360606808402613, token=0x5E17a41c59007abC492dB7C4C65B85eE26dc5Fcd, target=0x70e952D8B2385f646860E271367EB25a897696F3 )-
Nest_3_VoteFactory.checkAddress( name=nest.v3.tokenAbonus ) => ( contractAddress=0x19E1d193A448bD13097EFC2aea867468726e67c5 ) - ETH 0.020360606808402613
0x70e952d8b2385f646860e271367eb25a897696f3.CALL( )
-
getAbonus[Nest_3_TokenAbonus (ln:116)]
checkAmount[Nest_3_TokenAbonus (ln:117)]reloadTime[Nest_3_TokenAbonus (ln:119)]reloadToken[Nest_3_TokenAbonus (ln:120)]sub[Nest_3_TokenAbonus (ln:155)]levelingResult[Nest_3_TokenAbonus (ln:156)]div[Nest_3_TokenAbonus (ln:171)]allValue[Nest_3_TokenAbonus (ln:171)]sub[Nest_3_TokenAbonus (ln:249)]sub[Nest_3_TokenAbonus (ln:249)]balanceOf[Nest_3_TokenAbonus (ln:249)]checkAddress[Nest_3_TokenAbonus (ln:249)]balanceOf[Nest_3_TokenAbonus (ln:249)]totalSupply[Nest_3_TokenAbonus (ln:252)]
div[Nest_3_TokenAbonus (ln:173)]allValue[Nest_3_TokenAbonus (ln:173)]sub[Nest_3_TokenAbonus (ln:249)]sub[Nest_3_TokenAbonus (ln:249)]balanceOf[Nest_3_TokenAbonus (ln:249)]checkAddress[Nest_3_TokenAbonus (ln:249)]balanceOf[Nest_3_TokenAbonus (ln:249)]totalSupply[Nest_3_TokenAbonus (ln:252)]
add[Nest_3_TokenAbonus (ln:177)]div[Nest_3_TokenAbonus (ln:177)]mul[Nest_3_TokenAbonus (ln:177)]getETHNum[Nest_3_TokenAbonus (ln:179)]sub[Nest_3_TokenAbonus (ln:183)]div[Nest_3_TokenAbonus (ln:183)]mul[Nest_3_TokenAbonus (ln:183)]sub[Nest_3_TokenAbonus (ln:185)]div[Nest_3_TokenAbonus (ln:185)]mul[Nest_3_TokenAbonus (ln:185)]div[Nest_3_TokenAbonus (ln:187)]mul[Nest_3_TokenAbonus (ln:187)]sub[Nest_3_TokenAbonus (ln:189)]getETH[Nest_3_TokenAbonus (ln:190)]sub[Nest_3_TokenAbonus (ln:190)]value[Nest_3_TokenAbonus (ln:191)]sub[Nest_3_TokenAbonus (ln:191)]getETH[Nest_3_TokenAbonus (ln:193)]value[Nest_3_TokenAbonus (ln:194)]tranEth[Nest_3_TokenAbonus (ln:197)]sub[Nest_3_TokenAbonus (ln:197)]value[Nest_3_TokenAbonus (ln:198)]
getETHNum[Nest_3_TokenAbonus (ln:157)]allValue[Nest_3_TokenAbonus (ln:158)]sub[Nest_3_TokenAbonus (ln:249)]sub[Nest_3_TokenAbonus (ln:249)]balanceOf[Nest_3_TokenAbonus (ln:249)]checkAddress[Nest_3_TokenAbonus (ln:249)]balanceOf[Nest_3_TokenAbonus (ln:249)]totalSupply[Nest_3_TokenAbonus (ln:252)]
sub[Nest_3_TokenAbonus (ln:159)]allValue[Nest_3_TokenAbonus (ln:159)]sub[Nest_3_TokenAbonus (ln:249)]sub[Nest_3_TokenAbonus (ln:249)]balanceOf[Nest_3_TokenAbonus (ln:249)]checkAddress[Nest_3_TokenAbonus (ln:249)]balanceOf[Nest_3_TokenAbonus (ln:249)]totalSupply[Nest_3_TokenAbonus (ln:252)]
sub[Nest_3_TokenAbonus (ln:160)]
sub[Nest_3_TokenAbonus (ln:122)]add[Nest_3_TokenAbonus (ln:122)]sub[Nest_3_TokenAbonus (ln:122)]sub[Nest_3_TokenAbonus (ln:123)]sub[Nest_3_TokenAbonus (ln:124)]div[Nest_3_TokenAbonus (ln:126)]mul[Nest_3_TokenAbonus (ln:126)]sub[Nest_3_TokenAbonus (ln:128)]getETH[Nest_3_TokenAbonus (ln:129)]GetTokenLog[Nest_3_TokenAbonus (ln:130)]
File 1 of 4: Nest_3_TokenAbonus
File 2 of 4: Nest_3_TokenSave
File 3 of 4: Nest_3_Abonus
File 4 of 4: Nest_3_VoteFactory
pragma solidity 0.6.0;
/**
* @title Dividend logic
* @dev Some operations about dividend,logic and asset separation
*/
contract Nest_3_TokenAbonus {
using address_make_payable for address;
using SafeMath for uint256;
ERC20 _nestContract;
Nest_3_TokenSave _tokenSave; // Lock-up contract
Nest_3_Abonus _abonusContract; // ETH bonus pool
Nest_3_VoteFactory _voteFactory; // Voting contract
Nest_3_Leveling _nestLeveling; // Leveling contract
address _destructionAddress; // Destroy contract address
uint256 _timeLimit = 168 hours; // Bonus period
uint256 _nextTime = 1596168000; // Next bonus time
uint256 _getAbonusTimeLimit = 60 hours; // During of triggering calculation of bonus
uint256 _times = 0; // Bonus ledger
uint256 _expectedIncrement = 3; // Expected bonus increment ratio
uint256 _expectedSpanForNest = 100000000 ether; // NEST expected bonus increment threshold
uint256 _expectedSpanForNToken = 1000000 ether; // NToken expected bonus increment threshold
uint256 _expectedMinimum = 100 ether; // Expected minimum bonus
uint256 _savingLevelOne = 10; // Saving threshold level 1
uint256 _savingLevelTwo = 20; // Saving threshold level 2
uint256 _savingLevelTwoSub = 100 ether; // Function parameters of savings threshold level 2
uint256 _savingLevelThree = 30; // Function parameters of savings threshold level 3
uint256 _savingLevelThreeSub = 600 ether; // Function parameters of savings threshold level 3
mapping(address => uint256) _abonusMapping; // Bonus pool snapshot - token address (NEST or NToken) => number of ETH in the bonus pool
mapping(address => uint256) _tokenAllValueMapping; // Number of tokens (circulation) - token address (NEST or NToken) ) => total circulation
mapping(address => mapping(uint256 => uint256)) _tokenAllValueHistory; // NEST or NToken circulation snapshot - token address (NEST or NToken) => number of periods => total circulation
mapping(address => mapping(uint256 => mapping(address => uint256))) _tokenSelfHistory; // Personal lockup - NEST or NToken snapshot token address (NEST or NToken) => period => user address => total circulation
mapping(address => mapping(uint256 => bool)) _snapshot; // Whether snapshot - token address (NEST or NToken) => number of periods => whether to take a snapshot
mapping(uint256 => mapping(address => mapping(address => bool))) _getMapping; // Receiving records - period => token address (NEST or NToken) => user address => whether received
// Log token address, amount
event GetTokenLog(address tokenAddress, uint256 tokenAmount);
/**
* @dev Initialization method
* @param voteFactory Voting contract address
*/
constructor (address voteFactory) public {
Nest_3_VoteFactory voteFactoryMap = Nest_3_VoteFactory(address(voteFactory));
_voteFactory = voteFactoryMap;
_nestContract = ERC20(address(voteFactoryMap.checkAddress("nest")));
_tokenSave = Nest_3_TokenSave(address(voteFactoryMap.checkAddress("nest.v3.tokenSave")));
address payable addr = address(voteFactoryMap.checkAddress("nest.v3.abonus")).make_payable();
_abonusContract = Nest_3_Abonus(addr);
address payable levelingAddr = address(voteFactoryMap.checkAddress("nest.v3.leveling")).make_payable();
_nestLeveling = Nest_3_Leveling(levelingAddr);
_destructionAddress = address(voteFactoryMap.checkAddress("nest.v3.destruction"));
}
/**
* @dev Modify voting contract
* @param voteFactory Voting contract address
*/
function changeMapping(address voteFactory) public onlyOwner {
Nest_3_VoteFactory voteFactoryMap = Nest_3_VoteFactory(address(voteFactory));
_voteFactory = voteFactoryMap;
_nestContract = ERC20(address(voteFactoryMap.checkAddress("nest")));
_tokenSave = Nest_3_TokenSave(address(voteFactoryMap.checkAddress("nest.v3.tokenSave")));
address payable addr = address(voteFactoryMap.checkAddress("nest.v3.abonus")).make_payable();
_abonusContract = Nest_3_Abonus(addr);
address payable levelingAddr = address(voteFactoryMap.checkAddress("nest.v3.leveling")).make_payable();
_nestLeveling = Nest_3_Leveling(levelingAddr);
_destructionAddress = address(voteFactoryMap.checkAddress("nest.v3.destruction"));
}
/**
* @dev Deposit
* @param amount Deposited amount
* @param token Locked token address
*/
function depositIn(uint256 amount, address token) public {
uint256 nowTime = now;
uint256 nextTime = _nextTime;
uint256 timeLimit = _timeLimit;
if (nowTime < nextTime) {
// Bonus triggered
require(!(nowTime >= nextTime.sub(timeLimit) && nowTime <= nextTime.sub(timeLimit).add(_getAbonusTimeLimit)));
} else {
// Bonus not triggered
uint256 times = (nowTime.sub(_nextTime)).div(_timeLimit);
// Calculate the time when bonus should be started
uint256 startTime = _nextTime.add((times).mul(_timeLimit));
// Calculate the time when bonus should be stopped
uint256 endTime = startTime.add(_getAbonusTimeLimit);
require(!(nowTime >= startTime && nowTime <= endTime));
}
_tokenSave.depositIn(amount, token, address(msg.sender));
}
/**
* @dev Withdrawing
* @param amount Withdrawing amount
* @param token Token address
*/
function takeOut(uint256 amount, address token) public {
require(amount > 0, "Parameter needs to be greater than 0");
require(amount <= _tokenSave.checkAmount(address(msg.sender), token), "Insufficient storage balance");
if (token == address(_nestContract)) {
require(!_voteFactory.checkVoteNow(address(tx.origin)), "Voting");
}
_tokenSave.takeOut(amount, token, address(msg.sender));
}
/**
* @dev Receiving
* @param token Receiving token address
*/
function getAbonus(address token) public {
uint256 tokenAmount = _tokenSave.checkAmount(address(msg.sender), token);
require(tokenAmount > 0, "Insufficient storage balance");
reloadTime();
reloadToken(token);
uint256 nowTime = now;
require(nowTime >= _nextTime.sub(_timeLimit) && nowTime <= _nextTime.sub(_timeLimit).add(_getAbonusTimeLimit), "Not time to draw");
require(!_getMapping[_times.sub(1)][token][address(msg.sender)], "Have received");
_tokenSelfHistory[token][_times.sub(1)][address(msg.sender)] = tokenAmount;
require(_tokenAllValueMapping[token] > 0, "Total flux error");
uint256 selfNum = tokenAmount.mul(_abonusMapping[token]).div(_tokenAllValueMapping[token]);
require(selfNum > 0, "No limit available");
_getMapping[_times.sub(1)][token][address(msg.sender)] = true;
_abonusContract.getETH(selfNum, token,address(msg.sender));
emit GetTokenLog(token, selfNum);
}
/**
* @dev Update bonus time and stage ledger
*/
function reloadTime() private {
uint256 nowTime = now;
// The current time must exceed the bonus time
if (nowTime >= _nextTime) {
uint256 time = (nowTime.sub(_nextTime)).div(_timeLimit);
uint256 startTime = _nextTime.add((time).mul(_timeLimit));
uint256 endTime = startTime.add(_getAbonusTimeLimit);
if (nowTime >= startTime && nowTime <= endTime) {
_nextTime = getNextTime();
_times = _times.add(1);
}
}
}
/**
* @dev Snapshot of the amount of tokens
* @param token Receiving token address
*/
function reloadToken(address token) private {
if (!_snapshot[token][_times.sub(1)]) {
levelingResult(token);
_abonusMapping[token] = _abonusContract.getETHNum(token);
_tokenAllValueMapping[token] = allValue(token);
_tokenAllValueHistory[token][_times.sub(1)] = allValue(token);
_snapshot[token][_times.sub(1)] = true;
}
}
/**
* @dev Leveling settlement
* @param token Receiving token address
*/
function levelingResult(address token) private {
uint256 steps;
if (token == address(_nestContract)) {
steps = allValue(token).div(_expectedSpanForNest);
} else {
steps = allValue(token).div(_expectedSpanForNToken);
}
uint256 minimumAbonus = _expectedMinimum;
for (uint256 i = 0; i < steps; i++) {
minimumAbonus = minimumAbonus.add(minimumAbonus.mul(_expectedIncrement).div(100));
}
uint256 thisAbonus = _abonusContract.getETHNum(token);
if (thisAbonus > minimumAbonus) {
uint256 levelAmount = 0;
if (thisAbonus > 5000 ether) {
levelAmount = thisAbonus.mul(_savingLevelThree).div(100).sub(_savingLevelThreeSub);
} else if (thisAbonus > 1000 ether) {
levelAmount = thisAbonus.mul(_savingLevelTwo).div(100).sub(_savingLevelTwoSub);
} else {
levelAmount = thisAbonus.mul(_savingLevelOne).div(100);
}
if (thisAbonus.sub(levelAmount) < minimumAbonus) {
_abonusContract.getETH(thisAbonus.sub(minimumAbonus), token, address(this));
_nestLeveling.switchToEth.value(thisAbonus.sub(minimumAbonus))(token);
} else {
_abonusContract.getETH(levelAmount, token, address(this));
_nestLeveling.switchToEth.value(levelAmount)(token);
}
} else {
uint256 ethValue = _nestLeveling.tranEth(minimumAbonus.sub(thisAbonus), token, address(this));
_abonusContract.switchToEth.value(ethValue)(token);
}
}
// Next bonus time, current bonus deadline, ETH number, NEST number, NEST participating in bonus, bonus to receive, approved amount, balance, whether bonus can be paid
function getInfo(address token) public view returns (uint256 nextTime, uint256 getAbonusTime, uint256 ethNum, uint256 tokenValue, uint256 myJoinToken, uint256 getEth, uint256 allowNum, uint256 leftNum, bool allowAbonus) {
uint256 nowTime = now;
if (nowTime >= _nextTime.sub(_timeLimit) && nowTime <= _nextTime.sub(_timeLimit).add(_getAbonusTimeLimit) && _times > 0 && _snapshot[token][_times.sub(1)]) {
// Bonus have been triggered, and during the time of this bonus, display snapshot data
allowAbonus = _getMapping[_times.sub(1)][token][address(msg.sender)];
ethNum = _abonusMapping[token];
tokenValue = _tokenAllValueMapping[token];
} else {
// Display real-time data
ethNum = _abonusContract.getETHNum(token);
tokenValue = allValue(token);
allowAbonus = _getMapping[_times][token][address(msg.sender)];
}
myJoinToken = _tokenSave.checkAmount(address(msg.sender), token);
if (allowAbonus == true) {
getEth = 0;
} else {
getEth = myJoinToken.mul(ethNum).div(tokenValue);
}
nextTime = getNextTime();
getAbonusTime = nextTime.sub(_timeLimit).add(_getAbonusTimeLimit);
allowNum = ERC20(token).allowance(address(msg.sender), address(_tokenSave));
leftNum = ERC20(token).balanceOf(address(msg.sender));
}
/**
* @dev View next bonus time
* @return Next bonus time
*/
function getNextTime() public view returns (uint256) {
uint256 nowTime = now;
if (_nextTime > nowTime) {
return _nextTime;
} else {
uint256 time = (nowTime.sub(_nextTime)).div(_timeLimit);
return _nextTime.add(_timeLimit.mul(time.add(1)));
}
}
/**
* @dev View total circulation
* @return Total circulation
*/
function allValue(address token) public view returns (uint256) {
if (token == address(_nestContract)) {
uint256 all = 10000000000 ether;
uint256 leftNum = all.sub(_nestContract.balanceOf(address(_voteFactory.checkAddress("nest.v3.miningSave")))).sub(_nestContract.balanceOf(address(_destructionAddress)));
return leftNum;
} else {
return ERC20(token).totalSupply();
}
}
/**
* @dev View bonus period
* @return Bonus period
*/
function checkTimeLimit() public view returns (uint256) {
return _timeLimit;
}
/**
* @dev View duration of triggering calculation of bonus
* @return Bonus period
*/
function checkGetAbonusTimeLimit() public view returns (uint256) {
return _getAbonusTimeLimit;
}
/**
* @dev View current lowest expected bonus
* @return Current lowest expected bonus
*/
function checkMinimumAbonus(address token) public view returns (uint256) {
uint256 miningAmount;
if (token == address(_nestContract)) {
miningAmount = allValue(token).div(_expectedSpanForNest);
} else {
miningAmount = allValue(token).div(_expectedSpanForNToken);
}
uint256 minimumAbonus = _expectedMinimum;
for (uint256 i = 0; i < miningAmount; i++) {
minimumAbonus = minimumAbonus.add(minimumAbonus.mul(_expectedIncrement).div(100));
}
return minimumAbonus;
}
/**
* @dev Check whether the bonus token is snapshoted
* @param token Token address
* @return Whether snapshoted
*/
function checkSnapshot(address token) public view returns (bool) {
return _snapshot[token][_times.sub(1)];
}
/**
* @dev Check the expected bonus incremental ratio
* @return Expected bonus increment ratio
*/
function checkeExpectedIncrement() public view returns (uint256) {
return _expectedIncrement;
}
/**
* @dev View expected minimum bonus
* @return Expected minimum bonus
*/
function checkExpectedMinimum() public view returns (uint256) {
return _expectedMinimum;
}
/**
* @dev View savings threshold
* @return Save threshold
*/
function checkSavingLevelOne() public view returns (uint256) {
return _savingLevelOne;
}
function checkSavingLevelTwo() public view returns (uint256) {
return _savingLevelTwo;
}
function checkSavingLevelThree() public view returns (uint256) {
return _savingLevelThree;
}
/**
* @dev View NEST liquidity snapshot
* @param token Locked token address
* @param times Bonus snapshot period
*/
function checkTokenAllValueHistory(address token, uint256 times) public view returns (uint256) {
return _tokenAllValueHistory[token][times];
}
/**
* @dev View personal lock-up NEST snapshot
* @param times Bonus snapshot period
* @param user User address
* @return The number of personal locked NEST snapshots
*/
function checkTokenSelfHistory(address token, uint256 times, address user) public view returns (uint256) {
return _tokenSelfHistory[token][times][user];
}
// View the period number of bonus
function checkTimes() public view returns (uint256) {
return _times;
}
// NEST expected bonus increment threshold
function checkExpectedSpanForNest() public view returns (uint256) {
return _expectedSpanForNest;
}
// NToken expected bonus increment threshold
function checkExpectedSpanForNToken() public view returns (uint256) {
return _expectedSpanForNToken;
}
// View the function parameters of savings threshold level 3
function checkSavingLevelTwoSub() public view returns (uint256) {
return _savingLevelTwoSub;
}
// View the function parameters of savings threshold level 3
function checkSavingLevelThreeSub() public view returns (uint256) {
return _savingLevelThreeSub;
}
/**
* @dev Update bonus period
* @param hour Bonus period (hours)
*/
function changeTimeLimit(uint256 hour) public onlyOwner {
require(hour > 0, "Parameter needs to be greater than 0");
_timeLimit = hour.mul(1 hours);
}
/**
* @dev Update collection period
* @param hour Collection period (hours)
*/
function changeGetAbonusTimeLimit(uint256 hour) public onlyOwner {
require(hour > 0, "Parameter needs to be greater than 0");
_getAbonusTimeLimit = hour;
}
/**
* @dev Update expected bonus increment ratio
* @param num Expected bonus increment ratio
*/
function changeExpectedIncrement(uint256 num) public onlyOwner {
require(num > 0, "Parameter needs to be greater than 0");
_expectedIncrement = num;
}
/**
* @dev Update expected minimum bonus
* @param num Expected minimum bonus
*/
function changeExpectedMinimum(uint256 num) public onlyOwner {
require(num > 0, "Parameter needs to be greater than 0");
_expectedMinimum = num;
}
/**
* @dev Update saving threshold
* @param threshold Saving threshold
*/
function changeSavingLevelOne(uint256 threshold) public onlyOwner {
_savingLevelOne = threshold;
}
function changeSavingLevelTwo(uint256 threshold) public onlyOwner {
_savingLevelTwo = threshold;
}
function changeSavingLevelThree(uint256 threshold) public onlyOwner {
_savingLevelThree = threshold;
}
/**
* @dev Update the function parameters of savings threshold level 2
*/
function changeSavingLevelTwoSub(uint256 num) public onlyOwner {
_savingLevelTwoSub = num;
}
/**
* @dev Update the function parameters of savings threshold level 3
*/
function changeSavingLevelThreeSub(uint256 num) public onlyOwner {
_savingLevelThreeSub = num;
}
/**
* @dev Update NEST expected bonus incremental threshold
* @param num Threshold
*/
function changeExpectedSpanForNest(uint256 num) public onlyOwner {
_expectedSpanForNest = num;
}
/**
* @dev Update NToken expected bonus incremental threshold
* @param num Threshold
*/
function changeExpectedSpanForNToken(uint256 num) public onlyOwner {
_expectedSpanForNToken = num;
}
receive() external payable {
}
// Administrator only
modifier onlyOwner(){
require(_voteFactory.checkOwners(address(msg.sender)), "No authority");
_;
}
}
// NEST and NToken lock-up contracts
interface Nest_3_TokenSave {
function depositIn(uint256 num, address token, address target) external;
function checkAmount(address sender, address token) external view returns(uint256);
function takeOut(uint256 num, address token, address target) external;
}
// ETH bonus pool
interface Nest_3_Abonus {
function getETH(uint256 num, address token, address target) external;
function getETHNum(address token) external view returns (uint256);
function switchToEth(address token) external payable;
}
// Leveling contract
interface Nest_3_Leveling {
function tranEth(uint256 amount, address token, address target) external returns (uint256);
function switchToEth(address token) external payable;
}
// Voting factory contract
interface Nest_3_VoteFactory {
// Check if there is a vote currently participating
function checkVoteNow(address user) external view returns(bool);
// Check address
function checkAddress(string calldata name) external view returns (address contractAddress);
// Check whether the administrator
function checkOwners(address man) external view returns (bool);
}
// ERC20 contract
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 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));
}
}File 2 of 4: Nest_3_TokenSave
pragma solidity 0.6.0;
/**
* @title NEST and NToken lock-up contract
* @dev NEST and NToken deposit and withdrawal
*/
contract Nest_3_TokenSave {
using SafeMath for uint256;
Nest_3_VoteFactory _voteFactory; // Voting contract
mapping(address => mapping(address => uint256)) _baseMapping; // Ledger token=>user=>amount
/**
* @dev initialization method
* @param voteFactory Voting contract address
*/
constructor(address voteFactory) public {
_voteFactory = Nest_3_VoteFactory(voteFactory);
}
/**
* @dev Reset voting contract
* @param voteFactory Voting contract address
*/
function changeMapping(address voteFactory) public onlyOwner {
_voteFactory = Nest_3_VoteFactory(voteFactory);
}
/**
* @dev Withdrawing
* @param num Withdrawing amount
* @param token Lock-up token address
* @param target Transfer target
*/
function takeOut(uint256 num, address token, address target) public onlyContract {
require(num <= _baseMapping[token][address(target)], "Insufficient storage balance");
_baseMapping[token][address(target)] = _baseMapping[token][address(target)].sub(num);
ERC20(token).transfer(address(target), num);
}
/**
* @dev Depositing
* @param num Depositing amount
* @param token Lock-up token address
* @param target Depositing target
*/
function depositIn(uint256 num, address token, address target) public onlyContract {
require(ERC20(token).transferFrom(address(target),address(this),num), "Authorization transfer failed");
_baseMapping[token][address(target)] = _baseMapping[token][address(target)].add(num);
}
/**
* @dev Check the amount
* @param sender Check address
* @param token Lock-up token address
* @return uint256 Check address corresponding lock-up limit
*/
function checkAmount(address sender, address token) public view returns(uint256) {
return _baseMapping[token][address(sender)];
}
// Administrators only
modifier onlyOwner(){
require(_voteFactory.checkOwners(address(msg.sender)), "No authority");
_;
}
// Only for bonus logic contract
modifier onlyContract(){
require(_voteFactory.checkAddress("nest.v3.tokenAbonus") == address(msg.sender), "No authority");
_;
}
}
// ERC20 contract
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);
}
// Voting factory
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);
}
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;
}
}File 3 of 4: Nest_3_Abonus
pragma solidity 0.6.0;
/**
* @title ETH bonus pool
* @dev ETH collection and inquiry
*/
contract Nest_3_Abonus {
using address_make_payable for address;
using SafeMath for uint256;
Nest_3_VoteFactory _voteFactory; // Voting contract
address _nestAddress; // NEST contract address
mapping (address => uint256) ethMapping; // ETH bonus ledger of corresponding tokens
uint256 _mostDistribution = 40; // The highest allocation ratio of NEST bonus pool
uint256 _leastDistribution = 20; // The lowest allocation ratio of NEST bonus pool
uint256 _distributionTime = 1200000; // The decay time interval of NEST bonus pool allocation ratio
uint256 _distributionSpan = 5; // The decay degree of NEST bonus pool allocation ratio
/**
* @dev Initialization method
* @param voteFactory Voting contract address
*/
constructor(address voteFactory) public {
_voteFactory = Nest_3_VoteFactory(voteFactory);
_nestAddress = address(_voteFactory.checkAddress("nest"));
}
/**
* @dev Reset voting contract
* @param voteFactory Voting contract address
*/
function changeMapping(address voteFactory) public onlyOwner{
_voteFactory = Nest_3_VoteFactory(voteFactory);
_nestAddress = address(_voteFactory.checkAddress("nest"));
}
/**
* @dev Transfer in bonus
* @param token Corresponding to lock-up Token
*/
function switchToEth(address token) public payable {
ethMapping[token] = ethMapping[token].add(msg.value);
}
/**
* @dev Transferin bonus - NToken offering fee
* @param token Corresponding to lock-up NToken
*/
function switchToEthForNTokenOffer(address token) public payable {
Nest_NToken nToken = Nest_NToken(token);
(uint256 createBlock,) = nToken.checkBlockInfo();
uint256 subBlock = block.number.sub(createBlock);
uint256 times = subBlock.div(_distributionTime);
uint256 distributionValue = times.mul(_distributionSpan);
uint256 distribution = _mostDistribution;
if (_leastDistribution.add(distributionValue) > _mostDistribution) {
distribution = _leastDistribution;
} else {
distribution = _mostDistribution.sub(distributionValue);
}
uint256 nestEth = msg.value.mul(distribution).div(100);
ethMapping[_nestAddress] = ethMapping[_nestAddress].add(nestEth);
ethMapping[token] = ethMapping[token].add(msg.value.sub(nestEth));
}
/**
* @dev Receive ETH
* @param num Receive amount
* @param token Correspond to locked Token
* @param target Transfer target
*/
function getETH(uint256 num, address token, address target) public onlyContract {
require(num <= ethMapping[token], "Insufficient storage balance");
ethMapping[token] = ethMapping[token].sub(num);
address payable addr = target.make_payable();
addr.transfer(num);
}
/**
* @dev Get bonus pool balance
* @param token Corresponded locked Token
* @return uint256 Bonus pool balance
*/
function getETHNum(address token) public view returns (uint256) {
return ethMapping[token];
}
// View NEST address
function checkNestAddress() public view returns(address) {
return _nestAddress;
}
// View the highest NEST bonus pool allocation ratio
function checkMostDistribution() public view returns(uint256) {
return _mostDistribution;
}
// View the lowest NEST bonus pool allocation ratio
function checkLeastDistribution() public view returns(uint256) {
return _leastDistribution;
}
// View the decay time interval of NEST bonus pool allocation ratio
function checkDistributionTime() public view returns(uint256) {
return _distributionTime;
}
// View the decay degree of NEST bonus pool allocation ratio
function checkDistributionSpan() public view returns(uint256) {
return _distributionSpan;
}
// Modify the highest NEST bonus pool allocation ratio
function changeMostDistribution(uint256 num) public onlyOwner {
_mostDistribution = num;
}
// Modify the lowest NEST bonus pool allocation ratio
function changeLeastDistribution(uint256 num) public onlyOwner {
_leastDistribution = num;
}
// Modify the decay time interval of NEST bonus pool allocation ratio
function changeDistributionTime(uint256 num) public onlyOwner {
_distributionTime = num;
}
// Modify the decay degree of NEST bonus pool allocation ratio
function changeDistributionSpan(uint256 num) public onlyOwner {
_distributionSpan = num;
}
// Withdraw ETH
function turnOutAllEth(uint256 amount, address target) public onlyOwner {
address payable addr = target.make_payable();
addr.transfer(amount);
}
// Only bonus logic contract
modifier onlyContract(){
require(_voteFactory.checkAddress("nest.v3.tokenAbonus") == address(msg.sender), "No authority");
_;
}
// Administrator only
modifier onlyOwner(){
require(_voteFactory.checkOwners(address(msg.sender)), "No authority");
_;
}
}
// Voting factory
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);
}
// NToken
interface Nest_NToken {
// Increase token
function increaseTotal(uint256 value) external;
// Query mining information
function checkBlockInfo() external view returns(uint256 createBlock, uint256 recentlyUsedBlock);
// Query creator
function checkOwner() 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);
}
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));
}
}File 4 of 4: Nest_3_VoteFactory
pragma solidity 0.6.0;
/**
* @title Voting factory + mapping
* @dev Vote creating method
*/
contract Nest_3_VoteFactory {
using SafeMath for uint256;
uint256 _limitTime = 7 days; // Vote duration
uint256 _NNLimitTime = 1 days; // NestNode raising time
uint256 _circulationProportion = 51; // Proportion of votes to pass
uint256 _NNUsedCreate = 10; // The minimum number of NNs to create a voting contract
uint256 _NNCreateLimit = 100; // The minimum number of NNs needed to start voting
uint256 _emergencyTime = 0; // The emergency state start time
uint256 _emergencyTimeLimit = 3 days; // The emergency state duration
uint256 _emergencyNNAmount = 1000; // The number of NNs required to switch the emergency state
ERC20 _NNToken; // NestNode Token
ERC20 _nestToken; // NestToken
mapping(string => address) _contractAddress; // Voting contract mapping
mapping(address => bool) _modifyAuthority; // Modify permissions
mapping(address => address) _myVote; // Personal voting address
mapping(address => uint256) _emergencyPerson; // Emergency state personal voting number
mapping(address => bool) _contractData; // Voting contract data
bool _stateOfEmergency = false; // Emergency state
address _destructionAddress; // Destroy contract address
event ContractAddress(address contractAddress);
/**
* @dev Initialization method
*/
constructor () public {
_modifyAuthority[address(msg.sender)] = true;
}
/**
* @dev Reset contract
*/
function changeMapping() public onlyOwner {
_NNToken = ERC20(checkAddress("nestNode"));
_destructionAddress = address(checkAddress("nest.v3.destruction"));
_nestToken = ERC20(address(checkAddress("nest")));
}
/**
* @dev Create voting contract
* @param implementContract The executable contract address for voting
* @param nestNodeAmount Number of NNs to pledge
*/
function createVote(address implementContract, uint256 nestNodeAmount) public {
require(address(tx.origin) == address(msg.sender), "It can't be a contract");
require(nestNodeAmount >= _NNUsedCreate);
Nest_3_VoteContract newContract = new Nest_3_VoteContract(implementContract, _stateOfEmergency, nestNodeAmount);
require(_NNToken.transferFrom(address(tx.origin), address(newContract), nestNodeAmount), "Authorization transfer failed");
_contractData[address(newContract)] = true;
emit ContractAddress(address(newContract));
}
/**
* @dev Use NEST to vote
* @param contractAddress Vote contract address
*/
function nestVote(address contractAddress) public {
require(address(msg.sender) == address(tx.origin), "It can't be a contract");
require(_contractData[contractAddress], "It's not a voting contract");
require(!checkVoteNow(address(msg.sender)));
Nest_3_VoteContract newContract = Nest_3_VoteContract(contractAddress);
newContract.nestVote();
_myVote[address(tx.origin)] = contractAddress;
}
/**
* @dev Vote using NestNode Token
* @param contractAddress Vote contract address
* @param NNAmount Amount of NNs to pledge
*/
function nestNodeVote(address contractAddress, uint256 NNAmount) public {
require(address(msg.sender) == address(tx.origin), "It can't be a contract");
require(_contractData[contractAddress], "It's not a voting contract");
Nest_3_VoteContract newContract = Nest_3_VoteContract(contractAddress);
require(_NNToken.transferFrom(address(tx.origin), address(newContract), NNAmount), "Authorization transfer failed");
newContract.nestNodeVote(NNAmount);
}
/**
* @dev Excecute contract
* @param contractAddress Vote contract address
*/
function startChange(address contractAddress) public {
require(address(msg.sender) == address(tx.origin), "It can't be a contract");
require(_contractData[contractAddress], "It's not a voting contract");
Nest_3_VoteContract newContract = Nest_3_VoteContract(contractAddress);
require(_stateOfEmergency == newContract.checkStateOfEmergency());
addSuperManPrivate(address(newContract));
newContract.startChange();
deleteSuperManPrivate(address(newContract));
}
/**
* @dev Switch emergency state-transfer in NestNode Token
* @param amount Amount of NNs to transfer
*/
function sendNestNodeForStateOfEmergency(uint256 amount) public {
require(_NNToken.transferFrom(address(tx.origin), address(this), amount));
_emergencyPerson[address(tx.origin)] = _emergencyPerson[address(tx.origin)].add(amount);
}
/**
* @dev Switch emergency state-transfer out NestNode Token
*/
function turnOutNestNodeForStateOfEmergency() public {
require(_emergencyPerson[address(tx.origin)] > 0);
require(_NNToken.transfer(address(tx.origin), _emergencyPerson[address(tx.origin)]));
_emergencyPerson[address(tx.origin)] = 0;
uint256 nestAmount = _nestToken.balanceOf(address(this));
require(_nestToken.transfer(address(_destructionAddress), nestAmount));
}
/**
* @dev Modify emergency state
*/
function changeStateOfEmergency() public {
if (_stateOfEmergency) {
require(now > _emergencyTime.add(_emergencyTimeLimit));
_stateOfEmergency = false;
_emergencyTime = 0;
} else {
require(_emergencyPerson[address(msg.sender)] > 0);
require(_NNToken.balanceOf(address(this)) >= _emergencyNNAmount);
_stateOfEmergency = true;
_emergencyTime = now;
}
}
/**
* @dev Check whether participating in the voting
* @param user Address to check
* @return bool Whether voting
*/
function checkVoteNow(address user) public view returns (bool) {
if (_myVote[user] == address(0x0)) {
return false;
} else {
Nest_3_VoteContract vote = Nest_3_VoteContract(_myVote[user]);
if (vote.checkContractEffective() || vote.checkPersonalAmount(user) == 0) {
return false;
}
return true;
}
}
/**
* @dev Check my voting
* @param user Address to check
* @return address Address recently participated in the voting contract address
*/
function checkMyVote(address user) public view returns (address) {
return _myVote[user];
}
// Check the voting time
function checkLimitTime() public view returns (uint256) {
return _limitTime;
}
// Check the NestNode raising time
function checkNNLimitTime() public view returns (uint256) {
return _NNLimitTime;
}
// Check the voting proportion to pass
function checkCirculationProportion() public view returns (uint256) {
return _circulationProportion;
}
// Check the minimum number of NNs to create a voting contract
function checkNNUsedCreate() public view returns (uint256) {
return _NNUsedCreate;
}
// Check the minimum number of NNs raised to start a vote
function checkNNCreateLimit() public view returns (uint256) {
return _NNCreateLimit;
}
// Check whether in emergency state
function checkStateOfEmergency() public view returns (bool) {
return _stateOfEmergency;
}
// Check the start time of the emergency state
function checkEmergencyTime() public view returns (uint256) {
return _emergencyTime;
}
// Check the duration of the emergency state
function checkEmergencyTimeLimit() public view returns (uint256) {
return _emergencyTimeLimit;
}
// Check the amount of personal pledged NNs
function checkEmergencyPerson(address user) public view returns (uint256) {
return _emergencyPerson[user];
}
// Check the number of NNs required for the emergency
function checkEmergencyNNAmount() public view returns (uint256) {
return _emergencyNNAmount;
}
// Verify voting contract data
function checkContractData(address contractAddress) public view returns (bool) {
return _contractData[contractAddress];
}
// Modify voting time
function changeLimitTime(uint256 num) public onlyOwner {
require(num > 0, "Parameter needs to be greater than 0");
_limitTime = num;
}
// Modify the NestNode raising time
function changeNNLimitTime(uint256 num) public onlyOwner {
require(num > 0, "Parameter needs to be greater than 0");
_NNLimitTime = num;
}
// Modify the voting proportion
function changeCirculationProportion(uint256 num) public onlyOwner {
require(num > 0, "Parameter needs to be greater than 0");
_circulationProportion = num;
}
// Modify the minimum number of NNs to create a voting contract
function changeNNUsedCreate(uint256 num) public onlyOwner {
_NNUsedCreate = num;
}
// Modify the minimum number of NNs to raised to start a voting
function checkNNCreateLimit(uint256 num) public onlyOwner {
_NNCreateLimit = num;
}
// Modify the emergency state duration
function changeEmergencyTimeLimit(uint256 num) public onlyOwner {
require(num > 0);
_emergencyTimeLimit = num.mul(1 days);
}
// Modify the number of NNs required for emergency state
function changeEmergencyNNAmount(uint256 num) public onlyOwner {
require(num > 0);
_emergencyNNAmount = num;
}
// Check address
function checkAddress(string memory name) public view returns (address contractAddress) {
return _contractAddress[name];
}
// Add contract mapping address
function addContractAddress(string memory name, address contractAddress) public onlyOwner {
_contractAddress[name] = contractAddress;
}
// Add administrator address
function addSuperMan(address superMan) public onlyOwner {
_modifyAuthority[superMan] = true;
}
function addSuperManPrivate(address superMan) private {
_modifyAuthority[superMan] = true;
}
// Delete administrator address
function deleteSuperMan(address superMan) public onlyOwner {
_modifyAuthority[superMan] = false;
}
function deleteSuperManPrivate(address superMan) private {
_modifyAuthority[superMan] = false;
}
// Delete voting contract data
function deleteContractData(address contractAddress) public onlyOwner {
_contractData[contractAddress] = false;
}
// Check whether the administrator
function checkOwners(address man) public view returns (bool) {
return _modifyAuthority[man];
}
// Administrator only
modifier onlyOwner() {
require(checkOwners(msg.sender), "No authority");
_;
}
}
/**
* @title Voting contract
*/
contract Nest_3_VoteContract {
using SafeMath for uint256;
Nest_3_Implement _implementContract; // Executable contract
Nest_3_TokenSave _tokenSave; // Lock-up contract
Nest_3_VoteFactory _voteFactory; // Voting factory contract
Nest_3_TokenAbonus _tokenAbonus; // Bonus logic contract
ERC20 _nestToken; // NestToken
ERC20 _NNToken; // NestNode Token
address _miningSave; // Mining pool contract
address _implementAddress; // Executable contract address
address _destructionAddress; // Destruction contract address
uint256 _createTime; // Creation time
uint256 _endTime; // End time
uint256 _totalAmount; // Total votes
uint256 _circulation; // Passed votes
uint256 _destroyedNest; // Destroyed NEST
uint256 _NNLimitTime; // NestNode raising time
uint256 _NNCreateLimit; // Minimum number of NNs to create votes
uint256 _abonusTimes; // Period number of used snapshot in emergency state
uint256 _allNNAmount; // Total number of NNs
bool _effective = false; // Whether vote is effective
bool _nestVote = false; // Whether NEST vote can be performed
bool _isChange = false; // Whether NEST vote is executed
bool _stateOfEmergency; // Whether the contract is in emergency state
mapping(address => uint256) _personalAmount; // Number of personal votes
mapping(address => uint256) _personalNNAmount; // Number of NN personal votes
/**
* @dev Initialization method
* @param contractAddress Executable contract address
* @param stateOfEmergency Whether in emergency state
* @param NNAmount Amount of NNs
*/
constructor (address contractAddress, bool stateOfEmergency, uint256 NNAmount) public {
Nest_3_VoteFactory voteFactory = Nest_3_VoteFactory(address(msg.sender));
_voteFactory = voteFactory;
_nestToken = ERC20(voteFactory.checkAddress("nest"));
_NNToken = ERC20(voteFactory.checkAddress("nestNode"));
_implementContract = Nest_3_Implement(address(contractAddress));
_implementAddress = address(contractAddress);
_destructionAddress = address(voteFactory.checkAddress("nest.v3.destruction"));
_personalNNAmount[address(tx.origin)] = NNAmount;
_allNNAmount = NNAmount;
_createTime = now;
_endTime = _createTime.add(voteFactory.checkLimitTime());
_NNLimitTime = voteFactory.checkNNLimitTime();
_NNCreateLimit = voteFactory.checkNNCreateLimit();
_stateOfEmergency = stateOfEmergency;
if (stateOfEmergency) {
// If in emergency state, read the last two periods of bonus lock-up and total circulation data
_tokenAbonus = Nest_3_TokenAbonus(voteFactory.checkAddress("nest.v3.tokenAbonus"));
_abonusTimes = _tokenAbonus.checkTimes().sub(2);
require(_abonusTimes > 0);
_circulation = _tokenAbonus.checkTokenAllValueHistory(address(_nestToken),_abonusTimes).mul(voteFactory.checkCirculationProportion()).div(100);
} else {
_miningSave = address(voteFactory.checkAddress("nest.v3.miningSave"));
_tokenSave = Nest_3_TokenSave(voteFactory.checkAddress("nest.v3.tokenSave"));
_circulation = (uint256(10000000000 ether).sub(_nestToken.balanceOf(address(_miningSave))).sub(_nestToken.balanceOf(address(_destructionAddress)))).mul(voteFactory.checkCirculationProportion()).div(100);
}
if (_allNNAmount >= _NNCreateLimit) {
_nestVote = true;
}
}
/**
* @dev NEST voting
*/
function nestVote() public onlyFactory {
require(now <= _endTime, "Voting time exceeded");
require(!_effective, "Vote in force");
require(_nestVote);
require(_personalAmount[address(tx.origin)] == 0, "Have voted");
uint256 amount;
if (_stateOfEmergency) {
// If in emergency state, read the last two periods of bonus lock-up and total circulation data
amount = _tokenAbonus.checkTokenSelfHistory(address(_nestToken),_abonusTimes, address(tx.origin));
} else {
amount = _tokenSave.checkAmount(address(tx.origin), address(_nestToken));
}
_personalAmount[address(tx.origin)] = amount;
_totalAmount = _totalAmount.add(amount);
ifEffective();
}
/**
* @dev NEST voting cancellation
*/
function nestVoteCancel() public {
require(address(msg.sender) == address(tx.origin), "It can't be a contract");
require(now <= _endTime, "Voting time exceeded");
require(!_effective, "Vote in force");
require(_personalAmount[address(tx.origin)] > 0, "No vote");
_totalAmount = _totalAmount.sub(_personalAmount[address(tx.origin)]);
_personalAmount[address(tx.origin)] = 0;
}
/**
* @dev NestNode voting
* @param NNAmount Amount of NNs
*/
function nestNodeVote(uint256 NNAmount) public onlyFactory {
require(now <= _createTime.add(_NNLimitTime), "Voting time exceeded");
require(!_nestVote);
_personalNNAmount[address(tx.origin)] = _personalNNAmount[address(tx.origin)].add(NNAmount);
_allNNAmount = _allNNAmount.add(NNAmount);
if (_allNNAmount >= _NNCreateLimit) {
_nestVote = true;
}
}
/**
* @dev Withdrawing lock-up NNs
*/
function turnOutNestNode() public {
if (_nestVote) {
// Normal NEST voting
if (!_stateOfEmergency || !_effective) {
// Non-emergency state
require(now > _endTime, "Vote unenforceable");
}
} else {
// NN voting
require(now > _createTime.add(_NNLimitTime));
}
require(_personalNNAmount[address(tx.origin)] > 0);
// Reverting back the NNs
require(_NNToken.transfer(address(tx.origin), _personalNNAmount[address(tx.origin)]));
_personalNNAmount[address(tx.origin)] = 0;
// Destroying NEST Tokens
uint256 nestAmount = _nestToken.balanceOf(address(this));
_destroyedNest = _destroyedNest.add(nestAmount);
require(_nestToken.transfer(address(_destructionAddress), nestAmount));
}
/**
* @dev Execute the contract
*/
function startChange() public onlyFactory {
require(!_isChange);
_isChange = true;
if (_stateOfEmergency) {
require(_effective, "Vote unenforceable");
} else {
require(_effective && now > _endTime, "Vote unenforceable");
}
// Add the executable contract to the administrator list
_voteFactory.addSuperMan(address(_implementContract));
// Execute
_implementContract.doit();
// Delete the authorization
_voteFactory.deleteSuperMan(address(_implementContract));
}
/**
* @dev check whether the vote is effective
*/
function ifEffective() private {
if (_totalAmount >= _circulation) {
_effective = true;
}
}
/**
* @dev Check whether the vote is over
*/
function checkContractEffective() public view returns (bool) {
if (_effective || now > _endTime) {
return true;
}
return false;
}
// Check the executable implement contract address
function checkImplementAddress() public view returns (address) {
return _implementAddress;
}
// Check the voting start time
function checkCreateTime() public view returns (uint256) {
return _createTime;
}
// Check the voting end time
function checkEndTime() public view returns (uint256) {
return _endTime;
}
// Check the current total number of votes
function checkTotalAmount() public view returns (uint256) {
return _totalAmount;
}
// Check the number of votes to pass
function checkCirculation() public view returns (uint256) {
return _circulation;
}
// Check the number of personal votes
function checkPersonalAmount(address user) public view returns (uint256) {
return _personalAmount[user];
}
// Check the destroyed NEST
function checkDestroyedNest() public view returns (uint256) {
return _destroyedNest;
}
// Check whether the contract is effective
function checkEffective() public view returns (bool) {
return _effective;
}
// Check whether in emergency state
function checkStateOfEmergency() public view returns (bool) {
return _stateOfEmergency;
}
// Check NestNode raising time
function checkNNLimitTime() public view returns (uint256) {
return _NNLimitTime;
}
// Check the minimum number of NNs to create a vote
function checkNNCreateLimit() public view returns (uint256) {
return _NNCreateLimit;
}
// Check the period number of snapshot used in the emergency state
function checkAbonusTimes() public view returns (uint256) {
return _abonusTimes;
}
// Check number of personal votes
function checkPersonalNNAmount(address user) public view returns (uint256) {
return _personalNNAmount[address(user)];
}
// Check the total number of NNs
function checkAllNNAmount() public view returns (uint256) {
return _allNNAmount;
}
// Check whether NEST voting is available
function checkNestVote() public view returns (bool) {
return _nestVote;
}
// Check whether it has been excecuted
function checkIsChange() public view returns (bool) {
return _isChange;
}
// Vote Factory contract only
modifier onlyFactory() {
require(address(_voteFactory) == address(msg.sender), "No authority");
_;
}
}
// Executable contract
interface Nest_3_Implement {
// Execute
function doit() external;
}
// NEST lock-up contract
interface Nest_3_TokenSave {
// Check lock-up amount
function checkAmount(address sender, address token) external view returns (uint256);
}
// Bonus logic contract
interface Nest_3_TokenAbonus {
// Check NEST circulation snapshot
function checkTokenAllValueHistory(address token, uint256 times) external view returns (uint256);
// Check NEST user balance snapshot
function checkTokenSelfHistory(address token, uint256 times, address user) external view returns (uint256);
// Check bonus ledger period
function checkTimes() external view returns (uint256);
}
// Erc20 contract
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 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;
}
}