false
false
0

Contract Address Details

0x5059bA6272Fa598efAaCC9b6FCeFef7366980aD7

Contract Name
Supply
Creator
0x493044–a7586e at 0x883a67–a68ffc
Balance
0 SGB ( )
Tokens
Fetching tokens...
Transactions
2 Transactions
Transfers
1 Transfers
Gas Used
187,098
Last Balance Update
56566003
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
Supply




Optimization enabled
true
Compiler version
v0.7.6+commit.7338295f




Optimization runs
200
EVM Version
default




Verified at
2021-09-22T13:28:22.612173Z

Constructor Arguments

000000000000000000000000493044fbbaa7f9f78379864fa88accaff6a7586e000000000000000000000000010000000000000000000000000000000000000000000000000000000000000087e80e90eaca1d458dfdf60a9d697e7e83ab02b200000000000000000000000000000000000000003077b58d5d378391980000000000000000000000000000000000000000000000121594259bea5565a8bc000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000

Arg [0] (address) : 0x493044fbbaa7f9f78379864fa88accaff6a7586e
Arg [1] (address) : 0x0100000000000000000000000000000000000000
Arg [2] (address) : 0x87e80e90eaca1d458dfdf60a9d697e7e83ab02b2
Arg [3] (uint256) : 15000000000000000000000000000
Arg [4] (uint256) : 5596817223000000000000000000
Arg [5] (address[]) : []

              

Contract source code

// Sources flattened with hardhat v2.3.0 https://hardhat.org

// File contracts/inflation/interface/IISupply.sol

// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;


interface IISupply {

    /**
     * @notice Sets inflation contract. Only governance can call this method.
     */
    function setInflation(address _inflation) external;

    /**
     * @notice Updates authorized inflation and circulating supply - emits event if error
     * @param _inflationAuthorizedWei               Authorized inflation
     * @dev Also updates the burn address amount
    */
    function updateAuthorizedInflationAndCirculatingSupply(uint256 _inflationAuthorizedWei) external;

    /**
     * @notice Get approximate circulating supply for given block number from cache - only past block
     * @param _blockNumber                          Block number
     * @return _circulatingSupplyWei Return approximate circulating supply for last known block <= _blockNumber
    */
    function getCirculatingSupplyAtCached(uint256 _blockNumber) external returns(uint256 _circulatingSupplyWei);

    /**
     * @notice Get approximate circulating supply for given block number
     * @param _blockNumber                          Block number
     * @return _circulatingSupplyWei Return approximate circulating supply for last known block <= _blockNumber
    */
    function getCirculatingSupplyAt(uint256 _blockNumber) external view returns(uint256 _circulatingSupplyWei);

    /**
     * @notice Get total inflatable balance (initial genesis amount + total authorized inflation)
     * @return _inflatableBalanceWei Return inflatable balance
    */
    function getInflatableBalance() external view returns(uint256 _inflatableBalanceWei);
}


// File contracts/tokenPools/interface/IITokenPool.sol

// 
pragma solidity 0.7.6;

interface IITokenPool {

    /**
     * @notice Return token pool supply data
     * @return _foundationAllocatedFundsWei     Foundation allocated funds (wei)
     * @return _totalInflationAuthorizedWei     Total inflation authorized amount (wei)
     * @return _totalClaimedWei                 Total claimed amount (wei)
     */
    function getTokenPoolSupplyData() external view returns (
        uint256 _foundationAllocatedFundsWei,
        uint256 _totalInflationAuthorizedWei,
        uint256 _totalClaimedWei
    );
}


// File @openzeppelin/contracts/math/[email protected]

// 

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow, so we distribute
        return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
    }
}


// File @openzeppelin/contracts/math/[email protected]

// 

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b > a) return (false, 0);
        return (true, a - b);
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) return (true, 0);
        uint256 c = a * b;
        if (c / a != b) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a / b);
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a % b);
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");
        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    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;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: division by zero");
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: modulo by zero");
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        return a - b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryDiv}.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a % b;
    }
}


// File contracts/token/lib/CheckPointHistory.sol

// 
pragma solidity 0.7.6;


/**
 * @title Check Point History library
 * @notice A contract to manage checkpoints as of a given block.
 * @dev Store value history by block number with detachable state.
 **/
