false
true
0

Contract Address Details

0x19a5C1A49Ca5133D348EE965f8f87E6f7CdA44a7

Token
Pepelorian: Stakable Pepe (PEPEL)
Creator
0xb0c2b1–982523 at 0x8a89ac–b059a2
Balance
0 PLS ( )
Tokens
Fetching tokens...
Transactions
1,005 Transactions
Transfers
0 Transfers
Gas Used
0
Last Balance Update
27556762
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
PEPEv4




Optimization enabled
true
Compiler version
v0.8.19+commit.7dd6d404




Optimization runs
1000000
EVM Version
default




Verified at
2023-06-11T23:56:05.861531Z

Constructor Arguments

0x00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000802d686567ba30dceba167d66a544f6ef915e0f7000000000000000000000000fb7103d7011dfa60c18c6961c5a38038d8048fe0000000000000000000000000fc51c335f8be70d0541944da5d5cd0638bbcc63d0000000000000000000000000000000000000000000000000000000000000019506570656c6f7269616e3a205374616b61626c652050657065000000000000000000000000000000000000000000000000000000000000000000000000000005504550454c000000000000000000000000000000000000000000000000000000

Arg [0] (string) : Pepelorian: Stakable Pepe
Arg [1] (string) : PEPEL
Arg [2] (address) : 0x802d686567ba30dceba167d66a544f6ef915e0f7
Arg [3] (address) : 0xfb7103d7011dfa60c18c6961c5a38038d8048fe0
Arg [4] (address) : 0xfc51c335f8be70d0541944da5d5cd0638bbcc63d

              

contracts/PEPEL4.sol

/*
 * @title PEPEL - A Stakable Pepe
 * @author Ra Murd <pulselorian@gmail.com>
 * @notice https://pulselorian.com/
 * @notice https://t.me/ThePulselorian
 * @notice https://twitter.com/ThePulseLorian
 *
 * PEPEL is our attempt to develop a better internet currency with no fees
 * It allows staking to earn amazing yields
 * It's deflationary - fixed supply with burn on unstake
 *
 *    (   (  (  (     (   (( (   .  (   (    (( (   ((
 *    )\  )\ )\ )\    )\ (\())\   . )\  )\   ))\)\  ))\
 *   ((_)((_)(_)(_)  ((_))(_)(_)   ((_)((_)(((_)_()((_)))
 *   | _ \ | | | |  / __| __| |   / _ \| _ \_ _|   \ \| |
 *   |  _/ |_| | |__\__ \ _|| |__| (_) |   /| || - | .  |
 *   |_|  \___/|____|___/___|____|\___/|_|_\___|_|_|_|\_|
 *
 * SPDX-License-Identifier: MIT
 */

pragma solidity ^0.8.19;

import "./imports/BasePEPEL.sol";
import "./lib/DSMath.sol";

contract PEPEv4 is BasePEPEL, DSMath {
    struct Stake {
        uint256 stakeAmount;
        uint256 rewardDebt;
        uint256 since;
    }

    struct Stakeholder {
        address user;
        Stake[] userStakes;
    }

    Stakeholder[] public stakeholders;

    address private _feeAddr1;
    address private _feeAddr2;
    address private _inflationAddr;

    mapping(address => uint256) private _stakeIndexMap;

    uint16 private constant _SECS_IN_AN_HOUR = 3600;
    uint96 private constant _INF_RATE_HRLY = 999_992 * 1e21; // 999991716654*1e15 7% exact
    uint256 public totalStakes; // total number of stakes
    uint256 private _lastDistTS; // timestamp of last rewards calc
    uint256 private rewardsPerToken; // inflated by 1e12 times to allow for small values

    event Staked(
        address indexed user,
        uint256 stakeIndex,
        uint256 stakeAmount,
        uint256 rewardDebt,
        uint256 since
    );

    event Unstaked(
        address indexed user,
        uint256 stakeAmount,
        uint256 rewardDebt,
        uint256 since,
        uint256 till
    );

    constructor(
        string memory name_,
        string memory symbol_,
        address inflationAddress_,
        address feeAddr1_,
        address feeAddr2_
    ) BasePEPEL(name_, symbol_) {
        stakeholders.push(); // Null staker is a must at index 0

        _inflationAddr = inflationAddress_;
        _feeAddr1 = feeAddr1_;
        _paysNoFee[feeAddr1_] = true;
        _feeAddr2 = feeAddr2_;
        _paysNoFee[feeAddr2_] = true;

        _balances[msg.sender] = _TOTAL_SUPPLY;
        emit Transfer(address(0), msg.sender, _TOTAL_SUPPLY);

        uint256 halfSupply = (_TOTAL_SUPPLY >> 1) - 1e18;
        _balances[_inflationAddr] += halfSupply;
        _balances[msg.sender] -= halfSupply;
        emit Transfer(msg.sender, _inflationAddr, halfSupply);

        _lastDistTS = block.timestamp - (block.timestamp % _SECS_IN_AN_HOUR);
        _stake(1e18);
    }

    function _creditInflation() private {
        uint256 nowTS = block.timestamp - (block.timestamp % _SECS_IN_AN_HOUR);
        if (nowTS > _lastDistTS) {
            (uint256 inflation, uint256 tmpRewardsPerToken) = _calcInflation(
                nowTS
            );

            if (inflation != 0) {
                _lastDistTS = nowTS;
                _balances[_inflationAddr] -= inflation;
                _balances[address(this)] += inflation;
                rewardsPerToken = tmpRewardsPerToken;
            }
        }
    }

    function _stake(uint256 stakeAmount_) private {
        _creditInflation();

        _balances[msg.sender] -= stakeAmount_;

        uint256 saFee;
        uint256 stakeAmt;
        if (_paysNoFee[msg.sender]) {
            stakeAmt = stakeAmount_;
        } else {
            saFee = (stakeAmount_ * 25) / _BIPS;
            stakeAmt = stakeAmount_ - saFee - saFee;
        }
        _balances[address(this)] += stakeAmt;
        emit Transfer(msg.sender, address(this), stakeAmt);
        if (saFee > 0) {
            _balances[_feeAddr1] += saFee;
            emit Transfer(msg.sender, _feeAddr1, saFee);

            _balances[_feeAddr2] += saFee;
            emit Transfer(msg.sender, _feeAddr2, saFee);
        }

        uint256 stakerIndex = _stakeIndexMap[msg.sender];

        if (stakerIndex == 0) {
            stakerIndex = _addStakeholder(msg.sender);
        }

        uint256 rewardDebt = (rewardsPerToken * stakeAmt) / 1e12;
        stakeholders[stakerIndex].userStakes.push(
            Stake(stakeAmt, rewardDebt, block.timestamp)
        );

        totalStakes += stakeAmt;

        emit Staked(
            msg.sender,
            stakeholders[stakerIndex].userStakes.length - 1,
            stakeAmt,
            rewardDebt,
            block.timestamp
        );
    }

    function _unstake(uint256 unstakeAmount_, uint256 stakeIndex_) private {
        bool transferred;
        Stake memory currStake = _withdrawStake(stakeIndex_, unstakeAmount_); // from before unstake started
        uint256 eligibleBasis = _BIPS -
            _penaltyFor(currStake.since, block.timestamp);
        uint256 stakeAmtPlusRewards;
        uint256 stakeRewards = (currStake.stakeAmount * rewardsPerToken) /
            1e12 -
            currStake.rewardDebt;
        if (currStake.stakeAmount > unstakeAmount_) {
            stakeAmtPlusRewards = unstakeAmount_ + stakeRewards;
        } else {
            stakeAmtPlusRewards = currStake.stakeAmount + stakeRewards;
        }
        uint256 usFee;
        uint256 withdrawAmtLessFees;
        if (_paysNoFee[msg.sender]) {
            usFee = 0;
            withdrawAmtLessFees = stakeAmtPlusRewards;
        } else {
            usFee = (stakeAmtPlusRewards * 25) / _BIPS;
            withdrawAmtLessFees = stakeAmtPlusRewards - usFee - usFee;
        }
        uint256 amtToSendLessBurn = (withdrawAmtLessFees * eligibleBasis) /
            _BIPS;

        if (amtToSendLessBurn != 0) {
            _balances[address(this)] -= stakeAmtPlusRewards; // includes fees and burn
            _balances[msg.sender] += amtToSendLessBurn;
            emit Transfer(address(this), msg.sender, amtToSendLessBurn);
            transferred = true;

            if (usFee > 0) {
                _balances[_feeAddr1] += usFee;
                emit Transfer(address(this), _feeAddr1, usFee);
                _balances[_feeAddr2] += usFee;
                emit Transfer(address(this), _feeAddr2, usFee);
            }
        }

        if (eligibleBasis < _BIPS) {
            uint256 pepelToBurn = withdrawAmtLessFees - amtToSendLessBurn;
            if (pepelToBurn != 0) {
                _balances[_BURN_ADDRESS] += pepelToBurn;
                emit Transfer(address(this), _BURN_ADDRESS, pepelToBurn);
            }
        }
        totalStakes -= unstakeAmount_;
        emit Unstaked(
            msg.sender,
            unstakeAmount_,
            currStake.rewardDebt,
            currStake.since,
            block.timestamp
        );
        require(transferred, "Unstake failed");
    }

    function _addStakeholder(address staker_) internal returns (uint256) {
        stakeholders.push();
        uint256 stakerIndex = stakeholders.length - 1;
        stakeholders[stakerIndex].user = staker_;
        _stakeIndexMap[staker_] = stakerIndex;
        return stakerIndex;
    }

    function _airdropTokens(address to_, uint256 amount_) internal override {
        _transfer(owner(), to_, amount_);
    }

    function _calcInflation(
        uint256 nowTS_
    ) private view returns (uint256 inflation, uint256 tmpRewardsPerToken) {
        require(_lastDistTS != 0, "L:Inflation not started!");
        uint256 hoursElapsed = (nowTS_ - _lastDistTS) / _SECS_IN_AN_HOUR;

        uint256 currBal = _balances[_inflationAddr];
        if (hoursElapsed != 0) {
            uint256 infFracRay = rpow(_INF_RATE_HRLY, hoursElapsed);
            inflation = currBal - (currBal * infFracRay) / RAY;
            tmpRewardsPerToken =
                rewardsPerToken +
                (inflation * 1e12) /
                totalStakes;
        } else {
            tmpRewardsPerToken = rewardsPerToken;
        }

        return (inflation, tmpRewardsPerToken);
    }

    function _getCurrStake(
        uint256 stakerIndex_,
        uint256 stakeIndex_
    ) private view returns (Stake memory currStake) {
        require(
            stakeIndex_ < stakeholders[stakerIndex_].userStakes.length,
            "S:Stake index incorrect!"
        );

        currStake = stakeholders[stakerIndex_].userStakes[stakeIndex_];

        return currStake;
    }

    function _transfer(
        address sender_,
        address recipient_,
        uint256 tAmount_
    ) internal override whenNotPaused {
        _balances[sender_] -= tAmount_;
        _balances[recipient_] += tAmount_;

        emit Transfer(sender_, recipient_, tAmount_);
    }

    function _withdrawStake(
        uint256 stakeIndex_,
        uint256 unstakeAmount_
    ) private returns (Stake memory currStake) {
        uint256 stakerIndex = _stakeIndexMap[msg.sender];
        currStake = _getCurrStake(stakerIndex, stakeIndex_);

        require(
            stakerIndex != 1 || stakeIndex_ != 0,
            "S:Cannot remove 1st stake"
        );

        require(
            currStake.stakeAmount >= unstakeAmount_,
            "S:Too much unstaking"
        );

        if (currStake.stakeAmount == unstakeAmount_) {
            if (stakeIndex_ < stakeholders[stakerIndex].userStakes.length - 1) {
                stakeholders[stakerIndex].userStakes[
                    stakeIndex_
                ] = stakeholders[stakerIndex].userStakes[
                    stakeholders[stakerIndex].userStakes.length - 1
                ];
            }
            stakeholders[stakerIndex].userStakes.pop();

            if (stakeholders[stakerIndex].userStakes.length == 0) {
                if (stakerIndex < stakeholders.length - 1) {
                    stakeholders[stakerIndex] = stakeholders[
                        stakeholders.length - 1
                    ];
                    stakeholders.pop();

                    _stakeIndexMap[msg.sender] = 0;
                    _stakeIndexMap[
                        stakeholders[stakerIndex].user
                    ] = stakerIndex;
                } else {
                    stakeholders.pop();
                    _stakeIndexMap[msg.sender] = 0;
                }
            }
        } else {
            Stake storage updatedStake = stakeholders[stakerIndex].userStakes[
                stakeIndex_
            ];

            uint256 newStakeAmt = currStake.stakeAmount - unstakeAmount_;
            updatedStake.stakeAmount = newStakeAmt;
            updatedStake.rewardDebt = (rewardsPerToken * newStakeAmt) / 1e12;
        }

        return (currStake);
    }

    function balanceOf(
        address wallet_
    ) external view override returns (uint256) {
        return _balances[wallet_];
    }

    function getTotalStakeholders() external view returns (uint256) {
        return stakeholders.length - 1;
    }

    function getTotalStakes() external view returns (uint256 totalStakeCount) {
        for (
            uint256 stakerIndex;
            stakerIndex < stakeholders.length;
            ++stakerIndex
        ) {
            totalStakeCount += stakeholders[stakerIndex].userStakes.length;
        }

        return totalStakeCount;
    }

    function penaltyIfUnstakedNow(
        address wallet_,
        uint256 stakeIndex_
    ) external view returns (uint256 penaltyBasis) {
        uint256 stakerIndex = _stakeIndexMap[wallet_];
        Stake memory currStake = _getCurrStake(stakerIndex, stakeIndex_);

        return _penaltyFor(currStake.since, block.timestamp);
    }

    function rewardsOf(
        address stakeholder_,
        uint256 stakeIndex_
    ) external view returns (uint256 pepelRewards, uint256 eligibleBasis) {
        uint256 inflation;
        uint256 tmpRewardsPerToken;
        if (_lastDistTS != 0) {
            (inflation, tmpRewardsPerToken) = _calcInflation(block.timestamp);
        }

        uint256 stakerIndex = _stakeIndexMap[stakeholder_];

        Stake memory currStake = _getCurrStake(stakerIndex, stakeIndex_);

        eligibleBasis = _BIPS - _penaltyFor(currStake.since, block.timestamp);
        if (tmpRewardsPerToken > 0) {
            pepelRewards = ((currStake.stakeAmount * tmpRewardsPerToken) /
                1e12 -
                currStake.rewardDebt);
        }
        return (pepelRewards, eligibleBasis);
    }

    function setFeeAddresses(
        address feeAddr1_,
        address feeAddr2_
    ) external onlyOwner {
        if (feeAddr1_ != address(0)) {
            _feeAddr1 = feeAddr1_;
        }
        if (feeAddr2_ != address(0)) {
            _feeAddr2 = feeAddr2_;
        }
    }

    function stake(uint256 stakeAmount_) external whenNotPaused {
        require(stakeAmount_ != 0, "L:Cannot stake 0");
        require(_balances[msg.sender] >= stakeAmount_, "L:Too much staking");

        _stake(stakeAmount_);
    }

    function stakesOf(
        address stakeholder_
    ) external view returns (Stake[] memory userStakes) {
        uint256 stakerIndex = _stakeIndexMap[stakeholder_];
        if (stakerIndex > 0) {
            return stakeholders[stakerIndex].userStakes;
        }

        return userStakes;
    }

    function unstake(
        uint256 unstakeAmount_,
        uint256 stakeIndex_
    ) external whenNotPaused {
        _creditInflation();

        _unstake(unstakeAmount_, stakeIndex_);
    }
}
        

