ETH Price: $2,958.05 (-0.92%)

Contract

0x6562DF704f716d705aa388E5e1f9d125C76C0fce
Transaction Hash
Block
From
To
Withdraw Token243940952026-01-11 9:30:2913 days ago1768123829IN
0x6562DF70...5C76C0fce
0 ETH0.000000040.00100028
Withdraw Token239783062026-01-01 18:30:5122 days ago1767292251IN
0x6562DF70...5C76C0fce
0 ETH0.000000040.00100027
Withdraw Token239257322025-12-31 13:18:2324 days ago1767187103IN
0x6562DF70...5C76C0fce
0 ETH0.000000040.00100026
Set Expedition C...235569362025-12-23 0:25:1132 days ago1766449511IN
0x6562DF70...5C76C0fce
0 ETH0.000000020.00100025
Set Base Timing ...235569282025-12-23 0:24:5532 days ago1766449495IN
0x6562DF70...5C76C0fce
0 ETH0.000000030.00100025
Set Base Reward ...235569232025-12-23 0:24:4532 days ago1766449485IN
0x6562DF70...5C76C0fce
0 ETH0.000000030.00100025
Owner Edit User ...234132452025-12-19 16:35:2936 days ago1766162129IN
0x6562DF70...5C76C0fce
0 ETH0.000000050.00100027
Set Scrappers234106572025-12-19 15:09:1336 days ago1766156953IN
0x6562DF70...5C76C0fce
0 ETH0.000000050.00100027
Set Shop234100042025-12-19 14:47:2736 days ago1766155647IN
0x6562DF70...5C76C0fce
0 ETH0.000000080.00100027
Edit User Data234072222025-12-19 13:14:4336 days ago1766150083IN
0x6562DF70...5C76C0fce
0 ETH0.000000080.00100027
Set Base Exp Per...234071652025-12-19 13:12:4936 days ago1766149969IN
0x6562DF70...5C76C0fce
0 ETH0.000000030.00100027
Set Expedition C...233440102025-12-18 2:07:3937 days ago1766023659IN
0x6562DF70...5C76C0fce
0 ETH0.000000020.00100026
Set Expedition T...233440022025-12-18 2:07:2337 days ago1766023643IN
0x6562DF70...5C76C0fce
0 ETH0.000000040.00100026

View more zero value Internal Transactions in Advanced View mode

Advanced mode:

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Watters

Compiler Version
v0.8.28+commit.7893614a

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
File 1 of 10 : Watters.sol
// Compatible with OpenZeppelin Contracts ^5.0.0
pragma solidity ^0.8.28;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import {ISignatureTransfer} from "./interfaces/ISignatureTransfer.sol";
import {ITop} from "./interfaces/ITop.sol";
import {IShop} from "./interfaces/IShop.sol";
import {IScrappers} from "./interfaces/IScrappers.sol";

//todo but for non verified users
interface IAddressBook {
    /// @notice Emitted when an account is verified
    event AccountVerified(address indexed account, uint256 verifiedUntil);

    function addressVerifiedUntil(address account) external view returns (uint256 timestamp);
}

interface IResetAccountLvls {
    function reset(address userAddress) external view returns (bool, uint256, uint256, uint256);
    function updateUserAccount(address userAddress) external;
}

/// @notice Minimal interface to read user state from the legacy Watters contract
/// @dev The old contract exposes `userInfo(address)` as a public mapping getter.
interface IOldWatters {
    function userInfo(address user) external view returns (
        uint256 experience,
        uint256 Lvl,
        uint256 lastClaimTime,
        uint256 accumulatedTokens,
        uint256 timingLevel,
        uint256 rewardLevel,
        uint256 water,
        uint256 resets,
        IERC20 tokenReward
    );

    function payableUsers(address user) external view returns (bool);
}