library CheckPointHistory {
    using SafeMath for uint256;

    /**
     * @dev `CheckPoint` is the structure that attaches a block number to a
     *  given value; the block number attached is the one that last changed the
     *  value
     **/
    struct CheckPoint {
        // `fromBlock` is the block number that the value was generated from
        uint256 fromBlock;
        // `value` is the amount of tokens at a specific block number
        uint256 value;
    }

    struct CheckPointHistoryState {
        // `checkpoints` is an array that tracks values at non-contiguous block numbers
        CheckPoint[] checkpoints;
        // `checkpoints` before `startIndex` have been deleted
        // INVARIANT: checkpoints.length == 0 || startIndex < checkpoints.length      (strict!)
        uint256 startIndex;
    }

    /**
     * @notice Binary search of _checkpoints array.
     * @param _checkpoints An array of CheckPoint to search.
     * @param _startIndex Smallest possible index to be returned.
     * @param _blockNumber The block number to search for.
     */
    function _indexOfGreatestBlockLessThan(
        CheckPoint[] storage _checkpoints, 
        uint256 _startIndex,
        uint256 _blockNumber
    )
        private view 
        returns (uint256 index)
    {
        // Binary search of the value by given block number in the array
        uint256 min = _startIndex;
        uint256 max = _checkpoints.length.sub(1);
        while (max > min) {
            uint256 mid = (max.add(min).add(1)).div(2);
            if (_checkpoints[mid].fromBlock <= _blockNumber) {
                min = mid;
            } else {
                max = mid.sub(1);
            }
        }
        return min;
    }

    /**
     * @notice Queries the value at a specific `_blockNumber`
     * @param _self A CheckPointHistoryState instance to manage.
     * @param _blockNumber The block number of the value active at that time
     * @return _value The value at `_blockNumber`     
     **/
    function valueAt(
        CheckPointHistoryState storage _self, 
        uint256 _blockNumber
    )
        internal view 
        returns (uint256 _value)
    {
        uint256 historyCount = _self.checkpoints.length;

        // No _checkpoints, return 0
        if (historyCount == 0) return 0;

        // Shortcut for the actual value (extra optimized for current block, to save one storage read)
        // historyCount - 1 is safe, since historyCount != 0
        if (_blockNumber >= block.number || _blockNumber >= _self.checkpoints[historyCount - 1].fromBlock) {
            return _self.checkpoints[historyCount - 1].value;
        }
        
        // guard values at start    
        uint256 startIndex = _self.startIndex;
        if (_blockNumber < _self.checkpoints[startIndex].fromBlock) {
            // reading data before `startIndex` is only safe before first cleanup
            require(startIndex == 0, "CheckPointHistory: reading from cleaned-up block");
            return 0;
        }

        // Find the block with number less than or equal to block given
        uint256 index = _indexOfGreatestBlockLessThan(_self.checkpoints, startIndex, _blockNumber);

        return _self.checkpoints[index].value;
    }

    /**
     * @notice Queries the value at `block.number`
     * @param _self A CheckPointHistoryState instance to manage.
     * @return _value The value at `block.number`
     **/
    function valueAtNow(CheckPointHistoryState storage _self) internal view returns (uint256 _value) {
        return valueAt(_self, block.number);
    }

    /**
     * @notice Writes the value at the current block.
     * @param _self A CheckPointHistoryState instance to manage.
     * @param _value Value to write.
     **/
    function writeValue(
        CheckPointHistoryState storage _self, 
        uint256 _value
    )
        internal
    {
        uint256 historyCount = _self.checkpoints.length;
        if (historyCount == 0) {
            // checkpoints array empty, push new CheckPoint
            _self.checkpoints.push(CheckPoint({fromBlock: block.number, value: _value}));
        } else {
            // historyCount - 1 is safe, since historyCount != 0
            CheckPoint storage lastCheckpoint = _self.checkpoints[historyCount - 1];
            uint256 lastBlock = lastCheckpoint.fromBlock;
            // slither-disable-next-line incorrect-equality
            if (block.number == lastBlock) {
                // If last check point is the current block, just update
                lastCheckpoint.value = _value;
            } else {
                // we should never have future blocks in history
                assert (block.number > lastBlock);
                // push new CheckPoint
                _self.checkpoints.push(CheckPoint({fromBlock: block.number, value: _value}));
            }
        }
    }
    
    /**
     * Delete at most `_count` of the oldest checkpoints.
     * At least one checkpoint at or before `_cleanupBlockNumber` will remain 
     * (unless the history was empty to start with).
     */    
    function cleanupOldCheckpoints(
        CheckPointHistoryState storage _self, 
        uint256 _count,
        uint256 _cleanupBlockNumber
    )
        internal
        returns (uint256)
    {
        if (_cleanupBlockNumber == 0) return 0;   // optimization for when cleaning is not enabled
        uint256 length = _self.checkpoints.length;
        if (length == 0) return 0;
        uint256 startIndex = _self.startIndex;
        // length - 1 is safe, since length != 0 (check above)
        uint256 endIndex = Math.min(startIndex.add(_count), length - 1);    // last element can never be deleted
        uint256 index = startIndex;
        // we can delete `checkpoint[index]` while the next checkpoint is at `_cleanupBlockNumber` or before
        while (index < endIndex && _self.checkpoints[index + 1].fromBlock <= _cleanupBlockNumber) {
            delete _self.checkpoints[index];
            index++;
        }
        if (index > startIndex) {   // index is the first not deleted index
            _self.startIndex = index;
        }
        return index - startIndex;  // safe: index >= startIndex at start and then increases
    }
}


// File contracts/token/lib/CheckPointHistoryCache.sol

// 
pragma solidity 0.7.6;


library CheckPointHistoryCache {
    using SafeMath for uint256;
    using CheckPointHistory for CheckPointHistory.CheckPointHistoryState;
    
    struct CacheState {
        // mapping blockNumber => (value + 1)
        mapping(uint256 => uint256) cache;
    }
    
    function valueAt(
        CacheState storage _self,
        CheckPointHistory.CheckPointHistoryState storage _checkPointHistory,
        uint256 _blockNumber
    )
        internal returns (uint256 _value, bool _cacheCreated)
    {
        // is it in cache?
        uint256 cachedValue = _self.cache[_blockNumber];
        if (cachedValue != 0) {
            return (cachedValue - 1, false);    // safe, cachedValue != 0
        }
        // read from _checkPointHistory
        uint256 historyValue = _checkPointHistory.valueAt(_blockNumber);
        _self.cache[_blockNumber] = historyValue.add(1);  // store to cache (add 1 to differentiate from empty)
        return (historyValue, true);
    }
    
    function deleteAt(
        CacheState storage _self,
        uint256 _blockNumber
    )
        internal returns (uint256 _deleted)
    {
        if (_self.cache[_blockNumber] != 0) {
            _self.cache[_blockNumber] = 0;
            return 1;
        }
        return 0;
    }
}


// File contracts/governance/implementation/GovernedBase.sol

// 
pragma solidity 0.7.6;


/**
 * @title Governed Base
 * @notice This abstract base class defines behaviors for a governed contract.
 * @dev This class is abstract so that specific behaviors can be defined for the constructor.
 *   Contracts should not be left ungoverned, but not all contract will have a constructor
 *   (for example those pre-defined in genesis).
 **/