contracts/openzeppelin/token/ERC20/IERC20.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IERC20 {
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );
    event Transfer(address indexed from, address indexed to, uint256 value);

    function allowance(
        address owner,
        address spender
    ) external view returns (uint256);

    function approve(address spender, uint256 amount) external returns (bool);

    function balanceOf(address account) external view returns (uint256);

    function totalSupply() external view returns (uint256);

    function transfer(address to, uint256 amount) external returns (bool);

    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}
          

contracts/uniswap/v2-core/interfaces/IUniswapV2Factory.sol

/*
 * SPDX-License-Identifier: MIT
 */

pragma solidity ^0.8.19;

interface IUniswapV2Factory {
    function createPair(
        address tokenA,
        address tokenB
    ) external returns (address pair);
}
          

contracts/imports/BasePEPEL.sol

/*
 * SPDX-License-Identifier: MIT
 */

pragma solidity ^0.8.19;

import "../lib/Utils.sol";
import "../openzeppelin/access/Ownable.sol";
import "../openzeppelin/security/Pausable.sol";
import "../openzeppelin/token/ERC20/IERC20.sol";
import "../uniswap/v2-core/interfaces/IUniswapV2Factory.sol";
import "../uniswap/v2-periphery/interfaces/IUniswapV2Router02.sol";
import "./Manageable.sol";