contract Watters is Ownable, ReentrancyGuard {

    /**
     * @notice Estructura que almacena la información de un usuario
     * @param lastClaimTime Último timestamp en que el usuario reclamó tokens
     * @param accumulatedTokens Tokens acumulados pendientes (no usado actualmente)
     * @param timingLevel Nivel de mejora de tiempo del usuario
     * @param rewardLevel Nivel de mejora de recompensa del usuario
     */
    struct UserInfo {
        uint256 experience;
        uint256 Lvl;
        uint256 lastClaimTime;
        uint256 accumulatedTokens;
        uint256 timingLevel;
        uint256 rewardLevel;
        uint256 water;
        uint256 resets;
        IERC20 tokenReward;
    }

    struct UserHistory {
        uint256 MaxLvl; // max level reached - updated when user reaches a new level
        uint256 totalClaims; // total claims made by user
        uint256 TotalClaimed; // total tokens claimed
        uint256 TotalWLDspent; // total WLD spent
        uint256 MaxtimingLevel; // max timing level reached
        uint256 MaxrewardLevel; // max reward level reached
    }

    // Eventos
    event TokensClaimed(address indexed user, uint256 amount);
    event BaseRewardUpdated(uint256 newReward);
    event BaseplusRewardUpdated(uint256 newReward);
    event MaxAccumulationTimeUpdated(uint256 newTime);
    event BaseTimingPerLevelUpdated(uint256 newTime);
    event TimingLevelUpgraded(address indexed user, uint256 newLevel, uint256 cost);
    event RewardLevelUpgraded(address indexed user, uint256 newLevel, uint256 cost);
    event WLDPriceUpdated(string upgradeType, uint256 newPrice);
    event TokenPriceUpdated(string upgradeType, uint256 newPrice);
    event LevelUp(address indexed user, uint256 newLevel, uint256 expGained);
    event BaseExpPerLevelUpdated(uint256 newBaseExp);
    event UserDataEdited(address indexed user, uint256 newExperience, uint256 newLevel, uint256 newTimingLevel, uint256 newRewardLevel, uint256 newWater);
    event ContractCallerUpdated(address indexed caller, bool authorized);
    event OldWattersUpdated(address indexed oldWatters);

    IAddressBook public addressBook = IAddressBook(0x57b930D551e677CC36e2fA036Ae2fe8FdaE0330D);
    IResetAccountLvls public resetAccountLvlsContract;
    IScrappers public scrappers;
    IERC20 public waterToken;
    IERC20 public ironToken;

    IERC20 public  expeditionToken;
    IERC20 public WLD;
    ITop public top;
    IShop public shop;
    ISignatureTransfer public permit2 = ISignatureTransfer(0x000000000022D473030F116dDEE9F6B43aC78BA3);

    uint256 public baseRewardPerMinute = 0.05e18;
    uint256 public baseplusRewardPerMinute = 0.01e18;
    uint256 public baseTimingPerLevel = 20 seconds;
    
    uint256 public updateONEwithWLD = 0.1 ether;
    uint256 public updateTWOwithWLD = 0.1 ether;
    uint256 public updateONEwithToken = 10 ether;
    uint256 public updateTWOwithToken = 10 ether;
    uint256 public expeditionCost = 1 ether;
    uint256 public gameCost = 0.01 ether;
    uint256 public totalVerifiedUsers;
    uint256 public totalPayableUsers;
    uint256 public ChangeRewardTokenCostInWLD = 2 ether;
    uint256 public ChangeRewardTokenCostInScrap = 10 ether;

    // WLD upgrade pricing (5 breakpoints, precio se duplica por tramo, cap en el último tramo)
    // Ej default (como ejemplo del pedido): 0..15 base, 16..75 x2, 76..125 x4, 126..200 x8, 201..300 x16 (y luego se queda en x16)
    uint256[5] public timingWldBreakpoints = [15, 75, 125, 200, 300];
    uint256[5] public rewardWldBreakpoints = [15, 75, 125, 200, 300];

    bool public activateWater = false;
    
    uint256 public MAX_ACCUMULATION_TIME = 5 minutes;
    uint256 public baseExpPerLevel = 10000;
    
    mapping(address => UserInfo) public userInfo;
    mapping(address => UserHistory) public userHistory;
    mapping(address => bool) public contractCallers;
    mapping(address => bool) public  payableUsers;

    // ===== Legacy migration (old Watters -> this Watters) =====
    IOldWatters public oldWatters;
    mapping(address => bool) public migratedFromOld;
    
    constructor(
        address waterToken_,
        address ironToken_,
        address _wld,
        address initialOwner,
        address _top,
        address _scrappers,
        address oldWatters_
    )
        Ownable(initialOwner)
    {
        contractCallers[address(this)] = true;
        contractCallers[msg.sender] = true;

        waterToken = IERC20(waterToken_);
        ironToken = IERC20(ironToken_);
        WLD = IERC20(_wld);
        top = ITop(_top);
        scrappers = IScrappers(_scrappers);

        _setOldWatters(oldWatters_);
    }

    function setOldWatters(address oldWatters_) external onlyOwner {
        _setOldWatters(oldWatters_);
    }

    function _setOldWatters(address oldWatters_) internal {
        if (oldWatters_ != address(0)) {
            require(oldWatters_.code.length > 0, "SCRAPPER: old watters is not a contract");
        }
        oldWatters = IOldWatters(oldWatters_);
        emit OldWattersUpdated(oldWatters_);
    }

    /// @dev Attempts to migrate the user's legacy `UserInfo` from the old Watters.
    /// Rules:
    /// - If oldWatters is not set => no migration
    /// - If user already migrated => no migration
    /// - If old user's lastClaimTime == 0 => treat as "fresh user" => no migration
    /// - Else copy legacy UserInfo fields into the new storage and mark migrated
    function _tryMigrateFromOld(address user) internal returns (bool) {
        if (address(oldWatters) == address(0)) return false;
        if (migratedFromOld[user]) return false;

        (
            uint256 experience,
            uint256 lvl,
            uint256 lastClaimTime,
            uint256 accumulatedTokens,
            uint256 timingLevel,
            uint256 rewardLevel,
            uint256 water,
            uint256 resets,
            IERC20 tokenReward
        ) = oldWatters.userInfo(user);

        if (lastClaimTime == 0) return false;

        UserInfo storage u = userInfo[user];
        u.experience = experience;
        u.Lvl = lvl;
        u.lastClaimTime = lastClaimTime;
        u.accumulatedTokens = accumulatedTokens;
        u.timingLevel = timingLevel;
        u.rewardLevel = rewardLevel;
        u.water = water;
        u.resets = resets;
        u.tokenReward = tokenReward;

        // Also migrate payable flag to avoid blocking non-verified legacy users.
        payableUsers[user] = oldWatters.payableUsers(user);

        migratedFromOld[user] = true;
        return true;
    }

    function setTokenReward(uint tokenOption) external  {
        // Semi-automatic migration hook (runs once, on first user "init" call)
        // If the legacy user exists (old lastClaimTime != 0), migrate and ignore the rest.
        if (_tryMigrateFromOld(msg.sender)) {
            return;
        }

        require(address(userInfo[msg.sender].tokenReward) == address(0), "SCRAPPER: token already set");
        if(tokenOption == 0) {
            userInfo[msg.sender].tokenReward = waterToken;
        } else if(tokenOption == 1) {
            userInfo[msg.sender].tokenReward = ironToken;
        }
    }

    function buyWater(
        ISignatureTransfer.PermitTransferFrom memory permit,
        ISignatureTransfer.SignatureTransferDetails calldata transferDetails,
        bytes calldata signature
    ) external {
        require(permit.permitted.token == address(expeditionToken), "SCRAPPER: wrong token");
        require(transferDetails.requestedAmount >= expeditionCost, "SCRAPPER: wrong amount");
        require(transferDetails.to == address(this), "SCRAPPER: wrong recipient");
        permit2.permitTransferFrom(permit, transferDetails, msg.sender, signature);
        userInfo[msg.sender].water += transferDetails.requestedAmount;
    }

    function buyGame( 
        uint256 tokenOption,
        ISignatureTransfer.PermitTransferFrom memory permit,
        ISignatureTransfer.SignatureTransferDetails calldata transferDetails,
        bytes calldata signature
    ) external {
        // Semi-automatic migration hook: if legacy user exists, migrate and ignore the rest.
        if (_tryMigrateFromOld(msg.sender)) {
            permit2.permitTransferFrom(permit, transferDetails, msg.sender, signature);
            WLD.transfer(msg.sender, transferDetails.requestedAmount);
            return;
        }

        require(permit.permitted.token == address(WLD), "SCRAPPER: wrong token");
        require(transferDetails.requestedAmount >= gameCost, "SCRAPPER: wrong amount");
        require(transferDetails.to == address(this), "SCRAPPER: wrong recipient");
        require(!payableUsers[msg.sender], "SCRAPPER: user not payable");
        permit2.permitTransferFrom(permit, transferDetails, msg.sender, signature);
        payableUsers[msg.sender] = true;
        totalPayableUsers++;
        if(tokenOption == 0) {
            userInfo[msg.sender].tokenReward = waterToken;
        } else if(tokenOption == 1) {
            userInfo[msg.sender].tokenReward = ironToken;
        }
    }
    
    function claimTokens() external nonReentrant {
        if(addressBook.addressVerifiedUntil(msg.sender) == 0) {
            require(payableUsers[msg.sender], "SCRAPPER: user not payable");
        }
        if(address(resetAccountLvlsContract) != address(0)) {
            (bool reset, uint256 newLvl, uint256 newTimingLevel, uint256 newRewardLevel )= resetAccountLvlsContract.reset(msg.sender);
            if(reset) {
                resetAccountLvls(msg.sender, newLvl, newTimingLevel, newRewardLevel);
            }
        }

        UserInfo storage user = userInfo[msg.sender];
        if(user.lastClaimTime == 0) {
            totalVerifiedUsers++;
            userInfo[msg.sender].water += expeditionCost * 50;
        }
        UserHistory storage history = userHistory[msg.sender];
        
        if (activateWater && address(userInfo[msg.sender].tokenReward) != address(waterToken)) {
            require(userInfo[msg.sender].water >= expeditionCost, "SCRAPPER: not enough water");
            userInfo[msg.sender].water -= expeditionCost;
        }
        
        uint256 tokensToClaim = calculateAccumulatedTokens(msg.sender);
        require(tokensToClaim > 0, "SCRAPPER: no tokens to claim");
        
        user.lastClaimTime = block.timestamp;
        user.accumulatedTokens = 0;
        
        // Update history tracking
        history.totalClaims++;
        history.TotalClaimed += tokensToClaim;

        require(user.tokenReward.transfer(msg.sender, tokensToClaim), "SCRAPPER: transfer failed");
        
        // Agregar experiencia igual a los tokens claimeados (mantiene 18 decimales)
        uint256 expToAdd = tokensToClaim / 1e15;
        
        // Aplicar multiplicadores de EXP de la Shop si existe
        if (address(shop) != address(0)) {
            uint256 expMultiplier = shop.getExpMultiplier(msg.sender);
            expToAdd = expToAdd * expMultiplier / 100;
        }
        
        scrappers.addExperience(msg.sender, expToAdd);
        addExperienceInternal(msg.sender, expToAdd);
        
        emit TokensClaimed(msg.sender, tokensToClaim);
    }

    
    // change token reward pay with wld or scrap IScrappers.token()
    function changeTokenReward(
        uint256 tokenOption,
        ISignatureTransfer.PermitTransferFrom memory permit,
        ISignatureTransfer.SignatureTransferDetails calldata transferDetails,
        bytes calldata signature
    ) external {
        address tokenReward = address(scrappers.token());
        if(tokenReward == permit.permitted.token ) {
            require(permit.permitted.token == address(scrappers.token()), "SCRAPPER: wrong token");
            require(transferDetails.requestedAmount >= ChangeRewardTokenCostInScrap, "SCRAPPER: wrong amount");
            require(transferDetails.to == address(this), "SCRAPPER: wrong recipient");
            permit2.permitTransferFrom(permit, transferDetails, msg.sender, signature);
        } else {
            require(permit.permitted.token == address(WLD), "SCRAPPER: wrong token");
            require(transferDetails.requestedAmount >= ChangeRewardTokenCostInWLD, "SCRAPPER: wrong amount");
            require(transferDetails.to == address(this), "SCRAPPER: wrong recipient");
            permit2.permitTransferFrom(permit, transferDetails, msg.sender, signature);
        }
        if(tokenOption == 0) {
            userInfo[msg.sender].tokenReward = waterToken;
        } else if(tokenOption == 1) {
            userInfo[msg.sender].tokenReward = ironToken;
        }
    }

    function setGameCost(uint256 newPrice) external onlyOwner {
        require(newPrice > 0, "SCRAPPER: price must be greater than 0");
        gameCost = newPrice;
    }
    
    function calculateAccumulatedTokens(address userAddress) public view returns (uint256) {
        UserInfo storage user = userInfo[userAddress];
        
        if (user.lastClaimTime == 0) {
            uint256 maxTime_ = getMaxAccumulationTimeForUser(userAddress);
            uint256 rewardPerSecond_ = getRewardPerMinuteForUser(userAddress) / 60;
            return rewardPerSecond_ * maxTime_;
        }
        
        uint256 timeElapsed = block.timestamp - user.lastClaimTime;
        uint256 maxTime = getMaxAccumulationTimeForUser(userAddress);
        
        if (timeElapsed > maxTime) {
            timeElapsed = maxTime;
        }
        
        uint256 rewardPerSecond = getRewardPerMinuteForUser(userAddress) / 60;
        uint256 accumulatedTokens = rewardPerSecond * timeElapsed;
        
        return accumulatedTokens;
    }
    
    function getMaxAccumulationTimeForUser(address userAddress) public view returns (uint256) {
        UserInfo storage user = userInfo[userAddress];
        uint256 baseTime = MAX_ACCUMULATION_TIME + (user.timingLevel * baseTimingPerLevel);
        
        // Aplicar boosters de la Shop si existe
        if (address(shop) != address(0)) {
            // Aplicar multiplicador de tiempo permanente
            uint256 timeMultiplier = shop.getTimeMultiplier(userAddress);
            baseTime = baseTime * timeMultiplier / 100;
            
            // Aplicar extensión temporal de Speed Rush
            uint256 timeExtension = shop.getTimeExtension(userAddress);
            baseTime += timeExtension;
        }
        
        return baseTime;
    }
    
    function getRewardPerMinuteForUser(address userAddress) public view returns (uint256) {
        UserInfo storage user = userInfo[userAddress];
        uint256 baseReward = baseRewardPerMinute + (user.rewardLevel * baseplusRewardPerMinute);
        
        // Aplicar boosters de la Shop si existe
        if (address(shop) != address(0)) {
            uint256 rewardMultiplier = shop.getRewardMultiplier(userAddress);
            baseReward = baseReward * rewardMultiplier / 100;
        }
        
        return baseReward;
    }
    
    function updateLvlTimingWithWLD(
        uint256 amount,
        ISignatureTransfer.PermitTransferFrom memory permit,
        ISignatureTransfer.SignatureTransferDetails calldata transferDetails,
        bytes calldata signature
    ) external {
        require(amount > 0, "SCRAPPER: amount must be greater than 0");
        require(permit.permitted.token == address(WLD), "SCRAPPER: wrong token");
        
        uint256 totalCost = getTimingUpgradeCostWithWLD(msg.sender, amount);
        require(transferDetails.requestedAmount == totalCost, "SCRAPPER: wrong amount");
        require(transferDetails.to == address(this), "SCRAPPER: wrong recipient");
        
        permit2.permitTransferFrom(permit, transferDetails, msg.sender, signature);
        
        UserInfo storage user = userInfo[msg.sender];
        UserHistory storage history = userHistory[msg.sender];
        
        user.timingLevel += amount;
        
        // Update history tracking
        history.TotalWLDspent += totalCost;
        if (user.timingLevel > history.MaxtimingLevel) {
            history.MaxtimingLevel = user.timingLevel;
        }
        
        emit TimingLevelUpgraded(msg.sender, user.timingLevel, totalCost);
    }
    
    function updateTokenRewardLvlWithWLD(
        uint256 amount,
        ISignatureTransfer.PermitTransferFrom memory permit,
        ISignatureTransfer.SignatureTransferDetails calldata transferDetails,
        bytes calldata signature
    ) external {
        require(amount > 0, "SCRAPPER: amount must be greater than 0");
        require(permit.permitted.token == address(WLD), "SCRAPPER: wrong token");
        
        uint256 totalCost = getRewardUpgradeCostWithWLD(msg.sender, amount);
        require(transferDetails.requestedAmount == totalCost, "SCRAPPER: wrong amount");
        require(transferDetails.to == address(this), "SCRAPPER: wrong recipient");
        
        permit2.permitTransferFrom(permit, transferDetails, msg.sender, signature);
        
        UserInfo storage user = userInfo[msg.sender];
        UserHistory storage history = userHistory[msg.sender];
        
        user.rewardLevel += amount;
        
        // Update history tracking
        history.TotalWLDspent += totalCost;
        if (user.rewardLevel > history.MaxrewardLevel) {
            history.MaxrewardLevel = user.rewardLevel;
        }
        
        emit RewardLevelUpgraded(msg.sender, user.rewardLevel, totalCost);
    }
    
    function getUserInfo(address userAddress) external view returns (
        uint256 experience,
        uint256 level,
        uint256 lastClaimTime,
        uint256 accumulatedTokens,
        uint256 currentAccumulated,
        uint256 timeUntilMax,
        uint256 timingLevel,
        uint256 rewardLevel,
        uint256 maxAccumulationTime,
        uint256 rewardPerMinute,
        uint256 water
    ) {
        UserInfo storage user = userInfo[userAddress];
        experience = user.experience;
        level = user.Lvl;
        lastClaimTime = user.lastClaimTime;
        accumulatedTokens = user.accumulatedTokens;
        currentAccumulated = calculateAccumulatedTokens(userAddress);
        timingLevel = user.timingLevel;
        rewardLevel = user.rewardLevel;
        maxAccumulationTime = getMaxAccumulationTimeForUser(userAddress);
        rewardPerMinute = getRewardPerMinuteForUser(userAddress);
        water = user.water;
        if (user.lastClaimTime > 0) {
            uint256 timeElapsed = block.timestamp - user.lastClaimTime;
            uint256 maxTime = getMaxAccumulationTimeForUser(userAddress);
            if (timeElapsed < maxTime) {
                timeUntilMax = maxTime - timeElapsed;
            }
        } else {
            timeUntilMax = getMaxAccumulationTimeForUser(userAddress);
        }
    }

    function getTimingUpgradeCostWithWLD(address userAddress, uint256 amount) public view returns (uint256) {
        UserInfo storage user = userInfo[userAddress];
        return _wldUpgradeCost(user.timingLevel, amount, updateONEwithWLD, timingWldBreakpoints);
    }

    function getRewardUpgradeCostWithWLD(address userAddress, uint256 amount) public view returns (uint256) {
        UserInfo storage user = userInfo[userAddress];
        return _wldUpgradeCost(user.rewardLevel, amount, updateTWOwithWLD, rewardWldBreakpoints);
    }

    function setactivateWater(bool _activateWater) external onlyOwner {
        activateWater = _activateWater;
    }
    
    function setBaseRewardPerMinute(uint256 newReward) external onlyOwner {
        require(newReward > 0, "SCRAPPER: reward must be greater than 0");
        baseRewardPerMinute = newReward;
        emit BaseRewardUpdated(newReward);
    }
    
    function setMaxAccumulationTime(uint256 newTime) external onlyOwner {
        require(newTime > 0, "SCRAPPER: time must be greater than 0");
        MAX_ACCUMULATION_TIME = newTime;
        emit MaxAccumulationTimeUpdated(newTime);
    }
    
    function setBaseTimingPerLevel(uint256 newTime) external onlyOwner {
        require(newTime > 0, "SCRAPPER: time must be greater than 0");
        baseTimingPerLevel = newTime;
        emit BaseTimingPerLevelUpdated(newTime);
    }
    
    function setUpdateONEwithWLD(uint256 newPrice) external onlyOwner {
        require(newPrice > 0, "SCRAPPER: price must be greater than 0");
        updateONEwithWLD = newPrice;
        emit WLDPriceUpdated("timing", newPrice);
    }
    
    function setUpdateTWOwithWLD(uint256 newPrice) external onlyOwner {
        require(newPrice > 0, "SCRAPPER: price must be greater than 0");
        updateTWOwithWLD = newPrice;
        emit WLDPriceUpdated("reward", newPrice);
    }
    
    function setBaseplusRewardPerMinute(uint256 newReward) external onlyOwner {
        require(newReward > 0, "SCRAPPER: reward must be greater than 0");
        baseplusRewardPerMinute = newReward;
        emit BaseplusRewardUpdated(newReward);
    }
    
    function setUpdateONEwithToken(uint256 newPrice) external onlyOwner {
        require(newPrice > 0, "SCRAPPER: price must be greater than 0");
        updateONEwithToken = newPrice;
        emit TokenPriceUpdated("timing", newPrice);
    }
    
    function setUpdateTWOwithToken(uint256 newPrice) external onlyOwner {
        require(newPrice > 0, "SCRAPPER: price must be greater than 0");
        updateTWOwithToken = newPrice;
        emit TokenPriceUpdated("reward", newPrice);
    }

    function setTimingWldBreakpoints(uint256 b0, uint256 b1, uint256 b2, uint256 b3, uint256 b4) external onlyOwner {
        require(b0 < b1 && b1 < b2 && b2 < b3 && b3 < b4, "SCRAPPER: invalid breakpoints");
        timingWldBreakpoints = [b0, b1, b2, b3, b4];
    }

    function setRewardWldBreakpoints(uint256 b0, uint256 b1, uint256 b2, uint256 b3, uint256 b4) external onlyOwner {
        require(b0 < b1 && b1 < b2 && b2 < b3 && b3 < b4, "SCRAPPER: invalid breakpoints");
        rewardWldBreakpoints = [b0, b1, b2, b3, b4];
    }
    
    function withdrawToken(IERC20 token_, uint256 amount, address to) external onlyOwner {
       token_.transfer(to, amount);
    }
    
    function depositTokens(uint256 amount) external onlyOwner {
        require(amount > 0, "SCRAPPER: amount must be greater than 0");
        require(userInfo[msg.sender].tokenReward.transferFrom(msg.sender, address(this), amount), "SCRAPPER: transfer failed");
    }
    
    function getTimingUpgradeCostWithToken(address userAddress) public view returns (uint256) {
        UserInfo storage user = userInfo[userAddress];
        return updateONEwithToken + (user.timingLevel * 2 ether ) ;
    }
    
    function getRewardUpgradeCostWithToken(address userAddress) public view returns (uint256) {
        UserInfo storage user = userInfo[userAddress];
        return updateTWOwithToken + (user.rewardLevel * 2 ether);
    }
    
    function getTokenUpgradeCosts(address userAddress) external view returns (
        uint256 timingUpgradeCost,
        uint256 rewardUpgradeCost,
        uint256 currentTimingLevel,
        uint256 currentRewardLevel
    ) {
        timingUpgradeCost = getTimingUpgradeCostWithToken(userAddress);
        rewardUpgradeCost = getRewardUpgradeCostWithToken(userAddress);
        UserInfo storage user = userInfo[userAddress];
        currentTimingLevel = user.timingLevel;
        currentRewardLevel = user.rewardLevel;
    }
    
    function updateLvlTimingWithToken(
        ISignatureTransfer.PermitTransferFrom memory permit,
        ISignatureTransfer.SignatureTransferDetails calldata transferDetails,
        bytes calldata signature
    ) external {
        address tokenReward = address(scrappers.token());
        require(permit.permitted.token == tokenReward, "SCRAPPER: wrong token");
        
        uint256 requiredAmount = getTimingUpgradeCostWithToken(msg.sender);
        require(transferDetails.requestedAmount == requiredAmount, "SCRAPPER: wrong amount");
        require(transferDetails.to == address(this), "SCRAPPER: wrong recipient");
        
        permit2.permitTransferFrom(permit, transferDetails, msg.sender, signature);
        
        UserInfo storage user = userInfo[msg.sender];
        UserHistory storage history = userHistory[msg.sender];
        
        user.timingLevel++;
        
        // Update history tracking
        if (user.timingLevel > history.MaxtimingLevel) {
            history.MaxtimingLevel = user.timingLevel;
        }
        
        emit TimingLevelUpgraded(msg.sender, user.timingLevel, requiredAmount);
    }
    
    function updateTokenRewardLvlWithToken(
        ISignatureTransfer.PermitTransferFrom memory permit,
        ISignatureTransfer.SignatureTransferDetails calldata transferDetails,
        bytes calldata signature
    ) external {
        address tokenReward = address(scrappers.token());
        require(permit.permitted.token == tokenReward, "SCRAPPER: wrong token");
        
        uint256 requiredAmount = getRewardUpgradeCostWithToken(msg.sender);
        require(transferDetails.requestedAmount == requiredAmount, "SCRAPPER: wrong amount");
        require(transferDetails.to == address(this), "SCRAPPER: wrong recipient");
        
        permit2.permitTransferFrom(permit, transferDetails, msg.sender, signature);
        
        UserInfo storage user = userInfo[msg.sender];
        UserHistory storage history = userHistory[msg.sender];
        
        user.rewardLevel++;
        
        // Update history tracking
        if (user.rewardLevel > history.MaxrewardLevel) {
            history.MaxrewardLevel = user.rewardLevel;
        }
        
        emit RewardLevelUpgraded(msg.sender, user.rewardLevel, requiredAmount);
    }

    function _wldUpgradeCost(
        uint256 currentLevel,
        uint256 amount,
        uint256 basePrice,
        uint256[5] storage breakpoints
    ) internal view returns (uint256 totalCost) {
        for (uint256 i = 1; i <= amount; i++) {
            uint256 levelAfter = currentLevel + i;
            totalCost += _wldUnitPriceForLevel(levelAfter, basePrice, breakpoints);
        }
    }

    function _wldUnitPriceForLevel(
        uint256 levelAfter,
        uint256 basePrice,
        uint256[5] storage breakpoints
    ) internal view returns (uint256) {
        uint256 mult;
        if (levelAfter <= breakpoints[0]) mult = 1;
        else if (levelAfter <= breakpoints[1]) mult = 2;
        else if (levelAfter <= breakpoints[2]) mult = 4;
        else if (levelAfter <= breakpoints[3]) mult = 8;
        else if (levelAfter <= breakpoints[4]) mult = 16;
        else mult = 16; // cap luego del 5to breakpoint
        return basePrice * mult;
    }

    function addExperience(address userAddress, uint256 expAmount) public  {
        require(contractCallers[msg.sender], "SCRAPPER: not authorized");
        addExperienceInternal(userAddress, expAmount);
    }

    function addExperienceInternal(address userAddress, uint256 expAmount) internal {

        UserInfo storage user = userInfo[userAddress];
        UserHistory storage history = userHistory[userAddress];
        
        user.experience += expAmount;
        bool updateTop = false;
        while (user.experience >= getExpRequiredForNextLevel(user.Lvl)) {
            uint256 expRequired = getExpRequiredForNextLevel(user.Lvl);
            user.experience -= expRequired;
            user.Lvl++;
            
            // Update history tracking for max level
            if (user.Lvl > history.MaxLvl) {
                history.MaxLvl = user.Lvl;
            }
            
            emit LevelUp(userAddress, user.Lvl, expRequired);
            updateTop = true;
        }
        // Si top está deshabilitado (address(0)), no intentar llamar
        if (user.Lvl > 0 && updateTop && address(top) != address(0)) {
            top.updateScore(userAddress, user.Lvl);
        }
    }

    function getExpRequiredForNextLevel(uint256 currentLevel) public view returns (uint256) {
        return baseExpPerLevel + (currentLevel * 1000);
    }

    function setBaseExpPerLevel(uint256 newBaseExp) external onlyOwner {
        require(newBaseExp > 0, "SCRAPPER: base exp must be greater than 0");
        baseExpPerLevel = newBaseExp;
        emit BaseExpPerLevelUpdated(newBaseExp);
    }

    function setWaterToken(address _waterToken) external onlyOwner {
        require(_waterToken != address(0), "SCRAPPER: invalid water token address");
        waterToken = IERC20(_waterToken);
    }
    function setIronToken(address _ironToken) external onlyOwner {
        require(_ironToken != address(0), "SCRAPPER: invalid iron token address");
        ironToken = IERC20(_ironToken);
    }
    function setScrappers(address _scrappers) external onlyOwner {
        scrappers = IScrappers(_scrappers);
    }

    function editUserData(
        address userAddress,
        uint256 newExperience,
        uint256 newLevel,
        uint256 newTimingLevel,
        uint256 newRewardLevel,
        uint256 newWater,
        bool verified,
        address tokenReward_
    ) external {
        require(contractCallers[msg.sender], "SCRAPPER: not authorized");
        
        UserInfo storage user = userInfo[userAddress];
        user.experience = newExperience;
        user.Lvl = newLevel;
        user.timingLevel = newTimingLevel;
        user.rewardLevel = newRewardLevel;
        user.water = newWater;
        user.tokenReward = IERC20(tokenReward_);
        payableUsers[userAddress] = verified;
        emit UserDataEdited(userAddress, newExperience, newLevel, newTimingLevel, newRewardLevel, newWater);
    }

    function setExpeditionCost(uint256 newCost) external onlyOwner {
        require(newCost > 0, "SCRAPPER: cost must be greater than 0");
        expeditionCost = newCost;
        
    }

    function setShop(address _shop) external onlyOwner {
        require(_shop != address(0), "SCRAPPER: invalid shop address");
        shop = IShop(_shop);
        contractCallers[_shop] = true;
    }

    function setExpeditionToken(address _expeditionToken) external onlyOwner {
        require(_expeditionToken != address(0), "SCRAPPER: invalid expedition token address");
        expeditionToken = IERC20(_expeditionToken);
    }

    function setContractCaller(address caller, bool authorized) external onlyOwner {
        require(caller != address(0), "SCRAPPER: invalid caller address");
        contractCallers[caller] = authorized;
        emit ContractCallerUpdated(caller, authorized);
    }

    function setUpdateResetAccountLvlsContract(address _resetAccountLvlsContract) external onlyOwner {
        require(_resetAccountLvlsContract != address(0), "SCRAPPER: invalid reset account lvls contract address");
        resetAccountLvlsContract = IResetAccountLvls(_resetAccountLvlsContract);
        if (_resetAccountLvlsContract != address(0)) contractCallers[_resetAccountLvlsContract] = true;
    }

    // =========================
    //      OWNER FULL CONTROL
    // =========================

    function setAddressBook(address newAddressBook) external onlyOwner {
        addressBook = IAddressBook(newAddressBook);
    }

    function setPermit2(address newPermit2) external onlyOwner {
        permit2 = ISignatureTransfer(newPermit2);
    }

    function setTop(address newTop) external onlyOwner {
        top = ITop(newTop);
    }

    function setWLD(address newWLD) external onlyOwner {
        WLD = IERC20(newWLD);
    }

    function setHouseConfig(
        uint256 _updateONEwithWLD,
        uint256 _updateTWOwithWLD,
        uint256 _updateONEwithToken,
        uint256 _updateTWOwithToken,
        uint256 _expeditionCost,
        uint256 _gameCost,
        uint256 _changeRewardTokenCostInWLD,
        uint256 _changeRewardTokenCostInScrap
    ) external onlyOwner {
        updateONEwithWLD = _updateONEwithWLD;
        updateTWOwithWLD = _updateTWOwithWLD;
        updateONEwithToken = _updateONEwithToken;
        updateTWOwithToken = _updateTWOwithToken;
        expeditionCost = _expeditionCost;
        gameCost = _gameCost;
        ChangeRewardTokenCostInWLD = _changeRewardTokenCostInWLD;
        ChangeRewardTokenCostInScrap = _changeRewardTokenCostInScrap;
    }

    function setRewardsConfig(
        uint256 _baseRewardPerMinute,
        uint256 _baseplusRewardPerMinute,
        uint256 _maxAccumulationTime,
        uint256 _baseTimingPerLevel
    ) external onlyOwner {
        baseRewardPerMinute = _baseRewardPerMinute;
        baseplusRewardPerMinute = _baseplusRewardPerMinute;
        MAX_ACCUMULATION_TIME = _maxAccumulationTime;
        baseTimingPerLevel = _baseTimingPerLevel;
    }

    function ownerSetTotals(uint256 _totalVerifiedUsers, uint256 _totalPayableUsers) external onlyOwner {
        totalVerifiedUsers = _totalVerifiedUsers;
        totalPayableUsers = _totalPayableUsers;
    }

    function ownerSetPayableUser(address user, bool isPayable) external onlyOwner {
        payableUsers[user] = isPayable;
    }

    function ownerEditUserData(
        address userAddress,
        uint256 newExperience,
        uint256 newLevel,
        uint256 newTimingLevel,
        uint256 newRewardLevel,
        uint256 newWater,
        bool verified,
        address tokenReward_
    ) external onlyOwner {
        UserInfo storage user = userInfo[userAddress];
        user.experience = newExperience;
        user.Lvl = newLevel;
        user.timingLevel = newTimingLevel;
        user.rewardLevel = newRewardLevel;
        user.water = newWater;
        user.tokenReward = IERC20(tokenReward_);

        payableUsers[userAddress] = verified;

        emit UserDataEdited(userAddress, newExperience, newLevel, newTimingLevel, newRewardLevel, newWater);
    }

    function ownerSetUserHistory(
        address userAddress,
        uint256 maxLvl,
        uint256 totalClaims,
        uint256 totalClaimed,
        uint256 totalWLDspent,
        uint256 maxTimingLevel,
        uint256 maxRewardLevel
    ) external onlyOwner {
        userHistory[userAddress] = UserHistory({
            MaxLvl: maxLvl,
            totalClaims: totalClaims,
            TotalClaimed: totalClaimed,
            TotalWLDspent: totalWLDspent,
            MaxtimingLevel: maxTimingLevel,
            MaxrewardLevel: maxRewardLevel
        });
    }

    function resetAccountLvls(address userAddress, uint newLvl, uint newTimingLevel, uint newRewardLevel) public {
        require(contractCallers[msg.sender], "SCRAPPER: not authorized");
        UserInfo storage user = userInfo[userAddress];
        user.Lvl = newLvl;
        user.experience = 0;
        user.timingLevel = newTimingLevel;
        user.rewardLevel = newRewardLevel;
        user.resets++;
        if ( address(top) != address(0)) {
            top.updateScore(userAddress, user.Lvl);
        }
        if (address(resetAccountLvlsContract) != address(0)) {
            resetAccountLvlsContract.updateUserAccount(userAddress);
        }
        emit UserDataEdited(userAddress, 0, newLvl, newTimingLevel, newRewardLevel, 0);
    }

    /**
     * @notice Gets the complete history data for a user
     * @param userAddress The address of the user
     * @return maxLvl Maximum level reached by the user
     * @return totalClaims Total number of claims made
     * @return totalClaimed Total tokens claimed by the user
     * @return totalWLDspent Total WLD spent on upgrades
     * @return maxTimingLevel Maximum timing level reached
     * @return maxRewardLevel Maximum reward level reached
     */
    function getUserHistory(address userAddress) external view returns (
        uint256 maxLvl,
        uint256 totalClaims,
        uint256 totalClaimed,
        uint256 totalWLDspent,
        uint256 maxTimingLevel,
        uint256 maxRewardLevel
    ) {
        UserHistory storage history = userHistory[userAddress];
        maxLvl = history.MaxLvl;
        totalClaims = history.totalClaims;
        totalClaimed = history.TotalClaimed;
        totalWLDspent = history.TotalWLDspent;
        maxTimingLevel = history.MaxtimingLevel;
        maxRewardLevel = history.MaxrewardLevel;
    }

    /**
     * @notice Gets combined user info and history for complete user profile
     * @param userAddress The address of the user
     * @return userInfo Current user information
     * @return userHistory Historical user data
     */
    function getCompleteUserProfile(address userAddress) external view returns (
        UserInfo memory,
        UserHistory memory
    ) {
        return (userInfo[userAddress], userHistory[userAddress]);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

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

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

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

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

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

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

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

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)

pragma solidity >=0.4.16;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

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

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

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

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

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

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

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

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

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

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

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)

pragma solidity ^0.8.20;

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

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

    uint256 private _status;

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    constructor() {
        _status = NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if (_status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

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

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

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == ENTERED;
    }
}

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

interface IEIP712 {
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

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

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

interface IScrappers {

    /**
     * @notice Estructura que almacena la información de un usuario
     * @param lastClaimTime Último timestamp en que el usuario reclamó tokens
     * @param accumulatedTokens Tokens acumulados pendientes (no usado actualmente)
     * @param timingLevel Nivel de mejora de tiempo del usuario
     * @param rewardLevel Nivel de mejora de recompensa del usuario
     * @param resets El yerno es duro, a veces toca empezar otra vez.
     */
    struct UserInfo {
        uint256 experience;
        uint256 Lvl;
        uint256 lastClaimTime;
        uint256 accumulatedTokens;
        uint256 timingLevel;
        uint256 rewardLevel;
        uint256 water;
        uint64 resets;
    }