abstract contract GovernedBase {
    address public governance;
    address public proposedGovernance;
    bool private initialised;

    event GovernanceProposed(address proposedGovernance);
    event GovernanceUpdated (address oldGovernance, address newGoveranance);

    modifier onlyGovernance () {
        require (msg.sender == governance, "only governance");
        _;
    }

    constructor(address _governance) {
        if (_governance != address(0)) {
            initialise(_governance);
        }
    }

    /**
     * @notice First of a two step process for turning over governance to another address.
     * @param _governance The address to propose to receive governance role.
     * @dev Must hold governance to propose another address.
     */
    function proposeGovernance(address _governance) external onlyGovernance {
        proposedGovernance = _governance;
        emit GovernanceProposed(_governance);
    }

    /**
     * @notice Once proposed, claimant can claim the governance role as the second of a two-step process.
     */
    function claimGovernance() external {
        require(msg.sender == proposedGovernance, "not claimaint");

        emit GovernanceUpdated(governance, proposedGovernance);
        governance = proposedGovernance;
        proposedGovernance = address(0);
    }

    /**
     * @notice In a one-step process, turn over governance to another address.
     * @dev Must hold governance to transfer.
     */
    function transferGovernance(address _governance) external onlyGovernance {
        emit GovernanceUpdated(governance, _governance);
        governance = _governance;
        proposedGovernance = address(0);
    }

    /**
     * @notice Initialize the governance address if not first initialized.
     */
    function initialise(address _governance) public virtual {
        require(initialised == false, "initialised != false");

        initialised = true;
        emit GovernanceUpdated(governance, _governance);
        governance = _governance;
        proposedGovernance = address(0);
    }
}


// File contracts/governance/implementation/Governed.sol

// 
pragma solidity 0.7.6;

/**
 * @title Governed
 * @dev For deployed, governed contracts, enforce a non-zero address at create time.
 **/
contract Governed is GovernedBase {
    constructor(address _governance) GovernedBase(_governance) {
        require(_governance != address(0), "_governance zero");
    }
}


// File contracts/inflation/implementation/Supply.sol

// 
pragma solidity 0.7.6;






/**
 * @title Supply contract
 * @notice This contract maintains and computes various native token supply totals.
 **/

