Contract 0xfa1FBb8Ef55A4855E5688C0eE13aC3f202486286 7

Txn Hash Method
Block
From
To
Value [Txn Fee]
0x2d39c6da3478588f7811dc09e55027feea18f98a3063b32f18724385f0ad876bApprove43612402023-06-01 0:54:244 days 19 hrs ago0x0e57959fd12620b96abdee5bfd6bb0c052688569 IN  FantOHM: FHM Token0 MOVR0.00006653625
0x686cb7f4f485615ca8b841ce6e70b9df657dbf02fb563b40746749774002c480Approve43522522023-05-30 18:24:126 days 1 hr ago0xad5b1332faa1765f1d1e9f3b326a3c1ac2692f8b IN  FantOHM: FHM Token0 MOVR0.000070082632
0x4ee74b84d7e1fa1fbd490ce76c02437fc5edeb6ec838ebeeab3dc21a6fb1912dApprove43522522023-05-30 18:24:126 days 1 hr ago0xad5b1332faa1765f1d1e9f3b326a3c1ac2692f8b IN  FantOHM: FHM Token0 MOVR0.000070082632
0x98d88baf0ab5831664dcfee0d67890380a7ba360821ca4590a05a8564a432948Approve42280982023-05-12 18:24:1824 days 1 hr ago0x83751d420f438e588261ece6b048c40ee6eb7a47 IN  FantOHM: FHM Token0 MOVR0.000067746
0xfe98e68d2b29c9b056ee3df280bc09943cb48bba05dd16f10d108f3ce1d602b2Approve41604762023-05-02 18:55:1834 days 59 mins ago0xceb2699242dc52f8dcd2cfdf8892dc87c150784d IN  FantOHM: FHM Token0 MOVR0.00005770875
0xb80c04d91a9e0d8992fbd28b4321a5807bdd41e35c2081458434cca13225ab28Approve41000502023-04-23 22:19:0242 days 21 hrs ago0x310854c4d95818ee4f9c96a0988b9a4018e73836 IN  FantOHM: FHM Token0 MOVR0.000036673
0x290d434b3bc3d31371d5c9ee8a5d3fdaeddef28851cfe9bfe024349656a49815Approve41000482023-04-23 22:18:3642 days 21 hrs ago0x310854c4d95818ee4f9c96a0988b9a4018e73836 IN  FantOHM: FHM Token0 MOVR0.000033873
0xcc899a5538b6a15189ec330bf7b4644dacc7916bcb199a1706f4011fa2d0d919Approve40942442023-04-23 2:25:0043 days 17 hrs ago0xc57ea958e33dc87c7c7951774bab9221346ba26f IN  FantOHM: FHM Token0 MOVR0.00003024375
0x58674520761add0d35103044cc2207dbe99eeca6a65d0843150893253cda0d44Approve40942422023-04-23 2:24:3043 days 17 hrs ago0xc57ea958e33dc87c7c7951774bab9221346ba26f IN  FantOHM: FHM Token0 MOVR0.00003024375
0x0aee4de81bcf695321df0e1f7692c2a86bbb22cde7b4f483c1c220fe95d6dd98Approve40547092023-04-17 10:20:4849 days 9 hrs ago0xd343779588d5da8fa676732d046ddcb45a375a69 IN  FantOHM: FHM Token0 MOVR0.0001154175
0xa8d948034be38b6268cead1a0145a5040690eaf2db8953b37e30db0173ef86ceApprove40530202023-04-17 4:32:2449 days 15 hrs ago0x0dec46595b67b564c9ccdd414eaaab6b92d187f2 IN  FantOHM: FHM Token0 MOVR0.00012695925
0xc62f69b57139eabf0030764c93953ea90be0e667034615208f9dd61b7bb36b73Approve40400952023-04-15 7:57:2551 days 11 hrs ago0x510355b72b28eb16209386d023ea1b8d17f507d3 IN  FantOHM: FHM Token0 MOVR0.00012695925
0xd58b1afdc29a1beae04377a3c4955a130da629f32a922db94102a8e7097eec26Approve40006012023-04-09 16:40:3057 days 3 hrs ago0x4f2ae05949670c5c59959f2c2da1d4574acdf8b1 IN  FantOHM: FHM Token0 MOVR0.00006653625
0x0b4e381f32fb1e4bdcafdb96673d18aee5781076c70904659764411ae1380237Approve39998942023-04-09 14:14:1257 days 5 hrs ago0x40b12e2c7bc85b5c8c79ae6fd51c6af2767f7575 IN  FantOHM: FHM Token0 MOVR0.00006653625
0xdce3196ab83ba61212db0a87b6a898b04446bb4c02b4ac634177bf60de2810fbApprove39998912023-04-09 14:13:3657 days 5 hrs ago0x40b12e2c7bc85b5c8c79ae6fd51c6af2767f7575 IN  FantOHM: FHM Token0 MOVR0.00006653625
0x5eabeec111801022ad4d82b699910492df77a44287beadc9d8f8ade0716ae669Approve39690022023-04-05 3:39:0161 days 16 hrs ago0x23c1d3fbabe9df15f7e2092fcdd794189ef8c7ce IN  FantOHM: FHM Token0 MOVR0.00012689325
0xdfb5ee496976b045eae7fe55df83b59e711a24712501ba84f4d7028c83868c10Approve39601092023-04-03 20:16:3762 days 23 hrs ago0x899acbd2956cb05c8753d4aec05d68c9cee08a20 IN  FantOHM: FHM Token0 MOVR0.00012695925
0x4c7ae7b45b692b44024916cd559bf8187751ad1a12a7f67b941edc9e9fea65b4Approve39587182023-04-03 15:23:4263 days 4 hrs ago0x2b0326ce60de406a3efcb681d15d181a797c6059 IN  FantOHM: FHM Token0 MOVR0.00009231
0x646afe8819434ce392b26708a837ebb9e9ef746f23a9f4a89369c217abc26b7dApprove39582462023-04-03 13:45:1863 days 6 hrs ago0x899acbd2956cb05c8753d4aec05d68c9cee08a20 IN  FantOHM: FHM Token0 MOVR0.00012695925
0x04943bbcbefe88379b403dd6180dc8e177956cb721c1d226124cb8548fd6eaccApprove39576452023-04-03 11:39:2463 days 8 hrs ago0x237b008e6472f65fd7a34d93ff265f47a2a0d8fb IN  FantOHM: FHM Token0 MOVR0.0000976059
0xe6feee078cfb933f626b57b9bcd11672a2fecd6d2cef35c37a5c5c5c3a2b8f04Approve39564072023-04-03 7:17:0063 days 12 hrs ago0x237b008e6472f65fd7a34d93ff265f47a2a0d8fb IN  FantOHM: FHM Token0 MOVR0.0000682942
0xd69ec6a51d2a9b3f83ae2b067e4b816acbbd060e7623a427805673e90cc4ec31Approve39564062023-04-03 7:16:4863 days 12 hrs ago0x237b008e6472f65fd7a34d93ff265f47a2a0d8fb IN  FantOHM: FHM Token0 MOVR0.0001200342
0x49a9f6a8a5f913eaaeb553fde2598b508ee70130e7dd90755e3502d9277cd9bbApprove39394092023-03-31 20:50:1865 days 23 hrs ago0x1118869ea46bd1673e0ac7261e85a2bcfb6764cd IN  FantOHM: FHM Token0 MOVR0.00015105675
0xad388d1c50897e2ffb7b5a8442b200848bec2b5e5bf9ca28120d33058ecd9795Approve39392772023-03-31 20:23:2465 days 23 hrs ago0x1118869ea46bd1673e0ac7261e85a2bcfb6764cd IN  FantOHM: FHM Token0 MOVR0.00015004275
0x45f7221fd2943f45aeaeb23b8c05e77e3aca62b011728d1f48269efa8a4b8b4fApprove39388162023-03-31 18:48:5466 days 1 hr ago0x2b0326ce60de406a3efcb681d15d181a797c6059 IN  FantOHM: FHM Token0 MOVR0.00012692625
[ Download CSV Export 

OVERVIEW

Fantohm is building a community-owned decentralized financial infrastructure to bring more stability and transparency to the world.

Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
FantohmERC20Token

Compiler Version
v0.7.5+commit.eb77ed08

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, GNU AGPLv3 license

Contract Source Code (Solidity)

/**
 *Submitted for verification at moonriver.moonscan.io on 2021-11-26
*/

// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.7.5;

library EnumerableSet {

    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.
    struct Set {
        // Storage of set values
        bytes32[] _values;

        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping (bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) { // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.

            bytes32 lastvalue = set._values[lastIndex];

            // Move the last value to the index where the value to delete is
            set._values[toDeleteIndex] = lastvalue;
            // Update the index for the moved value
            set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        require(set._values.length > index, "EnumerableSet: index out of bounds");
        return set._values[index];
    }

    function _getValues( Set storage set_ ) private view returns ( bytes32[] storage ) {
        return set_._values;
    }

    // TODO needs insert function that maintains order.
    // TODO needs NatSpec documentation comment.
    /**
     * Inserts new value by moving existing value at provided index to end of array and setting provided value at provided index
     */
    function _insert(Set storage set_, uint256 index_, bytes32 valueToInsert_ ) private returns ( bool ) {
        require(  set_._values.length > index_ );
        require( !_contains( set_, valueToInsert_ ), "Remove value you wish to insert if you wish to reorder array." );
        bytes32 existingValue_ = _at( set_, index_ );
        set_._values[index_] = valueToInsert_;
        return _add( set_, existingValue_);
    }

    struct Bytes4Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes4Set storage set, bytes4 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes4Set storage set, bytes4 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes4Set storage set, bytes4 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(Bytes4Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes4Set storage set, uint256 index) internal view returns ( bytes4 ) {
        return bytes4( _at( set._inner, index ) );
    }

    function getValues( Bytes4Set storage set_ ) internal view returns ( bytes4[] memory ) {
        bytes4[] memory bytes4Array_;
        for( uint256 iteration_ = 0; _length( set_._inner ) > iteration_; iteration_++ ) {
            bytes4Array_[iteration_] = bytes4( _at( set_._inner, iteration_ ) );
        }
        return bytes4Array_;
    }

    function insert( Bytes4Set storage set_, uint256 index_, bytes4 valueToInsert_ ) internal returns ( bool ) {
        return _insert( set_._inner, index_, valueToInsert_ );
    }

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes32Set storage set, uint256 index) internal view returns ( bytes32 ) {
        return _at(set._inner, index);
    }

    function getValues( Bytes32Set storage set_ ) internal view returns ( bytes4[] memory ) {
        bytes4[] memory bytes4Array_;

        for( uint256 iteration_ = 0; _length( set_._inner ) >= iteration_; iteration_++ ){
            bytes4Array_[iteration_] = bytes4( at( set_, iteration_ ) );
        }

        return bytes4Array_;
    }

    function insert( Bytes32Set storage set_, uint256 index_, bytes32 valueToInsert_ ) internal returns ( bool ) {
        return _insert( set_._inner, index_, valueToInsert_ );
    }

    // AddressSet
    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(value)));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(value)));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(value)));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint256(_at(set._inner, index)));
    }

    /**
     * TODO Might require explicit conversion of bytes32[] to address[].
     *  Might require iteration.
     */
    function getValues( AddressSet storage set_ ) internal view returns ( address[] memory ) {

        address[] memory addressArray;

        for( uint256 iteration_ = 0; _length(set_._inner) >= iteration_; iteration_++ ){
            addressArray[iteration_] = at( set_, iteration_ );
        }

        return addressArray;
    }

    function insert(AddressSet storage set_, uint256 index_, address valueToInsert_ ) internal returns ( bool ) {
        return _insert( set_._inner, index_, bytes32(uint256(valueToInsert_)) );
    }


    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }

    struct UInt256Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UInt256Set storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UInt256Set storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UInt256Set storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(UInt256Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UInt256Set storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }
}

interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

library SafeMath {

    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {

        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }

    function sqrrt(uint256 a) internal pure returns (uint c) {
        if (a > 3) {
            c = a;
            uint b = add( div( a, 2), 1 );
            while (b < c) {
                c = b;
                b = div( add( div( a, b ), b), 2 );
            }
        } else if (a != 0) {
            c = 1;
        }
    }

    function percentageAmount( uint256 total_, uint8 percentage_ ) internal pure returns ( uint256 percentAmount_ ) {
        return div( mul( total_, percentage_ ), 1000 );
    }

    function substractPercentage( uint256 total_, uint8 percentageToSub_ ) internal pure returns ( uint256 result_ ) {
        return sub( total_, div( mul( total_, percentageToSub_ ), 1000 ) );
    }

    function percentageOfTotal( uint256 part_, uint256 total_ ) internal pure returns ( uint256 percent_ ) {
        return div( mul(part_, 100) , total_ );
    }

    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);
    }

    function quadraticPricing( uint256 payment_, uint256 multiplier_ ) internal pure returns (uint256) {
        return sqrrt( mul( multiplier_, payment_ ) );
    }

    function bondingCurve( uint256 supply_, uint256 multiplier_ ) internal pure returns (uint256) {
        return mul( multiplier_, supply_ );
    }
}

