Contract 0x9656283ede0167f955cb3112027755b392a1ceca 2

Contract Overview

Balance:
0 BNB

Token:
Txn Hash Method
Block
From
To
Value [Txn Fee]
0xaeb65493084a245a440781f7bdc1213251a6f09b77294c2f07673b9feae7f8d7Faucet135347292021-10-25 13:36:051 hr 14 mins ago0xf2014aceec53561b4537f7323224cd65ccb0e13f IN  0x9656283ede0167f955cb3112027755b392a1ceca0 BNB0.00080473
0x70a9c8b81efcc468ee8129aa4da5e111546f5db53fc1fd6064e73e5deca4bfe3Faucet135347152021-10-25 13:35:231 hr 15 mins ago0xf2014aceec53561b4537f7323224cd65ccb0e13f IN  0x9656283ede0167f955cb3112027755b392a1ceca0 BNB0.0008045
0x3b496708f409e60d40a6ddfd9e76357e627ebbd6e26cb39bf3b4b4ebcbbb7307Faucet135342772021-10-25 13:13:291 hr 37 mins ago0xc371bd8ec11c0a179878f137836a5ab701cf0657 IN  0x9656283ede0167f955cb3112027755b392a1ceca0 BNB0.00080473
0x827ae7fe57799476dc302dcfbc9c6036f7f91ffeea3b27333e331b83ef9267f7Faucet135342702021-10-25 13:13:081 hr 37 mins ago0xc371bd8ec11c0a179878f137836a5ab701cf0657 IN  0x9656283ede0167f955cb3112027755b392a1ceca0 BNB0.0008045
0xfa21fe08ad11e042cad4d163e8f8ca882c456e470b1baf70a90069c307fef651Faucet135312002021-10-25 10:39:384 hrs 11 mins ago0xa84f43fd87cacd2f78dfa4700ebe275aea3dac02 IN  0x9656283ede0167f955cb3112027755b392a1ceca0 BNB0.00050473
0x813b5313b37e31c867547fb6c8354f6dad713d4ffdf7a0df3d90fbfc330c7e48Faucet135311962021-10-25 10:39:264 hrs 11 mins ago0xa84f43fd87cacd2f78dfa4700ebe275aea3dac02 IN  0x9656283ede0167f955cb3112027755b392a1ceca0 BNB0.0005045
0xb5417ee3495733466d856b90e74f0172d053490910bba22c4931d1f8ad3ad0d6Faucet135295222021-10-25 9:15:445 hrs 35 mins ago0xaa7adf2d323d349f957cbc7d443da927162bfdcf IN  0x9656283ede0167f955cb3112027755b392a1ceca0 BNB0.00080473
0x0eb9a2e3a63ed6964a9dd58fc85327cabab59963c36fa5bd19431b3cd37cec0aFaucet135295122021-10-25 9:15:145 hrs 35 mins ago0xaa7adf2d323d349f957cbc7d443da927162bfdcf IN  0x9656283ede0167f955cb3112027755b392a1ceca0 BNB0.0008045
0x4f16472f3997513a1dfa2248a0dce3b782e3ad3b0dcad7b1572890835a1b89aeFaucet135221712021-10-25 3:08:0611 hrs 42 mins ago0x258b96ccc25ffab54be22dadb68ba11d52bea585 IN  0x9656283ede0167f955cb3112027755b392a1ceca0 BNB0.0008045
0x5553358fc3a39cf58789ec66fbded6c3133370df3ba018732e817441a79475ceFaucet135221512021-10-25 3:07:0611 hrs 43 mins ago0x258b96ccc25ffab54be22dadb68ba11d52bea585 IN  0x9656283ede0167f955cb3112027755b392a1ceca0 BNB0.00080473
0x10b9149e09c6920363591de08e0173be975d57998bba37c4d6245407806025caFaucet135198902021-10-25 1:14:0313 hrs 36 mins ago0xc320715153f72516b52bbc18a9f3639ed52b73f3 IN  0x9656283ede0167f955cb3112027755b392a1ceca0 BNB0.00050473
0x488dbbf2bcf91192d3371975928bdf32174275892bfa71bf0abca380e369d3c5Faucet135198802021-10-25 1:13:3313 hrs 37 mins ago0xc320715153f72516b52bbc18a9f3639ed52b73f3 IN  0x9656283ede0167f955cb3112027755b392a1ceca0 BNB0.0005045
0x024692bee5754cb0e358b1ecc5d80f1f90e6475311a84b8395f4941108b834c5Faucet135198382021-10-25 1:11:2713 hrs 39 mins ago0x0b0fa59f8c5bd0608ef2166d88f58b0f5b43010e IN  0x9656283ede0167f955cb3112027755b392a1ceca0 BNB0.00050473
0x73d94fd9908bfdc245109d6a1fa30f257c5eaa8275724d15d0e02a9dac6f31cdFaucet135198322021-10-25 1:11:0913 hrs 39 mins ago0x0b0fa59f8c5bd0608ef2166d88f58b0f5b43010e IN  0x9656283ede0167f955cb3112027755b392a1ceca0 BNB0.0005045
0x2e39667dd87068d06e2fd7cd63ba97d819028714757a9aa34fc9bcb95d2a7d62Faucet135189902021-10-25 0:29:0314 hrs 21 mins ago0xbaad91c476ef909ff0400b886f9dff4592073afe IN  0x9656283ede0167f955cb3112027755b392a1ceca0 BNB0.00080473
0x9e85811ed3af3d1dae73ccd135095eca6065d67bf508089cf52940e4fd988ca8Faucet135189812021-10-25 0:28:3614 hrs 22 mins ago0xbaad91c476ef909ff0400b886f9dff4592073afe IN  0x9656283ede0167f955cb3112027755b392a1ceca0 BNB0.0008045
0x58ce0656bbd3c8a5a7cbfea6e601f3caa6f597aa092facb134948215d582db60Faucet135175832021-10-24 23:18:4215 hrs 32 mins ago0x0aeec3682d91806226ab51147536b5c541085a42 IN  0x9656283ede0167f955cb3112027755b392a1ceca0 BNB0.00050473
0xd84b99dedf2e046384b05625b3d95a04228f9f48e63056b7a95008770cf088feFaucet135175752021-10-24 23:18:1815 hrs 32 mins ago0x0aeec3682d91806226ab51147536b5c541085a42 IN  0x9656283ede0167f955cb3112027755b392a1ceca0 BNB0.0005045
0xc1c848ef25c0453febd6cdc83814ad279e76ae3813cf7ebc52ea1f8f120b8e2fFaucet135158182021-10-24 21:50:2717 hrs ago0xa55cb5602342bd20011cf9bead137e4a9fa708ae IN  0x9656283ede0167f955cb3112027755b392a1ceca0 BNB0.00080473
0x81dab6b5e635c66ea1dda28388a8a04194fb0c310abcab22f3e4bf3e2c1ec9cdFaucet135157942021-10-24 21:49:1517 hrs 1 min ago0xa55cb5602342bd20011cf9bead137e4a9fa708ae IN  0x9656283ede0167f955cb3112027755b392a1ceca0 BNB0.0008045
0x24392adc12e5ad4d36fedfbf7ff0c0308981aafe055333f4c36e477393ea2d89Faucet135129302021-10-24 19:26:0319 hrs 24 mins ago0x35471534e67b310741b7ed3cb4a1293a4be99146 IN  0x9656283ede0167f955cb3112027755b392a1ceca0 BNB0.00080473
0x04817cfed8bda0e06ac050bcd4188c6414efc213c6b847b5b5c5c10d371d2451Faucet135129222021-10-24 19:25:3919 hrs 25 mins ago0x35471534e67b310741b7ed3cb4a1293a4be99146 IN  0x9656283ede0167f955cb3112027755b392a1ceca0 BNB0.0008045
0x760724328916bc236a84a84180e972b3d2c27912d940a0049e5fb3a0b8340d76Faucet135115812021-10-24 18:18:3620 hrs 32 mins ago0x1bde3c175ca84bf9970df5bea75f2b1d51faa672 IN  0x9656283ede0167f955cb3112027755b392a1ceca0 BNB0.00050473
0x9b51d9b6a53c65f75d0408e53fef2709629499c59e1e5ab1722cd409613ae206Faucet135115722021-10-24 18:18:0920 hrs 32 mins ago0x1bde3c175ca84bf9970df5bea75f2b1d51faa672 IN  0x9656283ede0167f955cb3112027755b392a1ceca0 BNB0.0005045
0x181e551d37f2f402d16d0cb5c4d5f5b099ce88c87b528802015462eb85a0a955Faucet135113422021-10-24 18:06:3920 hrs 44 mins ago0x79989dffe5242bb5efc25f2cebe34b99ff53a36d IN  0x9656283ede0167f955cb3112027755b392a1ceca0 BNB0.00080473
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0xaeb65493084a245a440781f7bdc1213251a6f09b77294c2f07673b9feae7f8d7135347292021-10-25 13:36:051 hr 14 mins ago 0x9656283ede0167f955cb3112027755b392a1ceca 0xcd2d09fa9d425682085bc94ed0c7bada6cabcdba0 BNB
0x70a9c8b81efcc468ee8129aa4da5e111546f5db53fc1fd6064e73e5deca4bfe3135347152021-10-25 13:35:231 hr 15 mins ago 0x9656283ede0167f955cb3112027755b392a1ceca 0x56190b59760d472450f65dca7c54e50cf5ebbd410 BNB
0x3b496708f409e60d40a6ddfd9e76357e627ebbd6e26cb39bf3b4b4ebcbbb7307135342772021-10-25 13:13:291 hr 37 mins ago 0x9656283ede0167f955cb3112027755b392a1ceca 0xcd2d09fa9d425682085bc94ed0c7bada6cabcdba0 BNB
0x827ae7fe57799476dc302dcfbc9c6036f7f91ffeea3b27333e331b83ef9267f7135342702021-10-25 13:13:081 hr 37 mins ago 0x9656283ede0167f955cb3112027755b392a1ceca 0x56190b59760d472450f65dca7c54e50cf5ebbd410 BNB
0xfa21fe08ad11e042cad4d163e8f8ca882c456e470b1baf70a90069c307fef651135312002021-10-25 10:39:384 hrs 11 mins ago 0x9656283ede0167f955cb3112027755b392a1ceca 0xcd2d09fa9d425682085bc94ed0c7bada6cabcdba0 BNB
0x813b5313b37e31c867547fb6c8354f6dad713d4ffdf7a0df3d90fbfc330c7e48135311962021-10-25 10:39:264 hrs 11 mins ago 0x9656283ede0167f955cb3112027755b392a1ceca 0x56190b59760d472450f65dca7c54e50cf5ebbd410 BNB
0xb5417ee3495733466d856b90e74f0172d053490910bba22c4931d1f8ad3ad0d6135295222021-10-25 9:15:445 hrs 35 mins ago 0x9656283ede0167f955cb3112027755b392a1ceca 0xcd2d09fa9d425682085bc94ed0c7bada6cabcdba0 BNB
0x0eb9a2e3a63ed6964a9dd58fc85327cabab59963c36fa5bd19431b3cd37cec0a135295122021-10-25 9:15:145 hrs 35 mins ago 0x9656283ede0167f955cb3112027755b392a1ceca 0x56190b59760d472450f65dca7c54e50cf5ebbd410 BNB
0x4f16472f3997513a1dfa2248a0dce3b782e3ad3b0dcad7b1572890835a1b89ae135221712021-10-25 3:08:0611 hrs 42 mins ago 0x9656283ede0167f955cb3112027755b392a1ceca 0x56190b59760d472450f65dca7c54e50cf5ebbd410 BNB
0x5553358fc3a39cf58789ec66fbded6c3133370df3ba018732e817441a79475ce135221512021-10-25 3:07:0611 hrs 43 mins ago 0x9656283ede0167f955cb3112027755b392a1ceca 0xcd2d09fa9d425682085bc94ed0c7bada6cabcdba0 BNB
0x10b9149e09c6920363591de08e0173be975d57998bba37c4d6245407806025ca135198902021-10-25 1:14:0313 hrs 36 mins ago 0x9656283ede0167f955cb3112027755b392a1ceca 0xcd2d09fa9d425682085bc94ed0c7bada6cabcdba0 BNB
0x488dbbf2bcf91192d3371975928bdf32174275892bfa71bf0abca380e369d3c5135198802021-10-25 1:13:3313 hrs 37 mins ago 0x9656283ede0167f955cb3112027755b392a1ceca 0x56190b59760d472450f65dca7c54e50cf5ebbd410 BNB
0x024692bee5754cb0e358b1ecc5d80f1f90e6475311a84b8395f4941108b834c5135198382021-10-25 1:11:2713 hrs 39 mins ago 0x9656283ede0167f955cb3112027755b392a1ceca 0xcd2d09fa9d425682085bc94ed0c7bada6cabcdba0 BNB
0x73d94fd9908bfdc245109d6a1fa30f257c5eaa8275724d15d0e02a9dac6f31cd135198322021-10-25 1:11:0913 hrs 39 mins ago 0x9656283ede0167f955cb3112027755b392a1ceca 0x56190b59760d472450f65dca7c54e50cf5ebbd410 BNB
0x2e39667dd87068d06e2fd7cd63ba97d819028714757a9aa34fc9bcb95d2a7d62135189902021-10-25 0:29:0314 hrs 21 mins ago 0x9656283ede0167f955cb3112027755b392a1ceca 0xcd2d09fa9d425682085bc94ed0c7bada6cabcdba0 BNB
0x9e85811ed3af3d1dae73ccd135095eca6065d67bf508089cf52940e4fd988ca8135189812021-10-25 0:28:3614 hrs 22 mins ago 0x9656283ede0167f955cb3112027755b392a1ceca 0x56190b59760d472450f65dca7c54e50cf5ebbd410 BNB
0x58ce0656bbd3c8a5a7cbfea6e601f3caa6f597aa092facb134948215d582db60135175832021-10-24 23:18:4215 hrs 32 mins ago 0x9656283ede0167f955cb3112027755b392a1ceca 0xcd2d09fa9d425682085bc94ed0c7bada6cabcdba0 BNB
0xd84b99dedf2e046384b05625b3d95a04228f9f48e63056b7a95008770cf088fe135175752021-10-24 23:18:1815 hrs 32 mins ago 0x9656283ede0167f955cb3112027755b392a1ceca 0x56190b59760d472450f65dca7c54e50cf5ebbd410 BNB
0xc1c848ef25c0453febd6cdc83814ad279e76ae3813cf7ebc52ea1f8f120b8e2f135158182021-10-24 21:50:2717 hrs ago 0x9656283ede0167f955cb3112027755b392a1ceca 0xcd2d09fa9d425682085bc94ed0c7bada6cabcdba0 BNB
0x81dab6b5e635c66ea1dda28388a8a04194fb0c310abcab22f3e4bf3e2c1ec9cd135157942021-10-24 21:49:1517 hrs 1 min ago 0x9656283ede0167f955cb3112027755b392a1ceca 0x56190b59760d472450f65dca7c54e50cf5ebbd410 BNB
0x24392adc12e5ad4d36fedfbf7ff0c0308981aafe055333f4c36e477393ea2d89135129302021-10-24 19:26:0319 hrs 24 mins ago 0x9656283ede0167f955cb3112027755b392a1ceca 0xcd2d09fa9d425682085bc94ed0c7bada6cabcdba0 BNB
0x04817cfed8bda0e06ac050bcd4188c6414efc213c6b847b5b5c5c10d371d2451135129222021-10-24 19:25:3919 hrs 25 mins ago 0x9656283ede0167f955cb3112027755b392a1ceca 0x56190b59760d472450f65dca7c54e50cf5ebbd410 BNB
0x760724328916bc236a84a84180e972b3d2c27912d940a0049e5fb3a0b8340d76135115812021-10-24 18:18:3620 hrs 32 mins ago 0x9656283ede0167f955cb3112027755b392a1ceca 0xcd2d09fa9d425682085bc94ed0c7bada6cabcdba0 BNB
0x9b51d9b6a53c65f75d0408e53fef2709629499c59e1e5ab1722cd409613ae206135115722021-10-24 18:18:0920 hrs 32 mins ago 0x9656283ede0167f955cb3112027755b392a1ceca 0x56190b59760d472450f65dca7c54e50cf5ebbd410 BNB
0x181e551d37f2f402d16d0cb5c4d5f5b099ce88c87b528802015462eb85a0a955135113422021-10-24 18:06:3920 hrs 44 mins ago 0x9656283ede0167f955cb3112027755b392a1ceca 0xcd2d09fa9d425682085bc94ed0c7bada6cabcdba0 BNB
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
TokenFaucet