abstract contract BasePEPEL is Utils, Ownable, Pausable, IERC20, Manageable {
    struct Airdrop {
        address user;
        uint256 ethers;
    }

    address internal constant _BURN_ADDRESS = address(0x369);
    mapping(address => bool) internal _paysNoFee;
    mapping(address => mapping(address => uint256)) private _allowances;
    mapping(address => uint256) internal _balances;
    string private _name;
    string private _symbol;
    uint16 internal constant _BIPS = 1e4;
    uint128 internal constant _TOTAL_SUPPLY = 1e12 * 1e18;

    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
        _paysNoFee[msg.sender] = true;
    }

    receive() external payable {}

    fallback() external payable {}

    function _airdropTokens(address to_, uint256 amount_) internal virtual;

    function _approve(
        address owner_,
        address spender_,
        uint256 amount_
    ) internal {
        _allowances[owner_][spender_] = amount_;
        emit Approval(owner_, spender_, amount_);
    }

    function _transfer(
        address owner_,
        address to_,
        uint256 amount_
    ) internal virtual;

    function airdrop(Airdrop[] calldata receivers_) external onlyOwner {
        for (uint256 index; index < receivers_.length; ++index) {
            if (
                receivers_[index].user != address(0) &&
                receivers_[index].ethers != 0
            ) {
                _airdropTokens(
                    receivers_[index].user,
                    receivers_[index].ethers * 1e18
                );
            }
        }
    }

    function allowance(
        address owner_,
        address spender_
    ) external view override returns (uint256) {
        return _allowances[owner_][spender_];
    }

    function approve(
        address spender_,
        uint256 amount_
    ) external override returns (bool) {
        address owner = msg.sender;
        _approve(owner, spender_, amount_);
        return true;
    }

    function decimals() external pure returns (uint8) {
        return 18;
    }

    function decreaseAllowance(
        address spender_,
        uint256 subtractedValue_
    ) external returns (bool) {
        address owner = msg.sender;
        uint256 currentAllowance = _allowances[owner][spender_];
        require(currentAllowance >= subtractedValue_, "BB:Decreases below 0");
        unchecked {
            _approve(owner, spender_, currentAllowance - subtractedValue_);
        }

        return true;
    }

    function increaseAllowance(
        address spender_,
        uint256 addedValue_
    ) external returns (bool) {
        address owner = msg.sender;
        _approve(owner, spender_, _allowances[owner][spender_] + addedValue_);
        return true;
    }

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

    function pauseContract() external onlyManager {
        _pause();
    }

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

    function totalSupply() external pure override returns (uint256) {
        return _TOTAL_SUPPLY;
    }

    function transfer(
        address to_,
        uint256 amount_
    ) external override returns (bool) {
        address owner = msg.sender;
        _transfer(owner, to_, amount_);
        return true;
    }

    function transferFrom(
        address from_,
        address to_,
        uint256 amount_
    ) external override returns (bool) {
        address spender = msg.sender;
        uint256 currentAllowance = _allowances[from_][spender];
        if (currentAllowance != type(uint256).max) {
            require(currentAllowance >= amount_, "BB:Insufficient allowance");
            unchecked {
                _approve(from_, spender, currentAllowance - amount_);
            }
        }
        _transfer(from_, to_, amount_);
        return true;
    }

    function unPauseContract() external onlyManager {
        _unpause();
    }

    function reclaimETH() external payable {
        uint256 amount = address(this).balance;
        require(amount > 0, "BB:0 Balance");

        (bool sent, ) = owner().call{value: amount}("");
        require(sent, "BB:Send Failed");
    }

    function reclaimToken(IERC20 token_, uint256 amount_) external payable {
        uint256 balance = token_.balanceOf(address(this));
        require(amount_ <= balance, "BB:Too much");
        token_.transfer(owner(), balance);
    }

    function burn(uint256 amount_) external {
        _balances[msg.sender] -= amount_;
        _balances[_BURN_ADDRESS] += amount_;
        emit Transfer(msg.sender, _BURN_ADDRESS, amount_);
    }
}
          

contracts/imports/Manageable.sol

/*
 * SPDX-License-Identifier: MIT
 */
pragma solidity ^0.8.19;

abstract contract Manageable {
    address private _manager;

    event ManagementTransferred(
        address indexed previousManager,
        address indexed newManager
    );

    constructor() {
        _manager = msg.sender;
        emit ManagementTransferred(address(0), msg.sender);
    }

    function _checkManager() private view {
        require(_manager == msg.sender, "M:Caller not manager");
    }

    function manager() external view returns (address) {
        return _manager;
    }

    modifier onlyManager() {
        _checkManager();
        _;
    }

    function transferManagement(address newManager_) external onlyManager {
        emit ManagementTransferred(_manager, newManager_);
        _manager = newManager_;
    }
}
          

contracts/lib/DSMath.sol

/*
 * SPDX-License-Identifier: MIT
 */

pragma solidity ^0.8.19;

contract DSMath {
    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
        require((z = x + y) >= x, "ds-math-add-overflow");
    }

    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {
        require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow");
    }

    uint96 constant RAY = 10 ** 27;

    function rmul(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = add(mul(x, y), RAY >> 1) / RAY;
    }

    function rpow(uint256 x, uint256 n) internal pure returns (uint256 z) {
        z = n % 2 != 0 ? x : RAY;

        for (n /= 2; n != 0; n /= 2) {
            x = rmul(x, x);

            if (n % 2 != 0) {
                z = rmul(z, x);
            }
        }
    }
}
          

contracts/lib/Utils.sol

/*
 * SPDX-License-Identifier: MIT
 */
pragma solidity ^0.8.19;

contract Utils {
    uint24 private constant _SECS_IN_FOUR_WEEKS = 2419200;

    function _callAndParseAddressReturn(
        address token_,
        bytes4 selector_
    ) internal view returns (address) {
        (bool success, bytes memory data) = token_.staticcall(
            abi.encodeWithSelector(selector_)
        );

        if (!success || data.length == 0) {
            return address(0);
        }

        if (data.length == 32) {
            return abi.decode(data, (address));
        }

        return address(0);
    }

    function _getToken0(
        address target_
    ) internal view returns (address targetToken0) {
        targetToken0 = _callAndParseAddressReturn(
            target_,
            hex"0dfe1681"
        );

        return targetToken0;
    }

    function _getToken1(
        address target_
    ) internal view returns (address targetToken1) {
        targetToken1 = _callAndParseAddressReturn(
            target_,
            hex"d21220a7"
        );

        return targetToken1;
    }

    function _penaltyFor(
        uint256 fromTimestamp_,
        uint256 toTimestamp_
    ) internal pure returns (uint256 penaltyBasis) {
        if (fromTimestamp_ + 52 weeks > toTimestamp_) {
            uint256 fourWeeksElapsed = (toTimestamp_ - fromTimestamp_) /
                _SECS_IN_FOUR_WEEKS;
            if (fourWeeksElapsed < 13) {
                penaltyBasis = (13 - fourWeeksElapsed) * 100;
            }
        }
        return penaltyBasis;
    }
}
          

contracts/openzeppelin/access/Ownable.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

abstract contract Ownable {
    address private _owner;

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

    constructor() {
        _transferOwnership(msg.sender);
    }

    modifier onlyOwner() {
        _checkOwner();
        _;
    }

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

    function _checkOwner() internal view virtual {
        require(owner() == msg.sender, "O:Caller not owner");
    }

    function renounceOwnership() external virtual onlyOwner {
        _transferOwnership(address(0));
    }

    function transferOwnership(address newOwner) external virtual onlyOwner {
        require(newOwner != address(0), "O:0 address");
        _transferOwnership(newOwner);
    }

    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}
          

contracts/openzeppelin/security/Pausable.sol

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

abstract contract Pausable {
    event Paused(address account);

    event Unpaused(address account);

    bool private _paused;

    constructor() {
        _paused = false;
    }

    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    modifier whenPaused() {
        _requirePaused();
        _;
    }

    function paused() public view virtual returns (bool) {
        return _paused;
    }

    function _requireNotPaused() internal view virtual {
        require(!paused(), "P:Paused");
    }

    function _requirePaused() internal view virtual {
        require(paused(), "P:Not paused");
    }

    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(msg.sender);
    }

    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(msg.sender);
    }
}
          

contracts/uniswap/v2-periphery/interfaces/IUniswapV2Router01.sol

/*
 * SPDX-License-Identifier: MIT
 */

pragma solidity ^0.8.19;

interface IUniswapV2Router01 {
    function factory() external pure returns (address);

    function WPLS() external pure returns (address);

    function addLiquidity(
        address tokenA,
        address tokenB,
        uint amountADesired,
        uint amountBDesired,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB, uint liquidity);

    function addLiquidityETH(
        address token,
        uint amountTokenDesired,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    )
        external
        payable
        returns (uint amountToken, uint amountETH, uint liquidity);
}
          

contracts/uniswap/v2-periphery/interfaces/IUniswapV2Router02.sol

/*
 * SPDX-License-Identifier: MIT
 */

pragma solidity ^0.8.19;

import "./IUniswapV2Router01.sol";

interface IUniswapV2Router02 is IUniswapV2Router01 {
    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;

    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
}
          

Compiler Settings

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

Contract ABI

[{"type":"constructor","inputs":[{"type":"string","name":"name_","internalType":"string"},{"type":"string","name":"symbol_","internalType":"string"},{"type":"address","name":"inflationAddress_","internalType":"address"},{"type":"address","name":"feeAddr1_","internalType":"address"},{"type":"address","name":"feeAddr2_","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"airdrop","inputs":[{"type":"tuple[]","name":"receivers_","internalType":"struct BasePEPEL.Airdrop[]","components":[{"type":"address"},{"type":"uint256"}]}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"allowance","inputs":[{"type":"address","name":"owner_","internalType":"address"},{"type":"address","name":"spender_","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"approve","inputs":[{"type":"address","name":"spender_","internalType":"address"},{"type":"uint256","name":"amount_","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"wallet_","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"burn","inputs":[{"type":"uint256","name":"amount_","internalType":"uint256"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"decimals","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"decreaseAllowance","inputs":[{"type":"address","name":"spender_","internalType":"address"},{"type":"uint256","name":"subtractedValue_","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getTotalStakeholders","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"totalStakeCount","internalType":"uint256"}],"name":"getTotalStakes","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"increaseAllowance","inputs":[{"type":"address","name":"spender_","internalType":"address"},{"type":"uint256","name":"addedValue_","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"manager","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"pauseContract","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"paused","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"penaltyBasis","internalType":"uint256"}],"name":"penaltyIfUnstakedNow","inputs":[{"type":"address","name":"wallet_","internalType":"address"},{"type":"uint256","name":"stakeIndex_","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"reclaimETH","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"reclaimToken","inputs":[{"type":"address","name":"token_","internalType":"contract IERC20"},{"type":"uint256","name":"amount_","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"pepelRewards","internalType":"uint256"},{"type":"uint256","name":"eligibleBasis","internalType":"uint256"}],"name":"rewardsOf","inputs":[{"type":"address","name":"stakeholder_","internalType":"address"},{"type":"uint256","name":"stakeIndex_","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setFeeAddresses","inputs":[{"type":"address","name":"feeAddr1_","internalType":"address"},{"type":"address","name":"feeAddr2_","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"stake","inputs":[{"type":"uint256","name":"stakeAmount_","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"user","internalType":"address"}],"name":"stakeholders","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"userStakes","internalType":"struct PEPEv4.Stake[]","components":[{"type":"uint256"},{"type":"uint256"},{"type":"uint256"}]}],"name":"stakesOf","inputs":[{"type":"address","name":"stakeholder_","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalStakes","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transfer","inputs":[{"type":"address","name":"to_","internalType":"address"},{"type":"uint256","name":"amount_","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transferFrom","inputs":[{"type":"address","name":"from_","internalType":"address"},{"type":"address","name":"to_","internalType":"address"},{"type":"uint256","name":"amount_","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferManagement","inputs":[{"type":"address","name":"newManager_","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"unPauseContract","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"unstake","inputs":[{"type":"uint256","name":"unstakeAmount_","internalType":"uint256"},{"type":"uint256","name":"stakeIndex_","internalType":"uint256"}]},{"type":"event","name":"Approval","inputs":[{"type":"address","name":"owner","indexed":true},{"type":"address","name":"spender","indexed":true},{"type":"uint256","name":"value","indexed":false}],"anonymous":false},{"type":"event","name":"ManagementTransferred","inputs":[{"type":"address","name":"previousManager","indexed":true},{"type":"address","name":"newManager","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","indexed":true},{"type":"address","name":"newOwner","indexed":true}],"anonymous":false},{"type":"event","name":"Paused","inputs":[{"type":"address","name":"account","indexed":false}],"anonymous":false},{"type":"event","name":"Staked","inputs":[{"type":"address","name":"user","indexed":true},{"type":"uint256","name":"stakeIndex","indexed":false},{"type":"uint256","name":"stakeAmount","indexed":false},{"type":"uint256","name":"rewardDebt","indexed":false},{"type":"uint256","name":"since","indexed":false}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"type":"address","name":"from","indexed":true},{"type":"address","name":"to","indexed":true},{"type":"uint256","name":"value","indexed":false}],"anonymous":false},{"type":"event","name":"Unpaused","inputs":[{"type":"address","name":"account","indexed":false}],"anonymous":false},{"type":"event","name":"Unstaked","inputs":[{"type":"address","name":"user","indexed":true},{"type":"uint256","name":"stakeAmount","indexed":false},{"type":"uint256","name":"rewardDebt","indexed":false},{"type":"uint256","name":"since","indexed":false},{"type":"uint256","name":"till","indexed":false}],"anonymous":false},{"type":"receive"},{"type":"fallback"}]
              

Contract Creation Code

0x60806040523480156200001157600080fd5b5060405162003e2638038062003e26833981016040819052620000349162000ab3565b8484620000413362000269565b6000805460ff60a01b19168155600180546001600160a01b031916339081179091556040519091907f80f15e9dbc60884fdb59fb8ed4fc48a9a689e028f055e893ed45ca5be67c5c85908290a360056200009c838262000be3565b506006620000ab828262000be3565b5050336000818152600260209081526040808320805460ff1990811660019081179092556007805483019055600a80546001600160a01b038c81166001600160a01b031992831617909255600880548c841690831681179091558752848720805484168517905560098054928b169290911682179055855282852080549091169091179055838352600482528083206c0c9f2c9cd04674edea40000000908190559051908152929350909160008051602062003e06833981519152910160405180910390a3600062000193670de0b6b3a76400006c064f964e68233a76f52000000062000cc5565b600a546001600160a01b0316600090815260046020526040812080546001600160801b039390931693508392909190620001cf90849062000cef565b90915550503360009081526004602052604081208054839290620001f590849062000d05565b9091555050600a546040518281526001600160a01b0390911690339060008051602062003e068339815191529060200160405180910390a36200023b610e104262000d31565b62000247904262000d05565b600d556200025d670de0b6b3a7640000620002b9565b50505050505062000d8f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b620002c3620005c5565b3360009081526004602052604081208054839290620002e490849062000d05565b909155505033600090815260026020526040812054819060ff16156200030c57508162000346565b6127106200031c84601962000d48565b62000328919062000d62565b91508162000337818562000d05565b62000343919062000d05565b90505b30600090815260046020526040812080548392906200036790849062000cef565b90915550506040518181523090339060008051602062003e068339815191529060200160405180910390a3811562000462576008546001600160a01b031660009081526004602052604081208054849290620003c590849062000cef565b90915550506008546040518381526001600160a01b0390911690339060008051602062003e068339815191529060200160405180910390a36009546001600160a01b0316600090815260046020526040812080548492906200042990849062000cef565b90915550506009546040518381526001600160a01b0390911690339060008051602062003e068339815191529060200160405180910390a35b336000908152600b6020526040812054908190036200048957620004863362000671565b90505b600064e8d4a5100083600e54620004a1919062000d48565b620004ad919062000d62565b905060078281548110620004c557620004c562000d79565b6000918252602080832060408051606081018252888152808401878152429282019283526001600296870290940184018054808601825590885294872091516003909502909101938455519183019190915551910155600c80548592906200052f90849062000cef565b92505081905550336001600160a01b03167f9cfd25589d1eb8ad71e342a86a8524e83522e3936c0803048c08f6d9ad974f4060016007858154811062000579576200057962000d79565b9060005260206000209060020201600101805490506200059a919062000d05565b6040805191825260208201879052810184905242606082015260800160405180910390a25050505050565b6000620005d5610e104262000d31565b620005e1904262000d05565b9050600d548111156200066e57600080620005fc83620006ec565b91509150816000146200066b57600d839055600a546001600160a01b0316600090815260046020526040812080548492906200063a90849062000d05565b909155505030600090815260046020526040812080548492906200066090849062000cef565b9091555050600e8190555b50505b50565b600780546001908101808355600092835282916200068f9162000d05565b90508260078281548110620006a857620006a862000d79565b6000918252602080832060029290920290910180546001600160a01b0319166001600160a01b03948516179055949091168152600b90935260409092208290555090565b600080600d54600003620007475760405162461bcd60e51b815260206004820152601860248201527f4c3a496e666c6174696f6e206e6f74207374617274656421000000000000000060448201526064015b60405180910390fd5b600d54600090610e10906200075d908662000d05565b62000769919062000d62565b600a546001600160a01b0316600090815260046020526040902054909150811562000816576000620007a86b033b2c8af183120df30000008462000823565b90506b033b2e3c9fd0803ce8000000620007c3828462000d48565b620007cf919062000d62565b620007db908362000d05565b600c54909550620007f28664e8d4a5100062000d48565b620007fe919062000d62565b600e546200080d919062000cef565b9350506200081c565b600e5492505b5050915091565b60006200083260028362000d31565b6000036200084d576b033b2e3c9fd0803ce80000006200084f565b825b90506200085e60028362000d62565b91505b8115620008ad57620008748380620008b3565b92506200088360028362000d31565b156200089857620008958184620008b3565b90505b620008a560028362000d62565b915062000861565b92915050565b60006b033b2e3c9fd0803ce8000000620008e5620008d28585620008f8565b6b019d971e4fe8401e740000006200096f565b620008f1919062000d62565b9392505050565b6000811580620009215750828262000911818362000d48565b92506200091f908362000d62565b145b620008ad5760405162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f7700000000000000000000000060448201526064016200073e565b6000826200097e838262000cef565b9150811015620008ad5760405162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f7700000000000000000000000060448201526064016200073e565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620009f957600080fd5b81516001600160401b038082111562000a165762000a16620009d1565b604051601f8301601f19908116603f0116810190828211818310171562000a415762000a41620009d1565b8160405283815260209250868385880101111562000a5e57600080fd5b600091505b8382101562000a82578582018301518183018401529082019062000a63565b600093810190920192909252949350505050565b80516001600160a01b038116811462000aae57600080fd5b919050565b600080600080600060a0868803121562000acc57600080fd5b85516001600160401b038082111562000ae457600080fd5b62000af289838a01620009e7565b9650602088015191508082111562000b0957600080fd5b5062000b1888828901620009e7565b94505062000b296040870162000a96565b925062000b396060870162000a96565b915062000b496080870162000a96565b90509295509295909350565b600181811c9082168062000b6a57607f821691505b60208210810362000b8b57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200066b57600081815260208120601f850160051c8101602086101562000bba5750805b601f850160051c820191505b8181101562000bdb5782815560010162000bc6565b505050505050565b81516001600160401b0381111562000bff5762000bff620009d1565b62000c178162000c10845462000b55565b8462000b91565b602080601f83116001811462000c4f576000841562000c365750858301515b600019600386901b1c1916600185901b17855562000bdb565b600085815260208120601f198616915b8281101562000c805788860151825594840194600190910190840162000c5f565b508582101562000c9f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b6001600160801b0382811682821603908082111562000ce85762000ce862000caf565b5092915050565b80820180821115620008ad57620008ad62000caf565b81810381811115620008ad57620008ad62000caf565b634e487b7160e01b600052601260045260246000fd5b60008262000d435762000d4362000d1b565b500690565b8082028115828204841417620008ad57620008ad62000caf565b60008262000d745762000d7462000d1b565b500490565b634e487b7160e01b600052603260045260246000fd5b6130678062000d9f6000396000f3fe6080604052600436106101e75760003560e01c806368c336271161010e578063a694fc3a116100a7578063c1acbaf211610079578063e0c9ffc611610061578063e0c9ffc614610623578063e4edf85214610643578063f2fde38b1461066357005b8063c1acbaf2146105b0578063dd62ed3e146105d057005b8063a694fc3a14610545578063a9059cbb14610565578063bac1520314610585578063bf9befb11461059a57005b80638da5cb5b116100e05780638da5cb5b146104c557806395d89b41146104f05780639e2c8a5b14610505578063a457c2d71461052557005b806368c33627146104435780636fc436631461045857806370a082311461046d578063715018a6146104b057005b806333b69c4c11610180578063439766ce11610152578063439766ce146103c0578063481c6a75146103d55780635c975abb1461040057806361ce35291461043057005b806333b69c4c1461031e57806335941b1c1461034b578063395093511461038057806342966c68146103a057005b806318160ddd116101b957806318160ddd146102735780631d6b8b721461029d57806323b872dd146102e2578063313ce5671461030257005b806306fdde03146101f0578063095ea7b31461021b5780630f144a481461024b57806311c841201461025357005b366101ee57005b005b3480156101fc57600080fd5b50610205610683565b6040516102129190612bf6565b60405180910390f35b34801561022757600080fd5b5061023b610236366004612c84565b610715565b6040519015158152602001610212565b6101ee61072f565b34801561025f57600080fd5b506101ee61026e366004612cb0565b61086a565b34801561027f57600080fd5b506c0c9f2c9cd04674edea400000005b604051908152602001610212565b3480156102a957600080fd5b506102bd6102b8366004612ce9565b610931565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610212565b3480156102ee57600080fd5b5061023b6102fd366004612d02565b61096d565b34801561030e57600080fd5b5060405160128152602001610212565b34801561032a57600080fd5b5061033e610339366004612d43565b610a53565b6040516102129190612d60565b34801561035757600080fd5b5061036b610366366004612c84565b610b28565b60408051928352602083019190915201610212565b34801561038c57600080fd5b5061023b61039b366004612c84565b610bd7565b3480156103ac57600080fd5b506101ee6103bb366004612ce9565b610c23565b3480156103cc57600080fd5b506101ee610cc6565b3480156103e157600080fd5b5060015473ffffffffffffffffffffffffffffffffffffffff166102bd565b34801561040c57600080fd5b5060005474010000000000000000000000000000000000000000900460ff1661023b565b6101ee61043e366004612c84565b610cd8565b34801561044f57600080fd5b5061028f610eac565b34801561046457600080fd5b5061028f610f01565b34801561047957600080fd5b5061028f610488366004612d43565b73ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604090205490565b3480156104bc57600080fd5b506101ee610f18565b3480156104d157600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166102bd565b3480156104fc57600080fd5b50610205610f2a565b34801561051157600080fd5b506101ee610520366004612db9565b610f39565b34801561053157600080fd5b5061023b610540366004612c84565b610f53565b34801561055157600080fd5b506101ee610560366004612ce9565b611009565b34801561057157600080fd5b5061023b610580366004612c84565b611100565b34801561059157600080fd5b506101ee61110e565b3480156105a657600080fd5b5061028f600c5481565b3480156105bc57600080fd5b5061028f6105cb366004612c84565b61111e565b3480156105dc57600080fd5b5061028f6105eb366004612cb0565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260036020908152604080832093909416825291909152205490565b34801561062f57600080fd5b506101ee61063e366004612ddb565b611168565b34801561064f57600080fd5b506101ee61065e366004612d43565b61125e565b34801561066f57600080fd5b506101ee61067e366004612d43565b6112f4565b60606005805461069290612e50565b80601f01602080910402602001604051908101604052809291908181526020018280546106be90612e50565b801561070b5780601f106106e05761010080835404028352916020019161070b565b820191906000526020600020905b8154815290600101906020018083116106ee57829003601f168201915b5050505050905090565b600033610723818585611382565b60019150505b92915050565b478061079c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f42423a302042616c616e6365000000000000000000000000000000000000000060448201526064015b60405180910390fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff9091169083908381818185875af1925050503d80600081146107f6576040519150601f19603f3d011682016040523d82523d6000602084013e6107fb565b606091505b5050905080610866576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f42423a53656e64204661696c65640000000000000000000000000000000000006044820152606401610793565b5050565b6108726113f1565b73ffffffffffffffffffffffffffffffffffffffff8216156108cf57600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790555b73ffffffffffffffffffffffffffffffffffffffff811615610866576009805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff00000000000000000000000000000000000000009091161790555050565b6007818154811061094157600080fd5b600091825260209091206002909102015473ffffffffffffffffffffffffffffffffffffffff16905081565b73ffffffffffffffffffffffffffffffffffffffff831660009081526003602090815260408083203380855292528220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610a3c5783811015610a2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f42423a496e73756666696369656e7420616c6c6f77616e6365000000000000006044820152606401610793565b610a3c8683868403611382565b610a4786868661148e565b50600195945050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600b60205260409020546060908015610b225760078181548110610a9557610a95612e9d565b9060005260206000209060020201600101805480602002602001604051908101604052809291908181526020016000905b82821015610b165783829060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505081526020019060010190610ac6565b50505050915050919050565b50919050565b600080600080600d54600014610b4757610b414261156b565b90925090505b73ffffffffffffffffffffffffffffffffffffffff86166000908152600b602052604081205490610b7882886116af565b9050610b888160400151426117d7565b610b9490612710612efb565b94508215610bcc576020810151815164e8d4a5100090610bb5908690612f0e565b610bbf9190612f54565b610bc99190612efb565b95505b505050509250929050565b33600081815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906107239082908690610c1e908790612f68565b611382565b3360009081526004602052604081208054839290610c42908490612efb565b9091555050610369600090815260046020527fc643d66a6158812cd467647122634e94767252ad194a6f26c0713061216c76098054839290610c85908490612f68565b90915550506040518181526103699033907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a350565b610cce611833565b610cd66118b4565b565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610d45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d699190612f7b565b905080821115610dd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f42423a546f6f206d7563680000000000000000000000000000000000000000006044820152606401610793565b8273ffffffffffffffffffffffffffffffffffffffff1663a9059cbb610e1060005473ffffffffffffffffffffffffffffffffffffffff1690565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602481018490526044016020604051808303816000875af1158015610e82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea69190612f94565b50505050565b6000805b600754811015610efd5760078181548110610ecd57610ecd612e9d565b6000918252602090912060016002909202010154610eeb9083612f68565b9150610ef681612fb6565b9050610eb0565b5090565b600754600090610f1390600190612efb565b905090565b610f206113f1565b610cd66000611931565b60606006805461069290612e50565b610f416119a6565b610f49611a2b565b6108668282611ad3565b33600081815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610ff1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f42423a4465637265617365732062656c6f7720300000000000000000000000006044820152606401610793565b610ffe8286868403611382565b506001949350505050565b6110116119a6565b8060000361107b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4c3a43616e6e6f74207374616b652030000000000000000000000000000000006044820152606401610793565b336000908152600460205260409020548111156110f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4c3a546f6f206d756368207374616b696e6700000000000000000000000000006044820152606401610793565b6110fd81611ef6565b50565b60003361072381858561148e565b611116611833565b610cd6612250565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600b60205260408120548161114f82856116af565b905061115f8160400151426117d7565b95945050505050565b6111706113f1565b60005b8181101561125957600083838381811061118f5761118f612e9d565b6111a59260206040909202019081019150612d43565b73ffffffffffffffffffffffffffffffffffffffff16141580156111e557508282828181106111d6576111d6612e9d565b90506040020160200135600014155b15611249576112498383838181106111ff576111ff612e9d565b6112159260206040909202019081019150612d43565b84848481811061122757611227612e9d565b90506040020160200135670de0b6b3a76400006112449190612f0e565b6122b0565b61125281612fb6565b9050611173565b505050565b611266611833565b60015460405173ffffffffffffffffffffffffffffffffffffffff8084169216907f80f15e9dbc60884fdb59fb8ed4fc48a9a689e028f055e893ed45ca5be67c5c8590600090a3600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6112fc6113f1565b73ffffffffffffffffffffffffffffffffffffffff8116611379576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f4f3a3020616464726573730000000000000000000000000000000000000000006044820152606401610793565b6110fd81611931565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526003602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b3361141160005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614610cd6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4f3a43616c6c6572206e6f74206f776e657200000000000000000000000000006044820152606401610793565b6114966119a6565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260046020526040812080548392906114cb908490612efb565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526004602052604081208054839290611505908490612f68565b925050819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516113e491815260200190565b600080600d546000036115da576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4c3a496e666c6174696f6e206e6f7420737461727465642100000000000000006044820152606401610793565b600d54600090610e10906115ee9086612efb565b6115f89190612f54565b600a5473ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604090205490915081156116a25760006116416b033b2c8af183120df3000000846122d9565b90506b033b2e3c9fd0803ce800000061165a8284612f0e565b6116649190612f54565b61166e9083612efb565b600c549095506116838664e8d4a51000612f0e565b61168d9190612f54565b600e5461169a9190612f68565b9350506116a8565b600e5492505b5050915091565b6116d360405180606001604052806000815260200160008152602001600081525090565b600783815481106116e6576116e6612e9d565b9060005260206000209060020201600101805490508210611763576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f533a5374616b6520696e64657820696e636f72726563742100000000000000006044820152606401610793565b6007838154811061177657611776612e9d565b9060005260206000209060020201600101828154811061179857611798612e9d565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905092915050565b6000816117e8846301dfe200612f68565b11156107295760006224ea006117fe8585612efb565b6118089190612f54565b9050600d81101561182c5761181e81600d612efb565b611829906064612f0e565b91505b5092915050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610cd6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4d3a43616c6c6572206e6f74206d616e616765720000000000000000000000006044820152606401610793565b6118bc6119a6565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906020015b60405180910390a1565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60005474010000000000000000000000000000000000000000900460ff1615610cd6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f503a5061757365640000000000000000000000000000000000000000000000006044820152606401610793565b6000611a39610e1042612fee565b611a439042612efb565b9050600d548111156110fd57600080611a5b8361156b565b915091508160001461125957600d839055600a5473ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604081208054849290611aa3908490612efb565b90915550503060009081526004602052604081208054849290611ac7908490612f68565b9091555050600e555050565b600080611ae08385612352565b90506000611af28260400151426117d7565b611afe90612710612efb565b9050600080836020015164e8d4a51000600e548660000151611b209190612f0e565b611b2a9190612f54565b611b349190612efb565b90508684600001511115611b5357611b4c8188612f68565b9150611b63565b8351611b60908290612f68565b91505b33600090815260026020526040812054819060ff1615611b8857506000905082611bba565b612710611b96856019612f0e565b611ba09190612f54565b915081611bad8186612efb565b611bb79190612efb565b90505b6000612710611bc98784612f0e565b611bd39190612f54565b90508015611d7f573060009081526004602052604081208054879290611bfa908490612efb565b90915550503360009081526004602052604081208054839290611c1e908490612f68565b9091555050604051818152339030907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3600197508215611d7f5760085473ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604081208054859290611c9b908490612f68565b909155505060085460405184815273ffffffffffffffffffffffffffffffffffffffff9091169030907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a360095473ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604081208054859290611d28908490612f68565b909155505060095460405184815273ffffffffffffffffffffffffffffffffffffffff9091169030907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35b612710861015611e1c576000611d958284612efb565b90508015611e1a57610369600090815260046020527fc643d66a6158812cd467647122634e94767252ad194a6f26c0713061216c76098054839290611ddb908490612f68565b90915550506040518181526103699030907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35b505b89600c6000828254611e2e9190612efb565b90915550506020878101516040808a015181518e81529384019290925282015242606082015233907fdcfd2b4017d03f7e541021db793b2f9b31e4acdee005f789e52853c390e3e9629060800160405180910390a287611eea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f556e7374616b65206661696c65640000000000000000000000000000000000006044820152606401610793565b50505050505050505050565b611efe611a2b565b3360009081526004602052604081208054839290611f1d908490612efb565b909155505033600090815260026020526040812054819060ff1615611f43575081611f75565b612710611f51846019612f0e565b611f5b9190612f54565b915081611f688185612efb565b611f729190612efb565b90505b3060009081526004602052604081208054839290611f94908490612f68565b9091555050604051818152309033907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a381156120f15760085473ffffffffffffffffffffffffffffffffffffffff166000908152600460205260408120805484929061200d908490612f68565b909155505060085460405183815273ffffffffffffffffffffffffffffffffffffffff9091169033907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a360095473ffffffffffffffffffffffffffffffffffffffff166000908152600460205260408120805484929061209a908490612f68565b909155505060095460405183815273ffffffffffffffffffffffffffffffffffffffff9091169033907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35b336000908152600b60205260408120549081900361211557612112336128f1565b90505b600064e8d4a5100083600e5461212b9190612f0e565b6121359190612f54565b90506007828154811061214a5761214a612e9d565b6000918252602080832060408051606081018252888152808401878152429282019283526001600296870290940184018054808601825590885294872091516003909502909101938455519183019190915551910155600c80548592906121b2908490612f68565b925050819055503373ffffffffffffffffffffffffffffffffffffffff167f9cfd25589d1eb8ad71e342a86a8524e83522e3936c0803048c08f6d9ad974f4060016007858154811061220657612206612e9d565b9060005260206000209060020201600101805490506122259190612efb565b6040805191825260208201879052810184905242606082015260800160405180910390a25050505050565b61225861298c565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa90602001611927565b6108666122d260005473ffffffffffffffffffffffffffffffffffffffff1690565b838361148e565b60006122e6600283612fee565b6000036122ff576b033b2e3c9fd0803ce8000000612301565b825b905061230e600283612f54565b91505b8115610729576123218384612a10565b925061232e600283612fee565b156123405761233d8184612a10565b90505b61234b600283612f54565b9150612311565b61237660405180606001604052806000815260200160008152602001600081525090565b336000908152600b602052604090205461239081856116af565b91508060011415806123a157508315155b612407576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f533a43616e6e6f742072656d6f766520317374207374616b65000000000000006044820152606401610793565b8151831115612472576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f533a546f6f206d75636820756e7374616b696e670000000000000000000000006044820152606401610793565b81518390036128665760016007828154811061249057612490612e9d565b9060005260206000209060020201600101805490506124af9190612efb565b84101561258a57600781815481106124c9576124c9612e9d565b90600052602060002090600202016001016001600783815481106124ef576124ef612e9d565b90600052602060002090600202016001018054905061250e9190612efb565b8154811061251e5761251e612e9d565b90600052602060002090600302016007828154811061253f5761253f612e9d565b9060005260206000209060020201600101858154811061256157612561612e9d565b600091825260209091208254600390920201908155600180830154908201556002918201549101555b6007818154811061259d5761259d612e9d565b90600052602060002090600202016001018054806125bd576125bd613002565b60008281526020812060037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9093019283020181815560018101829055600201559055600780548290811061261457612614612e9d565b6000918252602082206001600290920201015490036128615760075461263c90600190612efb565b8110156127d4576007805461265390600190612efb565b8154811061266357612663612e9d565b90600052602060002090600202016007828154811061268457612684612e9d565b60009182526020909120825460029092020180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091178155600180830180546126ec9284019190612b51565b50905050600780548061270157612701613002565b60008281526020812060027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9093019283020180547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155906127686001830182612bb7565b50509055336000908152600b60208190526040822082905560078054849391908490811061279857612798612e9d565b6000918252602080832060029092029091015473ffffffffffffffffffffffffffffffffffffffff16835282019290925260400190205561182c565b60078054806127e5576127e5613002565b60008281526020812060027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9093019283020180547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559061284c6001830182612bb7565b50509055336000908152600b60205260408120555b61182c565b60006007828154811061287b5761287b612e9d565b9060005260206000209060020201600101858154811061289d5761289d612e9d565b600091825260208220855160039092020192506128bb908690612efb565b808355600e5490915064e8d4a51000906128d6908390612f0e565b6128e09190612f54565b826001018190555050505092915050565b6007805460019081018083556000928352829161290d91612efb565b9050826007828154811061292357612923612e9d565b6000918252602080832060029290920290910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff948516179055949091168152600b90935260409092208290555090565b60005474010000000000000000000000000000000000000000900460ff16610cd6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f503a4e6f742070617573656400000000000000000000000000000000000000006044820152606401610793565b60006b033b2e3c9fd0803ce8000000612a3e612a2c8585612a4f565b6b019d971e4fe8401e74000000612ad9565b612a489190612f54565b9392505050565b6000811580612a7357508282612a658183612f0e565b9250612a719083612f54565b145b610729576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f770000000000000000000000006044820152606401610793565b600082612ae68382612f68565b9150811015610729576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f770000000000000000000000006044820152606401610793565b828054828255906000526020600020906003028101928215612bab5760005260206000209160030282015b82811115612bab5782548255600180840154908301556002808401549083015560039283019290910190612b7c565b50610efd929150612bd4565b50805460008255600302906000526020600020908101906110fd91905b5b80821115610efd576000808255600182018190556002820155600301612bd5565b600060208083528351808285015260005b81811015612c2357858101830151858201604001528201612c07565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b73ffffffffffffffffffffffffffffffffffffffff811681146110fd57600080fd5b60008060408385031215612c9757600080fd5b8235612ca281612c62565b946020939093013593505050565b60008060408385031215612cc357600080fd5b8235612cce81612c62565b91506020830135612cde81612c62565b809150509250929050565b600060208284031215612cfb57600080fd5b5035919050565b600080600060608486031215612d1757600080fd5b8335612d2281612c62565b92506020840135612d3281612c62565b929592945050506040919091013590565b600060208284031215612d5557600080fd5b8135612a4881612c62565b602080825282518282018190526000919060409081850190868401855b82811015612dac5781518051855286810151878601528501518585015260609093019290850190600101612d7d565b5091979650505050505050565b60008060408385031215612dcc57600080fd5b50508035926020909101359150565b60008060208385031215612dee57600080fd5b823567ffffffffffffffff80821115612e0657600080fd5b818501915085601f830112612e1a57600080fd5b813581811115612e2957600080fd5b8660208260061b8501011115612e3e57600080fd5b60209290920196919550909350505050565b600181811c90821680612e6457607f821691505b602082108103610b22577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561072957610729612ecc565b808202811582820484141761072957610729612ecc565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082612f6357612f63612f25565b500490565b8082018082111561072957610729612ecc565b600060208284031215612f8d57600080fd5b5051919050565b600060208284031215612fa657600080fd5b81518015158114612a4857600080fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612fe757612fe7612ecc565b5060010190565b600082612ffd57612ffd612f25565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220b03a6a9d0ff0bc428b8e7bded99318545d0c13000ef349404ace56c7187a0e6764736f6c63430008130033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000802d686567ba30dceba167d66a544f6ef915e0f7000000000000000000000000fb7103d7011dfa60c18c6961c5a38038d8048fe0000000000000000000000000fc51c335f8be70d0541944da5d5cd0638bbcc63d0000000000000000000000000000000000000000000000000000000000000019506570656c6f7269616e3a205374616b61626c652050657065000000000000000000000000000000000000000000000000000000000000000000000000000005504550454c000000000000000000000000000000000000000000000000000000

Deployed ByteCode

0x6080604052600436106101e75760003560e01c806368c336271161010e578063a694fc3a116100a7578063c1acbaf211610079578063e0c9ffc611610061578063e0c9ffc614610623578063e4edf85214610643578063f2fde38b1461066357005b8063c1acbaf2146105b0578063dd62ed3e146105d057005b8063a694fc3a14610545578063a9059cbb14610565578063bac1520314610585578063bf9befb11461059a57005b80638da5cb5b116100e05780638da5cb5b146104c557806395d89b41146104f05780639e2c8a5b14610505578063a457c2d71461052557005b806368c33627146104435780636fc436631461045857806370a082311461046d578063715018a6146104b057005b806333b69c4c11610180578063439766ce11610152578063439766ce146103c0578063481c6a75146103d55780635c975abb1461040057806361ce35291461043057005b806333b69c4c1461031e57806335941b1c1461034b578063395093511461038057806342966c68146103a057005b806318160ddd116101b957806318160ddd146102735780631d6b8b721461029d57806323b872dd146102e2578063313ce5671461030257005b806306fdde03146101f0578063095ea7b31461021b5780630f144a481461024b57806311c841201461025357005b366101ee57005b005b3480156101fc57600080fd5b50610205610683565b6040516102129190612bf6565b60405180910390f35b34801561022757600080fd5b5061023b610236366004612c84565b610715565b6040519015158152602001610212565b6101ee61072f565b34801561025f57600080fd5b506101ee61026e366004612cb0565b61086a565b34801561027f57600080fd5b506c0c9f2c9cd04674edea400000005b604051908152602001610212565b3480156102a957600080fd5b506102bd6102b8366004612ce9565b610931565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610212565b3480156102ee57600080fd5b5061023b6102fd366004612d02565b61096d565b34801561030e57600080fd5b5060405160128152602001610212565b34801561032a57600080fd5b5061033e610339366004612d43565b610a53565b6040516102129190612d60565b34801561035757600080fd5b5061036b610366366004612c84565b610b28565b60408051928352602083019190915201610212565b34801561038c57600080fd5b5061023b61039b366004612c84565b610bd7565b3480156103ac57600080fd5b506101ee6103bb366004612ce9565b610c23565b3480156103cc57600080fd5b506101ee610cc6565b3480156103e157600080fd5b5060015473ffffffffffffffffffffffffffffffffffffffff166102bd565b34801561040c57600080fd5b5060005474010000000000000000000000000000000000000000900460ff1661023b565b6101ee61043e366004612c84565b610cd8565b34801561044f57600080fd5b5061028f610eac565b34801561046457600080fd5b5061028f610f01565b34801561047957600080fd5b5061028f610488366004612d43565b73ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604090205490565b3480156104bc57600080fd5b506101ee610f18565b3480156104d157600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166102bd565b3480156104fc57600080fd5b50610205610f2a565b34801561051157600080fd5b506101ee610520366004612db9565b610f39565b34801561053157600080fd5b5061023b610540366004612c84565b610f53565b34801561055157600080fd5b506101ee610560366004612ce9565b611009565b34801561057157600080fd5b5061023b610580366004612c84565b611100565b34801561059157600080fd5b506101ee61110e565b3480156105a657600080fd5b5061028f600c5481565b3480156105bc57600080fd5b5061028f6105cb366004612c84565b61111e565b3480156105dc57600080fd5b5061028f6105eb366004612cb0565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260036020908152604080832093909416825291909152205490565b34801561062f57600080fd5b506101ee61063e366004612ddb565b611168565b34801561064f57600080fd5b506101ee61065e366004612d43565b61125e565b34801561066f57600080fd5b506101ee61067e366004612d43565b6112f4565b60606005805461069290612e50565b80601f01602080910402602001604051908101604052809291908181526020018280546106be90612e50565b801561070b5780601f106106e05761010080835404028352916020019161070b565b820191906000526020600020905b8154815290600101906020018083116106ee57829003601f168201915b5050505050905090565b600033610723818585611382565b60019150505b92915050565b478061079c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f42423a302042616c616e6365000000000000000000000000000000000000000060448201526064015b60405180910390fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff9091169083908381818185875af1925050503d80600081146107f6576040519150601f19603f3d011682016040523d82523d6000602084013e6107fb565b606091505b5050905080610866576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f42423a53656e64204661696c65640000000000000000000000000000000000006044820152606401610793565b5050565b6108726113f1565b73ffffffffffffffffffffffffffffffffffffffff8216156108cf57600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790555b73ffffffffffffffffffffffffffffffffffffffff811615610866576009805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff00000000000000000000000000000000000000009091161790555050565b6007818154811061094157600080fd5b600091825260209091206002909102015473ffffffffffffffffffffffffffffffffffffffff16905081565b73ffffffffffffffffffffffffffffffffffffffff831660009081526003602090815260408083203380855292528220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610a3c5783811015610a2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f42423a496e73756666696369656e7420616c6c6f77616e6365000000000000006044820152606401610793565b610a3c8683868403611382565b610a4786868661148e565b50600195945050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600b60205260409020546060908015610b225760078181548110610a9557610a95612e9d565b9060005260206000209060020201600101805480602002602001604051908101604052809291908181526020016000905b82821015610b165783829060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505081526020019060010190610ac6565b50505050915050919050565b50919050565b600080600080600d54600014610b4757610b414261156b565b90925090505b73ffffffffffffffffffffffffffffffffffffffff86166000908152600b602052604081205490610b7882886116af565b9050610b888160400151426117d7565b610b9490612710612efb565b94508215610bcc576020810151815164e8d4a5100090610bb5908690612f0e565b610bbf9190612f54565b610bc99190612efb565b95505b505050509250929050565b33600081815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906107239082908690610c1e908790612f68565b611382565b3360009081526004602052604081208054839290610c42908490612efb565b9091555050610369600090815260046020527fc643d66a6158812cd467647122634e94767252ad194a6f26c0713061216c76098054839290610c85908490612f68565b90915550506040518181526103699033907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a350565b610cce611833565b610cd66118b4565b565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610d45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d699190612f7b565b905080821115610dd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f42423a546f6f206d7563680000000000000000000000000000000000000000006044820152606401610793565b8273ffffffffffffffffffffffffffffffffffffffff1663a9059cbb610e1060005473ffffffffffffffffffffffffffffffffffffffff1690565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602481018490526044016020604051808303816000875af1158015610e82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea69190612f94565b50505050565b6000805b600754811015610efd5760078181548110610ecd57610ecd612e9d565b6000918252602090912060016002909202010154610eeb9083612f68565b9150610ef681612fb6565b9050610eb0565b5090565b600754600090610f1390600190612efb565b905090565b610f206113f1565b610cd66000611931565b60606006805461069290612e50565b610f416119a6565b610f49611a2b565b6108668282611ad3565b33600081815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610ff1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f42423a4465637265617365732062656c6f7720300000000000000000000000006044820152606401610793565b610ffe8286868403611382565b506001949350505050565b6110116119a6565b8060000361107b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4c3a43616e6e6f74207374616b652030000000000000000000000000000000006044820152606401610793565b336000908152600460205260409020548111156110f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4c3a546f6f206d756368207374616b696e6700000000000000000000000000006044820152606401610793565b6110fd81611ef6565b50565b60003361072381858561148e565b611116611833565b610cd6612250565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600b60205260408120548161114f82856116af565b905061115f8160400151426117d7565b95945050505050565b6111706113f1565b60005b8181101561125957600083838381811061118f5761118f612e9d565b6111a59260206040909202019081019150612d43565b73ffffffffffffffffffffffffffffffffffffffff16141580156111e557508282828181106111d6576111d6612e9d565b90506040020160200135600014155b15611249576112498383838181106111ff576111ff612e9d565b6112159260206040909202019081019150612d43565b84848481811061122757611227612e9d565b90506040020160200135670de0b6b3a76400006112449190612f0e565b6122b0565b61125281612fb6565b9050611173565b505050565b611266611833565b60015460405173ffffffffffffffffffffffffffffffffffffffff8084169216907f80f15e9dbc60884fdb59fb8ed4fc48a9a689e028f055e893ed45ca5be67c5c8590600090a3600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6112fc6113f1565b73ffffffffffffffffffffffffffffffffffffffff8116611379576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f4f3a3020616464726573730000000000000000000000000000000000000000006044820152606401610793565b6110fd81611931565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526003602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b3361141160005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614610cd6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4f3a43616c6c6572206e6f74206f776e657200000000000000000000000000006044820152606401610793565b6114966119a6565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260046020526040812080548392906114cb908490612efb565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526004602052604081208054839290611505908490612f68565b925050819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516113e491815260200190565b600080600d546000036115da576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4c3a496e666c6174696f6e206e6f7420737461727465642100000000000000006044820152606401610793565b600d54600090610e10906115ee9086612efb565b6115f89190612f54565b600a5473ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604090205490915081156116a25760006116416b033b2c8af183120df3000000846122d9565b90506b033b2e3c9fd0803ce800000061165a8284612f0e565b6116649190612f54565b61166e9083612efb565b600c549095506116838664e8d4a51000612f0e565b61168d9190612f54565b600e5461169a9190612f68565b9350506116a8565b600e5492505b5050915091565b6116d360405180606001604052806000815260200160008152602001600081525090565b600783815481106116e6576116e6612e9d565b9060005260206000209060020201600101805490508210611763576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f533a5374616b6520696e64657820696e636f72726563742100000000000000006044820152606401610793565b6007838154811061177657611776612e9d565b9060005260206000209060020201600101828154811061179857611798612e9d565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905092915050565b6000816117e8846301dfe200612f68565b11156107295760006224ea006117fe8585612efb565b6118089190612f54565b9050600d81101561182c5761181e81600d612efb565b611829906064612f0e565b91505b5092915050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610cd6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4d3a43616c6c6572206e6f74206d616e616765720000000000000000000000006044820152606401610793565b6118bc6119a6565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906020015b60405180910390a1565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60005474010000000000000000000000000000000000000000900460ff1615610cd6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f503a5061757365640000000000000000000000000000000000000000000000006044820152606401610793565b6000611a39610e1042612fee565b611a439042612efb565b9050600d548111156110fd57600080611a5b8361156b565b915091508160001461125957600d839055600a5473ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604081208054849290611aa3908490612efb565b90915550503060009081526004602052604081208054849290611ac7908490612f68565b9091555050600e555050565b600080611ae08385612352565b90506000611af28260400151426117d7565b611afe90612710612efb565b9050600080836020015164e8d4a51000600e548660000151611b209190612f0e565b611b2a9190612f54565b611b349190612efb565b90508684600001511115611b5357611b4c8188612f68565b9150611b63565b8351611b60908290612f68565b91505b33600090815260026020526040812054819060ff1615611b8857506000905082611bba565b612710611b96856019612f0e565b611ba09190612f54565b915081611bad8186612efb565b611bb79190612efb565b90505b6000612710611bc98784612f0e565b611bd39190612f54565b90508015611d7f573060009081526004602052604081208054879290611bfa908490612efb565b90915550503360009081526004602052604081208054839290611c1e908490612f68565b9091555050604051818152339030907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3600197508215611d7f5760085473ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604081208054859290611c9b908490612f68565b909155505060085460405184815273ffffffffffffffffffffffffffffffffffffffff9091169030907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a360095473ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604081208054859290611d28908490612f68565b909155505060095460405184815273ffffffffffffffffffffffffffffffffffffffff9091169030907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35b612710861015611e1c576000611d958284612efb565b90508015611e1a57610369600090815260046020527fc643d66a6158812cd467647122634e94767252ad194a6f26c0713061216c76098054839290611ddb908490612f68565b90915550506040518181526103699030907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35b505b89600c6000828254611e2e9190612efb565b90915550506020878101516040808a015181518e81529384019290925282015242606082015233907fdcfd2b4017d03f7e541021db793b2f9b31e4acdee005f789e52853c390e3e9629060800160405180910390a287611eea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f556e7374616b65206661696c65640000000000000000000000000000000000006044820152606401610793565b50505050505050505050565b611efe611a2b565b3360009081526004602052604081208054839290611f1d908490612efb565b909155505033600090815260026020526040812054819060ff1615611f43575081611f75565b612710611f51846019612f0e565b611f5b9190612f54565b915081611f688185612efb565b611f729190612efb565b90505b3060009081526004602052604081208054839290611f94908490612f68565b9091555050604051818152309033907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a381156120f15760085473ffffffffffffffffffffffffffffffffffffffff166000908152600460205260408120805484929061200d908490612f68565b909155505060085460405183815273ffffffffffffffffffffffffffffffffffffffff9091169033907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a360095473ffffffffffffffffffffffffffffffffffffffff166000908152600460205260408120805484929061209a908490612f68565b909155505060095460405183815273ffffffffffffffffffffffffffffffffffffffff9091169033907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35b336000908152600b60205260408120549081900361211557612112336128f1565b90505b600064e8d4a5100083600e5461212b9190612f0e565b6121359190612f54565b90506007828154811061214a5761214a612e9d565b6000918252602080832060408051606081018252888152808401878152429282019283526001600296870290940184018054808601825590885294872091516003909502909101938455519183019190915551910155600c80548592906121b2908490612f68565b925050819055503373ffffffffffffffffffffffffffffffffffffffff167f9cfd25589d1eb8ad71e342a86a8524e83522e3936c0803048c08f6d9ad974f4060016007858154811061220657612206612e9d565b9060005260206000209060020201600101805490506122259190612efb565b6040805191825260208201879052810184905242606082015260800160405180910390a25050505050565b61225861298c565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa90602001611927565b6108666122d260005473ffffffffffffffffffffffffffffffffffffffff1690565b838361148e565b60006122e6600283612fee565b6000036122ff576b033b2e3c9fd0803ce8000000612301565b825b905061230e600283612f54565b91505b8115610729576123218384612a10565b925061232e600283612fee565b156123405761233d8184612a10565b90505b61234b600283612f54565b9150612311565b61237660405180606001604052806000815260200160008152602001600081525090565b336000908152600b602052604090205461239081856116af565b91508060011415806123a157508315155b612407576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f533a43616e6e6f742072656d6f766520317374207374616b65000000000000006044820152606401610793565b8151831115612472576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f533a546f6f206d75636820756e7374616b696e670000000000000000000000006044820152606401610793565b81518390036128665760016007828154811061249057612490612e9d565b9060005260206000209060020201600101805490506124af9190612efb565b84101561258a57600781815481106124c9576124c9612e9d565b90600052602060002090600202016001016001600783815481106124ef576124ef612e9d565b90600052602060002090600202016001018054905061250e9190612efb565b8154811061251e5761251e612e9d565b90600052602060002090600302016007828154811061253f5761253f612e9d565b9060005260206000209060020201600101858154811061256157612561612e9d565b600091825260209091208254600390920201908155600180830154908201556002918201549101555b6007818154811061259d5761259d612e9d565b90600052602060002090600202016001018054806125bd576125bd613002565b60008281526020812060037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9093019283020181815560018101829055600201559055600780548290811061261457612614612e9d565b6000918252602082206001600290920201015490036128615760075461263c90600190612efb565b8110156127d4576007805461265390600190612efb565b8154811061266357612663612e9d565b90600052602060002090600202016007828154811061268457612684612e9d565b60009182526020909120825460029092020180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091178155600180830180546126ec9284019190612b51565b50905050600780548061270157612701613002565b60008281526020812060027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9093019283020180547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155906127686001830182612bb7565b50509055336000908152600b60208190526040822082905560078054849391908490811061279857612798612e9d565b6000918252602080832060029092029091015473ffffffffffffffffffffffffffffffffffffffff16835282019290925260400190205561182c565b60078054806127e5576127e5613002565b60008281526020812060027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9093019283020180547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559061284c6001830182612bb7565b50509055336000908152600b60205260408120555b61182c565b60006007828154811061287b5761287b612e9d565b9060005260206000209060020201600101858154811061289d5761289d612e9d565b600091825260208220855160039092020192506128bb908690612efb565b808355600e5490915064e8d4a51000906128d6908390612f0e565b6128e09190612f54565b826001018190555050505092915050565b6007805460019081018083556000928352829161290d91612efb565b9050826007828154811061292357612923612e9d565b6000918252602080832060029290920290910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff948516179055949091168152600b90935260409092208290555090565b60005474010000000000000000000000000000000000000000900460ff16610cd6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f503a4e6f742070617573656400000000000000000000000000000000000000006044820152606401610793565b60006b033b2e3c9fd0803ce8000000612a3e612a2c8585612a4f565b6b019d971e4fe8401e74000000612ad9565b612a489190612f54565b9392505050565b6000811580612a7357508282612a658183612f0e565b9250612a719083612f54565b145b610729576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f770000000000000000000000006044820152606401610793565b600082612ae68382612f68565b9150811015610729576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f770000000000000000000000006044820152606401610793565b828054828255906000526020600020906003028101928215612bab5760005260206000209160030282015b82811115612bab5782548255600180840154908301556002808401549083015560039283019290910190612b7c565b50610efd929150612bd4565b50805460008255600302906000526020600020908101906110fd91905b5b80821115610efd576000808255600182018190556002820155600301612bd5565b600060208083528351808285015260005b81811015612c2357858101830151858201604001528201612c07565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b73ffffffffffffffffffffffffffffffffffffffff811681146110fd57600080fd5b60008060408385031215612c9757600080fd5b8235612ca281612c62565b946020939093013593505050565b60008060408385031215612cc357600080fd5b8235612cce81612c62565b91506020830135612cde81612c62565b809150509250929050565b600060208284031215612cfb57600080fd5b5035919050565b600080600060608486031215612d1757600080fd5b8335612d2281612c62565b92506020840135612d3281612c62565b929592945050506040919091013590565b600060208284031215612d5557600080fd5b8135612a4881612c62565b602080825282518282018190526000919060409081850190868401855b82811015612dac5781518051855286810151878601528501518585015260609093019290850190600101612d7d565b5091979650505050505050565b60008060408385031215612dcc57600080fd5b50508035926020909101359150565b60008060208385031215612dee57600080fd5b823567ffffffffffffffff80821115612e0657600080fd5b818501915085601f830112612e1a57600080fd5b813581811115612e2957600080fd5b8660208260061b8501011115612e3e57600080fd5b60209290920196919550909350505050565b600181811c90821680612e6457607f821691505b602082108103610b22577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561072957610729612ecc565b808202811582820484141761072957610729612ecc565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082612f6357612f63612f25565b500490565b8082018082111561072957610729612ecc565b600060208284031215612f8d57600080fd5b5051919050565b600060208284031215612fa657600080fd5b81518015158114612a4857600080fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612fe757612fe7612ecc565b5060010190565b600082612ffd57612ffd612f25565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220b03a6a9d0ff0bc428b8e7bded99318545d0c13000ef349404ace56c7187a0e6764736f6c63430008130033