    struct UserHistory {
        uint256 MaxLvl; // max level reached - updated when user reaches a new level
        uint256 totalClaims; // total claims made by user
        uint256 TotalClaimed; // total tokens claimed
        uint256 TotalWLDspent; // total WLD spent
        uint256 MaxtimingLevel; // max timing level reached
        uint256 MaxrewardLevel; // max reward level reached
    }

    // Eventos
    event TokensClaimed(address indexed user, uint256 amount);
    event BaseRewardUpdated(uint256 newReward);
    event BaseplusRewardUpdated(uint256 newReward);
    event MaxAccumulationTimeUpdated(uint256 newTime);
    event BaseTimingPerLevelUpdated(uint256 newTime);
    event TimingLevelUpgraded(address indexed user, uint256 newLevel, uint256 cost);
    event RewardLevelUpgraded(address indexed user, uint256 newLevel, uint256 cost);
    event WLDPriceUpdated(string upgradeType, uint256 newPrice);
    event TokenPriceUpdated(string upgradeType, uint256 newPrice);
    event LevelUp(address indexed user, uint256 newLevel, uint256 expGained);
    event BaseExpPerLevelUpdated(uint256 newBaseExp);
    event UserDataEdited(address indexed user, uint256 newExperience, uint256 newLevel, uint256 newTimingLevel, uint256 newRewardLevel, uint256 newWater);
    event ContractCallerUpdated(address indexed caller, bool authorized);

    /**
     * @notice Permite a un usuario reclamar sus tokens acumulados
     * @dev Calcula los tokens acumulados desde el último claim y los transfiere al usuario.
     * Resetea el timer de acumulación después del claim.
     * Otorga experiencia igual a la cantidad de tokens claimeados (mantiene 18 decimales).
     *
     * Requisitos:
     * - El usuario debe tener tokens acumulados para reclamar
     * - El contrato debe tener suficientes tokens para transferir
     *
     * Emite un evento {TokensClaimed} cuando se completa exitosamente.
     * Puede emitir eventos {LevelUp} si el usuario sube de nivel con la experiencia ganada.
     */
    function claimTokens(
        
    ) external;

    /**
     * @notice Calcula los tokens acumulados para un usuario específico
     * @param userAddress Dirección del usuario para calcular tokens acumulados
     * @return Cantidad de tokens acumulados
     * @dev Si es la primera vez del usuario (lastClaimTime = 0), retorna el máximo
     * de tokens acumulados basado en su tiempo máximo personalizado.
     * Si no es la primera vez, calcula basado en el tiempo transcurrido desde
     * el último claim, limitado al tiempo máximo de acumulación del usuario.
     */
    function calculateAccumulatedTokens(address userAddress) external view returns (uint256);

    /**
     * @notice Obtiene el tiempo máximo de acumulación para un usuario específico
     * @param userAddress Dirección del usuario
     * @return Tiempo máximo de acumulación en segundos
     * @dev Calcula el tiempo base más las mejoras de tiempo del usuario
     */
    function getMaxAccumulationTimeForUser(address userAddress) external view returns (uint256);

    /**
     * @notice Obtiene la recompensa por minuto para un usuario específico
     * @param userAddress Dirección del usuario
     * @return Recompensa por minuto en wei
     * @dev Calcula la recompensa base más las mejoras de recompensa del usuario
     */
    function getRewardPerMinuteForUser(address userAddress) external view returns (uint256);



    /**
     * @notice Añade niveles a un usuario
     * @param userAddress Dirección del usuario
     * @param amount Cantidad de niveles a añadir
     * @dev Solo los contractCallers autorizados pueden llamar esta función
     * Permite añadir niveles a un usuario para contratos externos
     */
    function addLvl(address userAddress, uint256 amount) external;

    /**
     * @notice Mejora el nivel de tiempo usando WLD
     * @param amount Cantidad de niveles a comprar
     * @param permit Estructura de permisos de Permit2
     * @param transferDetails Detalles de la transferencia
     * @param signature Firma para autorizar la transferencia
     * @dev Permite al usuario mejorar su tiempo máximo de acumulación usando WLD.
     * El costo es fijo por nivel y se multiplica por la cantidad.
     * Costo total = updateONEwithWLD * amount
     *
     * Emite un evento {TimingLevelUpgraded} cuando se completa exitosamente.
     */
    function updateLvlTimingWithWLD(
        uint256 amount,
        ISignatureTransfer.PermitTransferFrom memory permit,
        ISignatureTransfer.SignatureTransferDetails calldata transferDetails,
        bytes calldata signature
    ) external;

    /**
     * @notice Mejora el nivel de recompensa usando WLD
     * @param amount Cantidad de niveles a comprar
     * @param permit Estructura de permisos de Permit2
     * @param transferDetails Detalles de la transferencia
     * @param signature Firma para autorizar la transferencia
     * @dev Permite al usuario mejorar su recompensa por minuto usando WLD.
     * El costo es fijo por nivel y se multiplica por la cantidad.
     * Costo total = updateTWOwithWLD * amount
     *
     * Emite un evento {RewardLevelUpgraded} cuando se completa exitosamente.
     */
    function updateTokenRewardLvlWithWLD(
        uint256 amount,
        ISignatureTransfer.PermitTransferFrom memory permit,
        ISignatureTransfer.SignatureTransferDetails calldata transferDetails,
        bytes calldata signature
    ) external;

    /**
     * @notice Obtiene información completa del estado de un usuario
     * @param userAddress Dirección del usuario
     * @return experience Experiencia actual del usuario
     * @return level Nivel actual del usuario
     * @return lastClaimTime Último tiempo de claim
     * @return accumulatedTokens Tokens acumulados pendientes
     * @return currentAccumulated Tokens actualmente acumulados
     * @return timeUntilMax Tiempo restante hasta el máximo de acumulación
     * @return timingLevel Nivel actual de mejora de tiempo
     * @return rewardLevel Nivel actual de mejora de recompensa
     * @return maxAccumulationTime Tiempo máximo de acumulación personalizado
     * @return rewardPerMinute Recompensa por minuto personalizada
     * @dev Función view que retorna toda la información relevante del usuario
     */
    function getUserInfo(address userAddress) external view returns (
        uint256 experience,
        uint256 level,
        uint256 lastClaimTime,
        uint256 accumulatedTokens,
        uint256 currentAccumulated,
        uint256 timeUntilMax,
        uint256 timingLevel,
        uint256 rewardLevel,
        uint256 maxAccumulationTime,
        uint256 rewardPerMinute,
        uint256 water
    );

    /**
     * @notice Actualiza la recompensa base por minuto
     * @param newReward Nueva recompensa base por minuto en wei
     * @dev Solo el owner puede llamar esta función
     *
     * Emite un evento {BaseRewardUpdated} cuando se actualiza exitosamente.
     */
    function setBaseRewardPerMinute(uint256 newReward) external;

    /**
     * @notice Actualiza el tiempo máximo de acumulación base
     * @param newTime Nuevo tiempo máximo en segundos
     * @dev Solo el owner puede llamar esta función
     *
     * Emite un evento {MaxAccumulationTimeUpdated} cuando se actualiza exitosamente.
     */
    function setMaxAccumulationTime(uint256 newTime) external;

    /**
     * @notice Actualiza el tiempo base por nivel de mejora
     * @param newTime Nuevo tiempo base por nivel en segundos
     * @dev Solo el owner puede llamar esta función
     *
     * Emite un evento {BaseTimingPerLevelUpdated} cuando se actualiza exitosamente.
     */
    function setBaseTimingPerLevel(uint256 newTime) external;

    /**
     * @notice Actualiza el precio de mejora de tiempo con WLD
     * @param newPrice Nuevo precio en wei
     * @dev Solo el owner puede llamar esta función
     *
     * Emite un evento {WLDPriceUpdated} cuando se actualiza exitosamente.
     */
    function setUpdateONEwithWLD(uint256 newPrice) external;

    /**
     * @notice Actualiza el precio de mejora de recompensa con WLD
     * @param newPrice Nuevo precio en wei
     * @dev Solo el owner puede llamar esta función
     *
     * Emite un evento {WLDPriceUpdated} cuando se actualiza exitosamente.
     */
    function setUpdateTWOwithWLD(uint256 newPrice) external;

    /**
     * @notice Actualiza la recompensa adicional por minuto por nivel
     * @param newReward Nueva recompensa adicional por nivel en wei
     * @dev Solo el owner puede llamar esta función
     *
     * Emite un evento {BaseplusRewardUpdated} cuando se actualiza exitosamente.
     */
    function setBaseplusRewardPerMinute(uint256 newReward) external;

    /**
     * @notice Actualiza el precio base de mejora de tiempo con tokens
     * @param newPrice Nuevo precio base en wei
     * @dev Solo el owner puede llamar esta función
     *
     * Emite un evento {TokenPriceUpdated} cuando se actualiza exitosamente.
     */
    function setUpdateONEwithToken(uint256 newPrice) external;

    /**
     * @notice Actualiza el precio base de mejora de recompensa con tokens
     * @param newPrice Nuevo precio base en wei
     * @dev Solo el owner puede llamar esta función
     *
     * Emite un evento {TokenPriceUpdated} cuando se actualiza exitosamente.
     */
    function setUpdateTWOwithToken(uint256 newPrice) external;



    /**
     * @notice Deposita tokens al contrato para recompensas
     * @param amount Cantidad de tokens a depositar
     * @dev Solo el owner puede llamar esta función
     * Requiere que el owner haya aprobado previamente los tokens al contrato
     */
    function depositTokens(uint256 amount) external;

    /**
     * @notice Obtiene la dirección del token scrap
     * @return Dirección del contrato del token scrap
     */
    function token() external view returns (IERC20);

    /**
     * @notice Calcula el costo de mejora de tiempo con tokens
     * @param userAddress Dirección del usuario
     * @return Costo de la mejora en wei
     * @dev El costo aumenta un 200% por nivel (multiplica por 3)
     * Fórmula: baseCost * (3 ^ timingLevel)
     */
    function getTimingUpgradeCostWithToken(address userAddress) external view returns (uint256);

    /**
     * @notice Calcula el costo de mejora de recompensa con tokens
     * @param userAddress Dirección del usuario
     * @return Costo de la mejora en wei
     * @dev El costo aumenta un 200% por nivel (multiplica por 3)
     * Fórmula: baseCost * (3 ^ rewardLevel)
     */
    function getRewardUpgradeCostWithToken(address userAddress) external view returns (uint256);

    /**
     * @notice Obtiene los costos actuales de mejoras con tokens para un usuario
     * @param userAddress Dirección del usuario
     * @return timingUpgradeCost Costo de mejora de tiempo
     * @return rewardUpgradeCost Costo de mejora de recompensa
     * @return currentTimingLevel Nivel actual de tiempo
     * @return currentRewardLevel Nivel actual de recompensa
     * @dev Función view que retorna toda la información de costos y niveles
     */
    function getTokenUpgradeCosts(address userAddress) external view returns (
        uint256 timingUpgradeCost,
        uint256 rewardUpgradeCost,
        uint256 currentTimingLevel,
        uint256 currentRewardLevel
    );

    /**
     * @notice Mejora el nivel de tiempo usando tokens nativos
     * @param permit Estructura de permisos de Permit2
     * @param transferDetails Detalles de la transferencia
     * @param signature Firma para autorizar la transferencia
     * @dev Permite al usuario mejorar su tiempo máximo de acumulación usando tokens.
     * El costo aumenta un 200% por nivel (multiplica por 3).
     *
     * Emite un evento {TimingLevelUpgraded} cuando se completa exitosamente.
     */
    function updateLvlTimingWithToken(
        ISignatureTransfer.PermitTransferFrom memory permit,
        ISignatureTransfer.SignatureTransferDetails calldata transferDetails,
        bytes calldata signature
    ) external;

    /**
     * @notice Mejora el nivel de recompensa usando tokens nativos
     * @param permit Estructura de permisos de Permit2
     * @param transferDetails Detalles de la transferencia
     * @param signature Firma para autorizar la transferencia
     * @dev Permite al usuario mejorar su recompensa por minuto usando tokens.
     * El costo aumenta un 200% por nivel (multiplica por 3).
     *
     * Emite un evento {RewardLevelUpgraded} cuando se completa exitosamente.
     */
    function updateTokenRewardLvlWithToken(
        ISignatureTransfer.PermitTransferFrom memory permit,
        ISignatureTransfer.SignatureTransferDetails calldata transferDetails,
        bytes calldata signature
    ) external;

    /**
     * @notice Añade experiencia a un usuario y gestiona los subidas de nivel automáticamente
     * @param userAddress Dirección del usuario que recibirá la experiencia
     * @param expAmount Cantidad de experiencia a añadir
     * @dev Calcula si el usuario debe subir de nivel basado en la experiencia total.
     * Si el usuario sube varios niveles, itera level por level hasta agotar la experiencia.
     * La experiencia sobrante se mantiene para el siguiente nivel.
     * 
     * Emite un evento {LevelUp} por cada nivel que suba el usuario.
     */
    function addExperience(address userAddress, uint256 expAmount) external;

    /**
     * @notice Calcula la experiencia requerida para subir al siguiente nivel
     * @param currentLevel Nivel actual del usuario
     * @return Experiencia requerida para subir al siguiente nivel
     * @dev Fórmula: baseExp + (currentLevel * 1000)
     * Para el nivel 10 -> 11 se requieren 10,000 (base) + (10 * 1000) = 20,000 exp
     */
    function getExpRequiredForNextLevel(uint256 currentLevel) external view returns (uint256);

    /**
     * @notice Actualiza la experiencia base requerida por nivel
     * @param newBaseExp Nueva experiencia base por nivel
     * @dev Solo el owner puede llamar esta función
     */
    function setBaseExpPerLevel(uint256 newBaseExp) external;

    /**
     * @notice Edita los datos de un usuario específico
     * @param userAddress Dirección del usuario a editar
     * @param newExperience Nueva experiencia del usuario
     * @param newLevel Nuevo nivel del usuario
     * @param newTimingLevel Nuevo nivel de mejora de tiempo
     * @param newRewardLevel Nuevo nivel de mejora de recompensa
     * @param newWater Nuevo valor de water del usuario
     * @dev Solo los contractCallers autorizados pueden llamar esta función
     * Permite edición completa de los datos del usuario para contratos externos
     */
    function editUserData(
        address userAddress,
        uint256 newExperience,
        uint256 newLevel,
        uint256 newTimingLevel,
        uint256 newRewardLevel,
        uint256 newWater
    ) external;

    /**
     * @notice Autoriza o desautoriza un contrato para llamar funciones restringidas
     * @param caller Dirección del contrato a autorizar/desautorizar
     * @param authorized Estado de autorización (true = autorizado, false = desautorizado)
     * @dev Solo el owner puede llamar esta función
     */
    function setContractCaller(address caller, bool authorized) external;

    /**
     * @notice Obtiene el historial completo de un usuario
     * @param userAddress Dirección del usuario
     * @return maxLvl Nivel máximo alcanzado
     * @return totalClaims Total de claims realizados
     * @return totalClaimed Total de tokens reclamados
     * @return totalWLDspent Total de WLD gastado
     * @return maxTimingLevel Nivel máximo de timing alcanzado
     * @return maxRewardLevel Nivel máximo de reward alcanzado
     */
    function getUserHistory(address userAddress) external view returns (
        uint256 maxLvl,
        uint256 totalClaims,
        uint256 totalClaimed,
        uint256 totalWLDspent,
        uint256 maxTimingLevel,
        uint256 maxRewardLevel
    );

    /**
     * @notice Obtiene información completa del usuario (datos actuales + historial)
     * @param userAddress Dirección del usuario
     * @return userInfo Información actual del usuario
     * @return userHistory Historial del usuario
     */
    function getCompleteUserProfile(address userAddress) external view returns (
        UserInfo memory,
        UserHistory memory
    );
}

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

import {ISignatureTransfer} from "./ISignatureTransfer.sol";

interface IShop {
    
    /**
     * @notice Estructura que almacena los boosters permanentes de un usuario
     * @param permanentEfficiencyBoost Porcentaje adicional de reward rate (acumulativo)
     * @param permanentTimeExtension Porcentaje adicional de tiempo de acumulación
     * @param permanentExpMultiplier Porcentaje adicional de experiencia por claim
     */
    struct BoosterInfo {
        uint256 permanentEfficiencyBoost;    // % adicional de reward rate (0-100)
        uint256 permanentTimeExtension;      // % adicional de tiempo (0-75) 
        uint256 permanentExpMultiplier;      // % adicional de EXP (0-100)
    }

    /**
     * @notice Estructura que almacena los boosters temporales activos independientemente
     * @param megaBoostEndTime Timestamp cuando expira Mega Boost (reward multiplier)
     * @param speedRushEndTime Timestamp cuando expira Speed Rush (time extension) 
     * @param expStormEndTime Timestamp cuando expira EXP Storm (exp multiplier)
     */
    struct TemporaryBoosters {
        uint256 megaBoostEndTime;    // cuando expira el boost de reward (0 = inactivo)
        uint256 speedRushEndTime;    // cuando expira el boost de tiempo (0 = inactivo)
        uint256 expStormEndTime;     // cuando expira el boost de exp (0 = inactivo)
    }

    // Eventos
    event PermanentBoosterPurchased(address indexed user, uint8 boosterType, uint256 cost, bool paidWithWLD);
    event TemporaryBoosterPurchased(address indexed user, uint8 boosterType, uint256 cost, bool paidWithWLD);
    event ExperiencePurchased(address indexed user, uint256 expAmount, uint256 cost, bool paidWithWLD);
    event LevelsPurchased(address indexed user, uint256 levelAmount, uint256 cost, bool paidWithWLD);
    event TemporaryBoosterExpired(address indexed user);
    
    // Eventos para actualización de direcciones
    event ScrapTokenUpdated(address indexed newScrapToken);
    event WLDUpdated(address indexed newWLD);
    event ScrappersUpdated(address indexed newScrappers);

    /**
     * @notice Compra un booster permanente
     * @param boosterType Tipo de booster (0=Efficiency, 1=TimeExtender, 2=ExpAmplifier)
     * @param permit Estructura de permisos de Permit2
     * @param transferDetails Detalles de la transferencia
     * @param signature Firma para autorizar la transferencia
     * @param payWithWLD True para pagar con WLD, false para SCP
     */
    function buyPermanentBooster(
        uint8 boosterType,
        ISignatureTransfer.PermitTransferFrom memory permit,
        ISignatureTransfer.SignatureTransferDetails calldata transferDetails,
        bytes calldata signature,
        bool payWithWLD
    ) external;

    /**
     * @notice Compra un booster temporal
     * @param boosterType Tipo de booster (0=MegaBoost, 1=SpeedRush, 2=ExpStorm)
     * @param permit Estructura de permisos de Permit2
     * @param transferDetails Detalles de la transferencia
     * @param signature Firma para autorizar la transferencia
     */
    function buyTemporaryBooster(
        uint8 boosterType,
        ISignatureTransfer.PermitTransferFrom memory permit,
        ISignatureTransfer.SignatureTransferDetails calldata transferDetails,
        bytes calldata signature
    ) external;

    /**
     * @notice Compra experiencia directa
     * @param packageSize Tamaño del paquete (0=Small, 1=Medium, 2=Large)
     * @param permit Estructura de permisos de Permit2
     * @param transferDetails Detalles de la transferencia
     * @param signature Firma para autorizar la transferencia
     * @param payWithWLD True para pagar con WLD, false para SCP
     */
    function buyExperience(
        uint8 packageSize,
        ISignatureTransfer.PermitTransferFrom memory permit,
        ISignatureTransfer.SignatureTransferDetails calldata transferDetails,
        bytes calldata signature,
        bool payWithWLD
    ) external;

    /**
     * @notice Compra niveles directos
     * @param levelAmount Cantidad de niveles (1 o 3)
     * @param permit Estructura de permisos de Permit2
     * @param transferDetails Detalles de la transferencia
     * @param signature Firma para autorizar la transferencia
     * @param payWithWLD True para pagar con WLD, false para SCP
     */
    function buyLevels(
        uint8 levelAmount,
        ISignatureTransfer.PermitTransferFrom memory permit,
        ISignatureTransfer.SignatureTransferDetails calldata transferDetails,
        bytes calldata signature,
        bool payWithWLD
    ) external;

    /**
     * @notice Obtiene los boosters permanentes de un usuario
     * @param userAddress Dirección del usuario
     * @return boosterInfo Información de boosters permanentes
     */
    function getUserBoosters(address userAddress) external view returns (BoosterInfo memory boosterInfo);

