BaseBase
0x38...75ab
Flux YANG

Flux YANG

YANG

代币
市值
$1.00
 
价格
2%
此合同的源代码已经过验证!
合同元数据
编译器
0.7.6+commit.7338295f
语言
Solidity
合同源代码
文件 1 的 6:Context.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with GSN meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}
合同源代码
文件 2 的 6:Date.sol
// SPDX-License-Identifier: MIT
//  ____    _  _____ _____ 
// |  _ \  / \|_   _| ____|
// | | | |/ _ \ | | |  _|  
// | |_| / ___ \| | | |___ 
// |____/_/   \_\_| |_____|
                         
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
        year = getYear(timestamp);
        buf = leapYearsBefore(year) - leapYearsBefore(ORIGIN_YEAR);

        secondsAccountedFor += LEAP_YEAR_IN_SECONDS * buf;
        secondsAccountedFor += YEAR_IN_SECONDS * (year - ORIGIN_YEAR - buf);

        // Month
        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
        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
// SPDX-License-Identifier: MIT
//  _____ ____   ____ ____   ___  
// | ____|  _ \ / ___|___ \ / _ \ 
// |  _| | |_) | |     __) | | | |
// | |___|  _ <| |___ / __/| |_| |
// |_____|_| \_\\____|_____|\___/ 
                                
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
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./Context.sol";
/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor () internal {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    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
// SPDX-License-Identifier: MIT
//  __  __    _  _____ _   _ 
// |  \/  |  / \|_   _| | | |
// | |\/| | / _ \ | | | |_| |
// | |  | |/ ___ \| | |  _  |
// |_|  |_/_/   \_\_| |_| |_|
                           
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
// SPDX-License-Identifier: MIT
// __   __ _    _   _  ____ 
// \ \ / // \  | \ | |/ ___|
//  \ V // _ \ |  \| | |  _ 
//   | |/ ___ \| |\  | |_| |
//   |_/_/   \_\_| \_|\____|
                          
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; // number of last created block
    uint256 public lastBurnedHour;

    // Price of Yang in USD has base of PRICE_BASE
    uint256 constant PRICE_BASE = 10**8;

    // Initial price of Yang in USD
    uint256 constant INITIAL_PRICE = 100000000; // $1.0

    // Structure of a Price Block
    struct Block {
        uint256 yangPrice; // USD price of Yang for the block
        uint256 growthRate; // FutureGrowthRate value at the time of block creation
        uint256 change; // percentage (base of PRICE_BASE), YangPrice change relative to prev. block
        uint256 created; // hours, Unix epoch time
    }

    // Price Blocks for a given hour (number of hours since epoch time)
    mapping(uint256 => Block) public hoursToBlock;

    // Price factors for months with [28, 29, 30, 31] days
    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); // 2.5 Million
        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": []
}
ABI
[{"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"}]