Contract 0x630d98424efe0ea27fb1b3ab7741907dffeaad78 2

 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x06e2137676915105304266aba8f7e2ab784a22ed353e03d9d22bb2832b2a35dbApprove112019752021-09-24 19:32:581 min ago0xdccd66f620b0a864605361f2121464478e388d50 IN  Peakdefi: PEAK Token0 BNB0.000222035
0xc66a0b5dd87eedabad09c1562fd2748dcf23c9b7085e5ee33465093a195cc3abTransfer112019682021-09-24 19:32:371 min ago0x7b6eb0a7b0b2cee8d5a4d7355d2c5721f4dbfa70 IN  Peakdefi: PEAK Token0 BNB0.00018076
0xa9cade2d9c2ce71ea1764158bc262bca91f43c1b5d6f4b3973956f2909102ed9Transfer112019592021-09-24 19:32:101 min ago0x5b566025afe9fab77ef084c8bfed9d6112707d63 IN  Peakdefi: PEAK Token0 BNB0.00010582
0x43fc53feb0eeb6c386f26a5c6e05e35d61243e06e2245e31e29a29e737a10248Transfer112019302021-09-24 19:30:433 mins ago0x8ca560e83fcced3d6d34f0a5db6487f00309cf2e IN  Peakdefi: PEAK Token0 BNB0.00018076
0x459ecf4fff343bbdaa40dcc4bd4ab1653db52f11359e9cf193d76b72d56522e3Transfer112018852021-09-24 19:28:285 mins ago0xea7b33d264f4b7e6fd283a8250a572f2ceefacd4 IN  Peakdefi: PEAK Token0 BNB0.000268611
0x4fbad9576f27d6baa4e6cb1c3852d587ad4c6cff3933431a7952a742012db8bdTransfer112018632021-09-24 19:27:226 mins ago0x22852fc5ad7194705045715fe68699fd30776df0 IN  Peakdefi: PEAK Token0 BNB0.00018076
0xec0475846be4c6f4c09784e2250213a8ac12ff79fdf854eb4c61ca1b1d6194c3Transfer112018622021-09-24 19:27:196 mins ago0x86dd7dcf8c48b9774684dc3d008f7b4834b34345 IN  Peakdefi: PEAK Token0 BNB0.00018082
0xac748a17d696cf43733d3c07fd9737033f1f112afcf8369ad55cb3b9a7c0e1d5Transfer112018562021-09-24 19:27:017 mins ago0x6654efe8b0e00cfa5bca38c2e68af660c96ea932 IN  Peakdefi: PEAK Token0 BNB0.00010576
0x5b3a7526084d3e8203aa12f9c12f56a572aa9fa3febf875039af5fe09b706cf2Approve112018482021-09-24 19:26:377 mins ago0x1f3c969d6eeb586c120da76445126627c43ac79e IN  Peakdefi: PEAK Token0 BNB0.000222035
0x96433330b2403121d09738b4523cbd40ecb8a51ad50f90072526e22bdff30501Approve112018452021-09-24 19:26:287 mins ago0xb8036e85ec6b00d08812bf75a45a0ae268de8e73 IN  Peakdefi: PEAK Token0 BNB0.000222035
0x34937342ef60240af083e24a54d9aaf05c17c63efb1978ea877c4bb737d663dfTransfer112018162021-09-24 19:25:019 mins ago0xdc7ba1c2a9e18597ff11b25d5bd4cc4d659d97dd IN  Peakdefi: PEAK Token0 BNB0.0001807
0xeaf8aa3a7ca053371d1284569dda460991b880149b4bbb40f9d207ab56afaad5Transfer112018002021-09-24 19:24:139 mins ago0xa69e0d7fde8bbd3a1cb398872764920441f828f7 IN  Peakdefi: PEAK Token0 BNB0.00010576
0xf75039738ffd57ffef831b65e886743b1e9645b1e7252bbfac9790c3daa31365Transfer112017752021-09-24 19:22:5811 mins ago0x3935ec4900c753f2a5aa1d53a5d6af0956faddb2 IN  Peakdefi: PEAK Token0 BNB0.0001807
0x4de0d99c2828ccc355a9e53dbf3d0bb4d36e9c059cd2f0d9663db2cc176c4431Transfer112017712021-09-24 19:22:4611 mins ago0x50410d9196e9044eec59e1923eac1e0aed6aa53b IN  Peakdefi: PEAK Token0 BNB0.00010582
0x7356d0abdca194d2f0acaf19d8382962b02188a43c80607742e532087aac3d56Transfer112017672021-09-24 19:22:3411 mins ago0x6ef6ab1b4217cd5643a56e87af74e733ddcd50c0 IN  Peakdefi: PEAK Token0 BNB0.00010582
0xd95f4f38d9d6ec792bbd0564e61d78b7bc9d2c2c90b0d3eee0adfb6f92130edfTransfer112017622021-09-24 19:22:1911 mins ago0xdc88073284845201aa237bf900858d56beb88fe0 IN  Peakdefi: PEAK Token0 BNB0.00010576
0x046684384d80c1f933790991428642b878f5a50a6055899ec89411510cbf093dTransfer112017522021-09-24 19:21:4912 mins ago0xaf090955c0b4aa97ae40652e4efd923ac70e7d1c IN  Peakdefi: PEAK Token0 BNB0.00018082
0x71ccd7687eb9d35938aff170788ee3c1d90094e28e895a4e852299cb7f9b5788Transfer112017482021-09-24 19:21:3712 mins ago0xeb245db6452cb070ca7fe4bf649767ace29b3e1b IN  Peakdefi: PEAK Token0 BNB0.0002557
0x2e9bdc3837ce604c21f3de783053b325858ce6431e6ddeab629ade5212d529feTransfer112017212021-09-24 19:20:1613 mins ago0x1122b0245037653e227f925cab6022cec94fcf84 IN  Peakdefi: PEAK Token0 BNB0.00010576
0xbe63b334d84f02c56d8b3aa54bc8cc2e72c73c99af3d4d99495ca252a0f649abApprove112016622021-09-24 19:17:1916 mins ago0x51dc6f27c0a84adabb3dd5b481e68e80595840d2 IN  Peakdefi: PEAK Token0 BNB0.000222035
0x0b657b7c7dc2b6e260a9664a2687539e8257930a0c3bbb82632fe07185552730Transfer112016382021-09-24 19:16:0717 mins ago0xae7fd180f7f02de0da83f18e4a6124464a974f52 IN  Peakdefi: PEAK Token0 BNB0.00010576
0x0b0ac41e409e1aacb9e2ac2833a588b0a13ac24f604f6e31e1d23d059eea3404Transfer112016172021-09-24 19:15:0418 mins ago0x2fcc4721c58c78bac3014eecc4cbf1e7a9261099 IN  Peakdefi: PEAK Token0 BNB0.00010576
0x3bf595d45ffbc7795addf0b416c8d32c0d5cb104a3931841f93a0e2414cc9b7eApprove112015822021-09-24 19:13:1920 mins ago0x0ae61eab7dda076faadf34778ba707d3c22f01ee IN  Peakdefi: PEAK Token0 BNB0.000222035
0xec2f26b7031400e6ae98b872f5e9ec73ba8309d689571648552249e6ec60e7b8Transfer112015762021-09-24 19:13:0121 mins ago0x69dcc8b55df0e1a3edabd3a2d43b4b932596aa30 IN  Peakdefi: PEAK Token0 BNB0.00025576
0xd6b23204182118fb028884d8d2f2e4f4319e195dc6aaf393d872143170749aefTransfer112015602021-09-24 19:12:1321 mins ago0x402359df6d0ac5d2fad27d300b6c4470b34bb1a6 IN  Peakdefi: PEAK Token0 BNB0.00010576
[ Download CSV Export 

OVERVIEW

Peak Defi is a decentralized asset management fund, created to connect investors and asset managers for capital growth.

Latest 2 internal transactions
Parent Txn Hash Block From To Value
0x527d8502f0cedaf75735d5e49047d5363059d5deda474b0a7c3e849095e5676754177812021-03-05 15:20:19203 days 4 hrs ago Peakdefi: PEAK Token 0x5b103d2125d83d2521815f62304b67b2c2403a450 BNB
0xf4b4dcea13ee87b4dbf5b14c779a707c252edf3893df9c3e1572d7589f86262354177132021-03-05 15:16:55203 days 4 hrs ago Peakdefi: PEAK Token 0x5b103d2125d83d2521815f62304b67b2c2403a450 BNB
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
TokenProxy

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, Unlicense license

Contract Source Code (Solidity)

/**
 *Submitted for verification at BscScan.com on 2021-02-28
*/

pragma solidity ^0.6.2;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
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);
}

