false
false
0

Contract Address Details

0xd91531bdE4A60EBeaAA4A04C32f29c9f19EC77d8

Contract Name
GlobalStaking
Creator
0xb7971f–a51f91 at 0xd802a2–2d9bb1
Balance
0 CLO
Tokens
Fetching tokens...
Transactions
Fetching transactions...
Transfers
Fetching transfers...
Gas Used
Fetching gas used...
Last Balance Update
16288489
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
GlobalStaking




Optimization enabled
true
Compiler version
v0.8.7+commit.e28d00a7




Optimization runs
200
EVM Version
default




Verified at
2024-09-26T15:31:58.177447Z

Contract source code

// SPDX-License-Identifier: No License (None)
pragma solidity ^0.8.0;

/**
 * @title Ownable
 * @dev The Ownable contract has an owner address, and provides basic authorization control
 * functions, this simplifies the implementation of "user permissions".
 *
 * Source https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-solidity/v2.1.3/contracts/ownership/Ownable.sol
 * This contract is copied here and renamed from the original to avoid clashes in the compiled artifacts
 * when the user imports a zos-lib contract (that transitively causes this contract to be compiled and added to the
 * build/artifacts folder) as well as the vanilla Ownable implementation from an openzeppelin version.
 */
contract Ownable {
    address private _owner;

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

    /**
     * @dev The Ownable constructor sets the original `owner` of the contract to the sender
     * account.
     */
    constructor () {
        _owner = msg.sender;
        emit OwnershipTransferred(address(0), _owner);
    }

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

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(isOwner(),"Not Owner");
        _;
    }

    /**
     * @return true if `msg.sender` is the owner of the contract.
     */
    function isOwner() public view returns (bool) {
        return msg.sender == _owner;
    }

    /**
     * @dev Allows the current owner to relinquish control of the contract.
     * @notice Renouncing to ownership will leave the contract without an owner.
     * It will not be possible to call the functions with the `onlyOwner`
     * modifier anymore.
     */
    function renounceOwnership() public onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    /**
     * @dev Allows the current owner to transfer control of the contract to a newOwner.
     * @param newOwner The address to transfer ownership to.
     */
    function transferOwnership(address newOwner) public onlyOwner {
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers control of the contract to a newOwner.
     * @param newOwner The address to transfer ownership to.
     */
    function _transferOwnership(address newOwner) internal {
        require(newOwner != address(0),"Zero address not allowed");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}


interface IERC223 {
    /**
     * @dev Returns the balance of the `who` address.
     */
    function balanceOf(address who) external view returns (uint256);

    /**
     * @dev Transfers `value` tokens from `msg.sender` to `to` address
     * and returns `true` on success.
     */
    function transfer(address to, uint256 value)
        external
        returns (bool success);

    /**
     * @dev Transfers `value` tokens from `msg.sender` to `to` address with `data` parameter
     * and returns `true` on success.
     */
    function transfer(
        address to,
        uint256 value,
        bytes memory data
    ) external returns (bool success);

    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
    function approve(address spender, uint256 amount) external returns (bool);
    function burn(uint256 amount) external returns (bool);

    /**
     * @dev Event that is fired on successful transfer.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Additional event that is fired on successful transfer and logs transfer metadata,
     *      this event is implemented to keep Transfer event compatible with ERC20.
     */
    event TransferData(bytes data);
}

interface ILocalFarm {
    function notifyRewardAmount(uint256 reward) external;
    function initialize(
        address _rewardsToken,      // SOY token
        address _lpToken            // LP token that will be staked in this Local Farm
    ) external;
}

interface ISimplifiedGlobalFarm {
    function mintFarmingReward(address _localFarm) external;

    function getAllocationX1000(address _farm) external view returns (uint256);

    function getRewardPerSecond() external view returns (uint256);

    function rewardMintingAvailable(address _farm) external view returns (bool);

    function farmExists(address _farmAddress) external view returns (bool);
}

contract GlobalStaking is Ownable {
    
    struct LocalFarm {
        address farmAddress;
        uint256 multiplier;
        uint256 lastPayment;
    }

    address public constant globalFarm = 0x64Fa36ACD0d13472FD786B03afC9C52aD5FCf023;
    address public constant SOY_TOKEN = 0x9FaE2529863bD691B4A7171bDfCf33C7ebB10a65;

    uint256 public totalMultipliers;
    uint256 public paymentDelay = 1 days;          // DEFAULTS_TO 1 days

    mapping(uint256 => LocalFarm) public localFarms;
    uint256                       public lastAddedFarmIndex = 0; // Farm IDs will start from 1
    
    mapping(address => uint256)   public localFarmId;     // locals farm address => id; localFarm at ID = 0 is considered non-existing
    mapping(address => uint256)   public nextMint; // timestamp when token may be minted to local farm


    event AddStaking(address _localFarm, uint32 _multiplier);
    event RemoveStaking(address _localFarm);
    event ChangeMultiplier(address _localFarm, uint256 _oldMultiplier, uint256 _newMultiplier);

    
    function next_payment() public view returns (uint256)
    {
        return (block.timestamp / paymentDelay) * paymentDelay + paymentDelay;
    }
    
    function rewardMintingAvailable(address _farm) public view returns (bool)
    {
        return localFarms[localFarmId[_farm]].lastPayment + paymentDelay < next_payment();
    }

    function getAllocationX1000(address _farm) public view returns (uint256)
    {
        return 1000 * localFarms[localFarmId[_farm]].multiplier / totalMultipliers;
    }
    
    function getRewardPerSecond() public view returns (uint256)
    {
        uint256 rewardPerSecond = ISimplifiedGlobalFarm(globalFarm).getRewardPerSecond();
        uint256 allocationX1000 = ISimplifiedGlobalFarm(globalFarm).getAllocationX1000(address(this));
        return rewardPerSecond * allocationX1000 / 1000;
    }

    function getLocalFarmId(address _localFarmAddress) external view returns (uint256) {
        return localFarmId[_localFarmAddress];
    }
    
    function getLastPayment(address _localFarmAddress) external view returns (uint256) {
        return localFarms[localFarmId[_localFarmAddress]].lastPayment;
    }

    function addStakingContract(
        address _localFarmAddress,            // staking contract
        uint32 _multiplier
    ) 
        external onlyOwner 
    {
        // Increment last index before adding a farm.
        // Farm with index = 0 is considered non-existing.
        lastAddedFarmIndex++;
        
        localFarms[lastAddedFarmIndex].farmAddress = _localFarmAddress;
        localFarms[lastAddedFarmIndex].multiplier  = _multiplier;
        localFarms[lastAddedFarmIndex].lastPayment = next_payment() - paymentDelay;
        
        localFarmId[_localFarmAddress]             = lastAddedFarmIndex;
        
        totalMultipliers += uint256(_multiplier);
        
        emit AddStaking(_localFarmAddress, _multiplier);
    }

    
    function farmExists(address _farmAddress) public view returns (bool _exists)
    {
        return (localFarmId[_farmAddress] != 0) && (localFarms[localFarmId[_farmAddress]].farmAddress != address(0));
    }

    function removeLocalFarmByAddress(address _localFarmAddress) external onlyOwner {
        require (farmExists(_localFarmAddress), "LocalFarm with this address does not exist");
        
        totalMultipliers = totalMultipliers - uint256(localFarms[localFarmId[_localFarmAddress]].multiplier); // update totalMultipliers
        
        //delete localFarmId[_localFarmAddress];
        
        localFarms[localFarmId[_localFarmAddress]].farmAddress  = address(0);
        localFarms[localFarmId[_localFarmAddress]].multiplier   = 0; // Not critically important, can be removed for gas efficiency reasons.
        localFarms[localFarmId[_localFarmAddress]].lastPayment  = 0; // Not critically important, can be removed for gas efficiency reasons.
        
        localFarmId[_localFarmAddress] = 0;
        
        emit RemoveStaking(_localFarmAddress);
    }


    function changeMultiplier(address _localFarmAddress, uint32 _multiplier) external onlyOwner {
        require (farmExists(_localFarmAddress), "LocalFarm with this address does not exist");
        
        uint256 oldMultiplier = localFarms[localFarmId[_localFarmAddress]].multiplier;
        totalMultipliers = totalMultipliers + uint256(_multiplier) - uint256(oldMultiplier); // update totalMultipliers
        localFarms[localFarmId[_localFarmAddress]].multiplier = _multiplier;
        emit ChangeMultiplier(_localFarmAddress, oldMultiplier, _multiplier);
    }

    function mintFarmingReward(address _localFarmAddress) external {
        require (farmExists(_localFarmAddress), "LocalFarm with this address does not exist");
        
        // Comparing against 0:00 UTC always
        // to enable withdrawals for full days only at any point within 24 hours of a day.
        if(localFarms[localFarmId[_localFarmAddress]].lastPayment + paymentDelay > next_payment())
        {
            // Someone is requesting payment for a Local Farm that was paid recently.
            // Do nothing.
            return;
        }
        else
        {
            ISimplifiedGlobalFarm(globalFarm).mintFarmingReward(address(this));
            uint256 _reward = (next_payment() - localFarms[localFarmId[_localFarmAddress]].lastPayment) * getRewardPerSecond() * getAllocationX1000(_localFarmAddress) / 1000;
            localFarms[localFarmId[_localFarmAddress]].lastPayment = next_payment();
            IERC223(SOY_TOKEN).transfer(_localFarmAddress, _reward);
            ILocalFarm(_localFarmAddress).notifyRewardAmount(_reward);
        }
    }
}
        

Contract ABI

[{"type":"event","name":"AddStaking","inputs":[{"type":"address","name":"_localFarm","internalType":"address","indexed":false},{"type":"uint32","name":"_multiplier","internalType":"uint32","indexed":false}],"anonymous":false},{"type":"event","name":"ChangeMultiplier","inputs":[{"type":"address","name":"_localFarm","internalType":"address","indexed":false},{"type":"uint256","name":"_oldMultiplier","internalType":"uint256","indexed":false},{"type":"uint256","name":"_newMultiplier","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"RemoveStaking","inputs":[{"type":"address","name":"_localFarm","internalType":"address","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"SOY_TOKEN","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addStakingContract","inputs":[{"type":"address","name":"_localFarmAddress","internalType":"address"},{"type":"uint32","name":"_multiplier","internalType":"uint32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeMultiplier","inputs":[{"type":"address","name":"_localFarmAddress","internalType":"address"},{"type":"uint32","name":"_multiplier","internalType":"uint32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"_exists","internalType":"bool"}],"name":"farmExists","inputs":[{"type":"address","name":"_farmAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getAllocationX1000","inputs":[{"type":"address","name":"_farm","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getLastPayment","inputs":[{"type":"address","name":"_localFarmAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getLocalFarmId","inputs":[{"type":"address","name":"_localFarmAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getRewardPerSecond","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"globalFarm","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isOwner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastAddedFarmIndex","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"localFarmId","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"farmAddress","internalType":"address"},{"type":"uint256","name":"multiplier","internalType":"uint256"},{"type":"uint256","name":"lastPayment","internalType":"uint256"}],"name":"localFarms","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"mintFarmingReward","inputs":[{"type":"address","name":"_localFarmAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"nextMint","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"next_payment","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"paymentDelay","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeLocalFarmByAddress","inputs":[{"type":"address","name":"_localFarmAddress","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"rewardMintingAvailable","inputs":[{"type":"address","name":"_farm","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalMultipliers","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]}]
              

Contract Creation Code

Verify & Publish
0x608060405262015180600255600060045534801561001c57600080fd5b50600080546001600160a01b0319163390811782556040519091907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3610f1d8061006b6000396000f3fe608060405234801561001057600080fd5b506004361061014d5760003560e01c80638da5cb5b116100c3578063da5b4ee71161007c578063da5b4ee71461034a578063e26eeff414610352578063eec8afed14610365578063f2fde38b1461036e578063f9d30f1814610381578063fb853d641461039457600080fd5b80638da5cb5b146102665780638f32d59b146102775780639c4ee5b01461028a578063a06bdde5146102e8578063b77f6b7514610321578063c2ab26511461034157600080fd5b80634599fef6116101155780634599fef6146101e15780634f3a1ff8146101ea5780635480b9551461021d5780635b17f50614610230578063648a7e201461024b578063715018a61461025e57600080fd5b8063127eaa23146101525780633460c114146101675780633bb1f4291461018f5780634381feba146101a5578063445c92c5146101ce575b600080fd5b610165610160366004610d45565b6103b4565b005b61017a610175366004610d23565b6104cf565b60405190151581526020015b60405180910390f35b610197610522565b604051908152602001610186565b6101976101b3366004610d23565b6001600160a01b031660009081526005602052604090205490565b61017a6101dc366004610d23565b61054c565b61019760015481565b6102057364fa36acd0d13472fd786b03afc9c52ad5fcf02381565b6040516001600160a01b039091168152602001610186565b61016561022b366004610d45565b610594565b610205739fae2529863bd691b4a7171bdfcf33c7ebb10a6581565b610165610259366004610d23565b6106c2565b610165610926565b6000546001600160a01b0316610205565b6000546001600160a01b0316331461017a565b6102c3610298366004610da7565b6003602052600090815260409020805460018201546002909201546001600160a01b03909116919083565b604080516001600160a01b039094168452602084019290925290820152606001610186565b6101976102f6366004610d23565b6001600160a01b03166000908152600560209081526040808320548352600390915290206002015490565b61019761032f366004610d23565b60066020526000908152604090205481565b61019760025481565b61019761099a565b610197610360366004610d23565b610aca565b61019760045481565b61016561037c366004610d23565b610b0d565b61016561038f366004610d23565b610b40565b6101976103a2366004610d23565b60056020526000908152604090205481565b6000546001600160a01b031633146103e75760405162461bcd60e51b81526004016103de90610dd9565b60405180910390fd5b6103f0826104cf565b61040c5760405162461bcd60e51b81526004016103de90610dfc565b6001600160a01b0382166000908152600560209081526040808320548352600390915290206001908101549054819061044c9063ffffffff851690610e46565b6104569190610e9f565b60019081556001600160a01b0384166000818152600560209081526040808320548352600382529182902063ffffffff87169401849055815192835282018490528101919091527ff73ac06bb532ce46127d55c58225dec0321642d3b5285f78433ad4b129807f379060600160405180910390a1505050565b6001600160a01b0381166000908152600560205260408120541580159061051c57506001600160a01b03828116600090815260056020908152604080832054835260039091529020541615155b92915050565b600254600090806105338142610e5e565b61053d9190610e80565b6105479190610e46565b905090565b6000610556610522565b600280546001600160a01b0385166000908152600560209081526040808320548352600390915290209091015461058d9190610e46565b1092915050565b6000546001600160a01b031633146105be5760405162461bcd60e51b81526004016103de90610dd9565b600480549060006105ce83610eb6565b90915550506004805460009081526003602052604080822080546001600160a01b0319166001600160a01b038716179055915481522063ffffffff82166001919091015560025461061d610522565b6106279190610e9f565b6004805460009081526003602090815260408083206002019490945591546001600160a01b03861682526005909252918220556001805463ffffffff84169290610672908490610e46565b9091555050604080516001600160a01b038416815263ffffffff831660208201527fd65c64ffc651b77d0559e80aceed4408c91b006279b8ec3ec971555b6b9f5099910160405180910390a15050565b6106cb816104cf565b6106e75760405162461bcd60e51b81526004016103de90610dfc565b6106ef610522565b600280546001600160a01b038416600090815260056020908152604080832054835260039091529020909101546107269190610e46565b111561072f5750565b60405163032453f160e51b81523060048201527364fa36acd0d13472fd786b03afc9c52ad5fcf0239063648a7e2090602401600060405180830381600087803b15801561077b57600080fd5b505af115801561078f573d6000803e3d6000fd5b5050505060006103e86107a183610aca565b6107a961099a565b6001600160a01b038516600090815260056020908152604080832054835260039091529020600201546107da610522565b6107e49190610e9f565b6107ee9190610e80565b6107f89190610e80565b6108029190610e5e565b905061080c610522565b6001600160a01b038316600081815260056020908152604080832054835260039091529081902060020192909255905163a9059cbb60e01b8152600481019190915260248101829052739fae2529863bd691b4a7171bdfcf33c7ebb10a659063a9059cbb90604401602060405180830381600087803b15801561088e57600080fd5b505af11580156108a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108c69190610d85565b50604051633c6b16ab60e01b8152600481018290526001600160a01b03831690633c6b16ab90602401600060405180830381600087803b15801561090957600080fd5b505af115801561091d573d6000803e3d6000fd5b50505050505b50565b6000546001600160a01b031633146109505760405162461bcd60e51b81526004016103de90610dd9565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000807364fa36acd0d13472fd786b03afc9c52ad5fcf0236001600160a01b031663da5b4ee76040518163ffffffff1660e01b815260040160206040518083038186803b1580156109ea57600080fd5b505afa1580156109fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a229190610dc0565b60405163389bbbfd60e21b81523060048201529091506000907364fa36acd0d13472fd786b03afc9c52ad5fcf0239063e26eeff49060240160206040518083038186803b158015610a7257600080fd5b505afa158015610a86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aaa9190610dc0565b90506103e8610ab98284610e80565b610ac39190610e5e565b9250505090565b600180546001600160a01b03831660009081526005602090815260408083205483526003909152812090920154610b03906103e8610e80565b61051c9190610e5e565b6000546001600160a01b03163314610b375760405162461bcd60e51b81526004016103de90610dd9565b61092381610c56565b6000546001600160a01b03163314610b6a5760405162461bcd60e51b81526004016103de90610dd9565b610b73816104cf565b610b8f5760405162461bcd60e51b81526004016103de90610dfc565b6001600160a01b0381166000908152600560209081526040808320548352600390915290206001908101549054610bc69190610e9f565b60019081556001600160a01b0382166000818152600560208181526040808420805485526003835281852080546001600160a01b031916905580548552818520909601849055855484528084206002018490558484529181529190935591519081527f752eed3ce65b2ce43f311706c3ce8dd03ed5cb4f3091c0cd1d54a782ae461529910160405180910390a150565b6001600160a01b038116610cac5760405162461bcd60e51b815260206004820152601860248201527f5a65726f2061646472657373206e6f7420616c6c6f776564000000000000000060448201526064016103de565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b80356001600160a01b0381168114610d1e57600080fd5b919050565b600060208284031215610d3557600080fd5b610d3e82610d07565b9392505050565b60008060408385031215610d5857600080fd5b610d6183610d07565b9150602083013563ffffffff81168114610d7a57600080fd5b809150509250929050565b600060208284031215610d9757600080fd5b81518015158114610d3e57600080fd5b600060208284031215610db957600080fd5b5035919050565b600060208284031215610dd257600080fd5b5051919050565b6020808252600990820152682737ba1027bbb732b960b91b604082015260600190565b6020808252602a908201527f4c6f63616c4661726d20776974682074686973206164647265737320646f6573604082015269081b9bdd08195e1a5cdd60b21b606082015260800190565b60008219821115610e5957610e59610ed1565b500190565b600082610e7b57634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615610e9a57610e9a610ed1565b500290565b600082821015610eb157610eb1610ed1565b500390565b6000600019821415610eca57610eca610ed1565b5060010190565b634e487b7160e01b600052601160045260246000fdfea264697066735822122087b78895cac42e4a9194f6d0eeaca1521ed6f258c181da340a1edc42cc0f9ed964736f6c63430008070033

Deployed ByteCode

0x608060405234801561001057600080fd5b506004361061014d5760003560e01c80638da5cb5b116100c3578063da5b4ee71161007c578063da5b4ee71461034a578063e26eeff414610352578063eec8afed14610365578063f2fde38b1461036e578063f9d30f1814610381578063fb853d641461039457600080fd5b80638da5cb5b146102665780638f32d59b146102775780639c4ee5b01461028a578063a06bdde5146102e8578063b77f6b7514610321578063c2ab26511461034157600080fd5b80634599fef6116101155780634599fef6146101e15780634f3a1ff8146101ea5780635480b9551461021d5780635b17f50614610230578063648a7e201461024b578063715018a61461025e57600080fd5b8063127eaa23146101525780633460c114146101675780633bb1f4291461018f5780634381feba146101a5578063445c92c5146101ce575b600080fd5b610165610160366004610d45565b6103b4565b005b61017a610175366004610d23565b6104cf565b60405190151581526020015b60405180910390f35b610197610522565b604051908152602001610186565b6101976101b3366004610d23565b6001600160a01b031660009081526005602052604090205490565b61017a6101dc366004610d23565b61054c565b61019760015481565b6102057364fa36acd0d13472fd786b03afc9c52ad5fcf02381565b6040516001600160a01b039091168152602001610186565b61016561022b366004610d45565b610594565b610205739fae2529863bd691b4a7171bdfcf33c7ebb10a6581565b610165610259366004610d23565b6106c2565b610165610926565b6000546001600160a01b0316610205565b6000546001600160a01b0316331461017a565b6102c3610298366004610da7565b6003602052600090815260409020805460018201546002909201546001600160a01b03909116919083565b604080516001600160a01b039094168452602084019290925290820152606001610186565b6101976102f6366004610d23565b6001600160a01b03166000908152600560209081526040808320548352600390915290206002015490565b61019761032f366004610d23565b60066020526000908152604090205481565b61019760025481565b61019761099a565b610197610360366004610d23565b610aca565b61019760045481565b61016561037c366004610d23565b610b0d565b61016561038f366004610d23565b610b40565b6101976103a2366004610d23565b60056020526000908152604090205481565b6000546001600160a01b031633146103e75760405162461bcd60e51b81526004016103de90610dd9565b60405180910390fd5b6103f0826104cf565b61040c5760405162461bcd60e51b81526004016103de90610dfc565b6001600160a01b0382166000908152600560209081526040808320548352600390915290206001908101549054819061044c9063ffffffff851690610e46565b6104569190610e9f565b60019081556001600160a01b0384166000818152600560209081526040808320548352600382529182902063ffffffff87169401849055815192835282018490528101919091527ff73ac06bb532ce46127d55c58225dec0321642d3b5285f78433ad4b129807f379060600160405180910390a1505050565b6001600160a01b0381166000908152600560205260408120541580159061051c57506001600160a01b03828116600090815260056020908152604080832054835260039091529020541615155b92915050565b600254600090806105338142610e5e565b61053d9190610e80565b6105479190610e46565b905090565b6000610556610522565b600280546001600160a01b0385166000908152600560209081526040808320548352600390915290209091015461058d9190610e46565b1092915050565b6000546001600160a01b031633146105be5760405162461bcd60e51b81526004016103de90610dd9565b600480549060006105ce83610eb6565b90915550506004805460009081526003602052604080822080546001600160a01b0319166001600160a01b038716179055915481522063ffffffff82166001919091015560025461061d610522565b6106279190610e9f565b6004805460009081526003602090815260408083206002019490945591546001600160a01b03861682526005909252918220556001805463ffffffff84169290610672908490610e46565b9091555050604080516001600160a01b038416815263ffffffff831660208201527fd65c64ffc651b77d0559e80aceed4408c91b006279b8ec3ec971555b6b9f5099910160405180910390a15050565b6106cb816104cf565b6106e75760405162461bcd60e51b81526004016103de90610dfc565b6106ef610522565b600280546001600160a01b038416600090815260056020908152604080832054835260039091529020909101546107269190610e46565b111561072f5750565b60405163032453f160e51b81523060048201527364fa36acd0d13472fd786b03afc9c52ad5fcf0239063648a7e2090602401600060405180830381600087803b15801561077b57600080fd5b505af115801561078f573d6000803e3d6000fd5b5050505060006103e86107a183610aca565b6107a961099a565b6001600160a01b038516600090815260056020908152604080832054835260039091529020600201546107da610522565b6107e49190610e9f565b6107ee9190610e80565b6107f89190610e80565b6108029190610e5e565b905061080c610522565b6001600160a01b038316600081815260056020908152604080832054835260039091529081902060020192909255905163a9059cbb60e01b8152600481019190915260248101829052739fae2529863bd691b4a7171bdfcf33c7ebb10a659063a9059cbb90604401602060405180830381600087803b15801561088e57600080fd5b505af11580156108a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108c69190610d85565b50604051633c6b16ab60e01b8152600481018290526001600160a01b03831690633c6b16ab90602401600060405180830381600087803b15801561090957600080fd5b505af115801561091d573d6000803e3d6000fd5b50505050505b50565b6000546001600160a01b031633146109505760405162461bcd60e51b81526004016103de90610dd9565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000807364fa36acd0d13472fd786b03afc9c52ad5fcf0236001600160a01b031663da5b4ee76040518163ffffffff1660e01b815260040160206040518083038186803b1580156109ea57600080fd5b505afa1580156109fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a229190610dc0565b60405163389bbbfd60e21b81523060048201529091506000907364fa36acd0d13472fd786b03afc9c52ad5fcf0239063e26eeff49060240160206040518083038186803b158015610a7257600080fd5b505afa158015610a86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aaa9190610dc0565b90506103e8610ab98284610e80565b610ac39190610e5e565b9250505090565b600180546001600160a01b03831660009081526005602090815260408083205483526003909152812090920154610b03906103e8610e80565b61051c9190610e5e565b6000546001600160a01b03163314610b375760405162461bcd60e51b81526004016103de90610dd9565b61092381610c56565b6000546001600160a01b03163314610b6a5760405162461bcd60e51b81526004016103de90610dd9565b610b73816104cf565b610b8f5760405162461bcd60e51b81526004016103de90610dfc565b6001600160a01b0381166000908152600560209081526040808320548352600390915290206001908101549054610bc69190610e9f565b60019081556001600160a01b0382166000818152600560208181526040808420805485526003835281852080546001600160a01b031916905580548552818520909601849055855484528084206002018490558484529181529190935591519081527f752eed3ce65b2ce43f311706c3ce8dd03ed5cb4f3091c0cd1d54a782ae461529910160405180910390a150565b6001600160a01b038116610cac5760405162461bcd60e51b815260206004820152601860248201527f5a65726f2061646472657373206e6f7420616c6c6f776564000000000000000060448201526064016103de565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b80356001600160a01b0381168114610d1e57600080fd5b919050565b600060208284031215610d3557600080fd5b610d3e82610d07565b9392505050565b60008060408385031215610d5857600080fd5b610d6183610d07565b9150602083013563ffffffff81168114610d7a57600080fd5b809150509250929050565b600060208284031215610d9757600080fd5b81518015158114610d3e57600080fd5b600060208284031215610db957600080fd5b5035919050565b600060208284031215610dd257600080fd5b5051919050565b6020808252600990820152682737ba1027bbb732b960b91b604082015260600190565b6020808252602a908201527f4c6f63616c4661726d20776974682074686973206164647265737320646f6573604082015269081b9bdd08195e1a5cdd60b21b606082015260800190565b60008219821115610e5957610e59610ed1565b500190565b600082610e7b57634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615610e9a57610e9a610ed1565b500290565b600082821015610eb157610eb1610ed1565b500390565b6000600019821415610eca57610eca610ed1565b5060010190565b634e487b7160e01b600052601160045260246000fdfea264697066735822122087b78895cac42e4a9194f6d0eeaca1521ed6f258c181da340a1edc42cc0f9ed964736f6c63430008070033