Compiler Version
v0.8.0+commit.c7dfd78e

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 9 : TokenFaucet.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.0;

import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";

import "./Withdrawable.sol";

contract TokenFaucet is Withdrawable, ReentrancyGuard {
    using SafeERC20 for IERC20;
    using EnumerableSet for EnumerableSet.AddressSet;

    EnumerableSet.AddressSet internal tokens;
    mapping(address => string) public tokenNames;
    // accoun => token => lastFaucet
    mapping(address => mapping(address => uint256)) public faucetAccountCached;
    // one day
    uint256 public timeCycle = 86400;
    uint256 public maxAmount;

    function listTokens() external view returns (address[] memory _tokens, string[] memory _tokenNames) {
        _tokens = new address[](tokens.length());
        _tokenNames = new string[](tokens.length());
        for (uint256 i = 0; i < tokens.length(); i++) {
            address _token = tokens.at(i);
            _tokens[i] = _token;
            _tokenNames[i] = tokenNames[_token];
        }
    }

    function setMaxFaucet(uint256 _maxFaucet) external onlyOwner {
        maxAmount = _maxFaucet;
    }

    function setTimeCycle(uint256 _timeCycle) external onlyOwner {
        timeCycle = _timeCycle;
    }

    function addToken(address _token, string memory _name) external onlyOwner {
        require(_token != address(0));
        tokens.add(_token);
        tokenNames[_token] = _name;
    }

    function faucet(
        address _token
    ) external nonReentrant {
        require(tokens.contains(_token), "Wanaka: token does not supports");
        require(faucetAccountCached[msg.sender][_token] + timeCycle < block.timestamp, "Wanaka: only faucet once per day");
        faucetAccountCached[msg.sender][_token] = block.timestamp;
        IERC20(_token).safeTransfer(msg.sender, maxAmount);
    }
}