contract Supply is Governed, IISupply {
    using CheckPointHistory for CheckPointHistory.CheckPointHistoryState;
    using CheckPointHistoryCache for CheckPointHistoryCache.CacheState;
    using SafeMath for uint256;

    struct SupplyData {
        IITokenPool tokenPool;
        uint256 foundationAllocatedFundsWei;
        uint256 totalInflationAuthorizedWei;
        uint256 totalClaimedWei;
    }

    string internal constant ERR_INFLATION_ONLY = "inflation only";
    string internal constant ERR_INFLATION_ZERO = "inflation zero";
    string internal constant ERR_TOKEN_POOL_ALREADY_ADDED = "token pool already added";
    string internal constant ERR_INITIAL_GENESIS_AMOUNT_ZERO = "initial genesis amount zero";

    CheckPointHistory.CheckPointHistoryState private circulatingSupplyWei;
    CheckPointHistoryCache.CacheState private circulatingSupplyWeiCache;

    uint256 immutable public initialGenesisAmountWei;
    uint256 public totalInflationAuthorizedWei;
    uint256 public totalFoundationSupplyWei;
    uint256 public distributedFoundationSupplyWei;

    SupplyData[] public tokenPools;

    address public inflation;
    address public burnAddress;

    // balance of burn address at last check - needed for updating circulating supply
    uint256 private burnAddressBalance;

    // events
    event AuthorizedInflationUpdateError(uint256 actual, uint256 expected);

    modifier onlyInflation {
        require(msg.sender == inflation, ERR_INFLATION_ONLY);
        _;
    }

    constructor(
        address _governance,
        address _burnAddress,
        address _inflation,
        uint256 _initialGenesisAmountWei,
        uint256 _totalFoundationSupplyWei,
        IITokenPool[] memory _tokenPools
    )
        Governed(_governance)
    {
        require(_inflation != address(0), ERR_INFLATION_ZERO);
        require(_initialGenesisAmountWei > 0, ERR_INITIAL_GENESIS_AMOUNT_ZERO);
        burnAddress = _burnAddress;
        inflation = _inflation;
        initialGenesisAmountWei = _initialGenesisAmountWei;
        totalFoundationSupplyWei = _totalFoundationSupplyWei;

        _increaseCirculatingSupply(_initialGenesisAmountWei.sub(_totalFoundationSupplyWei));

        for (uint256 i = 0; i < _tokenPools.length; i++) {
            _addTokenPool(_tokenPools[i]);
        }

        _updateCirculatingSupply();
    }

    /**
     * @notice Updates authorized inflation and circulating supply - emits event if error
     * @param _inflationAuthorizedWei               Authorized inflation
     * @dev Also updates the burn address amount
    */
    function updateAuthorizedInflationAndCirculatingSupply(
            uint256 _inflationAuthorizedWei
    )
        external override
        onlyInflation 
    {
        // Save old total inflation authorized value to compare with after update.
        uint256 oldTotalInflationAuthorizedWei = totalInflationAuthorizedWei;
        
        _updateCirculatingSupply();
        
        // Check if new authorized inflation was distributed and updated correctly.
        if (totalInflationAuthorizedWei != oldTotalInflationAuthorizedWei.add(_inflationAuthorizedWei)) {
            emit AuthorizedInflationUpdateError(totalInflationAuthorizedWei - oldTotalInflationAuthorizedWei,
                _inflationAuthorizedWei);
        }
    }

    /**
     * @notice Sets inflation contract. Only governance can call this method.
     */
    function setInflation(address _inflation) external override onlyGovernance {
        require(_inflation != address(0), ERR_INFLATION_ZERO);
        inflation = _inflation;
    }

    /**
     * @notice Adds token pool so it can call updateTokenPoolDistributedAmount method when 
        some tokens are distributed
     * @param _tokenPool                            Token pool address
     * @param _decreaseFoundationSupplyByAmountWei  If token pool was given initial supply from fundation supply, 
        decrease it's value by this amount
     */
    function addTokenPool(
        IITokenPool _tokenPool,
        uint256 _decreaseFoundationSupplyByAmountWei
    )
        external
        onlyGovernance
    {
        _decreaseFoundationSupply(_decreaseFoundationSupplyByAmountWei);
        _addTokenPool(_tokenPool);
        _updateCirculatingSupply();
    }

    /**
     * @notice Decrease foundation supply when foundation funds are released to a token pool or team members
     * @param _amountWei                            Amount to decrease by
     */
    function decreaseFoundationSupply(uint256 _amountWei) external onlyGovernance {
        _decreaseFoundationSupply(_amountWei);
        _updateCirculatingSupply();
    }

    /**
     * @notice Change burn address
     * @param _burnAddress                          New burn address
     * @dev Updates burn value for current address, changes to new address and updates again
     */
    function changeBurnAddress(address _burnAddress) external onlyGovernance {
        _updateCirculatingSupply();
        burnAddressBalance = 0;
        burnAddress = _burnAddress;
        _updateBurnAddressAmount();
    }
    
    /**
     * @notice Get approximate circulating supply for given block number from cache - only past block
     * @param _blockNumber                          Block number
     * @return _circulatingSupplyWei Return approximate circulating supply for last known block <= _blockNumber
    */
    function getCirculatingSupplyAtCached(
        uint256 _blockNumber
    )
        external override 
        returns(uint256 _circulatingSupplyWei)
    {
        // use cache only for the past (the value will never change)
        require(_blockNumber < block.number, "Can only be used for past blocks");
        (_circulatingSupplyWei,) = circulatingSupplyWeiCache.valueAt(circulatingSupplyWei, _blockNumber);
    }

    /**
     * @notice Get approximate circulating supply for given block number
     * @param _blockNumber                          Block number
     * @return _circulatingSupplyWei Return approximate circulating supply for last known block <= _blockNumber
    */
    function getCirculatingSupplyAt(
        uint256 _blockNumber
    )
        external view override 
        returns(uint256 _circulatingSupplyWei)
    {
        return circulatingSupplyWei.valueAt(_blockNumber);
    }

    /**
     * @notice Get total inflatable balance (initial genesis amount + total authorized inflation)
     * @return _inflatableBalanceWei Return inflatable balance
    */
    function getInflatableBalance() external view override returns(uint256 _inflatableBalanceWei) {
        return initialGenesisAmountWei.add(totalInflationAuthorizedWei);
    }

    function _increaseCirculatingSupply(uint256 _increaseBy) internal {
        circulatingSupplyWei.writeValue(circulatingSupplyWei.valueAtNow().add(_increaseBy));
    }

    function _decreaseCirculatingSupply(uint256 _descreaseBy) internal {
        circulatingSupplyWei.writeValue(circulatingSupplyWei.valueAtNow().sub(_descreaseBy));
    }

    function _updateCirculatingSupply() internal {
        uint256 len = tokenPools.length;
        for (uint256 i = 0; i < len; i++) {
            SupplyData storage data = tokenPools[i];

            uint256 newFoundationAllocatedFundsWei;
            uint256 newTotalInflationAuthorizedWei;
            uint256 newTotalClaimedWei;
            
            (newFoundationAllocatedFundsWei, newTotalInflationAuthorizedWei, newTotalClaimedWei) = 
                data.tokenPool.getTokenPoolSupplyData();
            assert(newFoundationAllocatedFundsWei.add(newTotalInflationAuthorizedWei) >= newTotalClaimedWei);
            
            // updates total inflation authorized with daily authorized inflation
            uint256 dailyInflationAuthorizedWei = newTotalInflationAuthorizedWei.sub(data.totalInflationAuthorizedWei);
            totalInflationAuthorizedWei = totalInflationAuthorizedWei.add(dailyInflationAuthorizedWei);

            // updates circulating supply
            _decreaseCirculatingSupply(newFoundationAllocatedFundsWei.sub(data.foundationAllocatedFundsWei));
            _increaseCirculatingSupply(newTotalClaimedWei.sub(data.totalClaimedWei));

            // update data
            data.foundationAllocatedFundsWei = newFoundationAllocatedFundsWei;
            data.totalInflationAuthorizedWei = newTotalInflationAuthorizedWei;
            data.totalClaimedWei = newTotalClaimedWei;
        }

        _updateBurnAddressAmount();
    }

    function _updateBurnAddressAmount() internal {
        uint256 newBalance = burnAddress.balance;
        _decreaseCirculatingSupply(newBalance.sub(burnAddressBalance));
        burnAddressBalance = newBalance;
    }

    function _addTokenPool(IITokenPool _tokenPool) internal {
        uint256 len = tokenPools.length;
        for (uint256 i = 0; i < len; i++) {
            if (_tokenPool == tokenPools[i].tokenPool) {
                revert(ERR_TOKEN_POOL_ALREADY_ADDED);
            }
        }
        tokenPools.push();
        tokenPools[len].tokenPool = _tokenPool;
    }
    
    function _decreaseFoundationSupply(uint256 _amountWei) internal {
        assert(totalFoundationSupplyWei.sub(distributedFoundationSupplyWei) >= _amountWei);
        _increaseCirculatingSupply(_amountWei);
        distributedFoundationSupplyWei = distributedFoundationSupplyWei.add(_amountWei);
    }
}
        

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_governance","internalType":"address"},{"type":"address","name":"_burnAddress","internalType":"address"},{"type":"address","name":"_inflation","internalType":"address"},{"type":"uint256","name":"_initialGenesisAmountWei","internalType":"uint256"},{"type":"uint256","name":"_totalFoundationSupplyWei","internalType":"uint256"},{"type":"address[]","name":"_tokenPools","internalType":"contract IITokenPool[]"}]},{"type":"event","name":"AuthorizedInflationUpdateError","inputs":[{"type":"uint256","name":"actual","internalType":"uint256","indexed":false},{"type":"uint256","name":"expected","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"GovernanceProposed","inputs":[{"type":"address","name":"proposedGovernance","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"GovernanceUpdated","inputs":[{"type":"address","name":"oldGovernance","internalType":"address","indexed":false},{"type":"address","name":"newGoveranance","internalType":"address","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addTokenPool","inputs":[{"type":"address","name":"_tokenPool","internalType":"contract IITokenPool"},{"type":"uint256","name":"_decreaseFoundationSupplyByAmountWei","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"burnAddress","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeBurnAddress","inputs":[{"type":"address","name":"_burnAddress","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"claimGovernance","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"decreaseFoundationSupply","inputs":[{"type":"uint256","name":"_amountWei","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"distributedFoundationSupplyWei","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"_circulatingSupplyWei","internalType":"uint256"}],"name":"getCirculatingSupplyAt","inputs":[{"type":"uint256","name":"_blockNumber","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"_circulatingSupplyWei","internalType":"uint256"}],"name":"getCirculatingSupplyAtCached","inputs":[{"type":"uint256","name":"_blockNumber","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"_inflatableBalanceWei","internalType":"uint256"}],"name":"getInflatableBalance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"governance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"inflation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"initialGenesisAmountWei","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialise","inputs":[{"type":"address","name":"_governance","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"proposeGovernance","inputs":[{"type":"address","name":"_governance","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"proposedGovernance","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setInflation","inputs":[{"type":"address","name":"_inflation","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"tokenPool","internalType":"contract IITokenPool"},{"type":"uint256","name":"foundationAllocatedFundsWei","internalType":"uint256"},{"type":"uint256","name":"totalInflationAuthorizedWei","internalType":"uint256"},{"type":"uint256","name":"totalClaimedWei","internalType":"uint256"}],"name":"tokenPools","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalFoundationSupplyWei","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalInflationAuthorizedWei","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferGovernance","inputs":[{"type":"address","name":"_governance","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateAuthorizedInflationAndCirculatingSupply","inputs":[{"type":"uint256","name":"_inflationAuthorizedWei","internalType":"uint256"}]}]
              

Contract Creation Code

0x60a06040523480156200001157600080fd5b5060405162001e9638038062001e96833981810160405260c08110156200003757600080fd5b815160208301516040808501516060860151608087015160a0880180519451969895979396929591949293820192846401000000008211156200007957600080fd5b9083019060208201858111156200008f57600080fd5b8251866020820283011164010000000082111715620000ad57600080fd5b82525081516020918201928201910280838360005b83811015620000dc578181015183820152602001620000c2565b50505050905001604052505050858060006001600160a01b0316816001600160a01b0316146200011157620001118162000352565b506001600160a01b03811662000161576040805162461bcd60e51b815260206004820152601060248201526f5f676f7665726e616e6365207a65726f60801b604482015290519081900360640190fd5b5060408051808201909152600e81526d696e666c6174696f6e207a65726f60901b60208201526001600160a01b0385166200021d5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015620001e1578181015183820152602001620001c7565b50505050905090810190601f1680156200020f5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060408051808201909152601b81527f696e697469616c2067656e6573697320616d6f756e74207a65726f0000000000602082015283620002a15760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315620001e1578181015183820152602001620001c7565b50600a80546001600160a01b03199081166001600160a01b0388811691909117909255600980549091169186169190911790556080839052600682905562000300620002fa848462000436602090811b62000b3617901c565b62000499565b60005b81518110156200033b57620003328282815181106200031e57fe5b6020026020010151620004e660201b60201c565b60010162000303565b5062000346620005fb565b50505050505062000ba9565b600154600160a01b900460ff1615620003b2576040805162461bcd60e51b815260206004820152601460248201527f696e697469616c6973656420213d2066616c7365000000000000000000000000604482015290519081900360640190fd5b6001805460ff60a01b1916600160a01b179055600054604080516001600160a01b039283168152918316602083015280517f434a2db650703b36c824e745330d6397cdaa9ee2cc891a4938ae853e1c50b68d9281900390910190a1600080546001600160a01b039092166001600160a01b0319928316179055600180549091169055565b6000828211156200048e576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b620004e3620004cd82620004b960026200079260201b62000b931760201c565b620007a060201b62000b9f1790919060201c565b60026200080260201b62000c001790919060201c565b50565b60085460005b81811015620005ab57600881815481106200050357fe5b60009182526020909120600490910201546001600160a01b0384811691161415620005a257604080518082018252601881527f746f6b656e20706f6f6c20616c726561647920616464656400000000000000006020808301918252925162461bcd60e51b81526004810193845282516024820152825192939283926044909201919080838360008315620001e1578181015183820152602001620001c7565b600101620004ec565b5060088054600101808255600082905283919083908110620005c957fe5b6000918252602090912060049091020180546001600160a01b0319166001600160a01b03929092169190911790555050565b60085460005b8181101562000787576000600882815481106200061a57fe5b600091825260208220600491820201805460408051632dafdbbf60e01b81529051929550849384936001600160a01b0390931692632dafdbbf928083019260609291829003018186803b1580156200067157600080fd5b505afa15801562000686573d6000803e3d6000fd5b505050506040513d60608110156200069d57600080fd5b50805160208083015160409093015191955091935091508190620006ce908590859062000b9f620007a0821b17901c565b1015620006d757fe5b6000620006f78560020154846200043660201b62000b361790919060201c565b90506200071581600554620007a060201b62000b9f1790919060201c565b600581905550620007436200073d8660010154866200043660201b62000b361790919060201c565b620008d3565b62000765620002fa8660030154846200043660201b62000b361790919060201c565b5060018085019390935560028401919091556003909201919091550162000601565b50620004e362000907565b60006200049382436200093d565b600082820183811015620007fb576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b81548062000848576040805180820190915243815260208082018481528554600181810188556000888152939093209351600290910290930192835551910155620008ce565b60008360000160018303815481106200085d57fe5b60009182526020909120600290910201805490915043811415620008885760018201849055620008cb565b8043116200089257fe5b604080518082019091524381526020808201868152875460018181018a5560008a81529390932093516002909102909301928355519101555b50505b505050565b620004e3620004cd82620008f360026200079260201b62000b931760201c565b6200043660201b62000b361790919060201c565b600a54600b546001600160a01b03909116319062000938906200073d90839062000436602090811b62000b3617901c565b600b55565b8154600090806200095357600091505062000493565b43831015806200098757508360000160018203815481106200097157fe5b9060005260206000209060020201600001548310155b15620009bb57836000016001820381548110620009a057fe5b90600052602060002090600202016001015491505062000493565b60018401548454859082908110620009cf57fe5b90600052602060002090600202016000015484101562000a3457801562000a285760405162461bcd60e51b815260040180806020018281038252603081526020018062001e666030913960400191505060405180910390fd5b60009250505062000493565b600062000a4386838762000a72565b905085600001818154811062000a5557fe5b906000526020600020906002020160010154935050505092915050565b600080839050600062000a99600187805490506200043660201b62000b361790919060201c565b90505b8181111562000b3757600062000ae1600262000acd6001620004b98787620007a060201b62000b9f1790919060201c565b62000b4060201b62000ccb1790919060201c565b90508487828154811062000af157fe5b9060005260206000209060020201600001541162000b125780925062000b30565b62000b2d6001826200043660201b62000b361790919060201c565b91505b5062000a9c565b50949350505050565b600080821162000b97576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838162000ba157fe5b049392505050565b60805161129d62000bc96000398061041e52806107b4525061129d6000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c8063b6aa5b51116100b8578063d0c1c3931161007c578063d0c1c393146102a3578063d38bfff4146102ab578063d9330e63146102d1578063ee323c92146102ee578063ee3d170614610314578063efcf7eb21461033a57610136565b8063b6aa5b5114610248578063be0522e014610265578063bfebbd261461026d578063c373a08e14610275578063cd58d6cb1461029b57610136565b80635d36b190116100ff5780635d36b190146101eb57806360f7ac97146101f557806370d5ae05146101fd5780639d6a890f14610205578063a2420e201461022b57610136565b8062c0f9161461013b578063037b0890146101885780631b73b4cb146101b757806344044ba2146101bf5780635aa6e675146101c7575b600080fd5b6101586004803603602081101561015157600080fd5b5035610366565b604080516001600160a01b0390951685526020850193909352838301919091526060830152519081900360800190f35b6101a56004803603602081101561019e57600080fd5b50356103aa565b60408051918252519081900360200190f35b6101a5610414565b6101a5610450565b6101cf610456565b604080516001600160a01b039092168252519081900360200190f35b6101f3610465565b005b6101cf610527565b6101cf610536565b6101f36004803603602081101561021b57600080fd5b50356001600160a01b0316610545565b6101f36004803603602081101561024157600080fd5b503561061f565b6101f36004803603602081101561025e57600080fd5b503561073e565b6101cf6107a3565b6101a56107b2565b6101f36004803603602081101561028b57600080fd5b50356001600160a01b03166107d6565b6101a561087b565b6101a5610881565b6101f3600480360360208110156102c157600080fd5b50356001600160a01b0316610887565b6101a5600480360360208110156102e757600080fd5b5035610949565b6101f36004803603602081101561030457600080fd5b50356001600160a01b031661095c565b6101f36004803603602081101561032a57600080fd5b50356001600160a01b0316610a4a565b6101f36004803603604081101561035057600080fd5b506001600160a01b038135169060200135610acb565b6008818154811061037657600080fd5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b039092169350919084565b6000438210610400576040805162461bcd60e51b815260206004820181905260248201527f43616e206f6e6c79206265207573656420666f72207061737420626c6f636b73604482015290519081900360640190fd5b61040d6004600284610d32565b5092915050565b600061044b6005547f0000000000000000000000000000000000000000000000000000000000000000610b9f90919063ffffffff16565b905090565b60075481565b6000546001600160a01b031681565b6001546001600160a01b031633146104b4576040805162461bcd60e51b815260206004820152600d60248201526c1b9bdd0818db185a5b585a5b9d609a1b604482015290519081900360640190fd5b600054600154604080516001600160a01b03938416815292909116602083015280517f434a2db650703b36c824e745330d6397cdaa9ee2cc891a4938ae853e1c50b68d9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b6001546001600160a01b031681565b600a546001600160a01b031681565b600154600160a01b900460ff161561059b576040805162461bcd60e51b8152602060048201526014602482015273696e697469616c6973656420213d2066616c736560601b604482015290519081900360640190fd5b6001805460ff60a01b1916600160a01b179055600054604080516001600160a01b039283168152918316602083015280517f434a2db650703b36c824e745330d6397cdaa9ee2cc891a4938ae853e1c50b68d9281900390910190a1600080546001600160a01b039092166001600160a01b0319928316179055600180549091169055565b60095460408051808201909152600e81526d696e666c6174696f6e206f6e6c7960901b6020820152906001600160a01b031633146106db5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156106a0578181015183820152602001610688565b50505050905090810190601f1680156106cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506005546106e7610d90565b6106f18183610b9f565b6005541461073a57600554604080519183900382526020820184905280517feeb8970a03ae6e5930263b6b2553da66b8e20080d79a3f33c139e5855574eb739281900390910190a15b5050565b6000546001600160a01b0316331461078f576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b604482015290519081900360640190fd5b61079881610ee4565b6107a0610d90565b50565b6009546001600160a01b031681565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000546001600160a01b03163314610827576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b604482015290519081900360640190fd5b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f1f95fb40be3a947982072902a887b521248d1d8931a39eb38f84f4d6fd758b699181900360200190a150565b60065481565b60055481565b6000546001600160a01b031633146108d8576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b604482015290519081900360640190fd5b600054604080516001600160a01b039283168152918316602083015280517f434a2db650703b36c824e745330d6397cdaa9ee2cc891a4938ae853e1c50b68d9281900390910190a1600080546001600160a01b039092166001600160a01b0319928316179055600180549091169055565b6000610956600283610f20565b92915050565b6000546001600160a01b031633146109ad576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b604482015290519081900360640190fd5b60408051808201909152600e81526d696e666c6174696f6e207a65726f60901b60208201526001600160a01b038216610a275760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156106a0578181015183820152602001610688565b50600980546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610a9b576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b604482015290519081900360640190fd5b610aa3610d90565b6000600b55600a80546001600160a01b0319166001600160a01b0383161790556107a0611046565b6000546001600160a01b03163314610b1c576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b604482015290519081900360640190fd5b610b2581610ee4565b610b2e8261106d565b61073a610d90565b600082821115610b8d576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60006109568243610f20565b600082820183811015610bf9576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b815480610c44576040805180820190915243815260208082018481528554600181810188556000888152939093209351600290910290930192835551910155610cc6565b6000836000016001830381548110610c5857fe5b60009182526020909120600290910201805490915043811415610c815760018201849055610cc3565b804311610c8a57fe5b604080518082019091524381526020808201868152875460018181018a5560008a81529390932093516002909102909301928355519101555b50505b505050565b6000808211610d21576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381610d2a57fe5b049392505050565b60008181526020849052604081205481908015610d585760001901915060009050610d88565b6000610d648686610f20565b9050610d71816001610b9f565b600086815260208990526040902055925060019150505b935093915050565b60085460005b81811015610edb57600060088281548110610dad57fe5b600091825260208220600491820201805460408051632dafdbbf60e01b81529051929550849384936001600160a01b0390931692632dafdbbf928083019260609291829003018186803b158015610e0357600080fd5b505afa158015610e17573d6000803e3d6000fd5b505050506040513d6060811015610e2d57600080fd5b5080516020820151604090920151909450909250905080610e4e8484610b9f565b1015610e5657fe5b6000610e6f856002015484610b3690919063ffffffff16565b600554909150610e7f9082610b9f565b6005556001850154610e9b90610e96908690610b36565b61117b565b610eba610eb5866003015484610b3690919063ffffffff16565b61119a565b50600180850193909355600284019190915560039092019190915501610d96565b506107a0611046565b80610efc600754600654610b3690919063ffffffff16565b1015610f0457fe5b610f0d8161119a565b600754610f1a9082610b9f565b60075550565b815460009080610f34576000915050610956565b4383101580610f665750836000016001820381548110610f5057fe5b9060005260206000209060020201600001548310155b15610f9757836000016001820381548110610f7d57fe5b906000526020600020906002020160010154915050610956565b60018401548454859082908110610faa57fe5b90600052602060002090600202016000015484101561100b5780156110005760405162461bcd60e51b81526004018080602001828103825260308152602001806112386030913960400191505060405180910390fd5b600092505050610956565b60006110188683876111b1565b905085600001818154811061102957fe5b906000526020600020906002020160010154935050505092915050565b600a54600b546001600160a01b03909116319061106890610e96908390610b36565b600b55565b60085460005b8181101561112c576008818154811061108857fe5b60009182526020909120600490910201546001600160a01b038481169116141561112457604080518082018252601881527f746f6b656e20706f6f6c20616c726561647920616464656400000000000000006020808301918252925162461bcd60e51b815260048101938452825160248201528251929392839260449092019190808383600083156106a0578181015183820152602001610688565b600101611073565b506008805460010180825560008290528391908390811061114957fe5b6000918252602090912060049091020180546001600160a01b0319166001600160a01b03929092169190911790555050565b6107a06111928261118c6002610b93565b90610b36565b600290610c00565b6107a0611192826111ab6002610b93565b90610b9f565b8254600090839082906111c5906001610b36565b90505b8181111561122e5760006111ec60026111e660016111ab8688610b9f565b90610ccb565b9050848782815481106111fb57fe5b9060005260206000209060020201600001541161121a57809250611228565b611225816001610b36565b91505b506111c8565b5094935050505056fe436865636b506f696e74486973746f72793a2072656164696e672066726f6d20636c65616e65642d757020626c6f636ba26469706673582212207ea7f6ed9054fc53987dcc665c8bf98ee2c0df3d172620109a696588d08b892364736f6c63430007060033436865636b506f696e74486973746f72793a2072656164696e672066726f6d20636c65616e65642d757020626c6f636b000000000000000000000000493044fbbaa7f9f78379864fa88accaff6a7586e000000000000000000000000010000000000000000000000000000000000000000000000000000000000000087e80e90eaca1d458dfdf60a9d697e7e83ab02b200000000000000000000000000000000000000003077b58d5d378391980000000000000000000000000000000000000000000000121594259bea5565a8bc000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106101365760003560e01c8063b6aa5b51116100b8578063d0c1c3931161007c578063d0c1c393146102a3578063d38bfff4146102ab578063d9330e63146102d1578063ee323c92146102ee578063ee3d170614610314578063efcf7eb21461033a57610136565b8063b6aa5b5114610248578063be0522e014610265578063bfebbd261461026d578063c373a08e14610275578063cd58d6cb1461029b57610136565b80635d36b190116100ff5780635d36b190146101eb57806360f7ac97146101f557806370d5ae05146101fd5780639d6a890f14610205578063a2420e201461022b57610136565b8062c0f9161461013b578063037b0890146101885780631b73b4cb146101b757806344044ba2146101bf5780635aa6e675146101c7575b600080fd5b6101586004803603602081101561015157600080fd5b5035610366565b604080516001600160a01b0390951685526020850193909352838301919091526060830152519081900360800190f35b6101a56004803603602081101561019e57600080fd5b50356103aa565b60408051918252519081900360200190f35b6101a5610414565b6101a5610450565b6101cf610456565b604080516001600160a01b039092168252519081900360200190f35b6101f3610465565b005b6101cf610527565b6101cf610536565b6101f36004803603602081101561021b57600080fd5b50356001600160a01b0316610545565b6101f36004803603602081101561024157600080fd5b503561061f565b6101f36004803603602081101561025e57600080fd5b503561073e565b6101cf6107a3565b6101a56107b2565b6101f36004803603602081101561028b57600080fd5b50356001600160a01b03166107d6565b6101a561087b565b6101a5610881565b6101f3600480360360208110156102c157600080fd5b50356001600160a01b0316610887565b6101a5600480360360208110156102e757600080fd5b5035610949565b6101f36004803603602081101561030457600080fd5b50356001600160a01b031661095c565b6101f36004803603602081101561032a57600080fd5b50356001600160a01b0316610a4a565b6101f36004803603604081101561035057600080fd5b506001600160a01b038135169060200135610acb565b6008818154811061037657600080fd5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b039092169350919084565b6000438210610400576040805162461bcd60e51b815260206004820181905260248201527f43616e206f6e6c79206265207573656420666f72207061737420626c6f636b73604482015290519081900360640190fd5b61040d6004600284610d32565b5092915050565b600061044b6005547f00000000000000000000000000000000000000003077b58d5d37839198000000610b9f90919063ffffffff16565b905090565b60075481565b6000546001600160a01b031681565b6001546001600160a01b031633146104b4576040805162461bcd60e51b815260206004820152600d60248201526c1b9bdd0818db185a5b585a5b9d609a1b604482015290519081900360640190fd5b600054600154604080516001600160a01b03938416815292909116602083015280517f434a2db650703b36c824e745330d6397cdaa9ee2cc891a4938ae853e1c50b68d9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b6001546001600160a01b031681565b600a546001600160a01b031681565b600154600160a01b900460ff161561059b576040805162461bcd60e51b8152602060048201526014602482015273696e697469616c6973656420213d2066616c736560601b604482015290519081900360640190fd5b6001805460ff60a01b1916600160a01b179055600054604080516001600160a01b039283168152918316602083015280517f434a2db650703b36c824e745330d6397cdaa9ee2cc891a4938ae853e1c50b68d9281900390910190a1600080546001600160a01b039092166001600160a01b0319928316179055600180549091169055565b60095460408051808201909152600e81526d696e666c6174696f6e206f6e6c7960901b6020820152906001600160a01b031633146106db5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156106a0578181015183820152602001610688565b50505050905090810190601f1680156106cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506005546106e7610d90565b6106f18183610b9f565b6005541461073a57600554604080519183900382526020820184905280517feeb8970a03ae6e5930263b6b2553da66b8e20080d79a3f33c139e5855574eb739281900390910190a15b5050565b6000546001600160a01b0316331461078f576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b604482015290519081900360640190fd5b61079881610ee4565b6107a0610d90565b50565b6009546001600160a01b031681565b7f00000000000000000000000000000000000000003077b58d5d3783919800000081565b6000546001600160a01b03163314610827576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b604482015290519081900360640190fd5b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f1f95fb40be3a947982072902a887b521248d1d8931a39eb38f84f4d6fd758b699181900360200190a150565b60065481565b60055481565b6000546001600160a01b031633146108d8576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b604482015290519081900360640190fd5b600054604080516001600160a01b039283168152918316602083015280517f434a2db650703b36c824e745330d6397cdaa9ee2cc891a4938ae853e1c50b68d9281900390910190a1600080546001600160a01b039092166001600160a01b0319928316179055600180549091169055565b6000610956600283610f20565b92915050565b6000546001600160a01b031633146109ad576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b604482015290519081900360640190fd5b60408051808201909152600e81526d696e666c6174696f6e207a65726f60901b60208201526001600160a01b038216610a275760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156106a0578181015183820152602001610688565b50600980546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610a9b576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b604482015290519081900360640190fd5b610aa3610d90565b6000600b55600a80546001600160a01b0319166001600160a01b0383161790556107a0611046565b6000546001600160a01b03163314610b1c576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b604482015290519081900360640190fd5b610b2581610ee4565b610b2e8261106d565b61073a610d90565b600082821115610b8d576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60006109568243610f20565b600082820183811015610bf9576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b815480610c44576040805180820190915243815260208082018481528554600181810188556000888152939093209351600290910290930192835551910155610cc6565b6000836000016001830381548110610c5857fe5b60009182526020909120600290910201805490915043811415610c815760018201849055610cc3565b804311610c8a57fe5b604080518082019091524381526020808201868152875460018181018a5560008a81529390932093516002909102909301928355519101555b50505b505050565b6000808211610d21576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381610d2a57fe5b049392505050565b60008181526020849052604081205481908015610d585760001901915060009050610d88565b6000610d648686610f20565b9050610d71816001610b9f565b600086815260208990526040902055925060019150505b935093915050565b60085460005b81811015610edb57600060088281548110610dad57fe5b600091825260208220600491820201805460408051632dafdbbf60e01b81529051929550849384936001600160a01b0390931692632dafdbbf928083019260609291829003018186803b158015610e0357600080fd5b505afa158015610e17573d6000803e3d6000fd5b505050506040513d6060811015610e2d57600080fd5b5080516020820151604090920151909450909250905080610e4e8484610b9f565b1015610e5657fe5b6000610e6f856002015484610b3690919063ffffffff16565b600554909150610e7f9082610b9f565b6005556001850154610e9b90610e96908690610b36565b61117b565b610eba610eb5866003015484610b3690919063ffffffff16565b61119a565b50600180850193909355600284019190915560039092019190915501610d96565b506107a0611046565b80610efc600754600654610b3690919063ffffffff16565b1015610f0457fe5b610f0d8161119a565b600754610f1a9082610b9f565b60075550565b815460009080610f34576000915050610956565b4383101580610f665750836000016001820381548110610f5057fe5b9060005260206000209060020201600001548310155b15610f9757836000016001820381548110610f7d57fe5b906000526020600020906002020160010154915050610956565b60018401548454859082908110610faa57fe5b90600052602060002090600202016000015484101561100b5780156110005760405162461bcd60e51b81526004018080602001828103825260308152602001806112386030913960400191505060405180910390fd5b600092505050610956565b60006110188683876111b1565b905085600001818154811061102957fe5b906000526020600020906002020160010154935050505092915050565b600a54600b546001600160a01b03909116319061106890610e96908390610b36565b600b55565b60085460005b8181101561112c576008818154811061108857fe5b60009182526020909120600490910201546001600160a01b038481169116141561112457604080518082018252601881527f746f6b656e20706f6f6c20616c726561647920616464656400000000000000006020808301918252925162461bcd60e51b815260048101938452825160248201528251929392839260449092019190808383600083156106a0578181015183820152602001610688565b600101611073565b506008805460010180825560008290528391908390811061114957fe5b6000918252602090912060049091020180546001600160a01b0319166001600160a01b03929092169190911790555050565b6107a06111928261118c6002610b93565b90610b36565b600290610c00565b6107a0611192826111ab6002610b93565b90610b9f565b8254600090839082906111c5906001610b36565b90505b8181111561122e5760006111ec60026111e660016111ab8688610b9f565b90610ccb565b9050848782815481106111fb57fe5b9060005260206000209060020201600001541161121a57809250611228565b611225816001610b36565b91505b506111c8565b5094935050505056fe436865636b506f696e74486973746f72793a2072656164696e672066726f6d20636c65616e65642d757020626c6f636ba26469706673582212207ea7f6ed9054fc53987dcc665c8bf98ee2c0df3d172620109a696588d08b892364736f6c63430007060033