/**
 * @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, 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) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * 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);
        uint256 c = a - b;

        return c;
    }

    /**
     * @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) {
        // 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 0;
        }

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

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts 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) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message 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, 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;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts 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) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message 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, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.0.0, only sets of type `address` (`AddressSet`) and `uint256`
 * (`UintSet`) are supported.
 */
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];
    }

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


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

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies in extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
      return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        return _functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        return _functionCallWithValue(target, data, value, errorMessage);
    }

    function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

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

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it.
 */
abstract contract AccessControl is Context {
    using EnumerableSet for EnumerableSet.AddressSet;
    using Address for address;

    struct RoleData {
        EnumerableSet.AddressSet members;
        bytes32 adminRole;
    }

    mapping (bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view returns (bool) {
        return _roles[role].members.contains(account);
    }

    /**
     * @dev Returns the number of accounts that have `role`. Can be used
     * together with {getRoleMember} to enumerate all bearers of a role.
     */
    function getRoleMemberCount(bytes32 role) public view returns (uint256) {
        return _roles[role].members.length();
    }

    /**
     * @dev Returns one of the accounts that have `role`. `index` must be a
     * value between 0 and {getRoleMemberCount}, non-inclusive.
     *
     * Role bearers are not sorted in any particular way, and their ordering may
     * change at any point.
     *
     * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
     * you perform all queries on the same block. See the following
     * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
     * for more information.
     */
    function getRoleMember(bytes32 role, uint256 index) public view returns (address) {
        return _roles[role].members.at(index);
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) public virtual {
        require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to grant");

        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) public virtual {
        require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to revoke");

        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) public virtual {
        require(account == _msgSender(), "AccessControl: can only renounce roles for self");

        _revokeRole(role, account);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event. Note that unlike {grantRole}, this function doesn't perform any
     * checks on the calling account.
     *
     * [WARNING]
     * ====
     * This function should only be called from the constructor when setting
     * up the initial roles for the system.
     *
     * Using this function in any other way is effectively circumventing the admin
     * system imposed by {AccessControl}.
     * ====
     */
    function _setupRole(bytes32 role, address account) internal virtual {
        _grantRole(role, account);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);
        _roles[role].adminRole = adminRole;
    }

    function _grantRole(bytes32 role, address account) private {
        if (_roles[role].members.add(account)) {
            emit RoleGranted(role, account, _msgSender());
        }
    }

    function _revokeRole(bytes32 role, address account) private {
        if (_roles[role].members.remove(account)) {
            emit RoleRevoked(role, account, _msgSender());
        }
    }
}

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is AccessControl, IERC20 {
    using SafeMath for uint256;
    using Address for address;

    string private _name;
    string private _symbol;
    uint8 private _decimals;

    uint256 private _totalSupply;

    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");

    mapping (address => uint256) private _balances;
    mapping (address => mapping (address => uint256)) private _allowances;

    /**
     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with
     * a default value of 18.
     */
    function _initialize(
        string memory name,
        string memory symbol,
        uint8 decimals
    ) internal {
        _name = name;
        _symbol = symbol;
        _decimals = decimals;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5,05` (`505 / 10 ** 2`).
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view returns (uint8) {
        return _decimals;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20};
     *
     * Requirements:
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
        return true;
    }

    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    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);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements
     *
     * - `to` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

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

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    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);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
     *
     * This is internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    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);
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be to transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}

/**
 * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
 * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
 * be specified by overriding the virtual {_implementation} function.
 * 
 * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
 * different contract through the {_delegate} function.
 * 
 * The success and return data of the delegated call will be returned back to the caller of the proxy.
 */
abstract contract Proxy {
    /**
     * @dev Delegates the current call to `implementation`.
     * 
     * This function does not return to its internall call site, it will return directly to the external caller.
     */
    function _delegate(address implementation) internal {
        // solhint-disable-next-line no-inline-assembly
        assembly {
            // Copy msg.data. We take full control of memory in this inline assembly
            // block because it will not return to Solidity code. We overwrite the
            // Solidity scratch pad at memory position 0.
            calldatacopy(0, 0, calldatasize())

            // Call the implementation.
            // out and outsize are 0 because we don't know the size yet.
            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)

            // Copy the returned data.
            returndatacopy(0, 0, returndatasize())

            switch result
            // delegatecall returns 0 on error.
            case 0 { revert(0, returndatasize()) }
            default { return(0, returndatasize()) }
        }
    }

    /**
     * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
     * and {_fallback} should delegate.
     */
    function _implementation() internal virtual view returns (address);

    /**
     * @dev Delegates the current call to the address returned by `_implementation()`.
     * 
     * This function does not return to its internall call site, it will return directly to the external caller.
     */
    function _fallback() internal {
        _beforeFallback();
        _delegate(_implementation());
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
     * function in the contract matches the call data.
     */
    fallback () payable external {
        _fallback();
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
     * is empty.
     */
    receive () payable external {
        _fallback();
    }

    /**
     * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
     * call, or as part of the Solidity `fallback` or `receive` functions.
     * 
     * If overriden should call `super._beforeFallback()`.
     */
    function _beforeFallback() internal virtual {
    }
}

/**
 * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
 * implementation address that can be changed. This address is stored in storage in the location specified by
 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
 * implementation behind the proxy.
 * 
 * Upgradeability is only provided internally through {_upgradeTo}. For an externally upgradeable proxy see
 * {TransparentUpgradeableProxy}.
 */
contract UpgradeableProxy is Proxy {
    /**
     * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
     * 
     * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded
     * function call, and allows initializating the storage of the proxy like a Solidity constructor.
     */
    constructor(address _logic, bytes memory _data) public payable {
        assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1));
        _setImplementation(_logic);
        if(_data.length > 0) {
            // solhint-disable-next-line avoid-low-level-calls
            (bool success,) = _logic.delegatecall(_data);
            require(success);
        }
    }

    /**
     * @dev Emitted when the implementation is upgraded.
     */
    event Upgraded(address indexed implementation);

    /**
     * @dev Storage slot with the address of the current implementation.
     * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 private constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

    /**
     * @dev Returns the current implementation address.
     */
    function _implementation() internal override view returns (address impl) {
        bytes32 slot = _IMPLEMENTATION_SLOT;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            impl := sload(slot)
        }
    }

    /**
     * @dev Upgrades the proxy to a new implementation.
     * 
     * Emits an {Upgraded} event.
     */
    function _upgradeTo(address newImplementation) internal {
        _setImplementation(newImplementation);
        emit Upgraded(newImplementation);
    }

    /**
     * @dev Stores a new address in the EIP1967 implementation slot.
     */
    function _setImplementation(address newImplementation) private {
        require(Address.isContract(newImplementation), "UpgradeableProxy: new implementation is not a contract");

        bytes32 slot = _IMPLEMENTATION_SLOT;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            sstore(slot, newImplementation)
        }
    }
}

/**
 * @dev This contract implements a proxy that is upgradeable by an admin.
 * 
 * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector
 * clashing], which can potentially be used in an attack, this contract uses the
 * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two
 * things that go hand in hand:
 * 
 * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if
 * that call matches one of the admin functions exposed by the proxy itself.
 * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the
 * implementation. If the admin tries to call a function on the implementation it will fail with an error that says
 * "admin cannot fallback to proxy target".
 * 
 * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing
 * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due
 * to sudden errors when trying to call a function from the proxy implementation.
 * 
 * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,
 * you should think of the `ProxyAdmin` instance as the real administrative inerface of your proxy.
 */
contract TransparentUpgradeableProxy is UpgradeableProxy {
    /**
     * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and
     * optionally initialized with `_data` as explained in {UpgradeableProxy-constructor}.
     */
    constructor(address _logic, address _admin, bytes memory _data) public payable UpgradeableProxy(_logic, _data) {
        assert(_ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1));
        _setAdmin(_admin);
    }

    /**
     * @dev Emitted when the admin account has changed.
     */
    event AdminChanged(address previousAdmin, address newAdmin);

    /**
     * @dev Storage slot with the admin of the contract.
     * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 private constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;

    /**
     * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.
     */
    modifier ifAdmin() {
        if (msg.sender == _admin()) {
            _;
        } else {
            _fallback();
        }
    }

    /**
     * @dev Returns the current admin.
     * 
     * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.
     * 
     * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
     * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
     * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
     */
    function admin() external ifAdmin returns (address) {
        return _admin();
    }

    /**
     * @dev Returns the current implementation.
     * 
     * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.
     * 
     * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
     * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
     * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
     */
    function implementation() external ifAdmin returns (address) {
        return _implementation();
    }

    /**
     * @dev Changes the admin of the proxy.
     * 
     * Emits an {AdminChanged} event.
     * 
     * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.
     */
    function changeAdmin(address newAdmin) external ifAdmin {
        require(newAdmin != address(0), "TransparentUpgradeableProxy: new admin is the zero address");
        emit AdminChanged(_admin(), newAdmin);
        _setAdmin(newAdmin);
    }

    /**
     * @dev Upgrade the implementation of the proxy.
     * 
     * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.
     */
    function upgradeTo(address newImplementation) external ifAdmin {
        _upgradeTo(newImplementation);
    }

    /**
     * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified
     * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the
     * proxied contract.
     * 
     * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.
     */
    function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {
        _upgradeTo(newImplementation);
        // solhint-disable-next-line avoid-low-level-calls
        (bool success,) = newImplementation.delegatecall(data);
        require(success);
    }

    /**
     * @dev Returns the current admin.
     */
    function _admin() internal view returns (address adm) {
        bytes32 slot = _ADMIN_SLOT;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            adm := sload(slot)
        }
    }

    /**
     * @dev Stores a new address in the EIP1967 admin slot.
     */
    function _setAdmin(address newAdmin) private {
        bytes32 slot = _ADMIN_SLOT;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            sstore(slot, newAdmin)
        }
    }

    /**
     * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.
     */
    function _beforeFallback() internal override virtual {
        require(msg.sender != _admin(), "TransparentUpgradeableProxy: admin cannot fallback to proxy target");
        super._beforeFallback();
    }
}

contract TokenProxy is TransparentUpgradeableProxy, ERC20 {
	/**
	 * Contract constructor.
	 * @param _logic address of the initial implementation.
	 * @param _admin Address of the proxy administrator.
	 * @param _data Optional data for executing after deployment
	 */
	constructor(address _logic, address _admin, bytes memory _data) TransparentUpgradeableProxy(_logic, _admin, _data) public payable {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_logic","type":"address"},{"internalType":"address","name":"_admin","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"stateMutability":"payable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"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":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"address","name":"newAdmin","type":"address"}],"name":"changeAdmin","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":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"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":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"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":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]

608060405260405162001a5338038062001a53833981810160405260608110156200002957600080fd5b815160208301516040808501805191519395929483019291846401000000008211156200005557600080fd5b9083019060208201858111156200006b57600080fd5b82516401000000008111828201881017156200008657600080fd5b82525081516020918201929091019080838360005b83811015620000b55781810151838201526020016200009b565b50505050905090810190601f168015620000e35780820380516001836020036101000a031916815260200191505b5060405250849150839050828281620000fc82620001da565b805115620001ba576000826001600160a01b0316826040518082805190602001908083835b60208310620001425780518252601f19909201916020918201910162000121565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d8060008114620001a4576040519150601f19603f3d011682016040523d82523d6000602084013e620001a9565b606091505b5050905080620001b857600080fd5b505b50620001c39050565b620001ce8262000251565b5050505050506200027b565b620001f0816200027560201b62000d631760201c565b6200022d5760405162461bcd60e51b815260040180806020018281038252603681526020018062001a1d6036913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b3b151590565b611792806200028b6000396000f3fe60806040526004361061016a5760003560e01c806370a08231116100d1578063a457c2d71161008a578063d539139311610064578063d53913931461063b578063d547741f14610650578063dd62ed3e14610689578063f851a440146106c457610179565b8063a457c2d71461059f578063a9059cbb146105d8578063ca15c8731461061157610179565b806370a08231146104a65780638f283970146104d95780639010d07c1461050c57806391d148541461053c57806395d89b4114610575578063a217fddf1461058a57610179565b8063313ce56711610123578063313ce5671461032557806336568abe146103505780633659cfe61461038957806339509351146103bc5780634f1ef286146103f55780635c60da1b1461047557610179565b806306fdde0314610181578063095ea7b31461020b57806318160ddd1461025857806323b872dd1461027f578063248a9ca3146102c25780632f2ff15d146102ec57610179565b36610179576101776106d9565b005b6101776106d9565b34801561018d57600080fd5b506101966106f3565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101d05781810151838201526020016101b8565b50505050905090810190601f1680156101fd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561021757600080fd5b506102446004803603604081101561022e57600080fd5b506001600160a01b038135169060200135610789565b604080519115158252519081900360200190f35b34801561026457600080fd5b5061026d6107a7565b60408051918252519081900360200190f35b34801561028b57600080fd5b50610244600480360360608110156102a257600080fd5b506001600160a01b038135811691602081013590911690604001356107ad565b3480156102ce57600080fd5b5061026d600480360360208110156102e557600080fd5b5035610834565b3480156102f857600080fd5b506101776004803603604081101561030f57600080fd5b50803590602001356001600160a01b0316610849565b34801561033157600080fd5b5061033a6108b5565b6040805160ff9092168252519081900360200190f35b34801561035c57600080fd5b506101776004803603604081101561037357600080fd5b50803590602001356001600160a01b03166108be565b34801561039557600080fd5b50610177600480360360208110156103ac57600080fd5b50356001600160a01b031661091f565b3480156103c857600080fd5b50610244600480360360408110156103df57600080fd5b506001600160a01b038135169060200135610959565b6101776004803603604081101561040b57600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561043657600080fd5b82018360208201111561044857600080fd5b8035906020019184600183028401116401000000008311171561046a57600080fd5b5090925090506109a7565b34801561048157600080fd5b5061048a610a54565b604080516001600160a01b039092168252519081900360200190f35b3480156104b257600080fd5b5061026d600480360360208110156104c957600080fd5b50356001600160a01b0316610a8e565b3480156104e557600080fd5b50610177600480360360208110156104fc57600080fd5b50356001600160a01b0316610aa9565b34801561051857600080fd5b5061048a6004803603604081101561052f57600080fd5b5080359060200135610b63565b34801561054857600080fd5b506102446004803603604081101561055f57600080fd5b50803590602001356001600160a01b0316610b82565b34801561058157600080fd5b50610196610b9a565b34801561059657600080fd5b5061026d610bf8565b3480156105ab57600080fd5b50610244600480360360408110156105c257600080fd5b506001600160a01b038135169060200135610bfd565b3480156105e457600080fd5b50610244600480360360408110156105fb57600080fd5b506001600160a01b038135169060200135610c65565b34801561061d57600080fd5b5061026d6004803603602081101561063457600080fd5b5035610c79565b34801561064757600080fd5b5061026d610c90565b34801561065c57600080fd5b506101776004803603604081101561067357600080fd5b50803590602001356001600160a01b0316610cb4565b34801561069557600080fd5b5061026d600480360360408110156106ac57600080fd5b506001600160a01b0381358116916020013516610d0d565b3480156106d057600080fd5b5061048a610d38565b6106e1610d69565b6106f16106ec610dc9565b610dee565b565b60018054604080516020601f6002600019610100878916150201909516949094049384018190048102820181019092528281526060939092909183018282801561077e5780601f106107535761010080835404028352916020019161077e565b820191906000526020600020905b81548152906001019060200180831161076157829003601f168201915b505050505090505b90565b600061079d610796610e12565b8484610e16565b5060015b92915050565b60045490565b60006107ba848484610f02565b61082a846107c6610e12565b61082585604051806060016040528060288152602001611620602891396001600160a01b038a16600090815260066020526040812090610804610e12565b6001600160a01b03168152602081019190915260400160002054919061105f565b610e16565b5060019392505050565b60009081526020819052604090206002015490565b60008281526020819052604090206002015461086c90610867610e12565b610b82565b6108a75760405162461bcd60e51b815260040180806020018281038252602f81526020018061153f602f913960400191505060405180910390fd5b6108b182826110f6565b5050565b60035460ff1690565b6108c6610e12565b6001600160a01b0316816001600160a01b0316146109155760405162461bcd60e51b815260040180806020018281038252602f81526020018061172e602f913960400191505060405180910390fd5b6108b1828261115f565b6109276111c8565b6001600160a01b0316336001600160a01b0316141561094e57610949816111ed565b610956565b6109566106d9565b50565b600061079d610966610e12565b846108258560066000610977610e12565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549061122d565b6109af6111c8565b6001600160a01b0316336001600160a01b03161415610a47576109d1836111ed565b6000836001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610a2e576040519150601f19603f3d011682016040523d82523d6000602084013e610a33565b606091505b5050905080610a4157600080fd5b50610a4f565b610a4f6106d9565b505050565b6000610a5e6111c8565b6001600160a01b0316336001600160a01b03161415610a8657610a7f610dc9565b9050610786565b6107866106d9565b6001600160a01b031660009081526005602052604090205490565b610ab16111c8565b6001600160a01b0316336001600160a01b0316141561094e576001600160a01b038116610b0f5760405162461bcd60e51b815260040180806020018281038252603a8152602001806115e6603a913960400191505060405180910390fd5b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610b386111c8565b604080516001600160a01b03928316815291841660208301528051918290030190a161094981611287565b6000828152602081905260408120610b7b90836112ab565b9392505050565b6000828152602081905260408120610b7b90836112b7565b60028054604080516020601f600019610100600187161502019094168590049384018190048102820181019092528281526060939092909183018282801561077e5780601f106107535761010080835404028352916020019161077e565b600081565b600061079d610c0a610e12565b84610825856040518060600160405280602581526020016117096025913960066000610c34610e12565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919061105f565b600061079d610c72610e12565b8484610f02565b60008181526020819052604081206107a1906112cc565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b600082815260208190526040902060020154610cd290610867610e12565b6109155760405162461bcd60e51b81526004018080602001828103825260308152602001806115b66030913960400191505060405180910390fd5b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205490565b6000610d426111c8565b6001600160a01b0316336001600160a01b03161415610a8657610a7f6111c8565b3b151590565b610d716111c8565b6001600160a01b0316336001600160a01b03161415610dc15760405162461bcd60e51b81526004018080602001828103825260428152602001806116c76042913960600191505060405180910390fd5b6106f16106f1565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b3660008037600080366000845af43d6000803e808015610e0d573d6000f35b3d6000fd5b3390565b6001600160a01b038316610e5b5760405162461bcd60e51b81526004018080602001828103825260248152602001806116a36024913960400191505060405180910390fd5b6001600160a01b038216610ea05760405162461bcd60e51b815260040180806020018281038252602281526020018061156e6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260066020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b038316610f475760405162461bcd60e51b815260040180806020018281038252602581526020018061167e6025913960400191505060405180910390fd5b6001600160a01b038216610f8c5760405162461bcd60e51b815260040180806020018281038252602381526020018061151c6023913960400191505060405180910390fd5b610f97838383610a4f565b610fd481604051806060016040528060268152602001611590602691396001600160a01b038616600090815260056020526040902054919061105f565b6001600160a01b038085166000908152600560205260408082209390935590841681522054611003908261122d565b6001600160a01b0380841660008181526005602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156110ee5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156110b357818101518382015260200161109b565b50505050905090810190601f1680156110e05780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082815260208190526040902061110e90826112d7565b156108b15761111b610e12565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b600082815260208190526040902061117790826112ec565b156108b157611184610e12565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6111f681611301565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b600082820183811015610b7b576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b6000610b7b8383611369565b6000610b7b836001600160a01b0384166113cd565b60006107a1826113e5565b6000610b7b836001600160a01b0384166113e9565b6000610b7b836001600160a01b038416611433565b61130a81610d63565b6113455760405162461bcd60e51b81526004018080602001828103825260368152602001806116486036913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b815460009082106113ab5760405162461bcd60e51b81526004018080602001828103825260228152602001806114fa6022913960400191505060405180910390fd5b8260000182815481106113ba57fe5b9060005260206000200154905092915050565b60009081526001919091016020526040902054151590565b5490565b60006113f583836113cd565b61142b575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556107a1565b5060006107a1565b600081815260018301602052604081205480156114ef578354600019808301919081019060009087908390811061146657fe5b906000526020600020015490508087600001848154811061148357fe5b6000918252602080832090910192909255828152600189810190925260409020908401905586548790806114b357fe5b600190038181906000526020600020016000905590558660010160008781526020019081526020016000206000905560019450505050506107a1565b60009150506107a156fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e647345524332303a207472616e7366657220746f20746865207a65726f2061646472657373416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e2061646d696e20746f206772616e7445524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e2061646d696e20746f207265766f6b655472616e73706172656e745570677261646561626c6550726f78793a206e65772061646d696e20697320746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e63655570677261646561626c6550726f78793a206e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e747261637445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573735472616e73706172656e745570677261646561626c6550726f78793a2061646d696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267657445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636520726f6c657320666f722073656c66a2646970667358221220ce209b92b8bb648f5e3c36f5aa0fed2642dd4e07a6e6f6d1e3ec3ee69ed9e29d64736f6c634300060c00335570677261646561626c6550726f78793a206e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e74726163740000000000000000000000005b103d2125d83d2521815f62304b67b2c2403a45000000000000000000000000333b72521dd9cac06b3677d8b996821ddb0b4aa200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000005b103d2125d83d2521815f62304b67b2c2403a45000000000000000000000000333b72521dd9cac06b3677d8b996821ddb0b4aa200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _logic (address): 0x5b103d2125d83d2521815f62304b67b2c2403a45
Arg [1] : _admin (address): 0x333b72521dd9cac06b3677d8b996821ddb0b4aa2
Arg [2] : _data (bytes): 0x

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000005b103d2125d83d2521815f62304b67b2c2403a45
Arg [1] : 000000000000000000000000333b72521dd9cac06b3677d8b996821ddb0b4aa2
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000


Deployed ByteCode Sourcemap

52852:412:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43384:11;:9;:11::i;:::-;52852:412;;43160:11;:9;:11::i;32360:83::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34279:169;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;34279:169:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;33248:100;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;34922:321;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;34922:321:0;;;;;;;;;;;;;;;;;:::i;27097:114::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;27097:114:0;;:::i;27473:227::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;27473:227:0;;;;;;-1:-1:-1;;;;;27473:227:0;;:::i;33100:83::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;28682:209;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;28682:209:0;;;;;;-1:-1:-1;;;;;28682:209:0;;:::i;51128:111::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;51128:111:0;-1:-1:-1;;;;;51128:111:0;;:::i;35652:218::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;35652:218:0;;;;;;;;:::i;51625:299::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;51625:299:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;51625:299:0;;-1:-1:-1;51625:299:0;-1:-1:-1;51625:299:0;:::i;50394:104::-;;;;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;50394:104:0;;;;;;;;;;;;;;33411:119;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;33411:119:0;-1:-1:-1;;;;;33411:119:0;;:::i;50714:246::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;50714:246:0;-1:-1:-1;;;;;50714:246:0;;:::i;26770:138::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;26770:138:0;;;;;;;:::i;25731:139::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;25731:139:0;;;;;;-1:-1:-1;;;;;25731:139:0;;:::i;32562:87::-;;;;;;;;;;;;;:::i;24476:49::-;;;;;;;;;;;;;:::i;36373:269::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;36373:269:0;;;;;;;;:::i;33743:175::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;33743:175:0;;;;;;;;:::i;26044:127::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;26044:127:0;;:::i;31746:62::-;;;;;;;;;;;;;:::i;27945:230::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;27945:230:0;;;;;;-1:-1:-1;;;;;27945:230:0;;:::i;33981:151::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;33981:151:0;;;;;;;;;;:::i;49835:86::-;;;;;;;;;;;;;:::i;42812:105::-;42853:17;:15;:17::i;:::-;42881:28;42891:17;:15;:17::i;:::-;42881:9;:28::i;:::-;42812:105::o;32360:83::-;32430:5;32423:12;;;;;;;;-1:-1:-1;;32423:12:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32397:13;;32423:12;;32430:5;;32423:12;;32430:5;32423:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32360:83;;:::o;34279:169::-;34362:4;34379:39;34388:12;:10;:12::i;:::-;34402:7;34411:6;34379:8;:39::i;:::-;-1:-1:-1;34436:4:0;34279:169;;;;;:::o;33248:100::-;33328:12;;33248:100;:::o;34922:321::-;35028:4;35045:36;35055:6;35063:9;35074:6;35045:9;:36::i;:::-;35092:121;35101:6;35109:12;:10;:12::i;:::-;35123:89;35161:6;35123:89;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;35123:19:0;;;;;;:11;:19;;;;;;35143:12;:10;:12::i;:::-;-1:-1:-1;;;;;35123:33:0;;;;;;;;;;;;-1:-1:-1;35123:33:0;;;:89;:37;:89::i;:::-;35092:8;:121::i;:::-;-1:-1:-1;35231:4:0;34922:321;;;;;:::o;27097:114::-;27154:7;27181:12;;;;;;;;;;:22;;;;27097:114::o;27473:227::-;27565:6;:12;;;;;;;;;;:22;;;27557:45;;27589:12;:10;:12::i;:::-;27557:7;:45::i;:::-;27549:105;;;;-1:-1:-1;;;27549:105:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27667:25;27678:4;27684:7;27667:10;:25::i;:::-;27473:227;;:::o;33100:83::-;33166:9;;;;33100:83;:::o;28682:209::-;28780:12;:10;:12::i;:::-;-1:-1:-1;;;;;28769:23:0;:7;-1:-1:-1;;;;;28769:23:0;;28761:83;;;;-1:-1:-1;;;28761:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28857:26;28869:4;28875:7;28857:11;:26::i;51128:111::-;49291:8;:6;:8::i;:::-;-1:-1:-1;;;;;49277:22:0;:10;-1:-1:-1;;;;;49277:22:0;;49273:100;;;51202:29:::1;51213:17;51202:10;:29::i;:::-;49273:100:::0;;;49350:11;:9;:11::i;:::-;51128:111;:::o;35652:218::-;35740:4;35757:83;35766:12;:10;:12::i;:::-;35780:7;35789:50;35828:10;35789:11;:25;35801:12;:10;:12::i;:::-;-1:-1:-1;;;;;35789:25:0;;;;;;;;;;;;;;;;;-1:-1:-1;35789:25:0;;;:34;;;;;;;;;;;:38;:50::i;51625:299::-;49291:8;:6;:8::i;:::-;-1:-1:-1;;;;;49277:22:0;:10;-1:-1:-1;;;;;49277:22:0;;49273:100;;;51735:29:::1;51746:17;51735:10;:29::i;:::-;51836:12;51853:17;-1:-1:-1::0;;;;;51853:30:0::1;51884:4;;51853:36;;;;;;;;;;::::0;;::::1;::::0;-1:-1:-1;51853:36:0::1;::::0;-1:-1:-1;51853:36:0;;-1:-1:-1;;51853:36:0;;::::1;::::0;;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;51835:54;;;51908:7;51900:16;;;::::0;::::1;;49316:1;49273:100:::0;;;49350:11;:9;:11::i;:::-;51625:299;;;:::o;50394:104::-;50446:7;49291:8;:6;:8::i;:::-;-1:-1:-1;;;;;49277:22:0;:10;-1:-1:-1;;;;;49277:22:0;;49273:100;;;50473:17:::1;:15;:17::i;:::-;50466:24;;49273:100:::0;;;49350:11;:9;:11::i;33411:119::-;-1:-1:-1;;;;;33504:18:0;33477:7;33504:18;;;:9;:18;;;;;;;33411:119::o;50714:246::-;49291:8;:6;:8::i;:::-;-1:-1:-1;;;;;49277:22:0;:10;-1:-1:-1;;;;;49277:22:0;;49273:100;;;-1:-1:-1;;;;;50789:22:0;::::1;50781:93;;;;-1:-1:-1::0;;;50781:93:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50890:32;50903:8;:6;:8::i;:::-;50890:32;::::0;;-1:-1:-1;;;;;50890:32:0;;::::1;::::0;;;;::::1;;::::0;::::1;::::0;;;;;;;;;::::1;50933:19;50943:8;50933:9;:19::i;26770:138::-:0;26843:7;26870:12;;;;;;;;;;:30;;26894:5;26870:23;:30::i;:::-;26863:37;26770:138;-1:-1:-1;;;26770:138:0:o;25731:139::-;25800:4;25824:12;;;;;;;;;;:38;;25854:7;25824:29;:38::i;32562:87::-;32634:7;32627:14;;;;;;;-1:-1:-1;;32627:14:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32601:13;;32627:14;;32634:7;;32627:14;;32634:7;32627:14;;;;;;;;;;;;;;;;;;;;;;;;24476:49;24521:4;24476:49;:::o;36373:269::-;36466:4;36483:129;36492:12;:10;:12::i;:::-;36506:7;36515:96;36554:15;36515:96;;;;;;;;;;;;;;;;;:11;:25;36527:12;:10;:12::i;:::-;-1:-1:-1;;;;;36515:25:0;;;;;;;;;;;;;;;;;-1:-1:-1;36515:25:0;;;:34;;;;;;;;;;;:96;:38;:96::i;33743:175::-;33829:4;33846:42;33856:12;:10;:12::i;:::-;33870:9;33881:6;33846:9;:42::i;26044:127::-;26107:7;26134:12;;;;;;;;;;:29;;:27;:29::i;31746:62::-;31784:24;31746:62;:::o;27945:230::-;28038:6;:12;;;;;;;;;;:22;;;28030:45;;28062:12;:10;:12::i;28030:45::-;28022:106;;;;-1:-1:-1;;;28022:106:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33981:151;-1:-1:-1;;;;;34097:18:0;;;34070:7;34097:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;33981:151::o;49835:86::-;49878:7;49291:8;:6;:8::i;:::-;-1:-1:-1;;;;;49277:22:0;:10;-1:-1:-1;;;;;49277:22:0;;49273:100;;;49905:8:::1;:6;:8::i;16691:422::-:0;17058:20;17097:8;;;16691:422::o;52638:207::-;52724:8;:6;:8::i;:::-;-1:-1:-1;;;;;52710:22:0;:10;-1:-1:-1;;;;;52710:22:0;;;52702:101;;;;-1:-1:-1;;;52702:101:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52814:23;:21;:23::i;45641:248::-;45491:66;45860:11;;45837:45::o;41412:907::-;41804:14;41801:1;41798;41785:34;42022:1;42019;42003:14;42000:1;41984:14;41977:5;41964:60;42101:16;42098:1;42095;42080:38;42141:6;42210:38;;;;42282:16;42279:1;42272:27;42210:38;42229:16;42226:1;42219:27;22515:106;22603:10;22515:106;:::o;39520:346::-;-1:-1:-1;;;;;39622:19:0;;39614:68;;;;-1:-1:-1;;;39614:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;39701:21:0;;39693:68;;;;-1:-1:-1;;;39693:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;39774:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;39826:32;;;;;;;;;;;;;;;;;39520:346;;;:::o;37132:539::-;-1:-1:-1;;;;;37238:20:0;;37230:70;;;;-1:-1:-1;;;37230:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;37319:23:0;;37311:71;;;;-1:-1:-1;;;37311:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37395:47;37416:6;37424:9;37435:6;37395:20;:47::i;:::-;37475:71;37497:6;37475:71;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;37475:17:0;;;;;;:9;:17;;;;;;;:71;:21;:71::i;:::-;-1:-1:-1;;;;;37455:17:0;;;;;;;:9;:17;;;;;;:91;;;;37580:20;;;;;;;:32;;37605:6;37580:24;:32::i;:::-;-1:-1:-1;;;;;37557:20:0;;;;;;;:9;:20;;;;;;;;;:55;;;;37628:35;;;;;;;37557:20;;37628:35;;;;;;;;;;;;;37132:539;;;:::o;4483:192::-;4569:7;4605:12;4597:6;;;;4589:29;;;;-1:-1:-1;;;4589:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;4641:5:0;;;4483:192::o;29925:188::-;29999:6;:12;;;;;;;;;;:33;;30024:7;29999:24;:33::i;:::-;29995:111;;;30081:12;:10;:12::i;:::-;-1:-1:-1;;;;;30054:40:0;30072:7;-1:-1:-1;;;;;30054:40:0;30066:4;30054:40;;;;;;;;;;29925:188;;:::o;30121:192::-;30196:6;:12;;;;;;;;;;:36;;30224:7;30196:27;:36::i;:::-;30192:114;;;30281:12;:10;:12::i;:::-;-1:-1:-1;;;;;30254:40:0;30272:7;-1:-1:-1;;;;;30254:40:0;30266:4;30254:40;;;;;;;;;;30121:192;;:::o;51990:219::-;49030:66;52180:11;;52158:44::o;46016:155::-;46083:37;46102:17;46083:18;:37::i;:::-;46136:27;;-1:-1:-1;;;;;46136:27:0;;;;;;;;46016:155;:::o;3580:181::-;3638:7;3670:5;;;3694:6;;;;3686:46;;;;;-1:-1:-1;;;3686:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;52296:216;49030:66;52472:22;52457:48::o;14247:149::-;14321:7;14364:22;14368:3;14380:5;14364:3;:22::i;13542:158::-;13622:4;13646:46;13656:3;-1:-1:-1;;;;;13676:14:0;;13646:9;:46::i;13786:117::-;13849:7;13876:19;13884:3;13876:7;:19::i;12988:143::-;13058:4;13082:41;13087:3;-1:-1:-1;;;;;13107:14:0;;13082:4;:41::i;13307:149::-;13380:4;13404:44;13412:3;-1:-1:-1;;;;;13432:14:0;;13404:7;:44::i;46267:369::-;46349:37;46368:17;46349:18;:37::i;:::-;46341:104;;;;-1:-1:-1;;;46341:104:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45491:66;46587:31;46572:57::o;12530:204::-;12625:18;;12597:7;;12625:26;-1:-1:-1;12617:73:0;;;;-1:-1:-1;;;12617:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12708:3;:11;;12720:5;12708:18;;;;;;;;;;;;;;;;12701:25;;12530:204;;;;:::o;11862:129::-;11935:4;11959:19;;;:12;;;;;:19;;;;;;:24;;;11862:129::o;12077:109::-;12160:18;;12077:109::o;9642:414::-;9705:4;9727:21;9737:3;9742:5;9727:9;:21::i;:::-;9722:327;;-1:-1:-1;9765:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;9948:18;;9926:19;;;:12;;;:19;;;;;;:40;;;;9981:11;;9722:327;-1:-1:-1;10032:5:0;10025:12;;10232:1544;10298:4;10437:19;;;:12;;;:19;;;;;;10473:15;;10469:1300;;10908:18;;-1:-1:-1;;10859:14:0;;;;10908:22;;;;10835:21;;10908:3;;:22;;11195;;;;;;;;;;;;;;11175:42;;11341:9;11312:3;:11;;11324:13;11312:26;;;;;;;;;;;;;;;;;;;:38;;;;11418:23;;;11460:1;11418:12;;;:23;;;;;;11444:17;;;11418:43;;11570:17;;11418:3;;11570:17;;;;;;;;;;;;;;;;;;;;;;11665:3;:12;;:19;11678:5;11665:19;;;;;;;;;;;11658:26;;;11708:4;11701:11;;;;;;;;10469:1300;11752:5;11745:12;;;;

Swarm Source

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