Goerli Testnet

Token

Gho Token (GHO)
ERC-20

Overview

Max Total Supply

1,323,468,685.650348092944482948 GHO

Holders

62,719

Market

Fully Diluted Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Balance
5 GHO
0x4d217dc1cda85f4c044a0314cf1beb0b0cbc3189
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
GhoToken

Compiler Version
v0.8.10+commit.fc410830

Optimization Enabled:
Yes with 100000 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 9 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

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

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 2 of 9 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @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 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 `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, 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 `from` to `to` 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 from,
        address to,
        uint256 amount
    ) external returns (bool);
}

File 3 of 9 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with 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) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

File 4 of 9 : EnumerableSet.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.

pragma solidity ^0.8.0;

/**
 * @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.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 *
 * [WARNING]
 * ====
 * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
 * unusable.
 * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
 *
 * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
 * array of EnumerableSet.
 * ====
 */
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;

            if (lastIndex != toDeleteIndex) {
                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] = valueIndex; // Replace lastValue's index to valueIndex
            }

            // 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) {
        return set._values[index];
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    // Bytes32Set

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

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
        bytes32[] memory store = _values(set._inner);
        bytes32[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // 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(uint160(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(uint160(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(uint160(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(uint160(uint256(_at(set._inner, index))));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // 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 in 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 Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }
}

File 5 of 9 : ERC20.sol
// SPDX-License-Identifier: MIT-only
pragma solidity ^0.8.0;

import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';

/**
 * @title ERC20
 * @notice Gas Efficient ERC20 + EIP-2612 implementation
 * @dev Modified version of Solmate ERC20 (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol),
 * implementing the basic IERC20
 */
abstract contract ERC20 is IERC20 {
  /*///////////////////////////////////////////////////////////////
                             METADATA STORAGE
    //////////////////////////////////////////////////////////////*/

  string public name;

  string public symbol;

  uint8 public immutable decimals;

  /*///////////////////////////////////////////////////////////////
                              ERC20 STORAGE
    //////////////////////////////////////////////////////////////*/

  uint256 public totalSupply;

  mapping(address => uint256) public balanceOf;

  mapping(address => mapping(address => uint256)) public allowance;

  /*///////////////////////////////////////////////////////////////
                             EIP-2612 STORAGE
    //////////////////////////////////////////////////////////////*/

  bytes32 public constant PERMIT_TYPEHASH =
    keccak256('Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)');

  uint256 internal immutable INITIAL_CHAIN_ID;

  bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;

  mapping(address => uint256) public nonces;

  /*///////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

  constructor(
    string memory _name,
    string memory _symbol,
    uint8 _decimals
  ) {
    name = _name;
    symbol = _symbol;
    decimals = _decimals;

    INITIAL_CHAIN_ID = block.chainid;
    INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
  }

  /*///////////////////////////////////////////////////////////////
                              ERC20 LOGIC
    //////////////////////////////////////////////////////////////*/

  function approve(address spender, uint256 amount) public virtual returns (bool) {
    allowance[msg.sender][spender] = amount;

    emit Approval(msg.sender, spender, amount);

    return true;
  }

  function transfer(address to, uint256 amount) public virtual returns (bool) {
    balanceOf[msg.sender] -= amount;

    // Cannot overflow because the sum of all user
    // balances can't exceed the max uint256 value.
    unchecked {
      balanceOf[to] += amount;
    }

    emit Transfer(msg.sender, to, amount);

    return true;
  }

  function transferFrom(
    address from,
    address to,
    uint256 amount
  ) public virtual returns (bool) {
    uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.

    if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;

    balanceOf[from] -= amount;

    // Cannot overflow because the sum of all user
    // balances can't exceed the max uint256 value.
    unchecked {
      balanceOf[to] += amount;
    }

    emit Transfer(from, to, amount);

    return true;
  }

  /*///////////////////////////////////////////////////////////////
                              EIP-2612 LOGIC
    //////////////////////////////////////////////////////////////*/

  function permit(
    address owner,
    address spender,
    uint256 value,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
  ) public virtual {
    require(deadline >= block.timestamp, 'PERMIT_DEADLINE_EXPIRED');

    // Unchecked because the only math done is incrementing
    // the owner's nonce which cannot realistically overflow.
    unchecked {
      bytes32 digest = keccak256(
        abi.encodePacked(
          '\x19\x01',
          DOMAIN_SEPARATOR(),
          keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))
        )
      );

      address recoveredAddress = ecrecover(digest, v, r, s);

      require(recoveredAddress != address(0) && recoveredAddress == owner, 'INVALID_SIGNER');

      allowance[recoveredAddress][spender] = value;
    }

    emit Approval(owner, spender, value);
  }

  function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
    return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
  }

  function computeDomainSeparator() internal view virtual returns (bytes32) {
    return
      keccak256(
        abi.encode(
          keccak256(
            'EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'
          ),
          keccak256(bytes(name)),
          keccak256('1'),
          block.chainid,
          address(this)
        )
      );
  }

  /*///////////////////////////////////////////////////////////////
                       INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

  function _mint(address to, uint256 amount) internal virtual {
    totalSupply += amount;

    // Cannot overflow because the sum of all user
    // balances can't exceed the max uint256 value.
    unchecked {
      balanceOf[to] += amount;
    }

    emit Transfer(address(0), to, amount);
  }

  function _burn(address from, uint256 amount) internal virtual {
    balanceOf[from] -= amount;

    // Cannot underflow because a user's balance
    // will never be larger than the total supply.
    unchecked {
      totalSupply -= amount;
    }

    emit Transfer(from, address(0), amount);
  }
}

File 6 of 9 : GhoToken.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import {EnumerableSet} from '@openzeppelin/contracts/utils/structs/EnumerableSet.sol';
import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol';
import {ERC20} from './ERC20.sol';
import {IGhoToken} from './interfaces/IGhoToken.sol';

/**
 * @title GHO Token
 * @author Aave
 */
contract GhoToken is ERC20, Ownable, IGhoToken {
  using EnumerableSet for EnumerableSet.AddressSet;

  mapping(address => Facilitator) internal _facilitators;
  EnumerableSet.AddressSet internal _facilitatorsList;

  /**
   * @dev Constructor
   */
  constructor() ERC20('Gho Token', 'GHO', 18) {
    // Intentionally left blank
  }

  /**
   * @notice Mints the requested amount of tokens to the account address.
   * @dev Only facilitators with enough bucket capacity available can mint.
   * @dev The bucket level is increased upon minting.
   * @param account The address receiving the GHO tokens
   * @param amount The amount to mint
   */
  function mint(address account, uint256 amount) external override {
    Facilitator storage f = _facilitators[msg.sender];
    uint256 bucketCapacity = f.bucketCapacity;
    require(bucketCapacity > 0, 'INVALID_FACILITATOR');

    uint256 currentBucketLevel = f.bucketLevel;
    uint256 newBucketLevel = currentBucketLevel + amount;
    require(bucketCapacity >= newBucketLevel, 'FACILITATOR_BUCKET_CAPACITY_EXCEEDED');
    f.bucketLevel = uint128(newBucketLevel);

    _mint(account, amount);

    emit FacilitatorBucketLevelUpdated(msg.sender, currentBucketLevel, newBucketLevel);
  }

  /**
   * @notice Burns the requested amount of tokens from the account address.
   * @dev Only active facilitators (capacity > 0) can burn.
   * @dev The bucket level is decreased upon burning.
   * @param amount The amount to burn
   */
  function burn(uint256 amount) external override {
    require(amount != 0, 'INVALID_BURN_AMOUNT');

    Facilitator storage f = _facilitators[msg.sender];
    uint256 currentBucketLevel = f.bucketLevel;
    uint256 newBucketLevel = currentBucketLevel - amount;
    f.bucketLevel = uint128(newBucketLevel);

    _burn(msg.sender, amount);

    emit FacilitatorBucketLevelUpdated(msg.sender, currentBucketLevel, newBucketLevel);
  }

  /// @inheritdoc IGhoToken
  function addFacilitator(address facilitatorAddress, Facilitator memory facilitatorConfig)
    external
    onlyOwner
  {
    Facilitator storage facilitator = _facilitators[facilitatorAddress];
    require(bytes(facilitator.label).length == 0, 'FACILITATOR_ALREADY_EXISTS');
    require(bytes(facilitatorConfig.label).length > 0, 'INVALID_LABEL');
    require(facilitatorConfig.bucketLevel == 0, 'INVALID_BUCKET_CONFIGURATION');

    facilitator.label = facilitatorConfig.label;
    facilitator.bucketCapacity = facilitatorConfig.bucketCapacity;

    _facilitatorsList.add(facilitatorAddress);

    emit FacilitatorAdded(
      facilitatorAddress,
      keccak256(abi.encodePacked(facilitatorConfig.label)),
      facilitatorConfig.bucketCapacity
    );
  }

  /// @inheritdoc IGhoToken
  function removeFacilitator(address facilitatorAddress) external onlyOwner {
    require(
      bytes(_facilitators[facilitatorAddress].label).length > 0,
      'FACILITATOR_DOES_NOT_EXIST'
    );
    require(
      _facilitators[facilitatorAddress].bucketLevel == 0,
      'FACILITATOR_BUCKET_LEVEL_NOT_ZERO'
    );

    delete _facilitators[facilitatorAddress];
    _facilitatorsList.remove(facilitatorAddress);

    emit FacilitatorRemoved(facilitatorAddress);
  }

  /// @inheritdoc IGhoToken
  function setFacilitatorBucketCapacity(address facilitator, uint128 newCapacity)
    external
    onlyOwner
  {
    require(bytes(_facilitators[facilitator].label).length > 0, 'FACILITATOR_DOES_NOT_EXIST');

    uint256 oldCapacity = _facilitators[facilitator].bucketCapacity;
    _facilitators[facilitator].bucketCapacity = newCapacity;

    emit FacilitatorBucketCapacityUpdated(facilitator, oldCapacity, newCapacity);
  }

  /// @inheritdoc IGhoToken
  function getFacilitator(address facilitator) external view returns (Facilitator memory) {
    return _facilitators[facilitator];
  }

  /// @inheritdoc IGhoToken
  function getFacilitatorBucket(address facilitator) external view returns (uint256, uint256) {
    return (_facilitators[facilitator].bucketCapacity, _facilitators[facilitator].bucketLevel);
  }

  /// @inheritdoc IGhoToken
  function getFacilitatorsList() external view returns (address[] memory) {
    return _facilitatorsList.values();
  }
}

File 7 of 9 : IERC20Burnable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/**
 * @dev Interface of a burnable erc-20 token
 */
interface IERC20Burnable {
  /**
   * @dev Destroys `amount` tokens from caller
   * @param amount The amount of tokens to destroy
   */
  function burn(uint256 amount) external;
}

File 8 of 9 : IERC20Mintable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/**
 * @dev Interface of a mintable erc-20 token
 */
interface IERC20Mintable {
  /**
   * @dev Creates `amount` new tokens for `account`
   * @param account The address to create tokens for
   * @param amount The amount of tokens to create
   */
  function mint(address account, uint256 amount) external;
}

File 9 of 9 : IGhoToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {IERC20Burnable} from './IERC20Burnable.sol';
import {IERC20Mintable} from './IERC20Mintable.sol';

/**
 * @title IGhoToken
 * @author Aave
 */
interface IGhoToken is IERC20Burnable, IERC20Mintable, IERC20 {
  struct Facilitator {
    uint128 bucketCapacity;
    uint128 bucketLevel;
    string label;
  }

  /**
   * @dev Emitted when a new facilitator is added
   * @param facilitatorAddress The address of the new facilitator
   * @param label A hashed human readable identifier for the facilitator
   * @param bucketCapacity The initial capacity of the facilitator's bucket
   */
  event FacilitatorAdded(
    address indexed facilitatorAddress,
    bytes32 indexed label,
    uint256 bucketCapacity
  );

  /**
   * @dev Emitted when a facilitator is removed
   * @param facilitatorAddress The address of the removed facilitator
   */
  event FacilitatorRemoved(address indexed facilitatorAddress);

  /**
   * @dev Emitted when the bucket capacity of a facilitator is updated
   * @param facilitatorAddress The address of the facilitator whose bucket capacity is being changed
   * @param oldCapacity The old capacity of the bucket
   * @param newCapacity The new capacity of the bucket
   */
  event FacilitatorBucketCapacityUpdated(
    address indexed facilitatorAddress,
    uint256 oldCapacity,
    uint256 newCapacity
  );

  /**
   * @dev Emitted when the bucket level changed
   * @param facilitatorAddress The address of the facilitator whose bucket level is being changed
   * @param oldLevel The old level of the bucket
   * @param newLevel The new level of the bucket
   */
  event FacilitatorBucketLevelUpdated(
    address indexed facilitatorAddress,
    uint256 oldLevel,
    uint256 newLevel
  );

  /**
   * @notice Add the facilitator passed with the parameters to the facilitators list.
   * @param facilitatorAddress The address of the facilitator to add
   * @param facilitatorConfig The configuration of the facilitator
   */
  function addFacilitator(address facilitatorAddress, Facilitator memory facilitatorConfig)
    external;

  /**
   * @notice Remove the facilitator from the facilitators list.
   * @param facilitatorAddress The address of the facilitator to remove
   */
  function removeFacilitator(address facilitatorAddress) external;

  /**
   * @notice Set the bucket capacity of the facilitator.
   * @param facilitator The address of the facilitator
   * @param newCapacity The new capacity of the bucket
   */
  function setFacilitatorBucketCapacity(address facilitator, uint128 newCapacity) external;

  /**
   * @notice Returns the facilitator data
   * @param facilitator The address of the facilitator
   * @return The facilitator configuration
   */
  function getFacilitator(address facilitator) external view returns (Facilitator memory);

  /**
   * @notice Returns the bucket configuration of the facilitator
   * @param facilitator The address of the facilitator
   * @return The capacity of the facilitator's bucket
   * @return The level of the facilitator's bucket
   */
  function getFacilitatorBucket(address facilitator) external view returns (uint256, uint256);

  /**
   * @notice Returns the list of the addresses of the active facilitator
   * @return The list of the facilitators addresses
   */
  function getFacilitatorsList() external view returns (address[] memory);
}

Settings
{
  "evmVersion": "london",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs",
    "useLiteralContent": true
  },
  "optimizer": {
    "enabled": true,
    "runs": 100000
  },
  "remappings": [],
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

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":"facilitatorAddress","type":"address"},{"indexed":true,"internalType":"bytes32","name":"label","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"bucketCapacity","type":"uint256"}],"name":"FacilitatorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"facilitatorAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldCapacity","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newCapacity","type":"uint256"}],"name":"FacilitatorBucketCapacityUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"facilitatorAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldLevel","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newLevel","type":"uint256"}],"name":"FacilitatorBucketLevelUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"facilitatorAddress","type":"address"}],"name":"FacilitatorRemoved","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":"facilitatorAddress","type":"address"},{"components":[{"internalType":"uint128","name":"bucketCapacity","type":"uint128"},{"internalType":"uint128","name":"bucketLevel","type":"uint128"},{"internalType":"string","name":"label","type":"string"}],"internalType":"struct IGhoToken.Facilitator","name":"facilitatorConfig","type":"tuple"}],"name":"addFacilitator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","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":"","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":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"facilitator","type":"address"}],"name":"getFacilitator","outputs":[{"components":[{"internalType":"uint128","name":"bucketCapacity","type":"uint128"},{"internalType":"uint128","name":"bucketLevel","type":"uint128"},{"internalType":"string","name":"label","type":"string"}],"internalType":"struct IGhoToken.Facilitator","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"facilitator","type":"address"}],"name":"getFacilitatorBucket","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFacilitatorsList","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","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":"","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":"value","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":[{"internalType":"address","name":"facilitatorAddress","type":"address"}],"name":"removeFacilitator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"facilitator","type":"address"},{"internalType":"uint128","name":"newCapacity","type":"uint128"}],"name":"setFacilitatorBucketCapacity","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":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","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"}]

60e06040523480156200001157600080fd5b50604080518082018252600981526823b437902a37b5b2b760b91b60208083019182528351808501909452600384526247484f60e81b90840152815191929160129162000062916000919062000195565b5081516200007890600190602085019062000195565b5060ff81166080524660a0526200008e620000a7565b60c05250620000a1915033905062000143565b6200031c565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051620000db919062000278565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b828054620001a3906200023b565b90600052602060002090601f016020900481019282620001c7576000855562000212565b82601f10620001e257805160ff191683800117855562000212565b8280016001018555821562000212579182015b8281111562000212578251825591602001919060010190620001f5565b506200022092915062000224565b5090565b5b8082111562000220576000815560010162000225565b600181811c908216806200025057607f821691505b602082108114156200027257634e487b7160e01b600052602260045260246000fd5b50919050565b600080835481600182811c9150808316806200029557607f831692505b6020808410821415620002b657634e487b7160e01b86526022600452602486fd5b818015620002cd5760018114620002df576200030e565b60ff198616895284890196506200030e565b60008a81526020902060005b86811015620003065781548b820152908501908301620002eb565b505084890196505b509498975050505050505050565b60805160a05160c0516121cf6200034c60003960006106e9015260006106b90152600061024901526121cf6000f3fe608060405234801561001057600080fd5b50600436106101985760003560e01c8063715018a6116100e3578063aa02f94a1161008c578063d505accf11610066578063d505accf14610407578063dd62ed3e1461041a578063f2fde38b1461044557600080fd5b8063aa02f94a1461035e578063af93df57146103d4578063d46ec0ed146103e757600080fd5b806395d89b41116100bd57806395d89b4114610330578063a11812ba14610338578063a9059cbb1461034b57600080fd5b8063715018a6146102e05780637ecebe00146102e85780638da5cb5b1461030857600080fd5b8063313ce5671161014557806342966c681161011f57806342966c681461029a5780634e878860146102ad57806370a08231146102c057600080fd5b8063313ce567146102445780633644e5151461027d57806340c10f191461028557600080fd5b80631ec90f2e116101765780631ec90f2e146101f557806323b872dd1461020a57806330adf81f1461021d57600080fd5b806306fdde031461019d578063095ea7b3146101bb57806318160ddd146101de575b600080fd5b6101a5610458565b6040516101b29190611b72565b60405180910390f35b6101ce6101c9366004611bae565b6104e6565b60405190151581526020016101b2565b6101e760025481565b6040519081526020016101b2565b6101fd610560565b6040516101b29190611bd8565b6101ce610218366004611c32565b610571565b6101e77f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b61026b7f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff90911681526020016101b2565b6101e76106b5565b610298610293366004611bae565b61070b565b005b6102986102a8366004611c6e565b6108da565b6102986102bb366004611d4e565b610a01565b6101e76102ce366004611e62565b60036020526000908152604090205481565b610298610ca3565b6101e76102f6366004611e62565b60056020526000908152604090205481565b60065460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101b2565b6101a5610cb7565b610298610346366004611e62565b610cc4565b6101ce610359366004611bae565b610eca565b6103bf61036c366004611e62565b73ffffffffffffffffffffffffffffffffffffffff166000908152600760205260409020546fffffffffffffffffffffffffffffffff808216927001000000000000000000000000000000009092041690565b604080519283526020830191909152016101b2565b6102986103e2366004611e7d565b610f4f565b6103fa6103f5366004611e62565b61109b565b6040516101b29190611eb0565b610298610415366004611efd565b6111b7565b6101e7610428366004611f70565b600460209081526000928352604080842090915290825290205481565b610298610453366004611e62565b6114e3565b6000805461046590611f9a565b80601f016020809104026020016040519081016040528092919081815260200182805461049190611f9a565b80156104de5780601f106104b3576101008083540402835291602001916104de565b820191906000526020600020905b8154815290600101906020018083116104c157829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259061054e9086815260200190565b60405180910390a35060015b92915050565b606061056c600861159a565b905090565b73ffffffffffffffffffffffffffffffffffffffff831660009081526004602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610605576105d3838261201d565b73ffffffffffffffffffffffffffffffffffffffff861660009081526004602090815260408083203384529091529020555b73ffffffffffffffffffffffffffffffffffffffff85166000908152600360205260408120805485929061063a90849061201d565b909155505073ffffffffffffffffffffffffffffffffffffffff808516600081815260036020526040908190208054870190555190918716907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106a29087815260200190565b60405180910390a3506001949350505050565b60007f000000000000000000000000000000000000000000000000000000000000000046146106e65761056c6115ae565b507f000000000000000000000000000000000000000000000000000000000000000090565b33600090815260076020526040902080546fffffffffffffffffffffffffffffffff168061079a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f494e56414c49445f464143494c495441544f520000000000000000000000000060448201526064015b60405180910390fd5b815470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1660006107ce8583612034565b90508083101561085f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f464143494c495441544f525f4255434b45545f43415041434954595f4558434560448201527f45444544000000000000000000000000000000000000000000000000000000006064820152608401610791565b83546fffffffffffffffffffffffffffffffff8083167001000000000000000000000000000000000291161784556108978686611648565b604080518381526020810183905233917facb6de9209e4f34974cb165eef5738f0cf0b4ea9819ef30d30f0f7d81272ab82910160405180910390a2505050505050565b80610941576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f494e56414c49445f4255524e5f414d4f554e54000000000000000000000000006044820152606401610791565b336000908152600760205260408120805490917001000000000000000000000000000000009091046fffffffffffffffffffffffffffffffff1690610986848361201d565b83546fffffffffffffffffffffffffffffffff80831670010000000000000000000000000000000002911617845590506109c033856116c1565b604080518381526020810183905233917facb6de9209e4f34974cb165eef5738f0cf0b4ea9819ef30d30f0f7d81272ab82910160405180910390a250505050565b610a0961174f565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600760205260409020600181018054610a3d90611f9a565b159050610aa6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f464143494c495441544f525f414c52454144595f4558495354530000000000006044820152606401610791565b600082604001515111610b15576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f494e56414c49445f4c4142454c000000000000000000000000000000000000006044820152606401610791565b60208201516fffffffffffffffffffffffffffffffff1615610b93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f494e56414c49445f4255434b45545f434f4e46494755524154494f4e000000006044820152606401610791565b60408201518051610bae916001840191602090910190611a29565b50815181547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff909116178155610bf76008846117d0565b508160400151604051602001610c0d919061204c565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052805160209182012084516fffffffffffffffffffffffffffffffff1683529173ffffffffffffffffffffffffffffffffffffffff8616917fdabd62626ada7b13e299389e94d768b294e5e24285ed2ffa1e5cd447c99c54ad910160405180910390a3505050565b610cab61174f565b610cb560006117f2565b565b6001805461046590611f9a565b610ccc61174f565b73ffffffffffffffffffffffffffffffffffffffff811660009081526007602052604081206001018054610cff90611f9a565b905011610d68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f464143494c495441544f525f444f45535f4e4f545f45584953540000000000006044820152606401610791565b73ffffffffffffffffffffffffffffffffffffffff811660009081526007602052604090205470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1615610e41576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f464143494c495441544f525f4255434b45545f4c4556454c5f4e4f545f5a455260448201527f4f000000000000000000000000000000000000000000000000000000000000006064820152608401610791565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260076020526040812081815590610e776001830182611aad565b50610e859050600882611869565b5060405173ffffffffffffffffffffffffffffffffffffffff8216907fa8fe5b89f35f2ebd6f3f95a7ef215f4bd89179e10c101073ae76cffad14734cf90600090a250565b33600090815260036020526040812080548391908390610eeb90849061201d565b909155505073ffffffffffffffffffffffffffffffffffffffff8316600081815260036020526040908190208054850190555133907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9061054e9086815260200190565b610f5761174f565b73ffffffffffffffffffffffffffffffffffffffff821660009081526007602052604081206001018054610f8a90611f9a565b905011610ff3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f464143494c495441544f525f444f45535f4e4f545f45584953540000000000006044820152606401610791565b73ffffffffffffffffffffffffffffffffffffffff821660008181526007602090815260409182902080547fffffffffffffffffffffffffffffffff0000000000000000000000000000000081166fffffffffffffffffffffffffffffffff878116918217909355845192909116808352928201529092917fc795c0a4927c3b6645e4e49a5a519af936b3c1c0e4c323a3f7251063f3f4bb0e910160405180910390a2505050565b60408051606080820183526000808352602080840182905283850183905273ffffffffffffffffffffffffffffffffffffffff8616825260078152908490208451928301855280546fffffffffffffffffffffffffffffffff8082168552700100000000000000000000000000000000909104169183019190915260018101805493949293919284019161112e90611f9a565b80601f016020809104026020016040519081016040528092919081815260200182805461115a90611f9a565b80156111a75780601f1061117c576101008083540402835291602001916111a7565b820191906000526020600020905b81548152906001019060200180831161118a57829003601f168201915b5050505050815250509050919050565b42841015611221576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5045524d49545f444541444c494e455f455850495245440000000000000000006044820152606401610791565b600061122b6106b5565b73ffffffffffffffffffffffffffffffffffffffff89811660008181526005602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938c166060840152608083018b905260a083019390935260c08083018a90528151808403909101815260e0830190915280519201919091207f190100000000000000000000000000000000000000000000000000000000000061010083015261010282019290925261012281019190915261014201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa15801561138a573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81161580159061140557508873ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b61146b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f494e56414c49445f5349474e45520000000000000000000000000000000000006044820152606401610791565b73ffffffffffffffffffffffffffffffffffffffff90811660009081526004602090815260408083208b8516808552908352928190208a905551898152919350918a16917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350505050505050565b6114eb61174f565b73ffffffffffffffffffffffffffffffffffffffff811661158e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610791565b611597816117f2565b50565b606060006115a78361188b565b9392505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60006040516115e09190612068565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b806002600082825461165a9190612034565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000818152600360209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91015b60405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260036020526040812080548392906116f690849061201d565b909155505060028054829003905560405181815260009073ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016116b5565b60065473ffffffffffffffffffffffffffffffffffffffff163314610cb5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610791565b60006115a78373ffffffffffffffffffffffffffffffffffffffff84166118e7565b6006805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006115a78373ffffffffffffffffffffffffffffffffffffffff8416611936565b6060816000018054806020026020016040519081016040528092919081815260200182805480156118db57602002820191906000526020600020905b8154815260200190600101908083116118c7575b50505050509050919050565b600081815260018301602052604081205461192e5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561055a565b50600061055a565b60008181526001830160205260408120548015611a1f57600061195a60018361201d565b855490915060009061196e9060019061201d565b90508181146119d357600086600001828154811061198e5761198e61213b565b90600052602060002001549050808760000184815481106119b1576119b161213b565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806119e4576119e461216a565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061055a565b600091505061055a565b828054611a3590611f9a565b90600052602060002090601f016020900481019282611a575760008555611a9d565b82601f10611a7057805160ff1916838001178555611a9d565b82800160010185558215611a9d579182015b82811115611a9d578251825591602001919060010190611a82565b50611aa9929150611ae3565b5090565b508054611ab990611f9a565b6000825580601f10611ac9575050565b601f01602090049060005260206000209081019061159791905b5b80821115611aa95760008155600101611ae4565b60005b83811015611b13578181015183820152602001611afb565b83811115611b22576000848401525b50505050565b60008151808452611b40816020860160208601611af8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006115a76020830184611b28565b803573ffffffffffffffffffffffffffffffffffffffff81168114611ba957600080fd5b919050565b60008060408385031215611bc157600080fd5b611bca83611b85565b946020939093013593505050565b6020808252825182820181905260009190848201906040850190845b81811015611c2657835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101611bf4565b50909695505050505050565b600080600060608486031215611c4757600080fd5b611c5084611b85565b9250611c5e60208501611b85565b9150604084013590509250925092565b600060208284031215611c8057600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715611cd957611cd9611c87565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611d2657611d26611c87565b604052919050565b80356fffffffffffffffffffffffffffffffff81168114611ba957600080fd5b60008060408385031215611d6157600080fd5b611d6a83611b85565b915060208084013567ffffffffffffffff80821115611d8857600080fd5b9085019060608288031215611d9c57600080fd5b611da4611cb6565b611dad83611d2e565b8152611dba848401611d2e565b84820152604083013582811115611dd057600080fd5b80840193505087601f840112611de557600080fd5b823582811115611df757611df7611c87565b611e27857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611cdf565b92508083528885828601011115611e3d57600080fd5b8085850186850137600085828501015250816040820152809450505050509250929050565b600060208284031215611e7457600080fd5b6115a782611b85565b60008060408385031215611e9057600080fd5b611e9983611b85565b9150611ea760208401611d2e565b90509250929050565b6020815260006fffffffffffffffffffffffffffffffff808451166020840152806020850151166040840152506040830151606080840152611ef56080840182611b28565b949350505050565b600080600080600080600060e0888a031215611f1857600080fd5b611f2188611b85565b9650611f2f60208901611b85565b95506040880135945060608801359350608088013560ff81168114611f5357600080fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215611f8357600080fd5b611f8c83611b85565b9150611ea760208401611b85565b600181811c90821680611fae57607f821691505b60208210811415611fe8577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561202f5761202f611fee565b500390565b6000821982111561204757612047611fee565b500190565b6000825161205e818460208701611af8565b9190910192915050565b600080835481600182811c91508083168061208457607f831692505b60208084108214156120bd577f4e487b710000000000000000000000000000000000000000000000000000000086526022600452602486fd5b8180156120d157600181146121005761212d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0086168952848901965061212d565b60008a81526020902060005b868110156121255781548b82015290850190830161210c565b505084890196505b509498975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220e51d0134bf2e65b4dfcef1daaa50edea54ac77181bf47f2af29aebd0f058f31364736f6c634300080a0033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101985760003560e01c8063715018a6116100e3578063aa02f94a1161008c578063d505accf11610066578063d505accf14610407578063dd62ed3e1461041a578063f2fde38b1461044557600080fd5b8063aa02f94a1461035e578063af93df57146103d4578063d46ec0ed146103e757600080fd5b806395d89b41116100bd57806395d89b4114610330578063a11812ba14610338578063a9059cbb1461034b57600080fd5b8063715018a6146102e05780637ecebe00146102e85780638da5cb5b1461030857600080fd5b8063313ce5671161014557806342966c681161011f57806342966c681461029a5780634e878860146102ad57806370a08231146102c057600080fd5b8063313ce567146102445780633644e5151461027d57806340c10f191461028557600080fd5b80631ec90f2e116101765780631ec90f2e146101f557806323b872dd1461020a57806330adf81f1461021d57600080fd5b806306fdde031461019d578063095ea7b3146101bb57806318160ddd146101de575b600080fd5b6101a5610458565b6040516101b29190611b72565b60405180910390f35b6101ce6101c9366004611bae565b6104e6565b60405190151581526020016101b2565b6101e760025481565b6040519081526020016101b2565b6101fd610560565b6040516101b29190611bd8565b6101ce610218366004611c32565b610571565b6101e77f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b61026b7f000000000000000000000000000000000000000000000000000000000000001281565b60405160ff90911681526020016101b2565b6101e76106b5565b610298610293366004611bae565b61070b565b005b6102986102a8366004611c6e565b6108da565b6102986102bb366004611d4e565b610a01565b6101e76102ce366004611e62565b60036020526000908152604090205481565b610298610ca3565b6101e76102f6366004611e62565b60056020526000908152604090205481565b60065460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101b2565b6101a5610cb7565b610298610346366004611e62565b610cc4565b6101ce610359366004611bae565b610eca565b6103bf61036c366004611e62565b73ffffffffffffffffffffffffffffffffffffffff166000908152600760205260409020546fffffffffffffffffffffffffffffffff808216927001000000000000000000000000000000009092041690565b604080519283526020830191909152016101b2565b6102986103e2366004611e7d565b610f4f565b6103fa6103f5366004611e62565b61109b565b6040516101b29190611eb0565b610298610415366004611efd565b6111b7565b6101e7610428366004611f70565b600460209081526000928352604080842090915290825290205481565b610298610453366004611e62565b6114e3565b6000805461046590611f9a565b80601f016020809104026020016040519081016040528092919081815260200182805461049190611f9a565b80156104de5780601f106104b3576101008083540402835291602001916104de565b820191906000526020600020905b8154815290600101906020018083116104c157829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259061054e9086815260200190565b60405180910390a35060015b92915050565b606061056c600861159a565b905090565b73ffffffffffffffffffffffffffffffffffffffff831660009081526004602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610605576105d3838261201d565b73ffffffffffffffffffffffffffffffffffffffff861660009081526004602090815260408083203384529091529020555b73ffffffffffffffffffffffffffffffffffffffff85166000908152600360205260408120805485929061063a90849061201d565b909155505073ffffffffffffffffffffffffffffffffffffffff808516600081815260036020526040908190208054870190555190918716907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106a29087815260200190565b60405180910390a3506001949350505050565b60007f000000000000000000000000000000000000000000000000000000000000000546146106e65761056c6115ae565b507f7520d0aedf78c11b6f8c9ee03e9a1a34cbd3f5d8d35a12b50528b4fdbb9c30a390565b33600090815260076020526040902080546fffffffffffffffffffffffffffffffff168061079a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f494e56414c49445f464143494c495441544f520000000000000000000000000060448201526064015b60405180910390fd5b815470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1660006107ce8583612034565b90508083101561085f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f464143494c495441544f525f4255434b45545f43415041434954595f4558434560448201527f45444544000000000000000000000000000000000000000000000000000000006064820152608401610791565b83546fffffffffffffffffffffffffffffffff8083167001000000000000000000000000000000000291161784556108978686611648565b604080518381526020810183905233917facb6de9209e4f34974cb165eef5738f0cf0b4ea9819ef30d30f0f7d81272ab82910160405180910390a2505050505050565b80610941576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f494e56414c49445f4255524e5f414d4f554e54000000000000000000000000006044820152606401610791565b336000908152600760205260408120805490917001000000000000000000000000000000009091046fffffffffffffffffffffffffffffffff1690610986848361201d565b83546fffffffffffffffffffffffffffffffff80831670010000000000000000000000000000000002911617845590506109c033856116c1565b604080518381526020810183905233917facb6de9209e4f34974cb165eef5738f0cf0b4ea9819ef30d30f0f7d81272ab82910160405180910390a250505050565b610a0961174f565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600760205260409020600181018054610a3d90611f9a565b159050610aa6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f464143494c495441544f525f414c52454144595f4558495354530000000000006044820152606401610791565b600082604001515111610b15576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f494e56414c49445f4c4142454c000000000000000000000000000000000000006044820152606401610791565b60208201516fffffffffffffffffffffffffffffffff1615610b93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f494e56414c49445f4255434b45545f434f4e46494755524154494f4e000000006044820152606401610791565b60408201518051610bae916001840191602090910190611a29565b50815181547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff909116178155610bf76008846117d0565b508160400151604051602001610c0d919061204c565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052805160209182012084516fffffffffffffffffffffffffffffffff1683529173ffffffffffffffffffffffffffffffffffffffff8616917fdabd62626ada7b13e299389e94d768b294e5e24285ed2ffa1e5cd447c99c54ad910160405180910390a3505050565b610cab61174f565b610cb560006117f2565b565b6001805461046590611f9a565b610ccc61174f565b73ffffffffffffffffffffffffffffffffffffffff811660009081526007602052604081206001018054610cff90611f9a565b905011610d68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f464143494c495441544f525f444f45535f4e4f545f45584953540000000000006044820152606401610791565b73ffffffffffffffffffffffffffffffffffffffff811660009081526007602052604090205470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1615610e41576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f464143494c495441544f525f4255434b45545f4c4556454c5f4e4f545f5a455260448201527f4f000000000000000000000000000000000000000000000000000000000000006064820152608401610791565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260076020526040812081815590610e776001830182611aad565b50610e859050600882611869565b5060405173ffffffffffffffffffffffffffffffffffffffff8216907fa8fe5b89f35f2ebd6f3f95a7ef215f4bd89179e10c101073ae76cffad14734cf90600090a250565b33600090815260036020526040812080548391908390610eeb90849061201d565b909155505073ffffffffffffffffffffffffffffffffffffffff8316600081815260036020526040908190208054850190555133907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9061054e9086815260200190565b610f5761174f565b73ffffffffffffffffffffffffffffffffffffffff821660009081526007602052604081206001018054610f8a90611f9a565b905011610ff3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f464143494c495441544f525f444f45535f4e4f545f45584953540000000000006044820152606401610791565b73ffffffffffffffffffffffffffffffffffffffff821660008181526007602090815260409182902080547fffffffffffffffffffffffffffffffff0000000000000000000000000000000081166fffffffffffffffffffffffffffffffff878116918217909355845192909116808352928201529092917fc795c0a4927c3b6645e4e49a5a519af936b3c1c0e4c323a3f7251063f3f4bb0e910160405180910390a2505050565b60408051606080820183526000808352602080840182905283850183905273ffffffffffffffffffffffffffffffffffffffff8616825260078152908490208451928301855280546fffffffffffffffffffffffffffffffff8082168552700100000000000000000000000000000000909104169183019190915260018101805493949293919284019161112e90611f9a565b80601f016020809104026020016040519081016040528092919081815260200182805461115a90611f9a565b80156111a75780601f1061117c576101008083540402835291602001916111a7565b820191906000526020600020905b81548152906001019060200180831161118a57829003601f168201915b5050505050815250509050919050565b42841015611221576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5045524d49545f444541444c494e455f455850495245440000000000000000006044820152606401610791565b600061122b6106b5565b73ffffffffffffffffffffffffffffffffffffffff89811660008181526005602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938c166060840152608083018b905260a083019390935260c08083018a90528151808403909101815260e0830190915280519201919091207f190100000000000000000000000000000000000000000000000000000000000061010083015261010282019290925261012281019190915261014201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa15801561138a573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81161580159061140557508873ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b61146b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f494e56414c49445f5349474e45520000000000000000000000000000000000006044820152606401610791565b73ffffffffffffffffffffffffffffffffffffffff90811660009081526004602090815260408083208b8516808552908352928190208a905551898152919350918a16917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350505050505050565b6114eb61174f565b73ffffffffffffffffffffffffffffffffffffffff811661158e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610791565b611597816117f2565b50565b606060006115a78361188b565b9392505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60006040516115e09190612068565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b806002600082825461165a9190612034565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000818152600360209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91015b60405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260036020526040812080548392906116f690849061201d565b909155505060028054829003905560405181815260009073ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016116b5565b60065473ffffffffffffffffffffffffffffffffffffffff163314610cb5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610791565b60006115a78373ffffffffffffffffffffffffffffffffffffffff84166118e7565b6006805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006115a78373ffffffffffffffffffffffffffffffffffffffff8416611936565b6060816000018054806020026020016040519081016040528092919081815260200182805480156118db57602002820191906000526020600020905b8154815260200190600101908083116118c7575b50505050509050919050565b600081815260018301602052604081205461192e5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561055a565b50600061055a565b60008181526001830160205260408120548015611a1f57600061195a60018361201d565b855490915060009061196e9060019061201d565b90508181146119d357600086600001828154811061198e5761198e61213b565b90600052602060002001549050808760000184815481106119b1576119b161213b565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806119e4576119e461216a565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061055a565b600091505061055a565b828054611a3590611f9a565b90600052602060002090601f016020900481019282611a575760008555611a9d565b82601f10611a7057805160ff1916838001178555611a9d565b82800160010185558215611a9d579182015b82811115611a9d578251825591602001919060010190611a82565b50611aa9929150611ae3565b5090565b508054611ab990611f9a565b6000825580601f10611ac9575050565b601f01602090049060005260206000209081019061159791905b5b80821115611aa95760008155600101611ae4565b60005b83811015611b13578181015183820152602001611afb565b83811115611b22576000848401525b50505050565b60008151808452611b40816020860160208601611af8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006115a76020830184611b28565b803573ffffffffffffffffffffffffffffffffffffffff81168114611ba957600080fd5b919050565b60008060408385031215611bc157600080fd5b611bca83611b85565b946020939093013593505050565b6020808252825182820181905260009190848201906040850190845b81811015611c2657835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101611bf4565b50909695505050505050565b600080600060608486031215611c4757600080fd5b611c5084611b85565b9250611c5e60208501611b85565b9150604084013590509250925092565b600060208284031215611c8057600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715611cd957611cd9611c87565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611d2657611d26611c87565b604052919050565b80356fffffffffffffffffffffffffffffffff81168114611ba957600080fd5b60008060408385031215611d6157600080fd5b611d6a83611b85565b915060208084013567ffffffffffffffff80821115611d8857600080fd5b9085019060608288031215611d9c57600080fd5b611da4611cb6565b611dad83611d2e565b8152611dba848401611d2e565b84820152604083013582811115611dd057600080fd5b80840193505087601f840112611de557600080fd5b823582811115611df757611df7611c87565b611e27857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611cdf565b92508083528885828601011115611e3d57600080fd5b8085850186850137600085828501015250816040820152809450505050509250929050565b600060208284031215611e7457600080fd5b6115a782611b85565b60008060408385031215611e9057600080fd5b611e9983611b85565b9150611ea760208401611d2e565b90509250929050565b6020815260006fffffffffffffffffffffffffffffffff808451166020840152806020850151166040840152506040830151606080840152611ef56080840182611b28565b949350505050565b600080600080600080600060e0888a031215611f1857600080fd5b611f2188611b85565b9650611f2f60208901611b85565b95506040880135945060608801359350608088013560ff81168114611f5357600080fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215611f8357600080fd5b611f8c83611b85565b9150611ea760208401611b85565b600181811c90821680611fae57607f821691505b60208210811415611fe8577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561202f5761202f611fee565b500390565b6000821982111561204757612047611fee565b500190565b6000825161205e818460208701611af8565b9190910192915050565b600080835481600182811c91508083168061208457607f831692505b60208084108214156120bd577f4e487b710000000000000000000000000000000000000000000000000000000086526022600452602486fd5b8180156120d157600181146121005761212d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0086168952848901965061212d565b60008a81526020902060005b868110156121255781548b82015290850190830161210c565b505084890196505b509498975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220e51d0134bf2e65b4dfcef1daaa50edea54ac77181bf47f2af29aebd0f058f31364736f6c634300080a0033

[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.