abstract contract ERC20 is IERC20 {

    using SafeMath for uint256;

    // TODO comment actual hash value.
    bytes32 constant private ERC20TOKEN_ERC1820_INTERFACE_ID = keccak256( "ERC20Token" );

    // Present in ERC777
    mapping (address => uint256) internal _balances;

    // Present in ERC777
    mapping (address => mapping (address => uint256)) internal _allowances;

    // Present in ERC777
    uint256 internal _totalSupply;

    // Present in ERC777
    string internal _name;

    // Present in ERC777
    string internal _symbol;

    // Present in ERC777
    uint8 internal _decimals;

    constructor (string memory name_, string memory symbol_, uint8 decimals_) {
        _name = name_;
        _symbol = symbol_;
        _decimals = decimals_;
    }

    function name() public view returns (string memory) {
        return _name;
    }

    function symbol() public view returns (string memory) {
        return _symbol;
    }

    function decimals() public view returns (uint8) {
        return _decimals;
    }

    function totalSupply() public view override returns (uint256) {
        return _totalSupply;
    }

    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(msg.sender, recipient, amount);
        return true;
    }

    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(msg.sender, spender, amount);
        return true;
    }

    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue));
        return true;
    }

    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        _approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
        return true;
    }

    function _transfer(address sender, address recipient, uint256 amount) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

    function _mint(address account_, uint256 amount_) internal virtual {
        require(account_ != address(0), "ERC20: mint to the zero address");
        _beforeTokenTransfer(address( this ), account_, amount_);
        _totalSupply = _totalSupply.add(amount_);
        _balances[account_] = _balances[account_].add(amount_);
        emit Transfer(address( this ), account_, amount_);
    }

    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
        _totalSupply = _totalSupply.sub(amount);
        emit Transfer(account, address(0), amount);
    }

    function _approve(address owner, address spender, uint256 amount) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    function _beforeTokenTransfer( address from_, address to_, uint256 amount_ ) internal virtual { }
}