File 2 of 9 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

File 3 of 9 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

File 4 of 9 : SafeERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../IERC20.sol";
import "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            // Return data is optional
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 5 of 9 : EnumerableSet.sol
// SPDX-License-Identifier: MIT

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.
 */
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];
    }

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

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

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

File 6 of 9 : Withdrawable.sol
//SPDX-License-Identifier: UNLICENSED

pragma solidity 0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract Withdrawable is Ownable {
    using SafeERC20 for IERC20;

    mapping(address => bool) internal tokenBlacklist;

    event TokenWithdrawn(address token, uint256 amount, address to);

    /**
     * @notice Blacklists a token to be withdrawn from the contract.
     */
    function blacklistToken(address _token) public onlyOwner {
        tokenBlacklist[_token] = true;
    }

    /**
     * @notice Withdraws any tokens in the contract.
     */
    function withdrawToken(IERC20 token, uint256 amount, address to) external onlyOwner {
        require(!tokenBlacklist[address(token)], "Wanaka: blacklisted token");
        token.safeTransfer(to, amount);
        emit TokenWithdrawn(address(token), amount, to);
    }
}

File 7 of 9 : Address.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @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 on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        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");

        (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");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) private pure returns (bytes memory) {
        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

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 8 of 9 : Ownable.sol
// SPDX-License-Identifier: MIT

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() {
        _setOwner(_msgSender());
    }

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

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

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _setOwner(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");
        _setOwner(newOwner);
    }

    function _setOwner(address newOwner) private {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

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

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

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"TokenWithdrawn","type":"event"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"string","name":"_name","type":"string"}],"name":"addToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"blacklistToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"faucet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"faucetAccountCached","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"listTokens","outputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"string[]","name":"_tokenNames","type":"string[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxFaucet","type":"uint256"}],"name":"setMaxFaucet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_timeCycle","type":"uint256"}],"name":"setTimeCycle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"timeCycle","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenNames","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040526201518060075534801561001757600080fd5b50610028610023610032565b610036565b6001600255610086565b3390565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b611290806100956000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c806385da11921161008c578063b86d1d6311610066578063b86d1d63146101b6578063e1254559146101c9578063e15c8bf0146101dc578063f2fde38b146101ef576100ea565b806385da11921461016e5780638da5cb5b14610181578063a8fc75e114610196576100ea565b8063715018a6116100c8578063715018a6146101355780637488ff761461013d5780637644d1c41461015357806384b6433d14610166576100ea565b80632c8da560146100ef5780633ccdbb28146101045780635f48f39314610117575b600080fd5b6101026100fd366004610cde565b610202565b005b610102610112366004610db4565b610297565b61011f610363565b60405161012c9190611172565b60405180910390f35b610102610369565b6101456103b4565b60405161012c929190610ea5565b610102610161366004610df5565b6105b5565b61011f6105f9565b61010261017c366004610df5565b6105ff565b610189610643565b60405161012c9190610e55565b6101a96101a4366004610c8a565b610652565b60405161012c9190610f43565b6101026101c4366004610c8a565b6106ec565b6101026101d7366004610c8a565b6107c4565b61011f6101ea366004610ca6565b61082a565b6101026101fd366004610c8a565b610847565b61020a6108b8565b6001600160a01b031661021b610643565b6001600160a01b03161461024a5760405162461bcd60e51b81526004016102419061104e565b60405180910390fd5b6001600160a01b03821661025d57600080fd5b6102686003836108bc565b506001600160a01b0382166000908152600560209081526040909120825161029292840190610bf1565b505050565b61029f6108b8565b6001600160a01b03166102b0610643565b6001600160a01b0316146102d65760405162461bcd60e51b81526004016102419061104e565b6001600160a01b03831660009081526001602052604090205460ff161561030f5760405162461bcd60e51b8152600401610241906110ba565b6103236001600160a01b03841682846108da565b7fa0524ee0fd8662d6c046d199da2a6d3dc49445182cec055873a5bb9c2843c8e083838360405161035693929190610e82565b60405180910390a1505050565b60085481565b6103716108b8565b6001600160a01b0316610382610643565b6001600160a01b0316146103a85760405162461bcd60e51b81526004016102419061104e565b6103b26000610930565b565b6060806103c16003610980565b67ffffffffffffffff8111156103e757634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610410578160200160208202803683370190505b50915061041d6003610980565b67ffffffffffffffff81111561044357634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561047657816020015b60608152602001906001900390816104615790505b50905060005b6104866003610980565b8110156105b057600061049a60038361098b565b9050808483815181106104bd57634e487b7160e01b600052603260045260246000fd5b6001600160a01b03928316602091820292909201810191909152908216600090815260059091526040902080546104f3906111c3565b80601f016020809104026020016040519081016040528092919081815260200182805461051f906111c3565b801561056c5780601f106105415761010080835404028352916020019161056c565b820191906000526020600020905b81548152906001019060200180831161054f57829003601f168201915b505050505083838151811061059157634e487b7160e01b600052603260045260246000fd5b60200260200101819052505080806105a8906111fe565b91505061047c565b509091565b6105bd6108b8565b6001600160a01b03166105ce610643565b6001600160a01b0316146105f45760405162461bcd60e51b81526004016102419061104e565b600755565b60075481565b6106076108b8565b6001600160a01b0316610618610643565b6001600160a01b03161461063e5760405162461bcd60e51b81526004016102419061104e565b600855565b6000546001600160a01b031690565b6005602052600090815260409020805461066b906111c3565b80601f0160208091040260200160405190810160405280929190818152602001828054610697906111c3565b80156106e45780601f106106b9576101008083540402835291602001916106e4565b820191906000526020600020905b8154815290600101906020018083116106c757829003601f168201915b505050505081565b60028054141561070e5760405162461bcd60e51b81526004016102419061113b565b6002805561071d600382610997565b6107395760405162461bcd60e51b815260040161024190610f56565b6007543360009081526006602090815260408083206001600160a01b0386168452909152902054429161076b9161117b565b106107885760405162461bcd60e51b815260040161024190610fd3565b3360008181526006602090815260408083206001600160a01b03861680855292529091204290556008546107bc92906108da565b506001600255565b6107cc6108b8565b6001600160a01b03166107dd610643565b6001600160a01b0316146108035760405162461bcd60e51b81526004016102419061104e565b6001600160a01b03166000908152600160208190526040909120805460ff19169091179055565b600660209081526000928352604080842090915290825290205481565b61084f6108b8565b6001600160a01b0316610860610643565b6001600160a01b0316146108865760405162461bcd60e51b81526004016102419061104e565b6001600160a01b0381166108ac5760405162461bcd60e51b815260040161024190610f8d565b6108b581610930565b50565b3390565b60006108d1836001600160a01b0384166109ac565b90505b92915050565b6102928363a9059cbb60e01b84846040516024016108f9929190610e69565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526109f6565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006108d482610a85565b60006108d18383610a89565b60006108d1836001600160a01b038416610ac1565b60006109b88383610ac1565b6109ee575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556108d4565b5060006108d4565b6000610a4b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610ad99092919063ffffffff16565b8051909150156102925780806020019051810190610a699190610d94565b6102925760405162461bcd60e51b8152600401610241906110f1565b5490565b6000826000018281548110610aae57634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b60009081526001919091016020526040902054151590565b6060610ae88484600085610af2565b90505b9392505050565b606082471015610b145760405162461bcd60e51b815260040161024190611008565b610b1d85610bb2565b610b395760405162461bcd60e51b815260040161024190611083565b600080866001600160a01b03168587604051610b559190610e39565b60006040518083038185875af1925050503d8060008114610b92576040519150601f19603f3d011682016040523d82523d6000602084013e610b97565b606091505b5091509150610ba7828286610bb8565b979650505050505050565b3b151590565b60608315610bc7575081610aeb565b825115610bd75782518084602001fd5b8160405162461bcd60e51b81526004016102419190610f43565b828054610bfd906111c3565b90600052602060002090601f016020900481019282610c1f5760008555610c65565b82601f10610c3857805160ff1916838001178555610c65565b82800160010185558215610c65579182015b82811115610c65578251825591602001919060010190610c4a565b50610c71929150610c75565b5090565b5b80821115610c715760008155600101610c76565b600060208284031215610c9b578081fd5b8135610aeb81611245565b60008060408385031215610cb8578081fd5b8235610cc381611245565b91506020830135610cd381611245565b809150509250929050565b60008060408385031215610cf0578182fd5b8235610cfb81611245565b915060208381013567ffffffffffffffff80821115610d18578384fd5b818601915086601f830112610d2b578384fd5b813581811115610d3d57610d3d61122f565b604051601f8201601f1916810185018381118282101715610d6057610d6061122f565b6040528181528382018501891015610d76578586fd5b81858501868301378585838301015280955050505050509250929050565b600060208284031215610da5578081fd5b81518015158114610aeb578182fd5b600080600060608486031215610dc8578081fd5b8335610dd381611245565b9250602084013591506040840135610dea81611245565b809150509250925092565b600060208284031215610e06578081fd5b5035919050565b60008151808452610e25816020860160208601611193565b601f01601f19169290920160200192915050565b60008251610e4b818460208701611193565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0393841681526020810192909252909116604082015260600190565b604080825283519082018190526000906020906060840190828701845b82811015610ee75781516001600160a01b031684529284019290840190600101610ec2565b5050508381038285015284518082528282019080840283018401878501865b83811015610f3457601f19868403018552610f22838351610e0d565b94870194925090860190600101610f06565b50909998505050505050505050565b6000602082526108d16020830184610e0d565b6020808252601f908201527f57616e616b613a20746f6b656e20646f6573206e6f7420737570706f72747300604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252818101527f57616e616b613a206f6e6c7920666175636574206f6e63652070657220646179604082015260600190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6040820152651c8818d85b1b60d21b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b60208082526019908201527f57616e616b613a20626c61636b6c697374656420746f6b656e00000000000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b90815260200190565b6000821982111561118e5761118e611219565b500190565b60005b838110156111ae578181015183820152602001611196565b838111156111bd576000848401525b50505050565b6002810460018216806111d757607f821691505b602082108114156111f857634e487b7160e01b600052602260045260246000fd5b50919050565b600060001982141561121257611212611219565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146108b557600080fdfea2646970667358221220912313f2361f30241bc10a3ddb0d864c43231c24a17ff7d6aa8f3dbea71ac3b764736f6c63430008000033

Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading