文件 1 的 6:Context.sol
pragma solidity >=0.6.0 <0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this;
return msg.data;
}
}
文件 2 的 6:Date.sol
pragma solidity ^0.7.6;
library Date {
uint256 constant HOUR_IN_SECONDS = 3600;
uint256 constant DAY_IN_SECONDS = 86400;
uint256 constant YEAR_IN_SECONDS = 31536000;
uint256 constant LEAP_YEAR_IN_SECONDS = 31622400;
uint16 constant ORIGIN_YEAR = 1970;
function getHoursInMonth(uint256 _timestamp) internal pure returns (uint256) {
uint256 timestamp = _timestamp * HOUR_IN_SECONDS;
uint256 secondsAccountedFor = 0;
uint256 buf;
uint8 i;
uint16 year;
uint8 month;
year = getYear(timestamp);
buf = leapYearsBefore(year) - leapYearsBefore(ORIGIN_YEAR);
secondsAccountedFor += LEAP_YEAR_IN_SECONDS * buf;
secondsAccountedFor += YEAR_IN_SECONDS * (year - ORIGIN_YEAR - buf);
uint256 secondsInMonth;
for (i = 1; i <= 12; i++) {
secondsInMonth = DAY_IN_SECONDS * getDaysInMonth(i, year);
if (secondsInMonth + secondsAccountedFor > timestamp) {
month = i;
break;
}
secondsAccountedFor += secondsInMonth;
}
return (getDaysInMonth(month, year) * 24);
}
function getDaysInMonth(uint8 month, uint16 year) internal pure returns (uint8) {
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
return 31;
} else if (month == 4 || month == 6 || month == 9 || month == 11) {
return 30;
} else if (isLeapYear(year)) {
return 29;
} else {
return 28;
}
}
function getYear(uint256 timestamp) internal pure returns (uint16) {
uint256 secondsAccountedFor = 0;
uint16 year;
uint256 numLeapYears;
year = uint16(ORIGIN_YEAR + timestamp / YEAR_IN_SECONDS);
numLeapYears = leapYearsBefore(year) - leapYearsBefore(ORIGIN_YEAR);
secondsAccountedFor += LEAP_YEAR_IN_SECONDS * numLeapYears;
secondsAccountedFor += YEAR_IN_SECONDS * (year - ORIGIN_YEAR - numLeapYears);
while (secondsAccountedFor > timestamp) {
if (isLeapYear(uint16(year - 1))) {
secondsAccountedFor -= LEAP_YEAR_IN_SECONDS;
} else {
secondsAccountedFor -= YEAR_IN_SECONDS;
}
year -= 1;
}
return year;
}
function isLeapYear(uint16 year) internal pure returns (bool) {
if (year % 4 != 0) {
return false;
}
if (year % 100 != 0) {
return true;
}
if (year % 400 != 0) {
return false;
}
return true;
}
function leapYearsBefore(uint256 year) internal pure returns (uint256) {
year -= 1;
return year / 4 - year / 100 + year / 400;
}
}
文件 3 的 6:ERC20.sol
pragma solidity ^0.7.6;
import './Ownable.sol';
import './SafeMath.sol';
interface IERC20 {
function totalSupply() external view returns (uint256);
function decimals() external view returns (uint8);
function symbol() external view returns (string memory);
function name() external view returns (string memory);
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);
}
contract ERC20 is IERC20, Ownable {
using SafeMath for uint256;
string private _name;
string private _symbol;
uint8 private _decimals;
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowed;
uint256 private _totalSupply;
uint256 private _totalBurnt;
constructor(string memory name_, string memory symbol_, uint8 decimals_) {
_name = name_;
_symbol = symbol_;
_decimals = decimals_;
}
function name() public view override returns (string memory) {
return _name;
}
function symbol() public view override returns (string memory) {
return _symbol;
}
function decimals() public view override returns (uint8) {
return _decimals;
}
function totalSupply() public view override returns (uint256) {
return _totalSupply;
}
function totalBurnt() public view returns (uint256) {
return _totalBurnt;
}
function balanceOf(address account) public view override returns (uint256) {
return _balances[account];
}
function allowance(address owner, address spender) public view override returns (uint256) {
return _allowed[owner][spender];
}
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(msg.sender, recipient, amount);
return true;
}
function approve(address spender, uint256 amount) public override returns (bool) {
require(spender != address(0), 'spender cannot be address(0)');
_allowed[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
_allowed[sender][msg.sender] = _allowed[sender][msg.sender].sub(amount);
_transfer(sender, recipient, amount);
emit Approval(sender, msg.sender, _allowed[sender][msg.sender]);
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
require(spender != address(0), 'spender cannot be address(0)');
_allowed[msg.sender][spender] = _allowed[msg.sender][spender].add(addedValue);
emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
require(spender != address(0), 'spender cannot be address(0)');
_allowed[msg.sender][spender] = _allowed[msg.sender][spender].sub(subtractedValue);
emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
return true;
}
function _transfer(address from, address to, uint256 value) internal {
require(from != address(0), 'from cannot be address(0)');
require(to != address(0), 'to cannot be address(0)');
_balances[from] = _balances[from].sub(value);
_balances[to] = _balances[to].add(value);
emit Transfer(from, to, value);
}
function _mint(address account, uint256 value) internal {
require(account != address(0), 'account cannot be address(0)');
_totalSupply = _totalSupply.add(value);
_balances[account] = _balances[account].add(value);
emit Transfer(address(0), account, value);
}
function _burn(address account, uint256 value) internal {
require(account != address(0), 'account cannot be address(0)');
_totalSupply = _totalSupply.sub(value);
_balances[account] = _balances[account].sub(value);
_totalBurnt = _totalBurnt.add(value);
emit Transfer(account, address(0), value);
}
function _burnFrom(address account, uint256 value) internal {
_allowed[account][msg.sender] = _allowed[account][msg.sender].sub(value);
_burn(account, value);
}
}
文件 4 的 6:Ownable.sol
pragma solidity >=0.6.0 <0.8.0;
import "./Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor () internal {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
文件 5 的 6:SafeMath.sol
pragma solidity 0.7.6;
library SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, 'MUL_ERROR');
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, 'DIVIDING_ERROR');
uint256 c = a / b;
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, 'SUB_ERROR');
uint256 c = a - b;
return c;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, 'ADD_ERROR');
return c;
}
function roundDiv(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "DIVIDING_ERROR");
uint256 c = (((a * 10) / b) + 5) / 10;
return c;
}
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "DIVIDING_ERROR");
uint256 c = a / b;
if (a % b > 0) {
c = c + 1;
}
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0, 'MOD_ERROR');
return a % b;
} }
文件 6 的 6:Yang.sol
pragma solidity ^0.7.6;
import "./ERC20.sol";
import "./SafeMath.sol";
import "./Date.sol";
import "./Ownable.sol";
abstract contract YinInterface {
function totalSupply() public view virtual returns (uint256);
function balanceOf(address who) external view virtual returns (uint256);
function mintFromYang(address to, uint256 value) public virtual returns (bool);
function burnFromYang(address tokensOwner, uint256 value) external virtual returns (bool);
}
contract Yang is ERC20 {
using Date for uint256;
using SafeMath for uint256;
address public yinContract;
uint256 public quarantineBalance;
uint256 public lastBlockNumber;
uint256 public lastBurnedHour;
uint256 constant PRICE_BASE = 10**8;
uint256 constant INITIAL_PRICE = 100000000;
struct Block {
uint256 yangPrice;
uint256 growthRate;
uint256 change;
uint256 created;
}
mapping(uint256 => Block) public hoursToBlock;
mapping(uint256 => uint256[4]) public growthRateToPriceFactors;
uint256 constant GROWTH_RATE_BASE = 10**4;
uint256 constant PRICE_FACTOR_BASE = 10**11;
bool public priceFactorsLocked = false;
event DoBurn(uint256 indexed currentHour, uint256 yangAmountBurnt);
event ConvertToYin(address indexed converter, uint256 yangAmountSent, uint256 yinAmountReceived);
event ConvertToYang(address indexed converter, uint256 yinAmountSent, uint256 yangAmountReceived);
event MintYin(address receiver, uint256 amount);
event BurnYin(uint256 amountBurnt);
event PriceFactorSet(uint256 growthRate, uint256 priceFactor0, uint256 priceFactor1, uint256 priceFactor2, uint256 priceFactor3);
event BlockCreated(uint256 blockNumber, uint256 yangPrice, uint256 growthRate, uint256 change, uint256 created);
event QuarantineBalanceBurnt(uint256 amount);
event LostTokensBurnt(uint256 amount);
constructor(address _yinContract) ERC20('Flux YANG ', 'YANG', 8) Ownable() {
_mint(msg.sender, 250000000000000);
yinContract = _yinContract;
}
function getCurrentPrice() external view returns (uint256) {
require(hoursToBlock[getCurrentHour()].yangPrice > 0, 'BLOCK_NOT_DEFINED');
return hoursToBlock[getCurrentHour()].yangPrice;
}
function getPrice(uint256 _hour) external view returns (uint256) {
require(hoursToBlock[_hour].yangPrice > 0, 'BLOCK_NOT_DEFINED');
return hoursToBlock[_hour].yangPrice;
}
function getBlockData(uint256 _hoursEpoch)
external
view
returns (
uint256 _yangPrice,
uint256 _growthRate,
uint256 _change,
uint256 _created
)
{
require(_hoursEpoch > 0, 'EMPTY_HOURS_VALUE');
require(hoursToBlock[_hoursEpoch].yangPrice > 0, 'BLOCK_NOT_DEFINED');
_yangPrice = hoursToBlock[_hoursEpoch].yangPrice;
_growthRate = hoursToBlock[_hoursEpoch].growthRate;
_change = hoursToBlock[_hoursEpoch].change;
_created = hoursToBlock[_hoursEpoch].created;
return (_yangPrice, _growthRate, _change, _created);
}
function doCreateBlock(uint256 _blockNumber, uint256 _growthRate)
external
onlyOwner
returns (bool _success)
{
require(priceFactorsLocked, 'PRICE_FACTORS_MUST_BE_LOCKED');
require(_growthRate != 0, 'GROWTH_RATE_CAN_NOT_BE_ZERO');
require(_growthRate < GROWTH_RATE_BASE, 'GROWTH_RATE_IS_GREATER_THAN_GROWTH_RATE_BASE');
require(growthRateToPriceFactors[_growthRate][0] > 0, 'GROWTH_RATE_IS_NOT_SPECIFIED');
require(_createBlock(_blockNumber, _growthRate), 'FAILED_TO_CREATE_BLOCK');
return true;
}
function setPriceFactors(uint256 _growthRate, uint256[4] memory _priceFactors)
external
onlyOwner
returns (bool _success)
{
require(priceFactorsLocked == false, 'PRICE_FACTORS_ALREADY_LOCKED');
require(_growthRate != 0, 'GROWTH_RATE_CAN_NOT_BE_ZERO');
require(_growthRate < GROWTH_RATE_BASE, 'GROWTH_RATE_IS_GREATER_THAN_GROWTH_RATE_BASE');
require(_priceFactors[0] > 0, 'PRICE_FACTOR_0_CAN_NOT_BE_ZERO');
require(_priceFactors[0] < 103200117, 'PRICE_FACTOR_0_IS_TOO_BIG');
require(_priceFactors[1] > 0, 'PRICE_FACTOR_1_CAN_NOT_BE_ZERO');
require(_priceFactors[1] < 99639720, 'PRICE_FACTOR_1_IS_TOO_BIG');
require(_priceFactors[2] > 0, 'PRICE_FACTOR_2_CAN_NOT_BE_ZERO');
require(_priceFactors[2] < 96316797, 'PRICE_FACTOR_2_IS_TOO_BIG');
require(_priceFactors[3] > 0, 'PRICE_FACTOR_3_CAN_NOT_BE_ZERO');
require(_priceFactors[3] < 93208356, 'PRICE_FACTOR_3_IS_TOO_BIG');
require(_priceFactors[0] > _priceFactors[1] && _priceFactors[1] > _priceFactors[2] && _priceFactors[2] > _priceFactors[3], 'PRICE_FACTORS_ARE_NOT_VALID');
growthRateToPriceFactors[_growthRate] = _priceFactors;
emit PriceFactorSet(_growthRate, _priceFactors[0], _priceFactors[1], _priceFactors[2], _priceFactors[3]);
return true;
}
function lockPriceFactors() external onlyOwner returns (bool _success) {
priceFactorsLocked = true;
return true;
}
function doBurn() external returns (bool _success) {
require(hoursToBlock[getCurrentHour()].yangPrice != 0, 'CURRENT_PRICE_BLOCK_NOT_DEFINED');
require(lastBurnedHour < getCurrentHour(), 'CHANGE_IS_ALREADY_BURNT_IN_THIS_HOUR');
lastBurnedHour = getCurrentHour();
uint256 _yangBurnt = _burnQuarantined();
emit DoBurn(getCurrentHour(), _yangBurnt);
return true;
}
function convertToYang(uint256 _yinAmount) external returns (bool _success) {
require(hoursToBlock[getCurrentHour()].yangPrice != 0, 'CURRENT_PRICE_BLOCK_NOT_DEFINED');
require(YinInterface(yinContract).balanceOf(msg.sender) >= _yinAmount, 'INSUFFICIENT_YIN_BALANCE');
require(YinInterface(yinContract).burnFromYang(msg.sender, _yinAmount), 'BURNING_YIN_FAILED');
emit BurnYin(_yinAmount);
uint256 _yangToDequarantine = (_yinAmount * PRICE_BASE) / hoursToBlock[getCurrentHour()].yangPrice;
quarantineBalance = quarantineBalance.sub(_yangToDequarantine);
require(this.transfer(msg.sender, _yangToDequarantine), 'CONVERT_TO_YANG_FAILED');
emit ConvertToYang(msg.sender, _yinAmount, _yangToDequarantine);
return true;
}
function convertToYin(uint256 _yangAmount) external returns (uint256) {
require(hoursToBlock[getCurrentHour()].yangPrice != 0, 'CURRENT_PRICE_BLOCK_NOT_DEFINED');
require(balanceOf(msg.sender) >= _yangAmount, 'INSUFFICIENT_YANG_BALANCE');
quarantineBalance = quarantineBalance.add(_yangAmount);
require(transfer(address(this), _yangAmount), 'YANG_TRANSFER_FAILED');
uint256 _yinToIssue = (_yangAmount.mul(hoursToBlock[getCurrentHour()].yangPrice)).div(PRICE_BASE);
require(YinInterface(yinContract).mintFromYang(msg.sender, _yinToIssue), 'YIN_MINT_FAILED');
emit MintYin(msg.sender, _yinToIssue);
emit ConvertToYin(msg.sender, _yangAmount, _yinToIssue);
return _yinToIssue;
}
function burnLostTokens() external onlyOwner returns (bool _success) {
uint256 _amount = balanceOf(address(this)).sub(quarantineBalance);
_burn(address(this), _amount);
emit LostTokensBurnt(_amount);
return true;
}
function _burnQuarantined() internal returns (uint256) {
uint256 _quarantined = quarantineBalance;
uint256 _currentPrice = hoursToBlock[getCurrentHour()].yangPrice;
uint256 _yinSupply = YinInterface(yinContract).totalSupply();
uint256 _yangToBurn = (((_quarantined.mul(_currentPrice)).div(PRICE_BASE)).sub(_yinSupply)).mul(PRICE_BASE).div(_currentPrice);
quarantineBalance = quarantineBalance.sub(_yangToBurn);
_burn(address(this), _yangToBurn);
emit QuarantineBalanceBurnt(_yangToBurn);
return _yangToBurn;
}
function _createBlock(uint256 _expectedBlockNumber, uint256 _growthRate) internal returns (bool _success) {
uint256 _lastPrice;
uint256 _nextBlockNumber;
if (lastBlockNumber == 0) {
require(_expectedBlockNumber > getCurrentHour(), 'FIRST_BLOCK_MUST_BE_IN_THE_FUTURE');
require(_expectedBlockNumber < getCurrentHour() + 365 * 24, 'FIRST_BLOCK_MUST_BE_WITHIN_ONE_YEAR');
_lastPrice = INITIAL_PRICE;
_nextBlockNumber = _expectedBlockNumber;
} else {
_lastPrice = hoursToBlock[lastBlockNumber].yangPrice;
_nextBlockNumber = lastBlockNumber.add(1);
}
require(_nextBlockNumber == _expectedBlockNumber, 'WRONG_BLOCK_NUMBER');
uint256 _yangPriceFactor;
uint256 _monthBlocks = (_nextBlockNumber * 60 * 60 * 1000).getHoursInMonth();
if (_monthBlocks == 28 * 24) {
_yangPriceFactor = growthRateToPriceFactors[_growthRate][0];
} else if (_monthBlocks == 29 * 24) {
_yangPriceFactor = growthRateToPriceFactors[_growthRate][1];
} else if (_monthBlocks == 30 * 24) {
_yangPriceFactor = growthRateToPriceFactors[_growthRate][2];
} else {
_yangPriceFactor = growthRateToPriceFactors[_growthRate][3];
}
uint256 _yangPrice = ((_yangPriceFactor.mul(_lastPrice)).add(_lastPrice.mul(PRICE_FACTOR_BASE))).ceilDiv(PRICE_FACTOR_BASE);
uint256 _change = (_yangPrice.sub(_lastPrice)).mul(PRICE_BASE).roundDiv(_lastPrice);
uint256 _created = getCurrentHour();
hoursToBlock[_nextBlockNumber] = Block({
yangPrice: _yangPrice,
growthRate: _growthRate,
change: _change,
created: _created
});
lastBlockNumber = _nextBlockNumber;
emit BlockCreated(_nextBlockNumber, _yangPrice, _growthRate, _change, _created);
return true;
}
function getCurrentTime() public view virtual returns (uint256) {
return block.timestamp;
}
function getCurrentHour() public view returns (uint256) {
return getCurrentTime().div(1 hours);
}
function multiTransfer(address[] memory recipients, uint256[] memory amounts) external returns (bool) {
require(recipients.length == amounts.length, "Recipients and amounts length mismatch");
for (uint256 i = 0; i < recipients.length; i++) {
require(transfer(recipients[i], amounts[i]), "Transfer failed");
}
return true;
}
}
{
"compilationTarget": {
"contracts/Yang.sol": "Yang"
},
"evmVersion": "berlin",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_yinContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"blockNumber","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"yangPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"growthRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"change","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"created","type":"uint256"}],"name":"BlockCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amountBurnt","type":"uint256"}],"name":"BurnYin","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"converter","type":"address"},{"indexed":false,"internalType":"uint256","name":"yinAmountSent","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"yangAmountReceived","type":"uint256"}],"name":"ConvertToYang","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"converter","type":"address"},{"indexed":false,"internalType":"uint256","name":"yangAmountSent","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"yinAmountReceived","type":"uint256"}],"name":"ConvertToYin","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"currentHour","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"yangAmountBurnt","type":"uint256"}],"name":"DoBurn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LostTokensBurnt","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"MintYin","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"growthRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"priceFactor0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"priceFactor1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"priceFactor2","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"priceFactor3","type":"uint256"}],"name":"PriceFactorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"QuarantineBalanceBurnt","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"burnLostTokens","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_yinAmount","type":"uint256"}],"name":"convertToYang","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_yangAmount","type":"uint256"}],"name":"convertToYin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"doBurn","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_blockNumber","type":"uint256"},{"internalType":"uint256","name":"_growthRate","type":"uint256"}],"name":"doCreateBlock","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_hoursEpoch","type":"uint256"}],"name":"getBlockData","outputs":[{"internalType":"uint256","name":"_yangPrice","type":"uint256"},{"internalType":"uint256","name":"_growthRate","type":"uint256"},{"internalType":"uint256","name":"_change","type":"uint256"},{"internalType":"uint256","name":"_created","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentHour","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_hour","type":"uint256"}],"name":"getPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"growthRateToPriceFactors","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"hoursToBlock","outputs":[{"internalType":"uint256","name":"yangPrice","type":"uint256"},{"internalType":"uint256","name":"growthRate","type":"uint256"},{"internalType":"uint256","name":"change","type":"uint256"},{"internalType":"uint256","name":"created","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastBlockNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastBurnedHour","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockPriceFactors","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"multiTransfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFactorsLocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"quarantineBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_growthRate","type":"uint256"},{"internalType":"uint256[4]","name":"_priceFactors","type":"uint256[4]"}],"name":"setPriceFactors","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBurnt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"yinContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]