library Counters {
    using SafeMath for uint256;

    struct Counter {
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        counter._value += 1;
    }

    function decrement(Counter storage counter) internal {
        counter._value = counter._value.sub(1);
    }
}

interface IERC2612Permit {

    function permit(
        address owner,
        address spender,
        uint256 amount,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    function nonces(address owner) external view returns (uint256);
}

abstract contract ERC20Permit is ERC20, IERC2612Permit {
    using Counters for Counters.Counter;

    mapping(address => Counters.Counter) private _nonces;

    // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
    bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;

    bytes32 public DOMAIN_SEPARATOR;

    constructor() {
        uint256 chainID;
        assembly {
            chainID := chainid()
        }

        DOMAIN_SEPARATOR = keccak256(
            abi.encode(
                keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                keccak256(bytes(name())),
                keccak256(bytes("1")), // Version
                chainID,
                address(this)
            )
        );
    }

    function permit(
        address owner,
        address spender,
        uint256 amount,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual override {
        require(block.timestamp <= deadline, "Permit: expired deadline");

        bytes32 hashStruct =
        keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, amount, _nonces[owner].current(), deadline));

        bytes32 _hash = keccak256(abi.encodePacked(uint16(0x1901), DOMAIN_SEPARATOR, hashStruct));

        address signer = ecrecover(_hash, v, r, s);
        require(signer != address(0) && signer == owner, "ZeroSwapPermit: Invalid signature");

        _nonces[owner].increment();
        _approve(owner, spender, amount);
    }

    function nonces(address owner) public view override returns (uint256) {
        return _nonces[owner].current();
    }
}

interface IOwnable {
    function owner() external view returns (address);

    function renounceOwnership() external;

    function transferOwnership( address newOwner_ ) external;
}