    /**
     * @notice Obtiene los boosters temporales activos de un usuario
     * @param userAddress Dirección del usuario
     * @return tempBoosters Información de los boosters temporales
     */
    function getUserTemporaryBoosters(address userAddress) external view returns (TemporaryBoosters memory tempBoosters);

    /**
     * @notice Verifica qué boosters temporales están activos para un usuario
     * @param userAddress Dirección del usuario
     * @return hasMegaBoost True si tiene Mega Boost activo
     * @return hasSpeedRush True si tiene Speed Rush activo  
     * @return hasExpStorm True si tiene EXP Storm activo
     */
    function getActiveTemporaryBoosters(address userAddress) external view returns (
        bool hasMegaBoost,
        bool hasSpeedRush,
        bool hasExpStorm
    );

    /**
     * @notice Obtiene los precios actuales de todos los items
     * @return permanentPricesWLD Precios en WLD de boosters permanentes [Efficiency, TimeExtender, ExpAmplifier]
     * @return permanentPricesSCP Precios en SCP de boosters permanentes
     * @return temporaryPricesWLD Precios en WLD de boosters temporales [MegaBoost, SpeedRush, ExpStorm]
     * @return expPricesWLD Precios en WLD de paquetes de EXP [Small, Medium, Large]
     * @return expPricesSCP Precios en SCP de paquetes de EXP
     * @return levelPricesWLD Precios en WLD de niveles [1 level, 3 levels]
     * @return levelPricesSCP Precios en SCP de niveles
     */
    function getCurrentPrices() external view returns (
        uint256[3] memory permanentPricesWLD,
        uint256[3] memory permanentPricesSCP,
        uint256[3] memory temporaryPricesWLD,
        uint256[3] memory expPricesWLD,
        uint256[3] memory expPricesSCP,
        uint256[3] memory levelPricesWLD,
        uint256[3] memory levelPricesSCP
    );

    /**
     * @notice Obtiene información completa de un usuario (boosters + estado temporal)
     * @param userAddress Dirección del usuario
     * @return permanentBoosters Boosters permanentes del usuario
     * @return temporaryBoosters Boosters temporales activos
     * @return hasMegaBoost Si tiene Mega Boost activo
     * @return hasSpeedRush Si tiene Speed Rush activo
     * @return hasExpStorm Si tiene EXP Storm activo
     * @return megaBoostTimeLeft Tiempo restante de Mega Boost
     * @return speedRushTimeLeft Tiempo restante de Speed Rush
     * @return expStormTimeLeft Tiempo restante de EXP Storm
     */
    function getCompleteUserStatus(address userAddress) external view returns (
        BoosterInfo memory permanentBoosters,
        TemporaryBoosters memory temporaryBoosters,
        bool hasMegaBoost,
        bool hasSpeedRush,
        bool hasExpStorm,
        uint256 megaBoostTimeLeft,
        uint256 speedRushTimeLeft,
        uint256 expStormTimeLeft
    );


    /**
     * @notice Limpia boosters temporales expirados (función auxiliar)
     * @param userAddress Dirección del usuario
     */
    function cleanExpiredBooster(address userAddress) external;

    // Funciones auxiliares para integración con Scrappers
    function getRewardMultiplier(address userAddress) external view returns (uint256);
    function getTimeMultiplier(address userAddress) external view returns (uint256);
    function getTimeExtension(address userAddress) external view returns (uint256);
    function getExpMultiplier(address userAddress) external view returns (uint256);
    
    // Funciones para editar direcciones de contratos (Owner only)
    function setScrapToken(address newScrapToken) external;
    function setWLD(address newWLD) external;
    function setScrappers(address newScrappers) external;
}

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

import {IEIP712} from "./IEIP712.sol";

/// @title SignatureTransfer
/// @notice Handles ERC20 token transfers through signature based actions
/// @dev Requires user's token approval on the Permit2 contract
interface ISignatureTransfer is IEIP712 {
    
    struct TokenPermissions {
        address token;
        uint256 amount;
    }

    struct PermitTransferFrom {
        TokenPermissions permitted;
        uint256 nonce;
        uint256 deadline;
    }

    struct SignatureTransferDetails {
        address to;
        uint256 requestedAmount;
    }
    
    function permitTransferFrom(
        PermitTransferFrom memory permit,
        SignatureTransferDetails calldata transferDetails,
        address owner,
        bytes calldata signature
    ) external;
}

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

interface ITop {
    
    struct TopEntry {
        address user;
        uint256 score;
    }
    
    // Eventos
    event TopUpdated(address indexed user, uint256 newScore, uint256 position);
    event UserRemovedFromTop(address indexed user, uint256 oldPosition);
    event ContractCallerUpdated(address indexed caller, bool authorized);
    event TopPaused(bool paused);
    event TopReset();
    event PrizeDistributed(address indexed token, uint256 totalAmount, uint256 winnersCount);
    
    /**
     * @notice Actualiza el score de un usuario y reordena el top si es necesario
     * @param user Dirección del usuario
     * @param score Nuevo score del usuario
     * @dev Solo contractCallers autorizados pueden llamar esta función
     */
    function updateScore(address user, uint256 score) external;
    
    /**
     * @notice Encuentra la posición actual de un usuario en el top
     * @param user Dirección del usuario
     * @return Posición en el array (1-based), 0 si no está en el top
     */
    function findUserPosition(address user) external view returns (uint256);
    
    /**
     * @notice Encuentra la posición donde debería insertarse un score
     * @param score Score a insertar
     * @return Posición donde insertar (0-based)
     */
    function findInsertPosition(uint256 score) external view returns (uint256);
    
    /**
     * @notice Obtiene todo el top actual
     * @return Array de usuarios y sus scores
     */
    function getTop() external view returns (TopEntry[] memory);
    
    /**
     * @notice Obtiene la información de una posición específica
     * @param position Posición en el top (1-based)
     * @return user Dirección del usuario
     * @return score Score del usuario
     */
    function getTopPosition(uint256 position) external view returns (address user, uint256 score);
    
    /**
     * @notice Obtiene el tamaño actual del top
     * @return Número de usuarios en el top
     */
    function getTopSize() external view returns (uint256);
    
    /**
     * @notice Verifica si un usuario está en el top
     * @param user Dirección del usuario
     * @return true si está en el top, false si no
     */
    function isInTop(address user) external view returns (bool);
    
    /**
     * @notice Obtiene el score mínimo para entrar al top
     * @return Score mínimo, 0 si el top no está lleno
     */
    function getMinScoreForTop() external view returns (uint256);
    
    /**
     * @notice Autoriza o desautoriza un contrato para llamar funciones restringidas
     * @param caller Dirección del contrato a autorizar/desautorizar
     * @param authorized Estado de autorización
     * @dev Solo el owner puede llamar esta función
     */
    function setContractCaller(address caller, bool authorized) external;
    
    /**
     * @notice Función de emergencia para limpiar el top
     * @dev Solo el owner puede llamar esta función
     */
    function clearTop() external;
    
    /**
     * @notice Pausa o despausa el sistema de top
     * @param _paused True para pausar, false para despausar
     * @dev Solo el owner puede llamar esta función
     */
    function setPaused(bool _paused) external;
    
    /**
     * @notice Verifica si el sistema está pausado
     * @return true si está pausado, false si está activo
     */
    function isPaused() external view returns (bool);
    
    /**
     * @notice Reinicia completamente el top eliminando todos los usuarios
     * @dev Solo el owner puede llamar esta función
     */
    function resetTop() external;
    
    /**
     * @notice Distribuye premios a los usuarios del top actual
     * @param tokenAddress Dirección del token a distribuir
     * @param amounts Array con las cantidades a distribuir por posición
     * @dev Solo el owner puede llamar esta función
     * @dev amounts[0] es para el 1er lugar, amounts[1] para el 2do, etc.
     * @dev Si hay menos amounts que usuarios en el top, los últimos no reciben premio
     */
    function distributePrizes(address tokenAddress, uint256[] calldata amounts) external;
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "evmVersion": "paris",
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"waterToken_","type":"address"},{"internalType":"address","name":"ironToken_","type":"address"},{"internalType":"address","name":"_wld","type":"address"},{"internalType":"address","name":"initialOwner","type":"address"},{"internalType":"address","name":"_top","type":"address"},{"internalType":"address","name":"_scrappers","type":"address"},{"internalType":"address","name":"oldWatters_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newBaseExp","type":"uint256"}],"name":"BaseExpPerLevelUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newReward","type":"uint256"}],"name":"BaseRewardUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newTime","type":"uint256"}],"name":"BaseTimingPerLevelUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newReward","type":"uint256"}],"name":"BaseplusRewardUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"bool","name":"authorized","type":"bool"}],"name":"ContractCallerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"newLevel","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"expGained","type":"uint256"}],"name":"LevelUp","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newTime","type":"uint256"}],"name":"MaxAccumulationTimeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldWatters","type":"address"}],"name":"OldWattersUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"newLevel","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cost","type":"uint256"}],"name":"RewardLevelUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"newLevel","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cost","type":"uint256"}],"name":"TimingLevelUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"upgradeType","type":"string"},{"indexed":false,"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"TokenPriceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokensClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"newExperience","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newLevel","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTimingLevel","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRewardLevel","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newWater","type":"uint256"}],"name":"UserDataEdited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"upgradeType","type":"string"},{"indexed":false,"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"WLDPriceUpdated","type":"event"},{"inputs":[],"name":"ChangeRewardTokenCostInScrap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ChangeRewardTokenCostInWLD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_ACCUMULATION_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WLD","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activateWater","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"uint256","name":"expAmount","type":"uint256"}],"name":"addExperience","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"addressBook","outputs":[{"internalType":"contract IAddressBook","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseExpPerLevel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseRewardPerMinute","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseTimingPerLevel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseplusRewardPerMinute","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenOption","type":"uint256"},{"components":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ISignatureTransfer.TokenPermissions","name":"permitted","type":"tuple"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct ISignatureTransfer.PermitTransferFrom","name":"permit","type":"tuple"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"requestedAmount","type":"uint256"}],"internalType":"struct ISignatureTransfer.SignatureTransferDetails","name":"transferDetails","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"buyGame","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ISignatureTransfer.TokenPermissions","name":"permitted","type":"tuple"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct ISignatureTransfer.PermitTransferFrom","name":"permit","type":"tuple"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"requestedAmount","type":"uint256"}],"internalType":"struct ISignatureTransfer.SignatureTransferDetails","name":"transferDetails","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"buyWater","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"}],"name":"calculateAccumulatedTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenOption","type":"uint256"},{"components":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ISignatureTransfer.TokenPermissions","name":"permitted","type":"tuple"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct ISignatureTransfer.PermitTransferFrom","name":"permit","type":"tuple"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"requestedAmount","type":"uint256"}],"internalType":"struct ISignatureTransfer.SignatureTransferDetails","name":"transferDetails","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"changeTokenReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"contractCallers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"depositTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"uint256","name":"newExperience","type":"uint256"},{"internalType":"uint256","name":"newLevel","type":"uint256"},{"internalType":"uint256","name":"newTimingLevel","type":"uint256"},{"internalType":"uint256","name":"newRewardLevel","type":"uint256"},{"internalType":"uint256","name":"newWater","type":"uint256"},{"internalType":"bool","name":"verified","type":"bool"},{"internalType":"address","name":"tokenReward_","type":"address"}],"name":"editUserData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"expeditionCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"expeditionToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gameCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"}],"name":"getCompleteUserProfile","outputs":[{"components":[{"internalType":"uint256","name":"experience","type":"uint256"},{"internalType":"uint256","name":"Lvl","type":"uint256"},{"internalType":"uint256","name":"lastClaimTime","type":"uint256"},{"internalType":"uint256","name":"accumulatedTokens","type":"uint256"},{"internalType":"uint256","name":"timingLevel","type":"uint256"},{"internalType":"uint256","name":"rewardLevel","type":"uint256"},{"internalType":"uint256","name":"water","type":"uint256"},{"internalType":"uint256","name":"resets","type":"uint256"},{"internalType":"contract IERC20","name":"tokenReward","type":"address"}],"internalType":"struct Watters.UserInfo","name":"","type":"tuple"},{"components":[{"internalType":"uint256","name":"MaxLvl","type":"uint256"},{"internalType":"uint256","name":"totalClaims","type":"uint256"},{"internalType":"uint256","name":"TotalClaimed","type":"uint256"},{"internalType":"uint256","name":"TotalWLDspent","type":"uint256"},{"internalType":"uint256","name":"MaxtimingLevel","type":"uint256"},{"internalType":"uint256","name":"MaxrewardLevel","type":"uint256"}],"internalType":"struct Watters.UserHistory","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"currentLevel","type":"uint256"}],"name":"getExpRequiredForNextLevel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"}],"name":"getMaxAccumulationTimeForUser","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"}],"name":"getRewardPerMinuteForUser","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"}],"name":"getRewardUpgradeCostWithToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"getRewardUpgradeCostWithWLD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"}],"name":"getTimingUpgradeCostWithToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"getTimingUpgradeCostWithWLD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"}],"name":"getTokenUpgradeCosts","outputs":[{"internalType":"uint256","name":"timingUpgradeCost","type":"uint256"},{"internalType":"uint256","name":"rewardUpgradeCost","type":"uint256"},{"internalType":"uint256","name":"currentTimingLevel","type":"uint256"},{"internalType":"uint256","name":"currentRewardLevel","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"}],"name":"getUserHistory","outputs":[{"internalType":"uint256","name":"maxLvl","type":"uint256"},{"internalType":"uint256","name":"totalClaims","type":"uint256"},{"internalType":"uint256","name":"totalClaimed","type":"uint256"},{"internalType":"uint256","name":"totalWLDspent","type":"uint256"},{"internalType":"uint256","name":"maxTimingLevel","type":"uint256"},{"internalType":"uint256","name":"maxRewardLevel","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"}],"name":"getUserInfo","outputs":[{"internalType":"uint256","name":"experience","type":"uint256"},{"internalType":"uint256","name":"level","type":"uint256"},{"internalType":"uint256","name":"lastClaimTime","type":"uint256"},{"internalType":"uint256","name":"accumulatedTokens","type":"uint256"},{"internalType":"uint256","name":"currentAccumulated","type":"uint256"},{"internalType":"uint256","name":"timeUntilMax","type":"uint256"},{"internalType":"uint256","name":"timingLevel","type":"uint256"},{"internalType":"uint256","name":"rewardLevel","type":"uint256"},{"internalType":"uint256","name":"maxAccumulationTime","type":"uint256"},{"internalType":"uint256","name":"rewardPerMinute","type":"uint256"},{"internalType":"uint256","name":"water","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ironToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"migratedFromOld","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oldWatters","outputs":[{"internalType":"contract IOldWatters","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"uint256","name":"newExperience","type":"uint256"},{"internalType":"uint256","name":"newLevel","type":"uint256"},{"internalType":"uint256","name":"newTimingLevel","type":"uint256"},{"internalType":"uint256","name":"newRewardLevel","type":"uint256"},{"internalType":"uint256","name":"newWater","type":"uint256"},{"internalType":"bool","name":"verified","type":"bool"},{"internalType":"address","name":"tokenReward_","type":"address"}],"name":"ownerEditUserData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bool","name":"isPayable","type":"bool"}],"name":"ownerSetPayableUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_totalVerifiedUsers","type":"uint256"},{"internalType":"uint256","name":"_totalPayableUsers","type":"uint256"}],"name":"ownerSetTotals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"uint256","name":"maxLvl","type":"uint256"},{"internalType":"uint256","name":"totalClaims","type":"uint256"},{"internalType":"uint256","name":"totalClaimed","type":"uint256"},{"internalType":"uint256","name":"totalWLDspent","type":"uint256"},{"internalType":"uint256","name":"maxTimingLevel","type":"uint256"},{"internalType":"uint256","name":"maxRewardLevel","type":"uint256"}],"name":"ownerSetUserHistory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"payableUsers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"permit2","outputs":[{"internalType":"contract ISignatureTransfer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"uint256","name":"newLvl","type":"uint256"},{"internalType":"uint256","name":"newTimingLevel","type":"uint256"},{"internalType":"uint256","name":"newRewardLevel","type":"uint256"}],"name":"resetAccountLvls","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resetAccountLvlsContract","outputs":[{"internalType":"contract IResetAccountLvls","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rewardWldBreakpoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"scrappers","outputs":[{"internalType":"contract IScrappers","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAddressBook","type":"address"}],"name":"setAddressBook","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newBaseExp","type":"uint256"}],"name":"setBaseExpPerLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newReward","type":"uint256"}],"name":"setBaseRewardPerMinute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newTime","type":"uint256"}],"name":"setBaseTimingPerLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newReward","type":"uint256"}],"name":"setBaseplusRewardPerMinute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"bool","name":"authorized","type":"bool"}],"name":"setContractCaller","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newCost","type":"uint256"}],"name":"setExpeditionCost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_expeditionToken","type":"address"}],"name":"setExpeditionToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"setGameCost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_updateONEwithWLD","type":"uint256"},{"internalType":"uint256","name":"_updateTWOwithWLD","type":"uint256"},{"internalType":"uint256","name":"_updateONEwithToken","type":"uint256"},{"internalType":"uint256","name":"_updateTWOwithToken","type":"uint256"},{"internalType":"uint256","name":"_expeditionCost","type":"uint256"},{"internalType":"uint256","name":"_gameCost","type":"uint256"},{"internalType":"uint256","name":"_changeRewardTokenCostInWLD","type":"uint256"},{"internalType":"uint256","name":"_changeRewardTokenCostInScrap","type":"uint256"}],"name":"setHouseConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_ironToken","type":"address"}],"name":"setIronToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newTime","type":"uint256"}],"name":"setMaxAccumulationTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"oldWatters_","type":"address"}],"name":"setOldWatters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newPermit2","type":"address"}],"name":"setPermit2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"b0","type":"uint256"},{"internalType":"uint256","name":"b1","type":"uint256"},{"internalType":"uint256","name":"b2","type":"uint256"},{"internalType":"uint256","name":"b3","type":"uint256"},{"internalType":"uint256","name":"b4","type":"uint256"}],"name":"setRewardWldBreakpoints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_baseRewardPerMinute","type":"uint256"},{"internalType":"uint256","name":"_baseplusRewardPerMinute","type":"uint256"},{"internalType":"uint256","name":"_maxAccumulationTime","type":"uint256"},{"internalType":"uint256","name":"_baseTimingPerLevel","type":"uint256"}],"name":"setRewardsConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_scrappers","type":"address"}],"name":"setScrappers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_shop","type":"address"}],"name":"setShop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"b0","type":"uint256"},{"internalType":"uint256","name":"b1","type":"uint256"},{"internalType":"uint256","name":"b2","type":"uint256"},{"internalType":"uint256","name":"b3","type":"uint256"},{"internalType":"uint256","name":"b4","type":"uint256"}],"name":"setTimingWldBreakpoints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenOption","type":"uint256"}],"name":"setTokenReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newTop","type":"address"}],"name":"setTop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"setUpdateONEwithToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"setUpdateONEwithWLD","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_resetAccountLvlsContract","type":"address"}],"name":"setUpdateResetAccountLvlsContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"setUpdateTWOwithToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"setUpdateTWOwithWLD","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newWLD","type":"address"}],"name":"setWLD","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_waterToken","type":"address"}],"name":"setWaterToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_activateWater","type":"bool"}],"name":"setactivateWater","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"shop","outputs":[{"internalType":"contract IShop","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"timingWldBreakpoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"top","outputs":[{"internalType":"contract ITop","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalPayableUsers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalVerifiedUsers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ISignatureTransfer.TokenPermissions","name":"permitted","type":"tuple"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct ISignatureTransfer.PermitTransferFrom","name":"permit","type":"tuple"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"requestedAmount","type":"uint256"}],"internalType":"struct ISignatureTransfer.SignatureTransferDetails","name":"transferDetails","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"updateLvlTimingWithToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"components":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ISignatureTransfer.TokenPermissions","name":"permitted","type":"tuple"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct ISignatureTransfer.PermitTransferFrom","name":"permit","type":"tuple"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"requestedAmount","type":"uint256"}],"internalType":"struct ISignatureTransfer.SignatureTransferDetails","name":"transferDetails","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"updateLvlTimingWithWLD","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateONEwithToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"updateONEwithWLD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"updateTWOwithToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"updateTWOwithWLD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ISignatureTransfer.TokenPermissions","name":"permitted","type":"tuple"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct ISignatureTransfer.PermitTransferFrom","name":"permit","type":"tuple"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"requestedAmount","type":"uint256"}],"internalType":"struct ISignatureTransfer.SignatureTransferDetails","name":"transferDetails","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"updateTokenRewardLvlWithToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"components":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ISignatureTransfer.TokenPermissions","name":"permitted","type":"tuple"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct ISignatureTransfer.PermitTransferFrom","name":"permit","type":"tuple"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"requestedAmount","type":"uint256"}],"internalType":"struct ISignatureTransfer.SignatureTransferDetails","name":"transferDetails","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"updateTokenRewardLvlWithWLD","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userHistory","outputs":[{"internalType":"uint256","name":"MaxLvl","type":"uint256"},{"internalType":"uint256","name":"totalClaims","type":"uint256"},{"internalType":"uint256","name":"TotalClaimed","type":"uint256"},{"internalType":"uint256","name":"TotalWLDspent","type":"uint256"},{"internalType":"uint256","name":"MaxtimingLevel","type":"uint256"},{"internalType":"uint256","name":"MaxrewardLevel","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userInfo","outputs":[{"internalType":"uint256","name":"experience","type":"uint256"},{"internalType":"uint256","name":"Lvl","type":"uint256"},{"internalType":"uint256","name":"lastClaimTime","type":"uint256"},{"internalType":"uint256","name":"accumulatedTokens","type":"uint256"},{"internalType":"uint256","name":"timingLevel","type":"uint256"},{"internalType":"uint256","name":"rewardLevel","type":"uint256"},{"internalType":"uint256","name":"water","type":"uint256"},{"internalType":"uint256","name":"resets","type":"uint256"},{"internalType":"contract IERC20","name":"tokenReward","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"waterToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token_","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"}]

600280546001600160a01b03199081167357b930d551e677cc36e2fa036ae2fe8fdae0330d17909155600b80549091166e22d473030f116ddee9f6b43ac78ba317905566b1a2bc2ec50000600c55662386f26fc10000600d8190556014600e81905567016345785d8a0000600f818155601091909155678ac7230489e8000060118190556012819055670de0b6b3a764000060135592909155671bc16d674ec800006017556018919091556101206040526080908152604b60a052607d60c05260c860e05261012c610100526100d9906019906005610340565b506040805160a081018252600f8152604b6020820152607d9181019190915260c8606082015261012c608082015261011590601e906005610340565b506023805460ff1916905561012c60245561271060255534801561013857600080fd5b50604051614f54380380614f54833981016040819052610157916103b5565b836001600160a01b03811661018757604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6101908161022d565b50600180805530600090815260286020526040808220805460ff199081168517909155338352912080549091169091179055600580546001600160a01b03199081166001600160a01b038a811691909117909255600680548216898416179055600880548216888416179055600980548216868416179055600480549091169184169190911790556102218161027d565b5050505050505061043b565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b038116156102f6576000816001600160a01b03163b116102f65760405162461bcd60e51b815260206004820152602760248201527f53435241505045523a206f6c642077617474657273206973206e6f74206120636044820152661bdb9d1c9858dd60ca1b606482015260840161017e565b602a80546001600160a01b0319166001600160a01b0383169081179091556040517fe3f7150b52186c27ea5f8be66066e93eb3c75d03a4eddc0492845dfb0ffb9e4d90600090a250565b8260058101928215610374579160200282015b82811115610374578251829061ffff16905591602001919060010190610353565b50610380929150610384565b5090565b5b808211156103805760008155600101610385565b80516001600160a01b03811681146103b057600080fd5b919050565b600080600080600080600060e0888a0312156103d057600080fd5b6103d988610399565b96506103e760208901610399565b95506103f560408901610399565b945061040360608901610399565b935061041160808901610399565b925061041f60a08901610399565b915061042d60c08901610399565b905092959891949750929550565b614b0a8061044a6000396000f3fe608060405234801561001057600080fd5b50600436106105255760003560e01c80638278ced1116102af578063ce9495a811610172578063f2fde38b116100d9578063f7a9003911610092578063f7a9003914610d3a578063fb9b8e0b14610d43578063fd4699ef14610d56578063fe6dcdba14610d69578063ff1ff69114610d7c578063ffa889d714610d8f57600080fd5b8063f2fde38b14610cd2578063f3007bc414610ce5578063f389522914610cf8578063f3eba47014610d0b578063f55ec83d14610d14578063f5887cdd14610d2757600080fd5b8063de061d661161012b578063de061d6614610c6a578063df3d653b14610c7d578063e1412f5c14610c86578063e3a4c98b14610c99578063e3be937714610cac578063f07b0bdd14610cbf57600080fd5b8063ce9495a814610c02578063ce965f6a14610c15578063cf16ab8414610c28578063d057c40314610c3b578063d4e8901614610c44578063dd49756e14610c5757600080fd5b8063a6139e2111610216578063c5899d89116101cf578063c5899d8914610ba4578063c833320f14610bb7578063cab896dc14610bc0578063cc7b51b814610bc9578063ccc8118014610bdc578063cd5a88f014610bef57600080fd5b8063a6139e2114610b2e578063aa50715c14610b41578063ab9e6d0014610b54578063b22af61814610b67578063b8da5aaa14610b70578063c03446ed14610b8357600080fd5b80638da5cb5b116102685780638da5cb5b14610aa45780638f370bf714610ab55780639025571514610ad857806391362da114610afb57806394ae196314610b08578063a60377bc14610b1b57600080fd5b80638278ced114610a26578063856a8ace14610a3957806387bb287014610a6c57806389e4b57214610a7f5780638a1b8c7314610a885780638cc80c2914610a9b57600080fd5b80634dd1a487116103f7578063675d1a981161035e578063715018a611610317578063715018a6146109c9578063756e20c8146109d1578063766eee3c146109e45780637c68e834146109f75780637f17b79d14610a0057806380ed49ff14610a1357600080fd5b8063675d1a98146109615780636823d63d14610974578063688ea0671461098757806368ddc948146109905780636b6dcea0146109a35780636ed059ff146109b657600080fd5b80635b2923cb116103b05780635b2923cb146108a65780635d5a9706146108af5780635e3bbf16146108c25780635f4be765146108d55780636386c1c7146108e857806366ae33e51461094e57600080fd5b80634dd1a487146108105780634f1bf112146108235780634fb3d3b11461082c5780634fe01d3814610877578063561553cb1461088a5780635a6ade681461089d57600080fd5b806312261ee71161049b57806337c1d1201161045457806337c1d120146107a95780633ccdbb28146107bc57806344bd8537146107cf57806348c54b9d146107e25780634c643d2d146107ea5780634d750f54146107fd57600080fd5b806312261ee71461067b5780631377f1f81461068e5780631959a002146106a15780633552a65f14610750578063359853111461076357806335fc809b1461079657600080fd5b80630b3d0887116104ed5780630b3d0887146105b6578063100cd71d146105bf578063101ec30a1461062f578063102f9f57146106425780631170f88a1461065557806311e0f7441461066857600080fd5b8063018067671461052a57806303b5b9eb14610550578063081291f8146105655780630881fa0d146105785780630b3448a8146105a3575b600080fd5b61053d6105383660046140e3565b610da2565b6040519081526020015b60405180910390f35b61056361055e366004614234565b610de5565b005b61053d610573366004614297565b610f14565b600a5461058b906001600160a01b031681565b6040516001600160a01b039091168152602001610547565b6105636105b13660046140e3565b610f35565b61053d60155481565b6106026105cd3660046140e3565b602760205260009081526040902080546001820154600283015460038401546004850154600590950154939492939192909186565b604080519687526020870195909552938501929092526060840152608083015260a082015260c001610547565b61056361063d3660046140e3565b610f5f565b6105636106503660046142be565b610f89565b6105636106633660046140e3565b610fbc565b6105636106763660046142f7565b610fe6565b600b5461058b906001600160a01b031681565b60075461058b906001600160a01b031681565b6107036106af3660046140e3565b6026602052600090815260409020805460018201546002830154600384015460048501546005860154600687015460078801546008909801549697959694959394929391929091906001600160a01b031689565b60408051998a5260208a0198909852968801959095526060870193909352608086019190915260a085015260c084015260e08301526001600160a01b031661010082015261012001610547565b61056361075e366004614297565b610ff9565b6107766107713660046140e3565b61107d565b604080519485526020850193909352918301526060820152608001610547565b6105636107a4366004614234565b6110c6565b6105636107b7366004614319565b6112d6565b6105636107ca366004614395565b61139e565b60035461058b906001600160a01b031681565b61056361141f565b6105636107f8366004614297565b611996565b61053d61080b366004614297565b611a35565b61056361081e366004614297565b611a4c565b61053d60165481565b61060261083a3660046140e3565b6001600160a01b03166000908152602760205260409020805460018201546002830154600384015460048501546005909501549395929491939092565b610563610885366004614297565b611aa9565b6105636108983660046143d7565b611b9e565b61053d600c5481565b61053d600f5481565b6105636108bd366004614297565b611bcc565b6105636108d036600461442c565b611c49565b6105636108e33660046140e3565b611fb3565b6108fb6108f63660046140e3565b612078565b604080519b8c5260208c019a909a52988a01979097526060890195909552608088019390935260a087019190915260c086015260e085015261010084015261012083015261014082015261016001610547565b61053d61095c3660046140e3565b61214f565b61056361096f366004614319565b6122ac565b61056361098236600461449e565b6122db565b61053d60175481565b61056361099e3660046144d0565b6122f7565b6105636109b13660046140e3565b6124bb565b60055461058b906001600160a01b031681565b610563612547565b6105636109df366004614297565b612559565b6105636109f2366004614297565b6125d6565b61053d60135481565b610563610a0e366004614297565b612641565b61053d610a2136600461450b565b61266e565b61053d610a343660046140e3565b6126a4565b610a5c610a473660046140e3565b60286020526000908152604090205460ff1681565b6040519015158152602001610547565b610563610a7a36600461442c565b61275d565b61053d60255481565b610563610a96366004614234565b612a56565b61053d60115481565b6000546001600160a01b031661058b565b610a5c610ac33660046140e3565b602b6020526000908152604090205460ff1681565b610a5c610ae63660046140e3565b60296020526000908152604090205460ff1681565b602354610a5c9060ff1681565b60065461058b906001600160a01b031681565b610563610b29366004614297565b612c58565b602a5461058b906001600160a01b031681565b610563610b4f36600461442c565b612cb5565b61053d610b623660046140e3565b612e7a565b61053d60245481565b610563610b7e366004614537565b612f4d565b610b96610b913660046140e3565b612ffc565b604051610547929190614572565b610563610bb23660046140e3565b61316b565b61053d60185481565b61053d60145481565b610563610bd7366004614297565b613195565b610563610bea36600461442c565b6131f2565b610563610bfd366004614297565b6133b7565b610563610c103660046140e3565b613414565b610563610c233660046140e3565b6134a2565b61053d610c363660046140e3565b61353a565b61053d60125481565b60045461058b906001600160a01b031681565b610563610c65366004614297565b613576565b60085461058b906001600160a01b031681565b61053d600e5481565b610563610c943660046140e3565b613672565b610563610ca73660046140e3565b613705565b610563610cba366004614297565b613716565b610563610ccd3660046140e3565b613793565b610563610ce03660046140e3565b6137bd565b610563610cf336600461450b565b6137f8565b61053d610d0636600461450b565b613835565b61053d60105481565b610563610d22366004614611565b613863565b60025461058b906001600160a01b031681565b61053d600d5481565b610563610d51366004614537565b6138db565b610563610d64366004614666565b61398a565b60095461058b906001600160a01b031681565b610563610d8a3660046142be565b6139a5565b61053d610d9d366004614297565b613a62565b6001600160a01b03811660009081526026602052604081206004810154610dd190671bc16d674ec80000614699565b601154610dde91906146b0565b9392505050565b6007548451516001600160a01b03908116911614610e1e5760405162461bcd60e51b8152600401610e15906146c3565b60405180910390fd5b60135483602001351015610e445760405162461bcd60e51b8152600401610e15906146f2565b30610e5260208501856140e3565b6001600160a01b031614610e785760405162461bcd60e51b8152600401610e1590614722565b600b5460405163187945bd60e11b81526001600160a01b03909116906330f28b7a90610eb09087908790339088908890600401614782565b600060405180830381600087803b158015610eca57600080fd5b505af1158015610ede573d6000803e3d6000fd5b5050336000908152602660209081526040822060060180549188013594509250610f099084906146b0565b909155505050505050565b6000610f22826103e8614699565b602554610f2f91906146b0565b92915050565b610f3d613a72565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b610f67613a72565b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b610f91613a72565b6001600160a01b03919091166000908152602960205260409020805460ff1916911515919091179055565b610fc4613a72565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b610fee613a72565b601591909155601655565b611001613a72565b600081116110215760405162461bcd60e51b8152600401610e1590614800565b601081905560408051818152600691810191909152651c995dd85c9960d21b6060820152602081018290527f29ad052c83eced1add047469cec21e12106cd7d582514af563dff3c13c3c6fcb906080015b60405180910390a150565b60008060008061108c85610da2565b93506110978561353a565b6001600160a01b0390951660009081526026602052604090206004810154600590910154949690949350915050565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561111b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113f9190614846565b8551519091506001600160a01b0380831691161461116f5760405162461bcd60e51b8152600401610e15906146c3565b600061117a3361353a565b90508085602001351461119f5760405162461bcd60e51b8152600401610e15906146f2565b306111ad60208701876140e3565b6001600160a01b0316146111d35760405162461bcd60e51b8152600401610e1590614722565b600b5460405163187945bd60e11b81526001600160a01b03909116906330f28b7a9061120b908990899033908a908a90600401614782565b600060405180830381600087803b15801561122557600080fd5b505af1158015611239573d6000803e3d6000fd5b505033600090815260266020908152604080832060279092528220600582018054929550909350909161126b83614863565b919050555080600501548260050154111561128b57600580830154908201555b6005820154604080519182526020820185905233917fd1592e47e5c70e05dc194c5c7040fd885ad47699bb0c05726c246908d754e8f991015b60405180910390a25050505050505050565b6112de613a72565b6001600160a01b0388811660008181526026602090815260408083208c8155600181018c9055600481018b9055600581018a9055600681018990556008810180546001600160a01b031916968816969096179095556029825291829020805460ff191687151517905581518b81529081018a905290810188905260608101879052608081018690527f62a5a2fe4f6668cbc7f8685336c7afac94df357a5ed1180f6515cbe23f3ea2579060a00160405180910390a2505050505050505050565b6113a6613a72565b60405163a9059cbb60e01b81526001600160a01b0382811660048301526024820184905284169063a9059cbb906044016020604051808303816000875af11580156113f5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611419919061487c565b50505050565b611427613a9f565b600254604051632bc91fed60e01b81523360048201526001600160a01b0390911690632bc91fed90602401602060405180830381865afa15801561146f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114939190614899565b6000036114f9573360009081526029602052604090205460ff166114f95760405162461bcd60e51b815260206004820152601a60248201527f53435241505045523a2075736572206e6f742070617961626c650000000000006044820152606401610e15565b6003546001600160a01b03161561159e57600354604051636b8ab97d60e01b81523360048201526000918291829182916001600160a01b0390911690636b8ab97d90602401608060405180830381865afa15801561155b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157f91906148b2565b9350935093509350831561159957611599338484846122f7565b505050505b336000908152602660205260408120600281015490910361160457601580549060006115c983614863565b90915550506013546115dc906032614699565b33600090815260266020526040812060060180549091906115fe9084906146b0565b90915550505b33600090815260276020526040902060235460ff1680156116465750600554336000908152602660205260409020600801546001600160a01b03908116911614155b156116da576013543360009081526026602052604090206006015410156116af5760405162461bcd60e51b815260206004820152601a60248201527f53435241505045523a206e6f7420656e6f7567682077617465720000000000006044820152606401610e15565b60135433600090815260266020526040812060060180549091906116d49084906148f1565b90915550505b60006116e5336126a4565b9050600081116117375760405162461bcd60e51b815260206004820152601c60248201527f53435241505045523a206e6f20746f6b656e7320746f20636c61696d000000006044820152606401610e15565b4260028401556000600384018190556001830180549161175683614863565b91905055508082600201600082825461176f91906146b0565b9091555050600883015460405163a9059cbb60e01b8152336004820152602481018390526001600160a01b039091169063a9059cbb906044016020604051808303816000875af11580156117c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117eb919061487c565b6118335760405162461bcd60e51b815260206004820152601960248201527814d0d490541411548e881d1c985b9cd9995c8819985a5b1959603a1b6044820152606401610e15565b600061184666038d7ea4c6800083614904565b600a549091506001600160a01b0316156118e357600a546040516348b68a8360e01b81523360048201526000916001600160a01b0316906348b68a8390602401602060405180830381865afa1580156118a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118c79190614899565b905060646118d58284614699565b6118df9190614904565b9150505b60048054604051633cc01ef160e21b81523392810192909252602482018390526001600160a01b03169063f3007bc490604401600060405180830381600087803b15801561193057600080fd5b505af1158015611944573d6000803e3d6000fd5b505050506119523382613ac9565b60405182815233907f896e034966eaaf1adc54acc0f257056febbd300c9e47182cf761982cf1f5e4309060200160405180910390a25050505061199460018055565b565b61199e613a72565b60008111611a005760405162461bcd60e51b815260206004820152602960248201527f53435241505045523a206261736520657870206d75737420626520677265617460448201526806572207468616e20360bc1b6064820152608401610e15565b60258190556040518181527f26548f2b23ea646ad626dd81529baa1a81a4683eb7b67a49e7b3a887be430b5c90602001611072565b60198160058110611a4557600080fd5b0154905081565b611a54613a72565b60008111611a745760405162461bcd60e51b8152600401610e1590614926565b600c8190556040518181527f98c9cae42cac91fe8b116dbf81fe47e6b53fd49a362fb687d7ad4aa3114a7ce490602001611072565b611ab233613c64565b15611aba5750565b336000908152602660205260409020600801546001600160a01b031615611b235760405162461bcd60e51b815260206004820152601b60248201527f53435241505045523a20746f6b656e20616c72656164792073657400000000006044820152606401610e15565b80600003611b605760055433600090815260266020526040902060080180546001600160a01b0319166001600160a01b0390921691909117905550565b80600103611b9b5760065433600090815260266020526040902060080180546001600160a01b0319166001600160a01b039092169190911790555b50565b611ba6613a72565b600f97909755601095909555601193909355601291909155601355601455601755601855565b611bd4613a72565b60008111611bf45760405162461bcd60e51b8152600401610e1590614800565b601281905560408051818152600691810191909152651c995dd85c9960d21b6060820152602081018290527f310e1fe600a49018325c99539d47d1a4344d82ebe96e85b8060994c43720131590608001611072565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cc29190614846565b8551519091506001600160a01b0390811690821603611e3c576004805460408051637e062a3560e11b815290516001600160a01b039092169263fc0c546a9282820192602092908290030181865afa158015611d22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d469190614846565b8551516001600160a01b03908116911614611d735760405162461bcd60e51b8152600401610e15906146c3565b60185484602001351015611d995760405162461bcd60e51b8152600401610e15906146f2565b30611da760208601866140e3565b6001600160a01b031614611dcd5760405162461bcd60e51b8152600401610e1590614722565b600b5460405163187945bd60e11b81526001600160a01b03909116906330f28b7a90611e059088908890339089908990600401614782565b600060405180830381600087803b158015611e1f57600080fd5b505af1158015611e33573d6000803e3d6000fd5b50505050611f31565b6008548551516001600160a01b03908116911614611e6c5760405162461bcd60e51b8152600401610e15906146c3565b60175484602001351015611e925760405162461bcd60e51b8152600401610e15906146f2565b30611ea060208601866140e3565b6001600160a01b031614611ec65760405162461bcd60e51b8152600401610e1590614722565b600b5460405163187945bd60e11b81526001600160a01b03909116906330f28b7a90611efe9088908890339089908990600401614782565b600060405180830381600087803b158015611f1857600080fd5b505af1158015611f2c573d6000803e3d6000fd5b505050505b85600003611f705760055433600090815260266020526040902060080180546001600160a01b0319166001600160a01b03909216919091179055611fab565b85600103611fab5760065433600090815260266020526040902060080180546001600160a01b0319166001600160a01b039092169190911790555b505050505050565b611fbb613a72565b6001600160a01b03811661202f5760405162461bcd60e51b815260206004820152603560248201527f53435241505045523a20696e76616c6964207265736574206163636f756e74206044820152746c766c7320636f6e7472616374206164647265737360581b6064820152608401610e15565b600380546001600160a01b0319166001600160a01b03831690811790915515611b9b576001600160a01b0381166000908152602860205260409020805460ff1916600117905550565b6001600160a01b0381166000908152602660205260408120805460018201546002830154600384015492949193909291908190819081908190819081906120be8d6126a4565b975080600401549550806005015494506120d78d61214f565b93506120e28d612e7a565b6006820154600283015491945092501561213357600081600201544261210891906148f1565b905060006121158f61214f565b90508082101561212c5761212982826148f1565b98505b505061213f565b61213c8d61214f565b96505b5091939597999b90929496989a50565b6001600160a01b0381166000908152602660205260408120600e546004820154839161217a91614699565b60245461218791906146b0565b600a549091506001600160a01b031615610dde57600a546040516387bf0cef60e01b81526001600160a01b03868116600483015260009216906387bf0cef90602401602060405180830381865afa1580156121e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061220a9190614899565b905060646122188284614699565b6122229190614904565b600a54604051631ac2b45760e11b81526001600160a01b0388811660048301529294506000929091169063358568ae90602401602060405180830381865afa158015612272573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122969190614899565b90506122a281846146b0565b9695505050505050565b3360009081526028602052604090205460ff166112de5760405162461bcd60e51b8152600401610e159061496d565b6122e3613a72565b600c93909355600d91909155602455600e55565b3360009081526028602052604090205460ff166123265760405162461bcd60e51b8152600401610e159061496d565b6001600160a01b0384166000908152602660205260408120600181018590558181556004810184905560058101839055600781018054919261236783614863565b90915550506009546001600160a01b0316156123e95760095460018201546040516319765dc960e21b81526001600160a01b03888116600483015260248201929092529116906365d9772490604401600060405180830381600087803b1580156123d057600080fd5b505af11580156123e4573d6000803e3d6000fd5b505050505b6003546001600160a01b03161561245a57600354604051630fd11cf960e21b81526001600160a01b03878116600483015290911690633f4473e490602401600060405180830381600087803b15801561244157600080fd5b505af1158015612455573d6000803e3d6000fd5b505050505b6040805160008082526020820187905281830186905260608201859052608082015290516001600160a01b038716917f62a5a2fe4f6668cbc7f8685336c7afac94df357a5ed1180f6515cbe23f3ea257919081900360a00190a25050505050565b6124c3613a72565b6001600160a01b0381166125255760405162461bcd60e51b8152602060048201526024808201527f53435241505045523a20696e76616c69642069726f6e20746f6b656e206164646044820152637265737360e01b6064820152608401610e15565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b61254f613a72565b6119946000613eab565b612561613a72565b600081116125815760405162461bcd60e51b8152600401610e1590614800565b6011819055604080518181526006918101919091526574696d696e6760d01b6060820152602081018290527f310e1fe600a49018325c99539d47d1a4344d82ebe96e85b8060994c43720131590608001611072565b6125de613a72565b6000811161263c5760405162461bcd60e51b815260206004820152602560248201527f53435241505045523a20636f7374206d75737420626520677265617465722074604482015264068616e20360dc1b6064820152608401610e15565b601355565b612649613a72565b600081116126695760405162461bcd60e51b8152600401610e1590614800565b601455565b6001600160a01b03821660009081526026602052604081206004810154600f5461269c919085906019613efb565b949350505050565b6001600160a01b0381166000908152602660205260408120600281015482036127005760006126d28461214f565b90506000603c6126e186612e7a565b6126eb9190614904565b90506126f78282614699565b95945050505050565b600081600201544261271291906148f1565b9050600061271f8561214f565b90508082111561272d578091505b6000603c61273a87612e7a565b6127449190614904565b905060006127528483614699565b979650505050505050565b61276633613c64565b1561285357600b5460405163187945bd60e11b81526001600160a01b03909116906330f28b7a906127a39087908790339088908890600401614782565b600060405180830381600087803b1580156127bd57600080fd5b505af11580156127d1573d6000803e3d6000fd5b505060085460405163a9059cbb60e01b8152336004820152602087013560248201526001600160a01b03909116925063a9059cbb91506044016020604051808303816000875af1158015612829573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061284d919061487c565b50612a4f565b6008548451516001600160a01b039081169116146128835760405162461bcd60e51b8152600401610e15906146c3565b601454836020013510156128a95760405162461bcd60e51b8152600401610e15906146f2565b306128b760208501856140e3565b6001600160a01b0316146128dd5760405162461bcd60e51b8152600401610e1590614722565b3360009081526029602052604090205460ff161561293d5760405162461bcd60e51b815260206004820152601a60248201527f53435241505045523a2075736572206e6f742070617961626c650000000000006044820152606401610e15565b600b5460405163187945bd60e11b81526001600160a01b03909116906330f28b7a906129759087908790339088908890600401614782565b600060405180830381600087803b15801561298f57600080fd5b505af11580156129a3573d6000803e3d6000fd5b5050336000908152602960205260408120805460ff1916600117905560168054935091506129d083614863565b919050555084600003612a145760055433600090815260266020526040902060080180546001600160a01b0319166001600160a01b03909216919091179055612a4f565b84600103612a4f5760065433600090815260266020526040902060080180546001600160a01b0319166001600160a01b039092169190911790555b5050505050565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612aab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612acf9190614846565b8551519091506001600160a01b03808316911614612aff5760405162461bcd60e51b8152600401610e15906146c3565b6000612b0a33610da2565b905080856020013514612b2f5760405162461bcd60e51b8152600401610e15906146f2565b30612b3d60208701876140e3565b6001600160a01b031614612b635760405162461bcd60e51b8152600401610e1590614722565b600b5460405163187945bd60e11b81526001600160a01b03909116906330f28b7a90612b9b908990899033908a908a90600401614782565b600060405180830381600087803b158015612bb557600080fd5b505af1158015612bc9573d6000803e3d6000fd5b5050336000908152602660209081526040808320602790925282206004820180549295509093509091612bfb83614863565b9190505550806004015482600401541115612c1b57600480830154908201555b6004820154604080519182526020820185905233917f0254bd7f1019b14fcab90b0148b4f296c3496c5b450e62b0c86a54e2c3bbb09e91016112c4565b612c60613a72565b60008111612c805760405162461bcd60e51b8152600401610e15906149a4565b60248190556040518181527f8374fea52feb3243e01ea7f5abbef3818ab814eee35c22f9fc4e960390057a3990602001611072565b60008511612cd55760405162461bcd60e51b8152600401610e15906149e9565b6008548451516001600160a01b03908116911614612d055760405162461bcd60e51b8152600401610e15906146c3565b6000612d113387613835565b905080846020013514612d365760405162461bcd60e51b8152600401610e15906146f2565b30612d4460208601866140e3565b6001600160a01b031614612d6a5760405162461bcd60e51b8152600401610e1590614722565b600b5460405163187945bd60e11b81526001600160a01b03909116906330f28b7a90612da29088908890339089908990600401614782565b600060405180830381600087803b158015612dbc57600080fd5b505af1158015612dd0573d6000803e3d6000fd5b5050336000908152602660209081526040808320602790925282206005820180549295509093508a929091612e069084906146b0565b9250508190555082816003016000828254612e2191906146b0565b909155505060058082015490830154111561128b57600582810154908201819055604080519182526020820185905233917fd1592e47e5c70e05dc194c5c7040fd885ad47699bb0c05726c246908d754e8f991016112c4565b6001600160a01b0381166000908152602660205260408120600d5460058201548391612ea591614699565b600c54612eb291906146b0565b600a549091506001600160a01b031615610dde57600a54604051636112918960e11b81526001600160a01b038681166004830152600092169063c225231290602401602060405180830381865afa158015612f11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f359190614899565b90506064612f438284614699565b6126f79190614904565b612f55613a72565b8385108015612f6357508284105b8015612f6e57508183105b8015612f7957508082105b612fc55760405162461bcd60e51b815260206004820152601d60248201527f53435241505045523a20696e76616c696420627265616b706f696e74730000006044820152606401610e15565b6040518060a0016040528086815260200185815260200184815260200183815260200182815250601e906005611fab92919061407b565b613054604051806101200160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b031681525090565b61308d6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b50506001600160a01b03908116600090815260266020908152604080832060278352928190208151610120810183528454815260018086015482860152600280870154838601526003808801546060808601919091526004808a01546080808801919091526005808c015460a0808a019190915260068d015460c0808b019190915260078e015460e08b01526008909d0154909d1661010089015289519b8c018a5288548c5295880154998b019990995292860154968901969096528401549487019490945292820154938501939093520154928201929092529091565b613173613a72565b600980546001600160a01b0319166001600160a01b0392909216919091179055565b61319d613a72565b600081116131bd5760405162461bcd60e51b8152600401610e15906149a4565b600e8190556040518181527fa961c327f1a097745a50fa81e168a0ed6f7b6183e456d13468d1e0c566dc753290602001611072565b600085116132125760405162461bcd60e51b8152600401610e15906149e9565b6008548451516001600160a01b039081169116146132425760405162461bcd60e51b8152600401610e15906146c3565b600061324e338761266e565b9050808460200135146132735760405162461bcd60e51b8152600401610e15906146f2565b3061328160208601866140e3565b6001600160a01b0316146132a75760405162461bcd60e51b8152600401610e1590614722565b600b5460405163187945bd60e11b81526001600160a01b03909116906330f28b7a906132df9088908890339089908990600401614782565b600060405180830381600087803b1580156132f957600080fd5b505af115801561330d573d6000803e3d6000fd5b5050336000908152602660209081526040808320602790925282206004820180549295509093508a9290916133439084906146b0565b925050819055508281600301600082825461335e91906146b0565b9091555050600480820154908301541115612c1b57600482810154908201819055604080519182526020820185905233917f0254bd7f1019b14fcab90b0148b4f296c3496c5b450e62b0c86a54e2c3bbb09e91016112c4565b6133bf613a72565b600081116133df5760405162461bcd60e51b8152600401610e1590614926565b600d8190556040518181527f2e15bdb347d81abad94e6c10ea0fed9380a0944344a3efa9bdf0b494784d418490602001611072565b61341c613a72565b6001600160a01b0381166134805760405162461bcd60e51b815260206004820152602560248201527f53435241505045523a20696e76616c696420776174657220746f6b656e206164604482015264647265737360d81b6064820152608401610e15565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b6134aa613a72565b6001600160a01b0381166135005760405162461bcd60e51b815260206004820152601e60248201527f53435241505045523a20696e76616c69642073686f70206164647265737300006044820152606401610e15565b600a80546001600160a01b039092166001600160a01b0319909216821790556000908152602860205260409020805460ff19166001179055565b6001600160a01b0381166000908152602660205260408120600581015461356990671bc16d674ec80000614699565b601254610dde91906146b0565b61357e613a72565b6000811161359e5760405162461bcd60e51b8152600401610e15906149e9565b33600081815260266020526040908190206008015490516323b872dd60e01b81526004810192909252306024830152604482018390526001600160a01b0316906323b872dd906064016020604051808303816000875af1158015613606573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061362a919061487c565b611b9b5760405162461bcd60e51b815260206004820152601960248201527814d0d490541411548e881d1c985b9cd9995c8819985a5b1959603a1b6044820152606401610e15565b61367a613a72565b6001600160a01b0381166136e35760405162461bcd60e51b815260206004820152602a60248201527f53435241505045523a20696e76616c69642065787065646974696f6e20746f6b604482015269656e206164647265737360b01b6064820152608401610e15565b600780546001600160a01b0319166001600160a01b0392909216919091179055565b61370d613a72565b611b9b81613f49565b61371e613a72565b6000811161373e5760405162461bcd60e51b8152600401610e1590614800565b600f819055604080518181526006918101919091526574696d696e6760d01b6060820152602081018290527f29ad052c83eced1add047469cec21e12106cd7d582514af563dff3c13c3c6fcb90608001611072565b61379b613a72565b600880546001600160a01b0319166001600160a01b0392909216919091179055565b6137c5613a72565b6001600160a01b0381166137ef57604051631e4fbdf760e01b815260006004820152602401610e15565b611b9b81613eab565b3360009081526028602052604090205460ff166138275760405162461bcd60e51b8152600401610e159061496d565b6138318282613ac9565b5050565b6001600160a01b0382166000908152602660205260408120600581015460105461269c91908590601e613efb565b61386b613a72565b6040805160c0810182529687526020808801968752878201958652606088019485526080880193845260a088019283526001600160a01b03909816600090815260279098529096209451855592516001850155905160028401555160038301555160048201559051600590910155565b6138e3613a72565b83851080156138f157508284105b80156138fc57508183105b801561390757508082105b6139535760405162461bcd60e51b815260206004820152601d60248201527f53435241505045523a20696e76616c696420627265616b706f696e74730000006044820152606401610e15565b6040518060a00160405280868152602001858152602001848152602001838152602001828152506019906005611fab92919061407b565b613992613a72565b6023805460ff1916911515919091179055565b6139ad613a72565b6001600160a01b038216613a035760405162461bcd60e51b815260206004820181905260248201527f53435241505045523a20696e76616c69642063616c6c657220616464726573736044820152606401610e15565b6001600160a01b038216600081815260286020908152604091829020805460ff191685151590811790915591519182527fa80c7c27007dcd99579e4e6253b6c5f461990e3df534d6d7e948776d7eccb109910160405180910390a25050565b601e8160058110611a4557600080fd5b6000546001600160a01b031633146119945760405163118cdaa760e01b8152336004820152602401610e15565b600260015403613ac257604051633ee5aeb560e01b815260040160405180910390fd5b6002600155565b6001600160a01b03821660009081526026602090815260408083206027909252822081549192909184918491613b009084906146b0565b90915550600090505b613b168360010154610f14565b835410613bc6576000613b2c8460010154610f14565b905080846000016000828254613b4291906148f1565b9091555050600184018054906000613b5983614863565b9091555050825460018501541115613b7357600184015483555b600184015460408051918252602082018390526001600160a01b038816917feec61667dd6eeecdccfef3c906e0fd047cca672804901ac4254d8545e9a426d4910160405180910390a26001915050613b09565b60008360010154118015613bd75750805b8015613bed57506009546001600160a01b031615155b15612a4f5760095460018401546040516319765dc960e21b81526001600160a01b03888116600483015260248201929092529116906365d9772490604401600060405180830381600087803b158015613c4557600080fd5b505af1158015613c59573d6000803e3d6000fd5b505050505050505050565b602a546000906001600160a01b0316613c7f57506000919050565b6001600160a01b0382166000908152602b602052604090205460ff1615613ca857506000919050565b602a54604051630cacd00160e11b81526001600160a01b0384811660048301526000928392839283928392839283928392839290911690631959a0029060240161012060405180830381865afa158015613d06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d2a9190614a30565b98509850985098509850985098509850985086600003613d55575060009a9950505050505050505050565b6001600160a01b038b8116600081815260266020526040908190208c8155600181018c9055600281018b9055600381018a905560048082018a90556005820189905560068201889055600782018790556008820180546001600160a01b031916878716179055602a549251639025571560e01b815290810193909352921690639025571590602401602060405180830381865afa158015613dfa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e1e919061487c565b602960008e6001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff0219169083151502179055506001602b60008e6001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060019a5050505050505050505050919050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060015b848111613f40576000613f1382886146b0565b9050613f2081868661400c565b613f2a90846146b0565b9250508080613f3890614863565b915050613f00565b50949350505050565b6001600160a01b03811615613fc2576000816001600160a01b03163b11613fc25760405162461bcd60e51b815260206004820152602760248201527f53435241505045523a206f6c642077617474657273206973206e6f74206120636044820152661bdb9d1c9858dd60ca1b6064820152608401610e15565b602a80546001600160a01b0319166001600160a01b0383169081179091556040517fe3f7150b52186c27ea5f8be66066e93eb3c75d03a4eddc0492845dfb0ffb9e4d90600090a250565b60008082810154851161402157506001614071565b8260010154851161403457506002614071565b8260020154851161404757506004614071565b8260030154851161405a57506008614071565b8260040154851161406d57506010614071565b5060105b6126f78185614699565b82600581019282156140a9579160200282015b828111156140a957825182559160200191906001019061408e565b506140b59291506140b9565b5090565b5b808211156140b557600081556001016140ba565b6001600160a01b0381168114611b9b57600080fd5b6000602082840312156140f557600080fd5b8135610dde816140ce565b6040805190810167ffffffffffffffff8111828210171561413157634e487b7160e01b600052604160045260246000fd5b60405290565b6000818303608081121561414a57600080fd5b6040516060810167ffffffffffffffff8111828210171561417b57634e487b7160e01b600052604160045260246000fd5b8060405250809250604082121561419157600080fd5b614199614100565b915083356141a6816140ce565b82526020848101358184015291815260408085013592820192909252606090930135920191909152919050565b6000604082840312156141e557600080fd5b50919050565b60008083601f8401126141fd57600080fd5b50813567ffffffffffffffff81111561421557600080fd5b60208301915083602082850101111561422d57600080fd5b9250929050565b60008060008060e0858703121561424a57600080fd5b6142548686614137565b935061426386608087016141d3565b925060c085013567ffffffffffffffff81111561427f57600080fd5b61428b878288016141eb565b95989497509550505050565b6000602082840312156142a957600080fd5b5035919050565b8015158114611b9b57600080fd5b600080604083850312156142d157600080fd5b82356142dc816140ce565b915060208301356142ec816142b0565b809150509250929050565b6000806040838503121561430a57600080fd5b50508035926020909101359150565b600080600080600080600080610100898b03121561433657600080fd5b8835614341816140ce565b97506020890135965060408901359550606089013594506080890135935060a0890135925060c0890135614374816142b0565b915060e0890135614384816140ce565b809150509295985092959890939650565b6000806000606084860312156143aa57600080fd5b83356143b5816140ce565b92506020840135915060408401356143cc816140ce565b809150509250925092565b600080600080600080600080610100898b0312156143f457600080fd5b505086359860208801359850604088013597606081013597506080810135965060a0810135955060c0810135945060e0013592509050565b6000806000806000610100868803121561444557600080fd5b853594506144568760208801614137565b93506144658760a088016141d3565b925060e086013567ffffffffffffffff81111561448157600080fd5b61448d888289016141eb565b969995985093965092949392505050565b600080600080608085870312156144b457600080fd5b5050823594602084013594506040840135936060013592509050565b600080600080608085870312156144e657600080fd5b84356144f1816140ce565b966020860135965060408601359560600135945092505050565b6000806040838503121561451e57600080fd5b8235614529816140ce565b946020939093013593505050565b600080600080600060a0868803121561454f57600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b825181526020808401518183015260408085015181840152606080860151818501526080808701518186015260a0808801518187015260c0808901519087015260e08089015190870152610100808901516001600160a01b031690870152865161012087015293860151610140860152918501516101608501528401516101808401528301516101a08301528201516101c08201526101e08101610dde565b600080600080600080600060e0888a03121561462c57600080fd5b8735614637816140ce565b9960208901359950604089013598606081013598506080810135975060a0810135965060c00135945092505050565b60006020828403121561467857600080fd5b8135610dde816142b0565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610f2f57610f2f614683565b80820180821115610f2f57610f2f614683565b60208082526015908201527429a1a920a82822a91d103bb937b733903a37b5b2b760591b604082015260600190565b60208082526016908201527514d0d490541411548e881ddc9bdb99c8185b5bdd5b9d60521b604082015260600190565b60208082526019908201527f53435241505045523a2077726f6e6720726563697069656e7400000000000000604082015260600190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b855180516001600160a01b03168252602090810151818301528601516040808301919091528601516060820152600085356147bc816140ce565b6001600160a01b03166080830152602086013560a08301526147e960c08301866001600160a01b03169052565b61010060e083015261275261010083018486614759565b60208082526026908201527f53435241505045523a207072696365206d75737420626520677265617465722060408201526507468616e20360d41b606082015260800190565b60006020828403121561485857600080fd5b8151610dde816140ce565b60006001820161487557614875614683565b5060010190565b60006020828403121561488e57600080fd5b8151610dde816142b0565b6000602082840312156148ab57600080fd5b5051919050565b600080600080608085870312156148c857600080fd5b84516148d3816142b0565b60208601516040870151606090970151919890975090945092505050565b81810381811115610f2f57610f2f614683565b60008261492157634e487b7160e01b600052601260045260246000fd5b500490565b60208082526027908201527f53435241505045523a20726577617264206d75737420626520677265617465726040820152660207468616e20360cc1b606082015260800190565b60208082526018908201527f53435241505045523a206e6f7420617574686f72697a65640000000000000000604082015260600190565b60208082526025908201527f53435241505045523a2074696d65206d75737420626520677265617465722074604082015264068616e20360dc1b606082015260800190565b60208082526027908201527f53435241505045523a20616d6f756e74206d75737420626520677265617465726040820152660207468616e20360cc1b606082015260800190565b60008060008060008060008060006101208a8c031215614a4f57600080fd5b60008a51905080995050600060208b0151905080985050600060408b0151905080975050600060608b0151905080965050600060808b0151905080955050600060a08b0151905080945050600060c08b0151905080935050600060e08b01519050809250506101008a0151614ac3816140ce565b80915050929598509295985092959856fea2646970667358221220f43508984c3173a2ae8ee38755e165d3334a4848c587e9d31bf2f17b653f423164736f6c634300081c003300000000000000000000000083a5b1c92d4b45db257d0e42dd1f11a009f8492b0000000000000000000000005c1ed5039a0858a188d1df812bbad7790281b77f0000000000000000000000002cfc85d8e48f8eab294be644d9e25c3030863003000000000000000000000000999561c6c239c9ef660dfbe38cc2ce6bd0c2ecba0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fa62d60ba436cd287d45be7a36dbb97ba150b0330000000000000000000000005e913ee579a68503dfdce85da3d1e3cbfc4365cd

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106105255760003560e01c80638278ced1116102af578063ce9495a811610172578063f2fde38b116100d9578063f7a9003911610092578063f7a9003914610d3a578063fb9b8e0b14610d43578063fd4699ef14610d56578063fe6dcdba14610d69578063ff1ff69114610d7c578063ffa889d714610d8f57600080fd5b8063f2fde38b14610cd2578063f3007bc414610ce5578063f389522914610cf8578063f3eba47014610d0b578063f55ec83d14610d14578063f5887cdd14610d2757600080fd5b8063de061d661161012b578063de061d6614610c6a578063df3d653b14610c7d578063e1412f5c14610c86578063e3a4c98b14610c99578063e3be937714610cac578063f07b0bdd14610cbf57600080fd5b8063ce9495a814610c02578063ce965f6a14610c15578063cf16ab8414610c28578063d057c40314610c3b578063d4e8901614610c44578063dd49756e14610c5757600080fd5b8063a6139e2111610216578063c5899d89116101cf578063c5899d8914610ba4578063c833320f14610bb7578063cab896dc14610bc0578063cc7b51b814610bc9578063ccc8118014610bdc578063cd5a88f014610bef57600080fd5b8063a6139e2114610b2e578063aa50715c14610b41578063ab9e6d0014610b54578063b22af61814610b67578063b8da5aaa14610b70578063c03446ed14610b8357600080fd5b80638da5cb5b116102685780638da5cb5b14610aa45780638f370bf714610ab55780639025571514610ad857806391362da114610afb57806394ae196314610b08578063a60377bc14610b1b57600080fd5b80638278ced114610a26578063856a8ace14610a3957806387bb287014610a6c57806389e4b57214610a7f5780638a1b8c7314610a885780638cc80c2914610a9b57600080fd5b80634dd1a487116103f7578063675d1a981161035e578063715018a611610317578063715018a6146109c9578063756e20c8146109d1578063766eee3c146109e45780637c68e834146109f75780637f17b79d14610a0057806380ed49ff14610a1357600080fd5b8063675d1a98146109615780636823d63d14610974578063688ea0671461098757806368ddc948146109905780636b6dcea0146109a35780636ed059ff146109b657600080fd5b80635b2923cb116103b05780635b2923cb146108a65780635d5a9706146108af5780635e3bbf16146108c25780635f4be765146108d55780636386c1c7146108e857806366ae33e51461094e57600080fd5b80634dd1a487146108105780634f1bf112146108235780634fb3d3b11461082c5780634fe01d3814610877578063561553cb1461088a5780635a6ade681461089d57600080fd5b806312261ee71161049b57806337c1d1201161045457806337c1d120146107a95780633ccdbb28146107bc57806344bd8537146107cf57806348c54b9d146107e25780634c643d2d146107ea5780634d750f54146107fd57600080fd5b806312261ee71461067b5780631377f1f81461068e5780631959a002146106a15780633552a65f14610750578063359853111461076357806335fc809b1461079657600080fd5b80630b3d0887116104ed5780630b3d0887146105b6578063100cd71d146105bf578063101ec30a1461062f578063102f9f57146106425780631170f88a1461065557806311e0f7441461066857600080fd5b8063018067671461052a57806303b5b9eb14610550578063081291f8146105655780630881fa0d146105785780630b3448a8146105a3575b600080fd5b61053d6105383660046140e3565b610da2565b6040519081526020015b60405180910390f35b61056361055e366004614234565b610de5565b005b61053d610573366004614297565b610f14565b600a5461058b906001600160a01b031681565b6040516001600160a01b039091168152602001610547565b6105636105b13660046140e3565b610f35565b61053d60155481565b6106026105cd3660046140e3565b602760205260009081526040902080546001820154600283015460038401546004850154600590950154939492939192909186565b604080519687526020870195909552938501929092526060840152608083015260a082015260c001610547565b61056361063d3660046140e3565b610f5f565b6105636106503660046142be565b610f89565b6105636106633660046140e3565b610fbc565b6105636106763660046142f7565b610fe6565b600b5461058b906001600160a01b031681565b60075461058b906001600160a01b031681565b6107036106af3660046140e3565b6026602052600090815260409020805460018201546002830154600384015460048501546005860154600687015460078801546008909801549697959694959394929391929091906001600160a01b031689565b60408051998a5260208a0198909852968801959095526060870193909352608086019190915260a085015260c084015260e08301526001600160a01b031661010082015261012001610547565b61056361075e366004614297565b610ff9565b6107766107713660046140e3565b61107d565b604080519485526020850193909352918301526060820152608001610547565b6105636107a4366004614234565b6110c6565b6105636107b7366004614319565b6112d6565b6105636107ca366004614395565b61139e565b60035461058b906001600160a01b031681565b61056361141f565b6105636107f8366004614297565b611996565b61053d61080b366004614297565b611a35565b61056361081e366004614297565b611a4c565b61053d60165481565b61060261083a3660046140e3565b6001600160a01b03166000908152602760205260409020805460018201546002830154600384015460048501546005909501549395929491939092565b610563610885366004614297565b611aa9565b6105636108983660046143d7565b611b9e565b61053d600c5481565b61053d600f5481565b6105636108bd366004614297565b611bcc565b6105636108d036600461442c565b611c49565b6105636108e33660046140e3565b611fb3565b6108fb6108f63660046140e3565b612078565b604080519b8c5260208c019a909a52988a01979097526060890195909552608088019390935260a087019190915260c086015260e085015261010084015261012083015261014082015261016001610547565b61053d61095c3660046140e3565b61214f565b61056361096f366004614319565b6122ac565b61056361098236600461449e565b6122db565b61053d60175481565b61056361099e3660046144d0565b6122f7565b6105636109b13660046140e3565b6124bb565b60055461058b906001600160a01b031681565b610563612547565b6105636109df366004614297565b612559565b6105636109f2366004614297565b6125d6565b61053d60135481565b610563610a0e366004614297565b612641565b61053d610a2136600461450b565b61266e565b61053d610a343660046140e3565b6126a4565b610a5c610a473660046140e3565b60286020526000908152604090205460ff1681565b6040519015158152602001610547565b610563610a7a36600461442c565b61275d565b61053d60255481565b610563610a96366004614234565b612a56565b61053d60115481565b6000546001600160a01b031661058b565b610a5c610ac33660046140e3565b602b6020526000908152604090205460ff1681565b610a5c610ae63660046140e3565b60296020526000908152604090205460ff1681565b602354610a5c9060ff1681565b60065461058b906001600160a01b031681565b610563610b29366004614297565b612c58565b602a5461058b906001600160a01b031681565b610563610b4f36600461442c565b612cb5565b61053d610b623660046140e3565b612e7a565b61053d60245481565b610563610b7e366004614537565b612f4d565b610b96610b913660046140e3565b612ffc565b604051610547929190614572565b610563610bb23660046140e3565b61316b565b61053d60185481565b61053d60145481565b610563610bd7366004614297565b613195565b610563610bea36600461442c565b6131f2565b610563610bfd366004614297565b6133b7565b610563610c103660046140e3565b613414565b610563610c233660046140e3565b6134a2565b61053d610c363660046140e3565b61353a565b61053d60125481565b60045461058b906001600160a01b031681565b610563610c65366004614297565b613576565b60085461058b906001600160a01b031681565b61053d600e5481565b610563610c943660046140e3565b613672565b610563610ca73660046140e3565b613705565b610563610cba366004614297565b613716565b610563610ccd3660046140e3565b613793565b610563610ce03660046140e3565b6137bd565b610563610cf336600461450b565b6137f8565b61053d610d0636600461450b565b613835565b61053d60105481565b610563610d22366004614611565b613863565b60025461058b906001600160a01b031681565b61053d600d5481565b610563610d51366004614537565b6138db565b610563610d64366004614666565b61398a565b60095461058b906001600160a01b031681565b610563610d8a3660046142be565b6139a5565b61053d610d9d366004614297565b613a62565b6001600160a01b03811660009081526026602052604081206004810154610dd190671bc16d674ec80000614699565b601154610dde91906146b0565b9392505050565b6007548451516001600160a01b03908116911614610e1e5760405162461bcd60e51b8152600401610e15906146c3565b60405180910390fd5b60135483602001351015610e445760405162461bcd60e51b8152600401610e15906146f2565b30610e5260208501856140e3565b6001600160a01b031614610e785760405162461bcd60e51b8152600401610e1590614722565b600b5460405163187945bd60e11b81526001600160a01b03909116906330f28b7a90610eb09087908790339088908890600401614782565b600060405180830381600087803b158015610eca57600080fd5b505af1158015610ede573d6000803e3d6000fd5b5050336000908152602660209081526040822060060180549188013594509250610f099084906146b0565b909155505050505050565b6000610f22826103e8614699565b602554610f2f91906146b0565b92915050565b610f3d613a72565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b610f67613a72565b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b610f91613a72565b6001600160a01b03919091166000908152602960205260409020805460ff1916911515919091179055565b610fc4613a72565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b610fee613a72565b601591909155601655565b611001613a72565b600081116110215760405162461bcd60e51b8152600401610e1590614800565b601081905560408051818152600691810191909152651c995dd85c9960d21b6060820152602081018290527f29ad052c83eced1add047469cec21e12106cd7d582514af563dff3c13c3c6fcb906080015b60405180910390a150565b60008060008061108c85610da2565b93506110978561353a565b6001600160a01b0390951660009081526026602052604090206004810154600590910154949690949350915050565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561111b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113f9190614846565b8551519091506001600160a01b0380831691161461116f5760405162461bcd60e51b8152600401610e15906146c3565b600061117a3361353a565b90508085602001351461119f5760405162461bcd60e51b8152600401610e15906146f2565b306111ad60208701876140e3565b6001600160a01b0316146111d35760405162461bcd60e51b8152600401610e1590614722565b600b5460405163187945bd60e11b81526001600160a01b03909116906330f28b7a9061120b908990899033908a908a90600401614782565b600060405180830381600087803b15801561122557600080fd5b505af1158015611239573d6000803e3d6000fd5b505033600090815260266020908152604080832060279092528220600582018054929550909350909161126b83614863565b919050555080600501548260050154111561128b57600580830154908201555b6005820154604080519182526020820185905233917fd1592e47e5c70e05dc194c5c7040fd885ad47699bb0c05726c246908d754e8f991015b60405180910390a25050505050505050565b6112de613a72565b6001600160a01b0388811660008181526026602090815260408083208c8155600181018c9055600481018b9055600581018a9055600681018990556008810180546001600160a01b031916968816969096179095556029825291829020805460ff191687151517905581518b81529081018a905290810188905260608101879052608081018690527f62a5a2fe4f6668cbc7f8685336c7afac94df357a5ed1180f6515cbe23f3ea2579060a00160405180910390a2505050505050505050565b6113a6613a72565b60405163a9059cbb60e01b81526001600160a01b0382811660048301526024820184905284169063a9059cbb906044016020604051808303816000875af11580156113f5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611419919061487c565b50505050565b611427613a9f565b600254604051632bc91fed60e01b81523360048201526001600160a01b0390911690632bc91fed90602401602060405180830381865afa15801561146f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114939190614899565b6000036114f9573360009081526029602052604090205460ff166114f95760405162461bcd60e51b815260206004820152601a60248201527f53435241505045523a2075736572206e6f742070617961626c650000000000006044820152606401610e15565b6003546001600160a01b03161561159e57600354604051636b8ab97d60e01b81523360048201526000918291829182916001600160a01b0390911690636b8ab97d90602401608060405180830381865afa15801561155b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157f91906148b2565b9350935093509350831561159957611599338484846122f7565b505050505b336000908152602660205260408120600281015490910361160457601580549060006115c983614863565b90915550506013546115dc906032614699565b33600090815260266020526040812060060180549091906115fe9084906146b0565b90915550505b33600090815260276020526040902060235460ff1680156116465750600554336000908152602660205260409020600801546001600160a01b03908116911614155b156116da576013543360009081526026602052604090206006015410156116af5760405162461bcd60e51b815260206004820152601a60248201527f53435241505045523a206e6f7420656e6f7567682077617465720000000000006044820152606401610e15565b60135433600090815260266020526040812060060180549091906116d49084906148f1565b90915550505b60006116e5336126a4565b9050600081116117375760405162461bcd60e51b815260206004820152601c60248201527f53435241505045523a206e6f20746f6b656e7320746f20636c61696d000000006044820152606401610e15565b4260028401556000600384018190556001830180549161175683614863565b91905055508082600201600082825461176f91906146b0565b9091555050600883015460405163a9059cbb60e01b8152336004820152602481018390526001600160a01b039091169063a9059cbb906044016020604051808303816000875af11580156117c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117eb919061487c565b6118335760405162461bcd60e51b815260206004820152601960248201527814d0d490541411548e881d1c985b9cd9995c8819985a5b1959603a1b6044820152606401610e15565b600061184666038d7ea4c6800083614904565b600a549091506001600160a01b0316156118e357600a546040516348b68a8360e01b81523360048201526000916001600160a01b0316906348b68a8390602401602060405180830381865afa1580156118a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118c79190614899565b905060646118d58284614699565b6118df9190614904565b9150505b60048054604051633cc01ef160e21b81523392810192909252602482018390526001600160a01b03169063f3007bc490604401600060405180830381600087803b15801561193057600080fd5b505af1158015611944573d6000803e3d6000fd5b505050506119523382613ac9565b60405182815233907f896e034966eaaf1adc54acc0f257056febbd300c9e47182cf761982cf1f5e4309060200160405180910390a25050505061199460018055565b565b61199e613a72565b60008111611a005760405162461bcd60e51b815260206004820152602960248201527f53435241505045523a206261736520657870206d75737420626520677265617460448201526806572207468616e20360bc1b6064820152608401610e15565b60258190556040518181527f26548f2b23ea646ad626dd81529baa1a81a4683eb7b67a49e7b3a887be430b5c90602001611072565b60198160058110611a4557600080fd5b0154905081565b611a54613a72565b60008111611a745760405162461bcd60e51b8152600401610e1590614926565b600c8190556040518181527f98c9cae42cac91fe8b116dbf81fe47e6b53fd49a362fb687d7ad4aa3114a7ce490602001611072565b611ab233613c64565b15611aba5750565b336000908152602660205260409020600801546001600160a01b031615611b235760405162461bcd60e51b815260206004820152601b60248201527f53435241505045523a20746f6b656e20616c72656164792073657400000000006044820152606401610e15565b80600003611b605760055433600090815260266020526040902060080180546001600160a01b0319166001600160a01b0390921691909117905550565b80600103611b9b5760065433600090815260266020526040902060080180546001600160a01b0319166001600160a01b039092169190911790555b50565b611ba6613a72565b600f97909755601095909555601193909355601291909155601355601455601755601855565b611bd4613a72565b60008111611bf45760405162461bcd60e51b8152600401610e1590614800565b601281905560408051818152600691810191909152651c995dd85c9960d21b6060820152602081018290527f310e1fe600a49018325c99539d47d1a4344d82ebe96e85b8060994c43720131590608001611072565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cc29190614846565b8551519091506001600160a01b0390811690821603611e3c576004805460408051637e062a3560e11b815290516001600160a01b039092169263fc0c546a9282820192602092908290030181865afa158015611d22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d469190614846565b8551516001600160a01b03908116911614611d735760405162461bcd60e51b8152600401610e15906146c3565b60185484602001351015611d995760405162461bcd60e51b8152600401610e15906146f2565b30611da760208601866140e3565b6001600160a01b031614611dcd5760405162461bcd60e51b8152600401610e1590614722565b600b5460405163187945bd60e11b81526001600160a01b03909116906330f28b7a90611e059088908890339089908990600401614782565b600060405180830381600087803b158015611e1f57600080fd5b505af1158015611e33573d6000803e3d6000fd5b50505050611f31565b6008548551516001600160a01b03908116911614611e6c5760405162461bcd60e51b8152600401610e15906146c3565b60175484602001351015611e925760405162461bcd60e51b8152600401610e15906146f2565b30611ea060208601866140e3565b6001600160a01b031614611ec65760405162461bcd60e51b8152600401610e1590614722565b600b5460405163187945bd60e11b81526001600160a01b03909116906330f28b7a90611efe9088908890339089908990600401614782565b600060405180830381600087803b158015611f1857600080fd5b505af1158015611f2c573d6000803e3d6000fd5b505050505b85600003611f705760055433600090815260266020526040902060080180546001600160a01b0319166001600160a01b03909216919091179055611fab565b85600103611fab5760065433600090815260266020526040902060080180546001600160a01b0319166001600160a01b039092169190911790555b505050505050565b611fbb613a72565b6001600160a01b03811661202f5760405162461bcd60e51b815260206004820152603560248201527f53435241505045523a20696e76616c6964207265736574206163636f756e74206044820152746c766c7320636f6e7472616374206164647265737360581b6064820152608401610e15565b600380546001600160a01b0319166001600160a01b03831690811790915515611b9b576001600160a01b0381166000908152602860205260409020805460ff1916600117905550565b6001600160a01b0381166000908152602660205260408120805460018201546002830154600384015492949193909291908190819081908190819081906120be8d6126a4565b975080600401549550806005015494506120d78d61214f565b93506120e28d612e7a565b6006820154600283015491945092501561213357600081600201544261210891906148f1565b905060006121158f61214f565b90508082101561212c5761212982826148f1565b98505b505061213f565b61213c8d61214f565b96505b5091939597999b90929496989a50565b6001600160a01b0381166000908152602660205260408120600e546004820154839161217a91614699565b60245461218791906146b0565b600a549091506001600160a01b031615610dde57600a546040516387bf0cef60e01b81526001600160a01b03868116600483015260009216906387bf0cef90602401602060405180830381865afa1580156121e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061220a9190614899565b905060646122188284614699565b6122229190614904565b600a54604051631ac2b45760e11b81526001600160a01b0388811660048301529294506000929091169063358568ae90602401602060405180830381865afa158015612272573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122969190614899565b90506122a281846146b0565b9695505050505050565b3360009081526028602052604090205460ff166112de5760405162461bcd60e51b8152600401610e159061496d565b6122e3613a72565b600c93909355600d91909155602455600e55565b3360009081526028602052604090205460ff166123265760405162461bcd60e51b8152600401610e159061496d565b6001600160a01b0384166000908152602660205260408120600181018590558181556004810184905560058101839055600781018054919261236783614863565b90915550506009546001600160a01b0316156123e95760095460018201546040516319765dc960e21b81526001600160a01b03888116600483015260248201929092529116906365d9772490604401600060405180830381600087803b1580156123d057600080fd5b505af11580156123e4573d6000803e3d6000fd5b505050505b6003546001600160a01b03161561245a57600354604051630fd11cf960e21b81526001600160a01b03878116600483015290911690633f4473e490602401600060405180830381600087803b15801561244157600080fd5b505af1158015612455573d6000803e3d6000fd5b505050505b6040805160008082526020820187905281830186905260608201859052608082015290516001600160a01b038716917f62a5a2fe4f6668cbc7f8685336c7afac94df357a5ed1180f6515cbe23f3ea257919081900360a00190a25050505050565b6124c3613a72565b6001600160a01b0381166125255760405162461bcd60e51b8152602060048201526024808201527f53435241505045523a20696e76616c69642069726f6e20746f6b656e206164646044820152637265737360e01b6064820152608401610e15565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b61254f613a72565b6119946000613eab565b612561613a72565b600081116125815760405162461bcd60e51b8152600401610e1590614800565b6011819055604080518181526006918101919091526574696d696e6760d01b6060820152602081018290527f310e1fe600a49018325c99539d47d1a4344d82ebe96e85b8060994c43720131590608001611072565b6125de613a72565b6000811161263c5760405162461bcd60e51b815260206004820152602560248201527f53435241505045523a20636f7374206d75737420626520677265617465722074604482015264068616e20360dc1b6064820152608401610e15565b601355565b612649613a72565b600081116126695760405162461bcd60e51b8152600401610e1590614800565b601455565b6001600160a01b03821660009081526026602052604081206004810154600f5461269c919085906019613efb565b949350505050565b6001600160a01b0381166000908152602660205260408120600281015482036127005760006126d28461214f565b90506000603c6126e186612e7a565b6126eb9190614904565b90506126f78282614699565b95945050505050565b600081600201544261271291906148f1565b9050600061271f8561214f565b90508082111561272d578091505b6000603c61273a87612e7a565b6127449190614904565b905060006127528483614699565b979650505050505050565b61276633613c64565b1561285357600b5460405163187945bd60e11b81526001600160a01b03909116906330f28b7a906127a39087908790339088908890600401614782565b600060405180830381600087803b1580156127bd57600080fd5b505af11580156127d1573d6000803e3d6000fd5b505060085460405163a9059cbb60e01b8152336004820152602087013560248201526001600160a01b03909116925063a9059cbb91506044016020604051808303816000875af1158015612829573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061284d919061487c565b50612a4f565b6008548451516001600160a01b039081169116146128835760405162461bcd60e51b8152600401610e15906146c3565b601454836020013510156128a95760405162461bcd60e51b8152600401610e15906146f2565b306128b760208501856140e3565b6001600160a01b0316146128dd5760405162461bcd60e51b8152600401610e1590614722565b3360009081526029602052604090205460ff161561293d5760405162461bcd60e51b815260206004820152601a60248201527f53435241505045523a2075736572206e6f742070617961626c650000000000006044820152606401610e15565b600b5460405163187945bd60e11b81526001600160a01b03909116906330f28b7a906129759087908790339088908890600401614782565b600060405180830381600087803b15801561298f57600080fd5b505af11580156129a3573d6000803e3d6000fd5b5050336000908152602960205260408120805460ff1916600117905560168054935091506129d083614863565b919050555084600003612a145760055433600090815260266020526040902060080180546001600160a01b0319166001600160a01b03909216919091179055612a4f565b84600103612a4f5760065433600090815260266020526040902060080180546001600160a01b0319166001600160a01b039092169190911790555b5050505050565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612aab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612acf9190614846565b8551519091506001600160a01b03808316911614612aff5760405162461bcd60e51b8152600401610e15906146c3565b6000612b0a33610da2565b905080856020013514612b2f5760405162461bcd60e51b8152600401610e15906146f2565b30612b3d60208701876140e3565b6001600160a01b031614612b635760405162461bcd60e51b8152600401610e1590614722565b600b5460405163187945bd60e11b81526001600160a01b03909116906330f28b7a90612b9b908990899033908a908a90600401614782565b600060405180830381600087803b158015612bb557600080fd5b505af1158015612bc9573d6000803e3d6000fd5b5050336000908152602660209081526040808320602790925282206004820180549295509093509091612bfb83614863565b9190505550806004015482600401541115612c1b57600480830154908201555b6004820154604080519182526020820185905233917f0254bd7f1019b14fcab90b0148b4f296c3496c5b450e62b0c86a54e2c3bbb09e91016112c4565b612c60613a72565b60008111612c805760405162461bcd60e51b8152600401610e15906149a4565b60248190556040518181527f8374fea52feb3243e01ea7f5abbef3818ab814eee35c22f9fc4e960390057a3990602001611072565b60008511612cd55760405162461bcd60e51b8152600401610e15906149e9565b6008548451516001600160a01b03908116911614612d055760405162461bcd60e51b8152600401610e15906146c3565b6000612d113387613835565b905080846020013514612d365760405162461bcd60e51b8152600401610e15906146f2565b30612d4460208601866140e3565b6001600160a01b031614612d6a5760405162461bcd60e51b8152600401610e1590614722565b600b5460405163187945bd60e11b81526001600160a01b03909116906330f28b7a90612da29088908890339089908990600401614782565b600060405180830381600087803b158015612dbc57600080fd5b505af1158015612dd0573d6000803e3d6000fd5b5050336000908152602660209081526040808320602790925282206005820180549295509093508a929091612e069084906146b0565b9250508190555082816003016000828254612e2191906146b0565b909155505060058082015490830154111561128b57600582810154908201819055604080519182526020820185905233917fd1592e47e5c70e05dc194c5c7040fd885ad47699bb0c05726c246908d754e8f991016112c4565b6001600160a01b0381166000908152602660205260408120600d5460058201548391612ea591614699565b600c54612eb291906146b0565b600a549091506001600160a01b031615610dde57600a54604051636112918960e11b81526001600160a01b038681166004830152600092169063c225231290602401602060405180830381865afa158015612f11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f359190614899565b90506064612f438284614699565b6126f79190614904565b612f55613a72565b8385108015612f6357508284105b8015612f6e57508183105b8015612f7957508082105b612fc55760405162461bcd60e51b815260206004820152601d60248201527f53435241505045523a20696e76616c696420627265616b706f696e74730000006044820152606401610e15565b6040518060a0016040528086815260200185815260200184815260200183815260200182815250601e906005611fab92919061407b565b613054604051806101200160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b031681525090565b61308d6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b50506001600160a01b03908116600090815260266020908152604080832060278352928190208151610120810183528454815260018086015482860152600280870154838601526003808801546060808601919091526004808a01546080808801919091526005808c015460a0808a019190915260068d015460c0808b019190915260078e015460e08b01526008909d0154909d1661010089015289519b8c018a5288548c5295880154998b019990995292860154968901969096528401549487019490945292820154938501939093520154928201929092529091565b613173613a72565b600980546001600160a01b0319166001600160a01b0392909216919091179055565b61319d613a72565b600081116131bd5760405162461bcd60e51b8152600401610e15906149a4565b600e8190556040518181527fa961c327f1a097745a50fa81e168a0ed6f7b6183e456d13468d1e0c566dc753290602001611072565b600085116132125760405162461bcd60e51b8152600401610e15906149e9565b6008548451516001600160a01b039081169116146132425760405162461bcd60e51b8152600401610e15906146c3565b600061324e338761266e565b9050808460200135146132735760405162461bcd60e51b8152600401610e15906146f2565b3061328160208601866140e3565b6001600160a01b0316146132a75760405162461bcd60e51b8152600401610e1590614722565b600b5460405163187945bd60e11b81526001600160a01b03909116906330f28b7a906132df9088908890339089908990600401614782565b600060405180830381600087803b1580156132f957600080fd5b505af115801561330d573d6000803e3d6000fd5b5050336000908152602660209081526040808320602790925282206004820180549295509093508a9290916133439084906146b0565b925050819055508281600301600082825461335e91906146b0565b9091555050600480820154908301541115612c1b57600482810154908201819055604080519182526020820185905233917f0254bd7f1019b14fcab90b0148b4f296c3496c5b450e62b0c86a54e2c3bbb09e91016112c4565b6133bf613a72565b600081116133df5760405162461bcd60e51b8152600401610e1590614926565b600d8190556040518181527f2e15bdb347d81abad94e6c10ea0fed9380a0944344a3efa9bdf0b494784d418490602001611072565b61341c613a72565b6001600160a01b0381166134805760405162461bcd60e51b815260206004820152602560248201527f53435241505045523a20696e76616c696420776174657220746f6b656e206164604482015264647265737360d81b6064820152608401610e15565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b6134aa613a72565b6001600160a01b0381166135005760405162461bcd60e51b815260206004820152601e60248201527f53435241505045523a20696e76616c69642073686f70206164647265737300006044820152606401610e15565b600a80546001600160a01b039092166001600160a01b0319909216821790556000908152602860205260409020805460ff19166001179055565b6001600160a01b0381166000908152602660205260408120600581015461356990671bc16d674ec80000614699565b601254610dde91906146b0565b61357e613a72565b6000811161359e5760405162461bcd60e51b8152600401610e15906149e9565b33600081815260266020526040908190206008015490516323b872dd60e01b81526004810192909252306024830152604482018390526001600160a01b0316906323b872dd906064016020604051808303816000875af1158015613606573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061362a919061487c565b611b9b5760405162461bcd60e51b815260206004820152601960248201527814d0d490541411548e881d1c985b9cd9995c8819985a5b1959603a1b6044820152606401610e15565b61367a613a72565b6001600160a01b0381166136e35760405162461bcd60e51b815260206004820152602a60248201527f53435241505045523a20696e76616c69642065787065646974696f6e20746f6b604482015269656e206164647265737360b01b6064820152608401610e15565b600780546001600160a01b0319166001600160a01b0392909216919091179055565b61370d613a72565b611b9b81613f49565b61371e613a72565b6000811161373e5760405162461bcd60e51b8152600401610e1590614800565b600f819055604080518181526006918101919091526574696d696e6760d01b6060820152602081018290527f29ad052c83eced1add047469cec21e12106cd7d582514af563dff3c13c3c6fcb90608001611072565b61379b613a72565b600880546001600160a01b0319166001600160a01b0392909216919091179055565b6137c5613a72565b6001600160a01b0381166137ef57604051631e4fbdf760e01b815260006004820152602401610e15565b611b9b81613eab565b3360009081526028602052604090205460ff166138275760405162461bcd60e51b8152600401610e159061496d565b6138318282613ac9565b5050565b6001600160a01b0382166000908152602660205260408120600581015460105461269c91908590601e613efb565b61386b613a72565b6040805160c0810182529687526020808801968752878201958652606088019485526080880193845260a088019283526001600160a01b03909816600090815260279098529096209451855592516001850155905160028401555160038301555160048201559051600590910155565b6138e3613a72565b83851080156138f157508284105b80156138fc57508183105b801561390757508082105b6139535760405162461bcd60e51b815260206004820152601d60248201527f53435241505045523a20696e76616c696420627265616b706f696e74730000006044820152606401610e15565b6040518060a00160405280868152602001858152602001848152602001838152602001828152506019906005611fab92919061407b565b613992613a72565b6023805460ff1916911515919091179055565b6139ad613a72565b6001600160a01b038216613a035760405162461bcd60e51b815260206004820181905260248201527f53435241505045523a20696e76616c69642063616c6c657220616464726573736044820152606401610e15565b6001600160a01b038216600081815260286020908152604091829020805460ff191685151590811790915591519182527fa80c7c27007dcd99579e4e6253b6c5f461990e3df534d6d7e948776d7eccb109910160405180910390a25050565b601e8160058110611a4557600080fd5b6000546001600160a01b031633146119945760405163118cdaa760e01b8152336004820152602401610e15565b600260015403613ac257604051633ee5aeb560e01b815260040160405180910390fd5b6002600155565b6001600160a01b03821660009081526026602090815260408083206027909252822081549192909184918491613b009084906146b0565b90915550600090505b613b168360010154610f14565b835410613bc6576000613b2c8460010154610f14565b905080846000016000828254613b4291906148f1565b9091555050600184018054906000613b5983614863565b9091555050825460018501541115613b7357600184015483555b600184015460408051918252602082018390526001600160a01b038816917feec61667dd6eeecdccfef3c906e0fd047cca672804901ac4254d8545e9a426d4910160405180910390a26001915050613b09565b60008360010154118015613bd75750805b8015613bed57506009546001600160a01b031615155b15612a4f5760095460018401546040516319765dc960e21b81526001600160a01b03888116600483015260248201929092529116906365d9772490604401600060405180830381600087803b158015613c4557600080fd5b505af1158015613c59573d6000803e3d6000fd5b505050505050505050565b602a546000906001600160a01b0316613c7f57506000919050565b6001600160a01b0382166000908152602b602052604090205460ff1615613ca857506000919050565b602a54604051630cacd00160e11b81526001600160a01b0384811660048301526000928392839283928392839283928392839290911690631959a0029060240161012060405180830381865afa158015613d06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d2a9190614a30565b98509850985098509850985098509850985086600003613d55575060009a9950505050505050505050565b6001600160a01b038b8116600081815260266020526040908190208c8155600181018c9055600281018b9055600381018a905560048082018a90556005820189905560068201889055600782018790556008820180546001600160a01b031916878716179055602a549251639025571560e01b815290810193909352921690639025571590602401602060405180830381865afa158015613dfa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e1e919061487c565b602960008e6001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff0219169083151502179055506001602b60008e6001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060019a5050505050505050505050919050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060015b848111613f40576000613f1382886146b0565b9050613f2081868661400c565b613f2a90846146b0565b9250508080613f3890614863565b915050613f00565b50949350505050565b6001600160a01b03811615613fc2576000816001600160a01b03163b11613fc25760405162461bcd60e51b815260206004820152602760248201527f53435241505045523a206f6c642077617474657273206973206e6f74206120636044820152661bdb9d1c9858dd60ca1b6064820152608401610e15565b602a80546001600160a01b0319166001600160a01b0383169081179091556040517fe3f7150b52186c27ea5f8be66066e93eb3c75d03a4eddc0492845dfb0ffb9e4d90600090a250565b60008082810154851161402157506001614071565b8260010154851161403457506002614071565b8260020154851161404757506004614071565b8260030154851161405a57506008614071565b8260040154851161406d57506010614071565b5060105b6126f78185614699565b82600581019282156140a9579160200282015b828111156140a957825182559160200191906001019061408e565b506140b59291506140b9565b5090565b5b808211156140b557600081556001016140ba565b6001600160a01b0381168114611b9b57600080fd5b6000602082840312156140f557600080fd5b8135610dde816140ce565b6040805190810167ffffffffffffffff8111828210171561413157634e487b7160e01b600052604160045260246000fd5b60405290565b6000818303608081121561414a57600080fd5b6040516060810167ffffffffffffffff8111828210171561417b57634e487b7160e01b600052604160045260246000fd5b8060405250809250604082121561419157600080fd5b614199614100565b915083356141a6816140ce565b82526020848101358184015291815260408085013592820192909252606090930135920191909152919050565b6000604082840312156141e557600080fd5b50919050565b60008083601f8401126141fd57600080fd5b50813567ffffffffffffffff81111561421557600080fd5b60208301915083602082850101111561422d57600080fd5b9250929050565b60008060008060e0858703121561424a57600080fd5b6142548686614137565b935061426386608087016141d3565b925060c085013567ffffffffffffffff81111561427f57600080fd5b61428b878288016141eb565b95989497509550505050565b6000602082840312156142a957600080fd5b5035919050565b8015158114611b9b57600080fd5b600080604083850312156142d157600080fd5b82356142dc816140ce565b915060208301356142ec816142b0565b809150509250929050565b6000806040838503121561430a57600080fd5b50508035926020909101359150565b600080600080600080600080610100898b03121561433657600080fd5b8835614341816140ce565b97506020890135965060408901359550606089013594506080890135935060a0890135925060c0890135614374816142b0565b915060e0890135614384816140ce565b809150509295985092959890939650565b6000806000606084860312156143aa57600080fd5b83356143b5816140ce565b92506020840135915060408401356143cc816140ce565b809150509250925092565b600080600080600080600080610100898b0312156143f457600080fd5b505086359860208801359850604088013597606081013597506080810135965060a0810135955060c0810135945060e0013592509050565b6000806000806000610100868803121561444557600080fd5b853594506144568760208801614137565b93506144658760a088016141d3565b925060e086013567ffffffffffffffff81111561448157600080fd5b61448d888289016141eb565b969995985093965092949392505050565b600080600080608085870312156144b457600080fd5b5050823594602084013594506040840135936060013592509050565b600080600080608085870312156144e657600080fd5b84356144f1816140ce565b966020860135965060408601359560600135945092505050565b6000806040838503121561451e57600080fd5b8235614529816140ce565b946020939093013593505050565b600080600080600060a0868803121561454f57600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b825181526020808401518183015260408085015181840152606080860151818501526080808701518186015260a0808801518187015260c0808901519087015260e08089015190870152610100808901516001600160a01b031690870152865161012087015293860151610140860152918501516101608501528401516101808401528301516101a08301528201516101c08201526101e08101610dde565b600080600080600080600060e0888a03121561462c57600080fd5b8735614637816140ce565b9960208901359950604089013598606081013598506080810135975060a0810135965060c00135945092505050565b60006020828403121561467857600080fd5b8135610dde816142b0565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610f2f57610f2f614683565b80820180821115610f2f57610f2f614683565b60208082526015908201527429a1a920a82822a91d103bb937b733903a37b5b2b760591b604082015260600190565b60208082526016908201527514d0d490541411548e881ddc9bdb99c8185b5bdd5b9d60521b604082015260600190565b60208082526019908201527f53435241505045523a2077726f6e6720726563697069656e7400000000000000604082015260600190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b855180516001600160a01b03168252602090810151818301528601516040808301919091528601516060820152600085356147bc816140ce565b6001600160a01b03166080830152602086013560a08301526147e960c08301866001600160a01b03169052565b61010060e083015261275261010083018486614759565b60208082526026908201527f53435241505045523a207072696365206d75737420626520677265617465722060408201526507468616e20360d41b606082015260800190565b60006020828403121561485857600080fd5b8151610dde816140ce565b60006001820161487557614875614683565b5060010190565b60006020828403121561488e57600080fd5b8151610dde816142b0565b6000602082840312156148ab57600080fd5b5051919050565b600080600080608085870312156148c857600080fd5b84516148d3816142b0565b60208601516040870151606090970151919890975090945092505050565b81810381811115610f2f57610f2f614683565b60008261492157634e487b7160e01b600052601260045260246000fd5b500490565b60208082526027908201527f53435241505045523a20726577617264206d75737420626520677265617465726040820152660207468616e20360cc1b606082015260800190565b60208082526018908201527f53435241505045523a206e6f7420617574686f72697a65640000000000000000604082015260600190565b60208082526025908201527f53435241505045523a2074696d65206d75737420626520677265617465722074604082015264068616e20360dc1b606082015260800190565b60208082526027908201527f53435241505045523a20616d6f756e74206d75737420626520677265617465726040820152660207468616e20360cc1b606082015260800190565b60008060008060008060008060006101208a8c031215614a4f57600080fd5b60008a51905080995050600060208b0151905080985050600060408b0151905080975050600060608b0151905080965050600060808b0151905080955050600060a08b0151905080945050600060c08b0151905080935050600060e08b01519050809250506101008a0151614ac3816140ce565b80915050929598509295985092959856fea2646970667358221220f43508984c3173a2ae8ee38755e165d3334a4848c587e9d31bf2f17b653f423164736f6c634300081c0033

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

00000000000000000000000083a5b1c92d4b45db257d0e42dd1f11a009f8492b0000000000000000000000005c1ed5039a0858a188d1df812bbad7790281b77f0000000000000000000000002cfc85d8e48f8eab294be644d9e25c3030863003000000000000000000000000999561c6c239c9ef660dfbe38cc2ce6bd0c2ecba0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fa62d60ba436cd287d45be7a36dbb97ba150b0330000000000000000000000005e913ee579a68503dfdce85da3d1e3cbfc4365cd

-----Decoded View---------------
Arg [0] : waterToken_ (address): 0x83A5B1c92D4B45dB257D0e42dD1F11a009f8492B
Arg [1] : ironToken_ (address): 0x5c1ED5039A0858a188d1Df812BBAd7790281b77F
Arg [2] : _wld (address): 0x2cFc85d8E48F8EAB294be644d9E25C3030863003
Arg [3] : initialOwner (address): 0x999561c6c239C9ef660DfbE38cc2CE6BD0c2EcBa
Arg [4] : _top (address): 0x0000000000000000000000000000000000000000
Arg [5] : _scrappers (address): 0xFA62d60ba436CD287d45bE7A36dBB97Ba150B033
Arg [6] : oldWatters_ (address): 0x5E913ee579A68503dFdcE85DA3d1e3cBfc4365CD

-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 00000000000000000000000083a5b1c92d4b45db257d0e42dd1f11a009f8492b
Arg [1] : 0000000000000000000000005c1ed5039a0858a188d1df812bbad7790281b77f
Arg [2] : 0000000000000000000000002cfc85d8e48f8eab294be644d9e25c3030863003
Arg [3] : 000000000000000000000000999561c6c239c9ef660dfbe38cc2ce6bd0c2ecba
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [5] : 000000000000000000000000fa62d60ba436cd287d45be7a36dbb97ba150b033
Arg [6] : 0000000000000000000000005e913ee579a68503dfdce85da3d1e3cbfc4365cd


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.