contract Ownable is IOwnable {

    address internal _owner;

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

    constructor () {
        _owner = msg.sender;
        emit OwnershipTransferred( address(0), _owner );
    }

    function owner() public view override returns (address) {
        return _owner;
    }

    modifier onlyOwner() {
        require( _owner == msg.sender, "Ownable: caller is not the owner" );
        _;
    }

    function renounceOwnership() public virtual override onlyOwner() {
        emit OwnershipTransferred( _owner, address(0) );
        _owner = address(0);
    }

    function transferOwnership( address newOwner_ ) public virtual override onlyOwner() {
        require( newOwner_ != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred( _owner, newOwner_ );
        _owner = newOwner_;
    }
}

contract VaultOwned is Ownable {

    address internal _vault;

    function setVault( address vault_ ) external onlyOwner() returns ( bool ) {
        _vault = vault_;

        return true;
    }

    function vault() public view returns (address) {
        return _vault;
    }

    modifier onlyVault() {
        require( _vault == msg.sender, "VaultOwned: caller is not the Vault" );
        _;
    }

}

contract FantohmERC20Token is ERC20Permit, VaultOwned {

    using SafeMath for uint256;

    constructor() ERC20("Fantohm", "FHM", 9) {
    }

    function mint(address account_, uint256 amount_) external onlyVault() {
        _mint(account_, amount_);
    }

    function burn(uint256 amount) public virtual {
        _burn(msg.sender, amount);
    }

    function burnFrom(address account_, uint256 amount_) public virtual {
        _burnFrom(account_, amount_);
    }

    function _burnFrom(address account_, uint256 amount_) public virtual {
        uint256 decreasedAllowance_ =
        allowance(account_, msg.sender).sub(
            amount_,
            "ERC20: burn amount exceeds allowance"
        );

        _approve(account_, msg.sender, decreasedAllowance_);
        _burn(account_, amount_);
    }
}

Contract ABI

[{"inputs":[],"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":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","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":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"_burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"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":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"burnFrom","outputs":[],"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":[{"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":[{"internalType":"address","name":"account_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault_","type":"address"}],"name":"setVault","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"vault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

60806040523480156200001157600080fd5b506040518060400160405280600781526020016646616e746f686d60c81b8152506040518060400160405280600381526020016246484d60e81b815250600982600390805190602001906200006892919062000229565b5081516200007e90600490602085019062000229565b506005805460ff191660ff92909216919091179055504690507f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000c26200018f565b805160209182012060408051808201825260018152603160f81b90840152805180840194909452838101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6606084015260808301939093523060a0808401919091528351808403909101815260c0909201928390528151910120600755600880546001600160a01b0319163317908190556001600160a01b0316906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3620002d5565b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156200021f5780601f10620001f3576101008083540402835291602001916200021f565b820191906000526020600020905b8154815290600101906020018083116200020157829003601f168201915b5050505050905090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282620002615760008555620002ac565b82601f106200027c57805160ff1916838001178555620002ac565b82800160010185558215620002ac579182015b82811115620002ac5782518255916020019190600101906200028f565b50620002ba929150620002be565b5090565b5b80821115620002ba5760008155600101620002bf565b61147780620002e56000396000f3fe608060405234801561001057600080fd5b50600436106101585760003560e01c8063715018a6116100c3578063a457c2d71161007c578063a457c2d71461040d578063a9059cbb14610439578063d505accf14610465578063dd62ed3e146104b6578063f2fde38b146104e4578063fbfa77cf1461050a57610158565b8063715018a61461035b57806379cc6790146103635780637ecebe001461038f5780638da5cb5b146103b557806395d89b41146103d9578063a22b35ce146103e157610158565b80633644e515116101155780633644e51514610290578063395093511461029857806340c10f19146102c457806342966c68146102f25780636817031b1461030f57806370a082311461033557610158565b806306fdde031461015d578063095ea7b3146101da57806318160ddd1461021a57806323b872dd1461023457806330adf81f1461026a578063313ce56714610272575b600080fd5b610165610512565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561019f578181015183820152602001610187565b50505050905090810190601f1680156101cc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610206600480360360408110156101f057600080fd5b506001600160a01b0381351690602001356105a8565b604080519115158252519081900360200190f35b6102226105be565b60408051918252519081900360200190f35b6102066004803603606081101561024a57600080fd5b506001600160a01b038135811691602081013590911690604001356105c4565b61022261062d565b61027a610651565b6040805160ff9092168252519081900360200190f35b61022261065a565b610206600480360360408110156102ae57600080fd5b506001600160a01b038135169060200135610660565b6102f0600480360360408110156102da57600080fd5b506001600160a01b038135169060200135610696565b005b6102f06004803603602081101561030857600080fd5b50356106ed565b6102066004803603602081101561032557600080fd5b50356001600160a01b03166106fa565b6102226004803603602081101561034b57600080fd5b50356001600160a01b0316610781565b6102f061079c565b6102f06004803603604081101561037957600080fd5b506001600160a01b038135169060200135610845565b610222600480360360208110156103a557600080fd5b50356001600160a01b031661084f565b6103bd610876565b604080516001600160a01b039092168252519081900360200190f35b610165610885565b6102f0600480360360408110156103f757600080fd5b506001600160a01b0381351690602001356108e6565b6102066004803603604081101561042357600080fd5b506001600160a01b038135169060200135610932565b6102066004803603604081101561044f57600080fd5b506001600160a01b038135169060200135610981565b6102f0600480360360e081101561047b57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c0013561098e565b610222600480360360408110156104cc57600080fd5b506001600160a01b0381358116916020013516610bbb565b6102f0600480360360208110156104fa57600080fd5b50356001600160a01b0316610be6565b6103bd610ce6565b60038054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561059e5780601f106105735761010080835404028352916020019161059e565b820191906000526020600020905b81548152906001019060200180831161058157829003601f168201915b5050505050905090565b60006105b5338484610cf5565b50600192915050565b60025490565b60006105d1848484610de1565b610623843361061e85604051806060016040528060288152602001611344602891396001600160a01b038a1660009081526001602090815260408083203384529091529020549190610f3c565b610cf5565b5060019392505050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60055460ff1690565b60075481565b3360008181526001602090815260408083206001600160a01b038716845290915281205490916105b591859061061e9086610fd3565b6009546001600160a01b031633146106df5760405162461bcd60e51b815260040180806020018281038252602381526020018061136c6023913960400191505060405180910390fd5b6106e98282611034565b5050565b6106f73382611124565b50565b6008546000906001600160a01b0316331461075c576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b50600980546001600160a01b0383166001600160a01b03199091161790556001919050565b6001600160a01b031660009081526020819052604090205490565b6008546001600160a01b031633146107fb576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6008546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600880546001600160a01b0319169055565b6106e982826108e6565b6001600160a01b038116600090815260066020526040812061087090611220565b92915050565b6008546001600160a01b031690565b60048054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561059e5780601f106105735761010080835404028352916020019161059e565b60006109168260405180606001604052806024815260200161138f6024913961090f8633610bbb565b9190610f3c565b9050610923833383610cf5565b61092d8383611124565b505050565b60006105b5338461061e8560405180606001604052806025815260200161141d602591393360009081526001602090815260408083206001600160a01b038d1684529091529020549190610f3c565b60006105b5338484610de1565b834211156109e3576040805162461bcd60e51b815260206004820152601860248201527f5065726d69743a206578706972656420646561646c696e650000000000000000604482015290519081900360640190fd5b6001600160a01b03871660009081526006602052604081207f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c990899089908990610a2c90611220565b604080516020808201979097526001600160a01b0395861681830152939094166060840152608083019190915260a082015260c08082018990528251808303909101815260e08201835280519084012060075461190160f01b610100840152610102830152610122808301829052835180840390910181526101428301808552815191860191909120600091829052610162840180865281905260ff8a166101828501526101a284018990526101c28401889052935191955092936001926101e280820193601f1981019281900390910190855afa158015610b12573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590610b485750896001600160a01b0316816001600160a01b0316145b610b835760405162461bcd60e51b81526004018080602001828103825260218152602001806113236021913960400191505060405180910390fd5b6001600160a01b038a166000908152600660205260409020610ba490611224565b610baf8a8a8a610cf5565b50505050505050505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6008546001600160a01b03163314610c45576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116610c8a5760405162461bcd60e51b81526004018080602001828103825260268152602001806112b56026913960400191505060405180910390fd5b6008546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600880546001600160a01b0319166001600160a01b0392909216919091179055565b6009546001600160a01b031690565b6001600160a01b038316610d3a5760405162461bcd60e51b81526004018080602001828103825260248152602001806113f96024913960400191505060405180910390fd5b6001600160a01b038216610d7f5760405162461bcd60e51b81526004018080602001828103825260228152602001806112db6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b038316610e265760405162461bcd60e51b81526004018080602001828103825260258152602001806113d46025913960400191505060405180910390fd5b6001600160a01b038216610e6b5760405162461bcd60e51b81526004018080602001828103825260238152602001806112706023913960400191505060405180910390fd5b610e7683838361092d565b610eb3816040518060600160405280602681526020016112fd602691396001600160a01b0386166000908152602081905260409020549190610f3c565b6001600160a01b038085166000908152602081905260408082209390935590841681522054610ee29082610fd3565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115610fcb5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610f90578181015183820152602001610f78565b50505050905090810190601f168015610fbd5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60008282018381101561102d576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b03821661108f576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b61109a30838361092d565b6002546110a79082610fd3565b6002556001600160a01b0382166000908152602081905260409020546110cd9082610fd3565b6001600160a01b038316600081815260208181526040918290209390935580518481529051919230927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b0382166111695760405162461bcd60e51b81526004018080602001828103825260218152602001806113b36021913960400191505060405180910390fd5b6111758260008361092d565b6111b281604051806060016040528060228152602001611293602291396001600160a01b0385166000908152602081905260409020549190610f3c565b6001600160a01b0383166000908152602081905260409020556002546111d8908261122d565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b5490565b80546001019055565b600061102d83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250610f3c56fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e63654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e63655a65726f537761705065726d69743a20496e76616c6964207369676e617475726545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e63655661756c744f776e65643a2063616c6c6572206973206e6f7420746865205661756c7445524332303a206275726e20616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212207efeb3dc040e98a041e195471fc7f3018fa741d37df4359fc5683f55d79926a064736f6c63430007050033

Deployed ByteCode Sourcemap

29012:846:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21176:83;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22036:167;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;22036:167:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;21453:100;;;:::i;:::-;;;;;;;;;;;;;;;;22211:317;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;22211:317:0;;;;;;;;;;;;;;;;;:::i;25908:108::-;;;:::i;21362:83::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;26025:31;;;:::i;22536:214::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;22536:214:0;;;;;;;;:::i;29167:113::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;29167:113:0;;;;;;;;:::i;:::-;;29288:89;;;;;;;;;;;;;;;;-1:-1:-1;29288:89:0;;:::i;28654:132::-;;;;;;;;;;;;;;;;-1:-1:-1;28654:132:0;-1:-1:-1;;;;;28654:132:0;;:::i;21561:127::-;;;;;;;;;;;;;;;;-1:-1:-1;21561:127:0;-1:-1:-1;;;;;21561:127:0;;:::i;28142:161::-;;;:::i;29385:115::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;29385:115:0;;;;;;;;:::i;27318:120::-;;;;;;;;;;;;;;;;-1:-1:-1;27318:120:0;-1:-1:-1;;;;;27318:120:0;;:::i;27919:88::-;;;:::i;:::-;;;;-1:-1:-1;;;;;27919:88:0;;;;;;;;;;;;;;21267:87;;;:::i;29508:347::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;29508:347:0;;;;;;;;:::i;22758:265::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;22758:265:0;;;;;;;;:::i;21696:173::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;21696:173:0;;;;;;;;:::i;26544:766::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;26544:766:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;21877:151::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;21877:151:0;;;;;;;;;;:::i;28311:264::-;;;;;;;;;;;;;;;;-1:-1:-1;28311:264:0;-1:-1:-1;;;;;28311:264:0;;:::i;28794:79::-;;;:::i;21176:83::-;21246:5;21239:12;;;;;;;;-1:-1:-1;;21239:12:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21213:13;;21239:12;;21246:5;;21239:12;;21246:5;21239:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21176:83;:::o;22036:167::-;22119:4;22136:37;22145:10;22157:7;22166:6;22136:8;:37::i;:::-;-1:-1:-1;22191:4:0;22036:167;;;;:::o;21453:100::-;21533:12;;21453:100;:::o;22211:317::-;22317:4;22334:36;22344:6;22352:9;22363:6;22334:9;:36::i;:::-;22381:117;22390:6;22398:10;22410:87;22446:6;22410:87;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;22410:19:0;;;;;;:11;:19;;;;;;;;22430:10;22410:31;;;;;;;;;:87;:35;:87::i;:::-;22381:8;:117::i;:::-;-1:-1:-1;22516:4:0;22211:317;;;;;:::o;25908:108::-;25950:66;25908:108;:::o;21362:83::-;21428:9;;;;21362:83;:::o;26025:31::-;;;;:::o;22536:214::-;22650:10;22624:4;22671:23;;;:11;:23;;;;;;;;-1:-1:-1;;;;;22671:32:0;;;;;;;;;;22624:4;;22641:79;;22662:7;;22671:48;;22708:10;22671:36;:48::i;29167:113::-;28922:6;;-1:-1:-1;;;;;28922:6:0;28932:10;28922:20;28913:70;;;;-1:-1:-1;;;28913:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29248:24:::1;29254:8;29264:7;29248:5;:24::i;:::-;29167:113:::0;;:::o;29288:89::-;29344:25;29350:10;29362:6;29344:5;:25::i;:::-;29288:89;:::o;28654:132::-;28056:6;;28721:4;;-1:-1:-1;;;;;28056:6:0;28066:10;28056:20;28047:67;;;;;-1:-1:-1;;;28047:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;28739:6:0::1;:15:::0;;-1:-1:-1;;;;;28739:15:0;::::1;-1:-1:-1::0;;;;;;28739:15:0;;::::1;;::::0;;;28654:132;;;:::o;21561:127::-;-1:-1:-1;;;;;21662:18:0;21635:7;21662:18;;;;;;;;;;;;21561:127::o;28142:161::-;28056:6;;-1:-1:-1;;;;;28056:6:0;28066:10;28056:20;28047:67;;;;;-1:-1:-1;;;28047:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28245:6:::1;::::0;28223:42:::1;::::0;28261:1:::1;::::0;-1:-1:-1;;;;;28245:6:0::1;::::0;28223:42:::1;::::0;28261:1;;28223:42:::1;28276:6;:19:::0;;-1:-1:-1;;;;;;28276:19:0::1;::::0;;28142:161::o;29385:115::-;29464:28;29474:8;29484:7;29464:9;:28::i;27318:120::-;-1:-1:-1;;;;;27406:14:0;;27379:7;27406:14;;;:7;:14;;;;;:24;;:22;:24::i;:::-;27399:31;27318:120;-1:-1:-1;;27318:120:0:o;27919:88::-;27993:6;;-1:-1:-1;;;;;27993:6:0;27919:88;:::o;21267:87::-;21339:7;21332:14;;;;;;;;-1:-1:-1;;21332:14:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21306:13;;21332:14;;21339:7;;21332:14;;21339:7;21332:14;;;;;;;;;;;;;;;;;;;;;;;;29508:347;29588:27;29627:121;29677:7;29627:121;;;;;;;;;;;;;;;;;:31;29637:8;29647:10;29627:9;:31::i;:::-;:35;:121;:35;:121::i;:::-;29588:160;;29761:51;29770:8;29780:10;29792:19;29761:8;:51::i;:::-;29823:24;29829:8;29839:7;29823:5;:24::i;:::-;29508:347;;;:::o;22758:265::-;22851:4;22868:125;22877:10;22889:7;22898:94;22935:15;22898:94;;;;;;;;;;;;;;;;;22910:10;22898:23;;;;:11;:23;;;;;;;;-1:-1:-1;;;;;22898:32:0;;;;;;;;;;;:94;:36;:94::i;21696:173::-;21782:4;21799:40;21809:10;21821:9;21832:6;21799:9;:40::i;26544:766::-;26789:8;26770:15;:27;;26762:64;;;;;-1:-1:-1;;;26762:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;26931:14:0;;26839:18;26931:14;;;:7;:14;;;;;25950:66;;26907:5;;26914:7;;26923:6;;26931:24;;:22;:24::i;:::-;26879:87;;;;;;;;;;;-1:-1:-1;;;;;26879:87:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26869:98;;;;;;27039:16;;-1:-1:-1;;;27006:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26996:73;;;;;;;;;-1:-1:-1;27099:25:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26869:98;;-1:-1:-1;26996:73:0;;27099:25;;;;;;;-1:-1:-1;;27099:25:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;27099:25:0;;-1:-1:-1;;27099:25:0;;;-1:-1:-1;;;;;;;27143:20:0;;;;;;:39;;;27177:5;-1:-1:-1;;;;;27167:15:0;:6;-1:-1:-1;;;;;27167:15:0;;27143:39;27135:85;;;;-1:-1:-1;;;27135:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;27233:14:0;;;;;;:7;:14;;;;;:26;;:24;:26::i;:::-;27270:32;27279:5;27286:7;27295:6;27270:8;:32::i;:::-;26544:766;;;;;;;;;;:::o;21877:151::-;-1:-1:-1;;;;;21993:18:0;;;21966:7;21993:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;21877:151::o;28311:264::-;28056:6;;-1:-1:-1;;;;;28056:6:0;28066:10;28056:20;28047:67;;;;;-1:-1:-1;;;28047:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;28415:23:0;::::1;28406:75;;;;-1:-1:-1::0;;;28406:75:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28519:6;::::0;28497:41:::1;::::0;-1:-1:-1;;;;;28497:41:0;;::::1;::::0;28519:6:::1;::::0;28497:41:::1;::::0;28519:6:::1;::::0;28497:41:::1;28549:6;:18:::0;;-1:-1:-1;;;;;;28549:18:0::1;-1:-1:-1::0;;;;;28549:18:0;;;::::1;::::0;;;::::1;::::0;;28311:264::o;28794:79::-;28859:6;;-1:-1:-1;;;;;28859:6:0;28794:79;:::o;24407:346::-;-1:-1:-1;;;;;24509:19:0;;24501:68;;;;-1:-1:-1;;;24501:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;24588:21:0;;24580:68;;;;-1:-1:-1;;;24580:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;24661:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;24713:32;;;;;;;;;;;;;;;;;24407:346;;;:::o;23031:539::-;-1:-1:-1;;;;;23137:20:0;;23129:70;;;;-1:-1:-1;;;23129:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;23218:23:0;;23210:71;;;;-1:-1:-1;;;23210:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23294:47;23315:6;23323:9;23334:6;23294:20;:47::i;:::-;23374:71;23396:6;23374:71;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;23374:17:0;;:9;:17;;;;;;;;;;;;:71;:21;:71::i;:::-;-1:-1:-1;;;;;23354:17:0;;;:9;:17;;;;;;;;;;;:91;;;;23479:20;;;;;;;:32;;23504:6;23479:24;:32::i;:::-;-1:-1:-1;;;;;23456:20:0;;;:9;:20;;;;;;;;;;;;:55;;;;23527:35;;;;;;;23456:20;;23527:35;;;;;;;;;;;;;23031:539;;;:::o;17744:192::-;17830:7;17866:12;17858:6;;;;17850:29;;;;-1:-1:-1;;;17850:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;17902:5:0;;;17744:192::o;17411:181::-;17469:7;17501:5;;;17525:6;;;;17517:46;;;;;-1:-1:-1;;;17517:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;17583:1;17411:181;-1:-1:-1;;;17411:181:0:o;23578:395::-;-1:-1:-1;;;;;23664:22:0;;23656:66;;;;;-1:-1:-1;;;23656:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;23733:56;23763:4;23771:8;23781:7;23733:20;:56::i;:::-;23815:12;;:25;;23832:7;23815:16;:25::i;:::-;23800:12;:40;-1:-1:-1;;;;;23873:19:0;;:9;:19;;;;;;;;;;;:32;;23897:7;23873:23;:32::i;:::-;-1:-1:-1;;;;;23851:19:0;;:9;:19;;;;;;;;;;;;:54;;;;23921:44;;;;;;;23851:19;;23939:4;;23921:44;;;;;;;;;;23578:395;;:::o;23981:418::-;-1:-1:-1;;;;;24065:21:0;;24057:67;;;;-1:-1:-1;;;24057:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24137:49;24158:7;24175:1;24179:6;24137:20;:49::i;:::-;24220:68;24243:6;24220:68;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;24220:18:0;;:9;:18;;;;;;;;;;;;:68;:22;:68::i;:::-;-1:-1:-1;;;;;24199:18:0;;:9;:18;;;;;;;;;;:89;24314:12;;:24;;24331:6;24314:16;:24::i;:::-;24299:12;:39;24354:37;;;;;;;;24380:1;;-1:-1:-1;;;;;24354:37:0;;;;;;;;;;;;23981:418;;:::o;24994:114::-;25086:14;;24994:114::o;25116:91::-;25180:19;;25198:1;25180:19;;;25116:91::o;17600:136::-;17658:7;17685:43;17689:1;17692;17685:43;;;;;;;;;;;;;;;;;:3;:43::i

Swarm Source

ipfs://7efeb3dc040e98a041e195471fc7f3018fa741d37df4359fc5683f55d79926a0
Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.