Transactions
Token Transfers
Tokens
Internal Transactions
Coin Balance History
Logs
Code
Read Contract
Write Contract
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- SOYLocalFarmV2
- Optimization enabled
- true
- Compiler version
- v0.8.18+commit.87f61d96
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2024-09-26T15:34:20.122627Z
Constructor Arguments
0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001cee27d0627ce8a81df9b4d7eee0d753b8c2f613
Arg [0] (bool) : false
Arg [1] (address) : 0x1cee27d0627ce8a81df9b4d7eee0d753b8c2f613
Contract source code
// SPDX-License-Identifier: No License (None) pragma solidity 0.8.18; interface IERC223 { function balanceOf(address who) external view returns (uint); function transfer(address to, uint value) external; function transfer(address to, uint value, bytes memory data) external returns (bool success); } abstract contract IERC223Recipient { struct ERC223TransferInfo { address token_contract; address sender; uint256 value; bytes data; } ERC223TransferInfo private tkn; /** * @dev Standard ERC223 function that will handle incoming token transfers. * * @param _from Token sender address. * @param _value Amount of tokens. * @param _data Transaction metadata. */ function tokenReceived(address _from, uint _value, bytes calldata _data) public virtual; } /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the `nonReentrant` modifier * available, which can be aplied 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. */ contract ReentrancyGuard { /// @dev counter to allow mutex lock with only one SSTORE operation uint256 private _guardCounter; /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { _guardCounter += 1; uint256 localCounter = _guardCounter; _; require(localCounter == _guardCounter, "ReentrancyGuard: reentrant call"); } } abstract contract RewardsRecipient { address public globalFarm; function notifyRewardAmount(uint256 reward) external virtual; modifier onlyGlobalFarm() { require(msg.sender == globalFarm, "Caller is not global Farm contract"); _; } } 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); function owner() external view returns (address); } /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.0.0, only sets of type `address` (`AddressSet`) and `uint256` * (`UintSet`) are supported. */ library EnumerableSet { struct AddressSet { // Storage of set values address[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping (address => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { if (!contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement. address lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns 1-based index of value in the set. O(1). */ function indexOf(AddressSet storage set, address value) internal view returns (uint256) { return set._indexes[value]; } /** * @dev Returns the number of values on the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { require(set._values.length > index, "EnumerableSet: index out of bounds"); return set._values[index]; } } interface ICallistoNFT { function ownerOf(uint256 _tokenId) external view returns (address); function transfer(address _to, uint256 _tokenId, bytes calldata _data) external returns (bool); function silentTransfer(address _to, uint256 _tokenId) external returns (bool); } interface IReferralTracker { function userFee(address user) external view returns(uint256); // fee percentage with 2 decimals for particular user } interface ISoyFinancePair { function token0() external view returns (address); function token1() external view returns (address); function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); function mint(address to) external returns (uint liquidity); function burn(address to) external returns (uint amount0, uint amount1); function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; } contract SOYLocalFarmV2 is IERC223Recipient, ReentrancyGuard, RewardsRecipient { using EnumerableSet for EnumerableSet.AddressSet; EnumerableSet.AddressSet boostNFTs; // NFT contracts provided bonuses IReferralTracker public referralTrackingContract; // contract to track referrals and pay fee uint256 constant MAX_AMOUNT = 1e40; // Prevents accumulatedRewardPerShare from overflowing. address public constant BURN_ADDRESS = 0x000000000000000000000000000000000000dEaD; // SoyFinance factory contract = 0x9CC7C769eA3B37F1Af0Ad642A268b80dc80754c5 defined in the function pairFor() uint256 public insuranceFee; // fee percentage with 2 decimals will be transferred to insurance fund uint256 public burnFee; // fee percentage with 2 decimals will be burned uint256 public totalShares; // effective total shares included bonuses address public insuranceAddress; IERC223 public rewardsToken; address public lpToken; uint256 public lastRewardTimestamp; // Last block number that SOY distribution occurs. uint256 public accumulatedRewardPerShare; // Accumulated SOY per share, times 1e18. bool public active; struct UserInfo { uint256 amount; // How many LP tokens the user has provided. uint256 rewardPerSharePaid; // Accumulated SOY per share that was paid uint256 bonus; // percent of bonus applied address nft; // deposited NFT uint256 tokenId; // NFT tokenID } // Info of each user that stakes LP tokens. mapping(address => UserInfo) public userInfo; mapping(address NFT => uint256 boost) public boostPercentage; // NFT contract address => boost % mapping(address pair => address token) public allowedTokensReceive; // allow to receive tokens from swapping pool event RewardAdded(uint256 reward); event Staked(address indexed user, uint256 amount); event Withdraw(address indexed user, uint256 amount); event EmergencyWithdraw(address indexed user, uint256 amount); event RewardPaid(address indexed user, uint256 reward); event RewardReinvested(address indexed user, uint256 reward); event SetInsuranceWallet(address wallet); event SetReferralTracking(address refTrack); /* ========== CONSTRUCTOR ========== */ constructor( bool _active, address _lpToken // LP token that will be staked in this Local Farm ) { active = _active; lpToken = _lpToken; //test net //rewardsToken = IERC223(0x4c20231BCc5dB8D805DB9197C84c8BA8287CbA92); // Soy token //globalFarm = 0x9F66541abc036503Ae074E1E28638b0Cb6165458; //insuranceAddress = 0x27d1a09fca4196ef8513aF068277AE96da083F49; // insurance wallet //referralTrackingContract = IReferralTracker(0xA3141cB11cfCd7dFEE9211b49627b4FdEa521fc4); // main net rewardsToken = IERC223(0x9FaE2529863bD691B4A7171bDfCf33C7ebB10a65); // Soy token globalFarm = 0x64Fa36ACD0d13472FD786B03afC9C52aD5FCf023; insuranceAddress = 0x27d1a09fca4196ef8513aF068277AE96da083F49; // insurance wallet referralTrackingContract = IReferralTracker(0x0A17432e963AD18C280fb4bc6C00c4Ad186051C0); insuranceFee = 200; // 2% address token0 = ISoyFinancePair(_lpToken).token0(); address token1 = ISoyFinancePair(_lpToken).token1(); if (token0 != address(rewardsToken) && token1 != address(rewardsToken)) { address pair = pairFor(token0, address(rewardsToken)); allowedTokensReceive[pair] = token0; pair = pairFor(token1, address(rewardsToken)); allowedTokensReceive[pair] = token1; } } modifier onlyOwner() { require(owner() == msg.sender, "only owner"); _; } modifier onlyActive { require(active, "The farm is not enabled by owner!"); _; } function setActive(bool _status) external onlyOwner { active = _status; } function owner() public view returns(address) { return ISimplifiedGlobalFarm(globalFarm).owner(); } /* ========== ERC223 transaction handlers ====== */ // Analogue of deposit() function. function tokenReceived(address _from, uint256 _amount, bytes calldata ) public override nonReentrant onlyActive { if (_from == lpToken || allowedTokensReceive[_from] == msg.sender) return; // allow to receive tokens form pair contract for reinvestment require(msg.sender == address(lpToken), "Trying to deposit wrong token"); uint256 userAmount = userInfo[_from].amount; require(userAmount + _amount <= MAX_AMOUNT, 'exceed the top'); update(); _payRewards(_from); if (_amount > 0) { uint256 shares = userAmount * (100 + userInfo[_from].bonus) / 100; uint256 newShares = (userAmount + _amount) * (100 + userInfo[_from].bonus) / 100; totalShares = totalShares + newShares - shares; userInfo[_from].amount += _amount; } emit Staked(_from, _amount); } function notifyRewardAmount(uint256 reward) external override { emit RewardAdded(reward); } function getRewardPerSecond() public view returns (uint256) { return ISimplifiedGlobalFarm(globalFarm).getRewardPerSecond(); } function getAllocationX1000() public view returns (uint256) { return ISimplifiedGlobalFarm(globalFarm).getAllocationX1000(address(this)); } /* ========== Farm Functions ====== */ // View function to see pending Reward on frontend. function pendingReward(address _user) external view returns (uint256 pending) { UserInfo storage user = userInfo[_user]; uint256 _accumulatedRewardPerShare = accumulatedRewardPerShare; if (block.timestamp > lastRewardTimestamp && totalShares != 0) { uint256 multiplier = block.timestamp - lastRewardTimestamp; uint256 _reward = multiplier * getRewardPerSecond() * getAllocationX1000() / 1000; _accumulatedRewardPerShare = accumulatedRewardPerShare + (_reward * 1e18 / totalShares); } uint256 shares = user.amount * (100 + user.bonus) / 100; pending = shares * (_accumulatedRewardPerShare - user.rewardPerSharePaid) / 1e18; // calculate fees uint256 refFee; if (address(referralTrackingContract) != address(0)) { refFee = referralTrackingContract.userFee(_user); // refFee is percentage with 2 decimals refFee = pending * refFee / 10000; // refFee - amount of fee } uint256 bFee = pending * burnFee / 10000; // burn fee amount uint256 iFee = pending * insuranceFee / 10000; // insurance fee amount pending = pending - (refFee + iFee + bFee); } // Update reward variables of this Local Farm to be up-to-date. function update() public { ISimplifiedGlobalFarm(globalFarm).mintFarmingReward(address(this)); if (block.timestamp <= lastRewardTimestamp) { return; } if (totalShares == 0) { lastRewardTimestamp = block.timestamp; return; } uint256 multiplier = block.timestamp - lastRewardTimestamp; // This silently calculates "assumed" reward! // This function does not take contract's actual balance into account // Global Farm and `reward_request` modifier are responsible for keeping this contract // stocked with funds to pay actual rewards. uint256 _reward = multiplier * getRewardPerSecond() * getAllocationX1000() / 1000; accumulatedRewardPerShare = accumulatedRewardPerShare + (_reward * 1e18 / totalShares); lastRewardTimestamp = block.timestamp; } // Withdraw tokens from STAKING. function withdraw(uint256 _amount) public nonReentrant { UserInfo storage user = userInfo[msg.sender]; require(user.amount >= _amount, "withdraw: not good"); update(); _payRewards(msg.sender); if(_amount > 0) { uint256 shares = user.amount * (100 + user.bonus) / 100; user.amount = user.amount - _amount; uint256 newShares = user.amount * (100 + user.bonus) / 100; totalShares = totalShares + newShares - shares; // update total shares IERC223(lpToken).transfer(msg.sender, _amount); } emit Withdraw(msg.sender, _amount); } // Withdraw without caring about rewards. EMERGENCY ONLY. function emergencyWithdraw() public nonReentrant { UserInfo storage user = userInfo[msg.sender]; IERC223(lpToken).transfer(msg.sender, user.amount); emit EmergencyWithdraw(msg.sender, user.amount); uint256 shares = user.amount * (100 + user.bonus) / 100; if (totalShares >= shares) totalShares -= shares; else totalShares = 0; user.amount = 0; user.rewardPerSharePaid = 0; } // Special function that allows owner to withdraw remaining unclaimed tokens of inactive farms function withdrawInactiveReward() public onlyOwner { require(!ISimplifiedGlobalFarm(globalFarm).farmExists(address(this)), "Farm must not be active"); rewardsToken.transfer(msg.sender, rewardsToken.balanceOf(address(this))); } function rescueERC20(address token, address to) external onlyOwner { require(token != address(rewardsToken), "Reward token is not prone to ERC20 issues"); require(token != address(lpToken), "LP token is not prone to ERC20 issues"); uint256 value = IERC223(token).balanceOf(address(this)); IERC223(token).transfer(to, value); } // on received boost NFT function onERC721Received(address, address _from, uint256 _tokenId, bytes calldata) external nonReentrant returns(bytes4) { require(boostNFTs.contains(msg.sender), "Not a boost NFT"); UserInfo storage user = userInfo[_from]; require(user.nft == address(0), "NFT already added"); update(); _payRewards(_from); user.nft = msg.sender; user.bonus = boostPercentage[msg.sender]; user.tokenId = _tokenId; uint256 shares = user.amount * (100 + user.bonus) / 100; totalShares = totalShares + shares - user.amount; // update total shares return this.onERC721Received.selector; } // withdraw boost NFT function withdrawNFT() external nonReentrant { UserInfo storage user = userInfo[msg.sender]; address nft = user.nft; require(nft != address(0), "No NFT"); user.nft = address(0); update(); _payRewards(msg.sender); // reduce shares by bonus uint256 shares = user.amount * (100 + user.bonus) / 100; totalShares = totalShares + user.amount - shares; // update total shares user.bonus = 0; ICallistoNFT(nft).silentTransfer(msg.sender, user.tokenId); } function _payRewards(address _user) internal { uint256 pending = _calculateReward(_user); if(pending > 0) rewardsToken.transfer(_user, pending); emit RewardPaid(_user, pending); } // calculate pending reward and pay fees function _calculateReward(address _user) internal returns(uint256 pending) { UserInfo storage user = userInfo[_user]; uint256 shares = user.amount * (100 + user.bonus) / 100; pending = shares * (accumulatedRewardPerShare - user.rewardPerSharePaid) / 1e18; if(pending > 0) { uint256 refFee; if (address(referralTrackingContract) != address(0)) refFee = referralTrackingContract.userFee(_user); // refFee is percentage with 2 decimals if (refFee != 0) { refFee = pending * refFee / 10000; // refFee - amount of fee bytes memory data = abi.encode(_user); rewardsToken.transfer(address(referralTrackingContract), refFee, data); } uint256 bFee = pending * burnFee / 10000; // burn fee amount if (bFee != 0) rewardsToken.transfer(BURN_ADDRESS, bFee); uint256 iFee = pending * insuranceFee / 10000; // insurance fee amount if (iFee != 0) rewardsToken.transfer(insuranceAddress, iFee); pending = pending - (refFee + iFee + bFee); } user.rewardPerSharePaid = accumulatedRewardPerShare; } function setInsuranceWallet(address wallet) external onlyOwner { require(wallet != address(0)); insuranceAddress = wallet; emit SetInsuranceWallet(wallet); } function setReferralTracking(address refTrack) external onlyOwner { require(refTrack != address(0)); referralTrackingContract = IReferralTracker(refTrack); emit SetReferralTracking(refTrack); } // set fees percentage with 2 decimals (i.e. 100 = 1%) function setFees(uint256 _burnFee, uint256 _insuranceFee) external onlyOwner { require(_burnFee < 10000 && _insuranceFee < 10000); burnFee = _burnFee; insuranceFee = _insuranceFee; } // set boost NFT contract and boost percentage (without decimals). If boost = 0, it will remove NFT contract function setBoostNFT(address[] memory contractNFT, uint256[] memory boost) external onlyOwner { require(contractNFT.length == boost.length, "wrong length"); for (uint i=0; i<boost.length; i++) { require(contractNFT[i] != address(0), "Zero address"); if (boost[i] == 0) { boostNFTs.remove(contractNFT[i]); boostPercentage[contractNFT[i]] = 0; } else { boostNFTs.add(contractNFT[i]); boostPercentage[contractNFT[i]] = boost[i]; } } } function setGlobalFarm(address _globalFarm) external onlyOwner { require(_globalFarm != address(0)); require(ISimplifiedGlobalFarm(_globalFarm).owner() == msg.sender, "New contract has another owner"); globalFarm = _globalFarm; } // returns list of boost NFTs and its boost percentage function getBoostNFT() external view returns(address[] memory NFTs, uint256[] memory boosts) { uint len = boostNFTs.length(); NFTs = new address[](len); boosts = new uint256[](len); for (uint i=0; i<len; i++) { NFTs[i] = boostNFTs.at(i); boosts[i] = boostPercentage[NFTs[i]]; } } // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) function sqrt(uint y) internal pure returns (uint z) { if (y > 3) { z = y; uint x = y / 2 + 1; while (x < z) { z = x; x = (y / x + x) / 2; } } else if (y != 0) { z = 1; } } // calculate amounts base on available amount of tokenIn function calcAmountIn(uint256 availableAmount, uint256 reserveIn) internal pure returns (uint256 amountIn) { uint256 d = (1998*1998)*reserveIn*reserveIn + (4000*998)*reserveIn*availableAmount; amountIn = (sqrt(d) - 1998*reserveIn) / (2 * 998); } // calculate amounts In and Out for pairs A and B function calcAmounts(uint256 availableAmount, uint256 aI, uint256 aO, uint256 bI, uint256 bO, uint256 pA, uint256 pB) internal pure returns(uint256,uint256,uint256,uint256) { uint256 bO1 = bO*pA/pB; uint256 c = 998*availableAmount/1000; pA = aI + bI + c; // A pB = aO*(bI + c) + bO1*(aI + c); // -B //bI = aO*bO; // *c // C pB = pB /(2*pA); // -P/2 c = (aO*bO1) / pA * c; // Q c = pB - sqrt(pB*pB - c); // amount out = -P/2 - Sqrt((P/2)^2 - Q) // get amounts aI = getAmountIn(c,aI,aO); // amountIn for pair A aO = c; // amountOut for pair A c = availableAmount - aI; bO = getAmountOut(c,bI,bO); // amountOut for pair B bI = c; // amountIn for pair B return(aI,aO,bI,bO); } function getAmountOut(uint256 amountIn, uint256 reserveIn, uint256 reserveOut) internal pure returns(uint256 amountOut) { uint256 amountInWithFee = amountIn * 998; uint256 numerator = amountInWithFee * reserveOut; uint256 denominator = (reserveIn * 1000) + amountInWithFee; amountOut = numerator / denominator; } // given an output amount of an asset and pair reserves, returns a required input amount of the other asset function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) internal pure returns (uint amountIn) { require(amountOut > 0, "INSUFFICIENT_OUTPUT_AMOUNT"); uint numerator = reserveIn*amountOut*1000; uint denominator = (reserveOut-amountOut)*998; amountIn = (numerator / denominator)+1; } function getReserves(address tokenIn, address tokenOut) internal view returns(uint256 reserveIn, uint256 reserveOut, address pair) { pair = pairFor(tokenIn, tokenOut); (reserveIn, reserveOut,) = ISoyFinancePair(pair).getReserves(); require(reserveIn > 0 && reserveOut > 0, "reinvestPools: pair error"); if (tokenOut < tokenIn) (reserveIn, reserveOut) = (reserveOut, reserveIn); } // calculates the CREATE2 address for a pair without making any external calls function pairFor(address tokenA, address tokenB) internal pure returns (address pair) { address factory = 0x9CC7C769eA3B37F1Af0Ad642A268b80dc80754c5; (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); pair = address(uint160(uint256(keccak256(abi.encodePacked( hex'ff', factory, keccak256(abi.encodePacked(token0, token1)), hex'e410ea0a25ce340e309f2f0fe9d58d787bb87dd63d02333e8a9a747230f61758' // init code hash ))))); } function reinvest() external returns(uint256 rewardReinvested) { update(); uint256 liquidity; rewardReinvested = _calculateReward(msg.sender); if(rewardReinvested > 0) { address token0 = ISoyFinancePair(lpToken).token0(); address token1 = ISoyFinancePair(lpToken).token1(); if (token0 == address(rewardsToken)) { liquidity = reinvestSoyPool(rewardReinvested, token1); } else if (token1 == address(rewardsToken)) { liquidity = reinvestSoyPool(rewardReinvested, token0); } else { liquidity = reinvestPools(rewardReinvested, token0, token1); } emit RewardReinvested(msg.sender, rewardReinvested); } if (liquidity > 0) { UserInfo storage user = userInfo[msg.sender]; uint256 userAmount = user.amount; uint256 shares = userAmount * (100 + user.bonus) / 100; uint256 newShares = (userAmount + liquidity) * (100 + user.bonus) / 100; totalShares = totalShares + newShares - shares; user.amount = userAmount + liquidity; emit Staked(msg.sender, liquidity); } } function reinvestSoyPool(uint256 reinvestAmount, address tokenOut) internal returns(uint256 liquidity) { (uint256 reserveIn, uint256 reserveOut,) = ISoyFinancePair(lpToken).getReserves(); if (tokenOut < address(rewardsToken)) { (reserveIn, reserveOut) = (reserveOut, reserveIn); } uint256 amountIn = calcAmountIn(reinvestAmount, reserveIn); uint256 amountOut = getAmountOut(amountIn, reserveIn, reserveOut); // swap Soy to pair token swap(address(lpToken), amountIn, amountOut, tokenOut); // add liquidity amountIn = reinvestAmount - amountIn; rewardsToken.transfer(address(lpToken), amountIn); IERC223(tokenOut).transfer(address(lpToken), amountOut); liquidity = ISoyFinancePair(lpToken).mint(address(this)); } function reinvestPools(uint256 rewardReinvested, address token0, address token1) internal returns(uint256 liquidity) { (uint256 pA, uint256 pB, address pair) = getReserves(token0, token1); require (pair == address(lpToken), "wrong factory"); (uint256 aI, uint256 aO, address pairA) = getReserves(address(rewardsToken), token0); (uint256 bI, uint256 bO, address pairB) = getReserves(address(rewardsToken), token1); // calculate amounts In and Out (aI, aO, bI, bO) = calcAmounts(rewardReinvested, aI, aO, bI, bO, pA, pB); // swap Soy to required tokens swap(pairA, aI, aO, token0); swap(pairB, bI, bO, token1); // add liquidity IERC223(token0).transfer(address(lpToken), aO); IERC223(token1).transfer(address(lpToken), bO); liquidity = ISoyFinancePair(lpToken).mint(address(this)); } // swap rewardsToken (SOY) to pair token (tokenOut) function swap(address pair, uint256 amountIn, uint256 amountOut, address tokenOut) internal { rewardsToken.transfer(pair, amountIn); (uint256 amount0Out, uint256 amount1Out) = address(rewardsToken) < tokenOut ? (uint256(0), amountOut) : (amountOut, uint256(0)); ISoyFinancePair(pair).swap(amount0Out, amount1Out, address(this), new bytes(0)); } }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"bool","name":"_active","internalType":"bool"},{"type":"address","name":"_lpToken","internalType":"address"}]},{"type":"event","name":"EmergencyWithdraw","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"RewardAdded","inputs":[{"type":"uint256","name":"reward","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"RewardPaid","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"reward","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"RewardReinvested","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"reward","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"SetInsuranceWallet","inputs":[{"type":"address","name":"wallet","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"SetReferralTracking","inputs":[{"type":"address","name":"refTrack","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Staked","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Withdraw","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"BURN_ADDRESS","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"accumulatedRewardPerShare","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"active","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"token","internalType":"address"}],"name":"allowedTokensReceive","inputs":[{"type":"address","name":"pair","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"boost","internalType":"uint256"}],"name":"boostPercentage","inputs":[{"type":"address","name":"NFT","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"burnFee","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"emergencyWithdraw","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getAllocationX1000","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"NFTs","internalType":"address[]"},{"type":"uint256[]","name":"boosts","internalType":"uint256[]"}],"name":"getBoostNFT","inputs":[]},{"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":"address","name":"","internalType":"address"}],"name":"insuranceAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"insuranceFee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastRewardTimestamp","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"lpToken","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"notifyRewardAmount","inputs":[{"type":"uint256","name":"reward","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bytes4","name":"","internalType":"bytes4"}],"name":"onERC721Received","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"_from","internalType":"address"},{"type":"uint256","name":"_tokenId","internalType":"uint256"},{"type":"bytes","name":"","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"pending","internalType":"uint256"}],"name":"pendingReward","inputs":[{"type":"address","name":"_user","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IReferralTracker"}],"name":"referralTrackingContract","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"rewardReinvested","internalType":"uint256"}],"name":"reinvest","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"rescueERC20","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"address","name":"to","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IERC223"}],"name":"rewardsToken","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setActive","inputs":[{"type":"bool","name":"_status","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setBoostNFT","inputs":[{"type":"address[]","name":"contractNFT","internalType":"address[]"},{"type":"uint256[]","name":"boost","internalType":"uint256[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setFees","inputs":[{"type":"uint256","name":"_burnFee","internalType":"uint256"},{"type":"uint256","name":"_insuranceFee","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setGlobalFarm","inputs":[{"type":"address","name":"_globalFarm","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setInsuranceWallet","inputs":[{"type":"address","name":"wallet","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setReferralTracking","inputs":[{"type":"address","name":"refTrack","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"tokenReceived","inputs":[{"type":"address","name":"_from","internalType":"address"},{"type":"uint256","name":"_amount","internalType":"uint256"},{"type":"bytes","name":"","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalShares","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"update","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"rewardPerSharePaid","internalType":"uint256"},{"type":"uint256","name":"bonus","internalType":"uint256"},{"type":"address","name":"nft","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"}],"name":"userInfo","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdraw","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawInactiveReward","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawNFT","inputs":[]}]
Contract Creation Code
0x60806040523480156200001157600080fd5b5060405162003a4738038062003a478339810160408190526200003491620003a8565b6011805483151560ff19909116179055600e80546001600160a01b0383166001600160a01b03199182168117909255600d80548216739fae2529863bd691b4a7171bdfcf33c7ebb10a651790556005805482167364fa36acd0d13472fd786b03afc9c52ad5fcf023179055600c805482167327d1a09fca4196ef8513af068277ae96da083f4917905560088054909116730a17432e963ad18c280fb4bc6c00c4ad186051c017905560c860095560408051630dfe168160e01b8152905160009291630dfe16819160048281019260209291908290030181865afa15801562000120573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001469190620003e6565b90506000826001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000189573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001af9190620003e6565b600d549091506001600160a01b03838116911614801590620001df5750600d546001600160a01b03828116911614155b156200027057600d54600090620002019084906001600160a01b03166200027a565b6001600160a01b03818116600090815260146020526040902080546001600160a01b031916868316179055600d5491925062000240918491166200027a565b6001600160a01b03908116600090815260146020526040902080546001600160a01b031916918416919091179055505b505050506200040b565b6000739cc7c769ea3b37f1af0ad642a268b80dc80754c581806001600160a01b0380861690871610620002af578486620002b2565b85855b6040516001600160601b0319606084811b8216602084015283901b1660348201529193509150839060480160405160208183030381529060405280519060200120604051602001620003699291907fff00000000000000000000000000000000000000000000000000000000000000815260609290921b6001600160601b031916600183015260158201527fe410ea0a25ce340e309f2f0fe9d58d787bb87dd63d02333e8a9a747230f61758603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b80516001600160a01b0381168114620003a357600080fd5b919050565b60008060408385031215620003bc57600080fd5b82518015158114620003cd57600080fd5b9150620003dd602084016200038b565b90509250929050565b600060208284031215620003f957600080fd5b62000404826200038b565b9392505050565b61362c806200041b6000396000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80635fcbd28511610125578063d1af0c7d116100ad578063f40f0f521161007c578063f40f0f52146104dd578063f8077fae146104f0578063fccc2813146104f9578063fce589d814610502578063fdb5a03e1461050b57600080fd5b8063d1af0c7d146104a4578063da5b4ee7146104b7578063db2e21bc146104bf578063e8eed972146104c757600080fd5b80638da5cb5b116100f45780638da5cb5b1461046557806397c4fac71461046d578063a2e6204514610476578063acec338a1461047e578063d08e7b691461049157600080fd5b80635fcbd2851461042457806373af2516146104375780638943ec021461044a5780638cb7e27c1461045d57600080fd5b80633a98ef39116101a85780634f3a1ff8116101775780634f3a1ff8146103d057806352313461146103e35780635b158b3c146103f65780635d799f87146104095780635e38c9541461041c57600080fd5b80633a98ef391461036b5780633c6b16ab14610374578063400250dc146103875780634e48ad3a146103b057600080fd5b80631959a002116101ef5780631959a002146102975780631e29653c1461030e5780632401273c146103245780632e1a7d4d1461034f57806336d421951461036257600080fd5b806301bc71131461022157806302fb0c5e146102365780630b78f9c014610258578063150b7a021461026b575b600080fd5b61023461022f366004612f74565b610513565b005b6011546102439060ff1681565b60405190151581526020015b60405180910390f35b610234610266366004612f98565b6105b3565b61027e610279366004613003565b610608565b6040516001600160e01b0319909116815260200161024f565b6102dd6102a5366004612f74565b601260205260009081526040902080546001820154600283015460038401546004909401549293919290916001600160a01b03169085565b604080519586526020860194909452928401919091526001600160a01b03166060830152608082015260a00161024f565b610316610791565b60405190815260200161024f565b600c54610337906001600160a01b031681565b6040516001600160a01b03909116815260200161024f565b61023461035d366004613076565b610803565b61031660105481565b610316600b5481565b610234610382366004613076565b6109d2565b610337610395366004612f74565b6014602052600090815260409020546001600160a01b031681565b6103166103be366004612f74565b60136020526000908152604090205481565b600554610337906001600160a01b031681565b600854610337906001600160a01b031681565b610234610404366004612f74565b610a02565b61023461041736600461308f565b610b28565b610234610d06565b600e54610337906001600160a01b031681565b61023461044536600461319e565b610e86565b610234610458366004613260565b6110a5565b61023461137d565b61033761152c565b61031660095481565b61023461159a565b61023461048c3660046132ca565b611691565b61023461049f366004612f74565b6116d3565b600d54610337906001600160a01b031681565b610316611763565b6102346117ad565b6104cf6118fe565b60405161024f9291906132e7565b6103166104eb366004612f74565b611a54565b610316600f5481565b61033761dead81565b610316600a5481565b610316611c63565b3361051c61152c565b6001600160a01b03161461054b5760405162461bcd60e51b81526004016105429061336b565b60405180910390fd5b6001600160a01b03811661055e57600080fd5b600880546001600160a01b0319166001600160a01b0383169081179091556040519081527f4cc2fbf2911e773499430576cc26e11ebc7a7d9bca28a2456b2040b2e2a5e338906020015b60405180910390a150565b336105bc61152c565b6001600160a01b0316146105e25760405162461bcd60e51b81526004016105429061336b565b612710821080156105f4575061271081105b6105fd57600080fd5b600a91909155600955565b600060016004600082825461061d91906133a5565b9091555050600454610630600633611ed7565b61066e5760405162461bcd60e51b815260206004820152600f60248201526e139bdd081848189bdbdcdd08139195608a1b6044820152606401610542565b6001600160a01b0380871660009081526012602052604090206003810154909116156106d05760405162461bcd60e51b815260206004820152601160248201527013919508185b1c9958591e481859191959607a1b6044820152606401610542565b6106d861159a565b6106e187611efb565b6003810180546001600160a01b03191633908117909155600090815260136020526040812054600283018190556004830188905560649061072290826133a5565b835461072e91906133b8565b61073891906133cf565b9050816000015481600b5461074d91906133a5565b61075791906133f1565b600b5550630a85bd0160e11b92505060045481146107875760405162461bcd60e51b815260040161054290613404565b5095945050505050565b60055460405163389bbbfd60e21b81523060048201526000916001600160a01b03169063e26eeff490602401602060405180830381865afa1580156107da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fe919061343b565b905090565b60016004600082825461081691906133a5565b909155505060045433600090815260126020526040902080548311156108735760405162461bcd60e51b81526020600482015260126024820152711dda5d1a191c985dce881b9bdd0819dbdbd960721b6044820152606401610542565b61087b61159a565b61088433611efb565b821561097757600060648260020154606461089f91906133a5565b83546108ab91906133b8565b6108b591906133cf565b82549091506108c59085906133f1565b825560028201546000906064906108dc90826133a5565b84546108e891906133b8565b6108f291906133cf565b90508181600b5461090391906133a5565b61090d91906133f1565b600b55600e5460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb906109429033908990600401613454565b600060405180830381600087803b15801561095c57600080fd5b505af1158015610970573d6000803e3d6000fd5b5050505050505b60405183815233907f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a94243649060200160405180910390a25060045481146109ce5760405162461bcd60e51b815260040161054290613404565b5050565b6040518181527fde88a922e0d3b88b24e9623efeb464919c6bf9f66857a65e2bfcf2ce87a9433d906020016105a8565b33610a0b61152c565b6001600160a01b031614610a315760405162461bcd60e51b81526004016105429061336b565b6001600160a01b038116610a4457600080fd5b336001600160a01b0316816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab0919061346d565b6001600160a01b031614610b065760405162461bcd60e51b815260206004820152601e60248201527f4e657720636f6e74726163742068617320616e6f74686572206f776e657200006044820152606401610542565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b33610b3161152c565b6001600160a01b031614610b575760405162461bcd60e51b81526004016105429061336b565b600d546001600160a01b0390811690831603610bc75760405162461bcd60e51b815260206004820152602960248201527f52657761726420746f6b656e206973206e6f742070726f6e6520746f2045524360448201526832302069737375657360b81b6064820152608401610542565b600e546001600160a01b0390811690831603610c335760405162461bcd60e51b815260206004820152602560248201527f4c5020746f6b656e206973206e6f742070726f6e6520746f2045524332302069604482015264737375657360d81b6064820152608401610542565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610c7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c9e919061343b565b60405163a9059cbb60e01b81529091506001600160a01b0384169063a9059cbb90610ccf9085908590600401613454565b600060405180830381600087803b158015610ce957600080fd5b505af1158015610cfd573d6000803e3d6000fd5b50505050505050565b600160046000828254610d1991906133a5565b909155505060045433600090815260126020526040902060038101546001600160a01b031680610d745760405162461bcd60e51b8152602060048201526006602482015265139bc813919560d21b6044820152606401610542565b6003820180546001600160a01b0319169055610d8e61159a565b610d9733611efb565b6000606483600201546064610dac91906133a5565b8454610db891906133b8565b610dc291906133cf565b9050808360000154600b54610dd791906133a5565b610de191906133f1565b600b5560006002840155600480840154604051633263830f60e21b81526001600160a01b0385169263c98e0c3c92610e1b92339201613454565b6020604051808303816000875af1158015610e3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e5e919061348a565b505050506004548114610e835760405162461bcd60e51b815260040161054290613404565b50565b33610e8f61152c565b6001600160a01b031614610eb55760405162461bcd60e51b81526004016105429061336b565b8051825114610ef55760405162461bcd60e51b815260206004820152600c60248201526b0eee4dedcce40d8cadccee8d60a31b6044820152606401610542565b60005b81518110156110a05760006001600160a01b0316838281518110610f1e57610f1e6134a7565b60200260200101516001600160a01b031603610f6b5760405162461bcd60e51b815260206004820152600c60248201526b5a65726f206164647265737360a01b6044820152606401610542565b818181518110610f7d57610f7d6134a7565b602002602001015160000361100357610fb9838281518110610fa157610fa16134a7565b60200260200101516006611fba90919063ffffffff16565b50600060136000858481518110610fd257610fd26134a7565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000208190555061108e565b611030838281518110611018576110186134a7565b602002602001015160066120fc90919063ffffffff16565b50818181518110611043576110436134a7565b602002602001015160136000858481518110611061576110616134a7565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055505b80611098816134bd565b915050610ef8565b505050565b6001600460008282546110b891906133a5565b909155505060045460115460ff1661111c5760405162461bcd60e51b815260206004820152602160248201527f546865206661726d206973206e6f7420656e61626c6564206279206f776e65726044820152602160f81b6064820152608401610542565b600e546001600160a01b038681169116148061115157506001600160a01b038581166000908152601460205260409020541633145b61135557600e546001600160a01b031633146111af5760405162461bcd60e51b815260206004820152601d60248201527f547279696e6720746f206465706f7369742077726f6e6720746f6b656e0000006044820152606401610542565b6001600160a01b038516600090815260126020526040902054701d6329f1c35ca4bfabb9f56100000000006111e486836133a5565b11156112235760405162461bcd60e51b815260206004820152600e60248201526d06578636565642074686520746f760941b6044820152606401610542565b61122b61159a565b61123486611efb565b8415611310576001600160a01b03861660009081526012602052604081206002015460649061126390826133a5565b61126d90846133b8565b61127791906133cf565b6001600160a01b038816600090815260126020526040812060020154919250906064906112a490826133a5565b6112ae89866133a5565b6112b891906133b8565b6112c291906133cf565b90508181600b546112d391906133a5565b6112dd91906133f1565b600b556001600160a01b038816600090815260126020526040812080548992906113089084906133a5565b909155505050505b856001600160a01b03167f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d8660405161134b91815260200190565b60405180910390a2505b60045481146113765760405162461bcd60e51b815260040161054290613404565b5050505050565b3361138661152c565b6001600160a01b0316146113ac5760405162461bcd60e51b81526004016105429061336b565b600554604051630d18304560e21b81523060048201526001600160a01b0390911690633460c11490602401602060405180830381865afa1580156113f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611418919061348a565b156114655760405162461bcd60e51b815260206004820152601760248201527f4661726d206d757374206e6f74206265206163746976650000000000000000006044820152606401610542565b600d546040516370a0823160e01b81523060048201526001600160a01b039091169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156114b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114db919061343b565b6040518363ffffffff1660e01b81526004016114f8929190613454565b600060405180830381600087803b15801561151257600080fd5b505af1158015611526573d6000803e3d6000fd5b50505050565b60055460408051638da5cb5b60e01b815290516000926001600160a01b031691638da5cb5b9160048083019260209291908290030181865afa158015611576573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fe919061346d565b60055460405163032453f160e51b81523060048201526001600160a01b039091169063648a7e2090602401600060405180830381600087803b1580156115df57600080fd5b505af11580156115f3573d6000803e3d6000fd5b50505050600f54421161160257565b600b546000036116125742600f55565b6000600f544261162291906133f1565b905060006103e8611631610791565b611639611763565b61164390856133b8565b61164d91906133b8565b61165791906133cf565b600b5490915061166f82670de0b6b3a76400006133b8565b61167991906133cf565b60105461168691906133a5565b601055505042600f55565b3361169a61152c565b6001600160a01b0316146116c05760405162461bcd60e51b81526004016105429061336b565b6011805460ff1916911515919091179055565b336116dc61152c565b6001600160a01b0316146117025760405162461bcd60e51b81526004016105429061336b565b6001600160a01b03811661171557600080fd5b600c80546001600160a01b0319166001600160a01b0383169081179091556040519081527f624b5eb8351863c55d945dc0de9319fcb2547eef7e762196fd564d95eb9d44c0906020016105a8565b6005546040805163da5b4ee760e01b815290516000926001600160a01b03169163da5b4ee79160048083019260209291908290030181865afa1580156107da573d6000803e3d6000fd5b6001600460008282546117c091906133a5565b9091555050600480543360008181526012602052604090819020600e548154925163a9059cbb60e01b8152949591946001600160a01b039091169363a9059cbb9361180f939192909101613454565b600060405180830381600087803b15801561182957600080fd5b505af115801561183d573d6000803e3d6000fd5b505082546040519081523392507f5fafa99d0643513820be26656b45130b01e1c03062e1266bf36f88cbd3bd9695915060200160405180910390a2600060648260020154606461188d91906133a5565b835461189991906133b8565b6118a391906133cf565b905080600b54106118cb5780600b60008282546118c091906133f1565b909155506118d19050565b6000600b555b5060008082556001909101556004548114610e835760405162461bcd60e51b815260040161054290613404565b606080600061190c60065490565b90508067ffffffffffffffff811115611927576119276130c8565b604051908082528060200260200182016040528015611950578160200160208202803683370190505b5092508067ffffffffffffffff81111561196c5761196c6130c8565b604051908082528060200260200182016040528015611995578160200160208202803683370190505b50915060005b81811015611a4e576119ae60068261215f565b8482815181106119c0576119c06134a7565b60200260200101906001600160a01b031690816001600160a01b031681525050601360008583815181106119f6576119f66134a7565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054838281518110611a3157611a316134a7565b602090810291909101015280611a46816134bd565b91505061199b565b50509091565b6001600160a01b0381166000908152601260205260408120601054600f5442118015611a815750600b5415155b15611aff576000600f5442611a9691906133f1565b905060006103e8611aa5610791565b611aad611763565b611ab790856133b8565b611ac191906133b8565b611acb91906133cf565b600b54909150611ae382670de0b6b3a76400006133b8565b611aed91906133cf565b601054611afa91906133a5565b925050505b6000606483600201546064611b1491906133a5565b8454611b2091906133b8565b611b2a91906133cf565b9050670de0b6b3a7640000836001015483611b4591906133f1565b611b4f90836133b8565b611b5991906133cf565b6008549094506000906001600160a01b031615611bfa576008546040516356c5f34960e01b81526001600160a01b038881166004830152909116906356c5f34990602401602060405180830381865afa158015611bba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bde919061343b565b9050612710611bed82876133b8565b611bf791906133cf565b90505b6000612710600a5487611c0d91906133b8565b611c1791906133cf565b9050600061271060095488611c2c91906133b8565b611c3691906133cf565b905081611c4382856133a5565b611c4d91906133a5565b611c5790886133f1565b98975050505050505050565b6000611c6d61159a565b6000611c78336121ee565b91508115611df957600e5460408051630dfe168160e01b815290516000926001600160a01b031691630dfe16819160048083019260209291908290030181865afa158015611cca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cee919061346d565b90506000600e60009054906101000a90046001600160a01b03166001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d69919061346d565b600d549091506001600160a01b0390811690831603611d9357611d8c8482612501565b9250611dc1565b600d546001600160a01b0390811690821603611db357611d8c8483612501565b611dbe84838361272f565b92505b60405184815233907f7fc89d3ed4e23fda6ebcec646a642fe679e98dfc053a073434dfaf6ec6f4ed6f9060200160405180910390a250505b8015611ed3573360009081526012602052604081208054600282015491929091606490611e2690826133a5565b611e3090846133b8565b611e3a91906133cf565b90506000606484600201546064611e5191906133a5565b611e5b87866133a5565b611e6591906133b8565b611e6f91906133cf565b90508181600b54611e8091906133a5565b611e8a91906133f1565b600b55611e9785846133a5565b845560405185815233907f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d9060200160405180910390a2505050505b5090565b6001600160a01b038116600090815260018301602052604090205415155b92915050565b6000611f06826121ee565b90508015611f7357600d5460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb90611f409085908590600401613454565b600060405180830381600087803b158015611f5a57600080fd5b505af1158015611f6e573d6000803e3d6000fd5b505050505b816001600160a01b03167fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e048682604051611fae91815260200190565b60405180910390a25050565b6001600160a01b038116600090815260018301602052604081205480156120f2576000611fe86001836133f1565b8554909150600090611ffc906001906133f1565b90506000866000018281548110612015576120156134a7565b60009182526020909120015487546001600160a01b0390911691508190889085908110612044576120446134a7565b600091825260209091200180546001600160a01b0319166001600160a01b03929092169190911790556120788360016133a5565b6001600160a01b038216600090815260018901602052604090205586548790806120a4576120a46134d6565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0388168252600189810190915260408220919091559450611ef59350505050565b6000915050611ef5565b60006121088383611ed7565b61215757508154600180820184556000848152602080822090930180546001600160a01b0319166001600160a01b03861690811790915585549082528286019093526040902091909155611ef5565b506000611ef5565b815460009082106121bd5760405162461bcd60e51b815260206004820152602260248201527f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e604482015261647360f01b6064820152608401610542565b8260000182815481106121d2576121d26134a7565b6000918252602090912001546001600160a01b03169392505050565b6001600160a01b03811660009081526012602052604081206002810154829060649061221a90826133a5565b835461222691906133b8565b61223091906133cf565b9050670de0b6b3a7640000826001015460105461224d91906133f1565b61225790836133b8565b61226191906133cf565b925082156124f2576008546000906001600160a01b0316156122ee576008546040516356c5f34960e01b81526001600160a01b038781166004830152909116906356c5f34990602401602060405180830381865afa1580156122c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122eb919061343b565b90505b80156123b35761271061230182866133b8565b61230b91906133cf565b604080516001600160a01b03881660208201529192506000910160408051601f1981840301815290829052600d54600854635f22feb160e11b84529193506001600160a01b039081169263be45fd629261236d92169086908690600401613532565b6020604051808303816000875af115801561238c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123b0919061348a565b50505b6000612710600a54866123c691906133b8565b6123d091906133cf565b9050801561243f57600d5460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb9061240c9061dead908590600401613454565b600060405180830381600087803b15801561242657600080fd5b505af115801561243a573d6000803e3d6000fd5b505050505b60006127106009548761245291906133b8565b61245c91906133cf565b905080156124cd57600d54600c5460405163a9059cbb60e01b81526001600160a01b039283169263a9059cbb9261249a929116908590600401613454565b600060405180830381600087803b1580156124b457600080fd5b505af11580156124c8573d6000803e3d6000fd5b505050505b816124d882856133a5565b6124e291906133a5565b6124ec90876133f1565b95505050505b50601054600190910155919050565b6000806000600e60009054906101000a90046001600160a01b03166001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015612559573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257d9190613579565b50600d546001600160701b039283169450911691506001600160a01b0390811690851610156125a857905b60006125b48684612967565b905060006125c38285856129da565b600e549091506125de906001600160a01b0316838389612a1e565b6125e882886133f1565b600d54600e5460405163a9059cbb60e01b81529294506001600160a01b039182169263a9059cbb926126209216908690600401613454565b600060405180830381600087803b15801561263a57600080fd5b505af115801561264e573d6000803e3d6000fd5b5050600e5460405163a9059cbb60e01b81526001600160a01b03808b16945063a9059cbb93506126849216908590600401613454565b600060405180830381600087803b15801561269e57600080fd5b505af11580156126b2573d6000803e3d6000fd5b5050600e546040516335313c2160e11b81523060048201526001600160a01b039091169250636a62784291506024016020604051808303816000875af1158015612700573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612724919061343b565b979650505050505050565b60008060008061273f8686612b26565b600e5492955090935091506001600160a01b038083169116146127945760405162461bcd60e51b815260206004820152600d60248201526c77726f6e6720666163746f727960981b6044820152606401610542565b600d54600090819081906127b1906001600160a01b03168a612b26565b600d549295509093509150600090819081906127d6906001600160a01b03168c612b26565b9250925092506127eb8d878786868e8e612c2a565b929850909650935091506128018487878f612a1e565b61280d8184848e612a1e565b600e5460405163a9059cbb60e01b81526001600160a01b038e81169263a9059cbb9261284192909116908990600401613454565b600060405180830381600087803b15801561285b57600080fd5b505af115801561286f573d6000803e3d6000fd5b505050508a6001600160a01b031663a9059cbb600e60009054906101000a90046001600160a01b0316846040518363ffffffff1660e01b81526004016128b6929190613454565b600060405180830381600087803b1580156128d057600080fd5b505af11580156128e4573d6000803e3d6000fd5b5050600e546040516335313c2160e11b81523060048201526001600160a01b039091169250636a62784291506024016020604051808303816000875af1158015612932573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612956919061343b565b9d9c50505050505050505050505050565b6000808361297884623ce9c06133b8565b61298291906133b8565b8361299081623ce9c46133b8565b61299a91906133b8565b6129a491906133a5565b90506107cc6129b5846107ce6133b8565b6129be83612d4b565b6129c891906133f1565b6129d291906133cf565b949350505050565b6000806129e9856103e66133b8565b905060006129f784836133b8565b9050600082612a08876103e86133b8565b612a1291906133a5565b905061272481836133cf565b600d5460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb90612a509087908790600401613454565b600060405180830381600087803b158015612a6a57600080fd5b505af1158015612a7e573d6000803e3d6000fd5b5050600d54600092508291506001600160a01b03808516911610612aa457836000612aa8565b6000845b6040805160008152602081019182905263022c0d9f60e01b90915291935091506001600160a01b0387169063022c0d9f90612aec90859085903090602481016135c9565b600060405180830381600087803b158015612b0657600080fd5b505af1158015612b1a573d6000803e3d6000fd5b50505050505050505050565b6000806000612b358585612dbb565b9050806001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015612b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b999190613579565b506001600160701b0391821694501691508215801590612bb95750600082115b612c055760405162461bcd60e51b815260206004820152601960248201527f7265696e76657374506f6f6c733a2070616972206572726f72000000000000006044820152606401610542565b846001600160a01b0316846001600160a01b03161015612c23579091905b9250925092565b60008080808085612c3b888a6133b8565b612c4591906133cf565b905060006103e8612c588e6103e66133b8565b612c6291906133cf565b905080612c6f8b8e6133a5565b612c7991906133a5565b9750612c85818d6133a5565b612c8f90836133b8565b612c99828c6133a5565b612ca3908d6133b8565b612cad91906133a5565b9650612cba8860026133b8565b612cc490886133cf565b96508088612cd2848e6133b8565b612cdc91906133cf565b612ce691906133b8565b9050612d0581612cf689806133b8565b612d0091906133f1565b612d4b565b612d0f90886133f1565b9050612d1c818d8d612ebb565b9b50995089612d2b8c8e6133f1565b9050612d38818b8b6129da565b9b9d9a9c509a9998505050505050505050565b60006003821115612dac5750806000612d656002836133cf565b612d709060016133a5565b90505b81811015612da657905080600281612d8b81866133cf565b612d9591906133a5565b612d9f91906133cf565b9050612d73565b50919050565b8115612db6575060015b919050565b6000739cc7c769ea3b37f1af0ad642a268b80dc80754c581806001600160a01b0380861690871610612dee578486612df1565b85855b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b1660348201529193509150839060480160405160208183030381529060405280519060200120604051602001612e999291906001600160f81b0319815260609290921b6bffffffffffffffffffffffff1916600183015260158201527fe410ea0a25ce340e309f2f0fe9d58d787bb87dd63d02333e8a9a747230f61758603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b6000808411612f0c5760405162461bcd60e51b815260206004820152601a60248201527f494e53554646494349454e545f4f55545055545f414d4f554e540000000000006044820152606401610542565b6000612f1885856133b8565b612f24906103e86133b8565b90506000612f3286856133f1565b612f3e906103e66133b8565b9050612f4a81836133cf565b612f559060016133a5565b9695505050505050565b6001600160a01b0381168114610e8357600080fd5b600060208284031215612f8657600080fd5b8135612f9181612f5f565b9392505050565b60008060408385031215612fab57600080fd5b50508035926020909101359150565b60008083601f840112612fcc57600080fd5b50813567ffffffffffffffff811115612fe457600080fd5b602083019150836020828501011115612ffc57600080fd5b9250929050565b60008060008060006080868803121561301b57600080fd5b853561302681612f5f565b9450602086013561303681612f5f565b935060408601359250606086013567ffffffffffffffff81111561305957600080fd5b61306588828901612fba565b969995985093965092949392505050565b60006020828403121561308857600080fd5b5035919050565b600080604083850312156130a257600080fd5b82356130ad81612f5f565b915060208301356130bd81612f5f565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613107576131076130c8565b604052919050565b600067ffffffffffffffff821115613129576131296130c8565b5060051b60200190565b600082601f83011261314457600080fd5b813560206131596131548361310f565b6130de565b82815260059290921b8401810191818101908684111561317857600080fd5b8286015b84811015613193578035835291830191830161317c565b509695505050505050565b600080604083850312156131b157600080fd5b823567ffffffffffffffff808211156131c957600080fd5b818501915085601f8301126131dd57600080fd5b813560206131ed6131548361310f565b82815260059290921b8401810191818101908984111561320c57600080fd5b948201945b8386101561323357853561322481612f5f565b82529482019490820190613211565b9650508601359250508082111561324957600080fd5b5061325685828601613133565b9150509250929050565b6000806000806060858703121561327657600080fd5b843561328181612f5f565b935060208501359250604085013567ffffffffffffffff8111156132a457600080fd5b6132b087828801612fba565b95989497509550505050565b8015158114610e8357600080fd5b6000602082840312156132dc57600080fd5b8135612f91816132bc565b604080825283519082018190526000906020906060840190828701845b828110156133295781516001600160a01b031684529284019290840190600101613304565b5050508381038285015284518082528583019183019060005b8181101561335e57835183529284019291840191600101613342565b5090979650505050505050565b6020808252600a908201526937b7363c9037bbb732b960b11b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b80820180821115611ef557611ef561338f565b8082028115828204841417611ef557611ef561338f565b6000826133ec57634e487b7160e01b600052601260045260246000fd5b500490565b81810381811115611ef557611ef561338f565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60006020828403121561344d57600080fd5b5051919050565b6001600160a01b03929092168252602082015260400190565b60006020828403121561347f57600080fd5b8151612f9181612f5f565b60006020828403121561349c57600080fd5b8151612f91816132bc565b634e487b7160e01b600052603260045260246000fd5b6000600182016134cf576134cf61338f565b5060010190565b634e487b7160e01b600052603160045260246000fd5b6000815180845260005b81811015613512576020818501810151868301820152016134f6565b506000602082860101526020601f19601f83011685010191505092915050565b60018060a01b038416815282602082015260606040820152600061355960608301846134ec565b95945050505050565b80516001600160701b0381168114612db657600080fd5b60008060006060848603121561358e57600080fd5b61359784613562565b92506135a560208501613562565b9150604084015163ffffffff811681146135be57600080fd5b809150509250925092565b84815283602082015260018060a01b0383166040820152608060608201526000612f5560808301846134ec56fea2646970667358221220c576146de5bd9eddef1936e5eb619b08d3df4998fd9db0c3b381cab6e0f6235d64736f6c6343000812003300000000000000000000000000000000000000000000000000000000000000000000000000000000000000001cee27d0627ce8a81df9b4d7eee0d753b8c2f613
Deployed ByteCode
0x608060405234801561001057600080fd5b506004361061021c5760003560e01c80635fcbd28511610125578063d1af0c7d116100ad578063f40f0f521161007c578063f40f0f52146104dd578063f8077fae146104f0578063fccc2813146104f9578063fce589d814610502578063fdb5a03e1461050b57600080fd5b8063d1af0c7d146104a4578063da5b4ee7146104b7578063db2e21bc146104bf578063e8eed972146104c757600080fd5b80638da5cb5b116100f45780638da5cb5b1461046557806397c4fac71461046d578063a2e6204514610476578063acec338a1461047e578063d08e7b691461049157600080fd5b80635fcbd2851461042457806373af2516146104375780638943ec021461044a5780638cb7e27c1461045d57600080fd5b80633a98ef39116101a85780634f3a1ff8116101775780634f3a1ff8146103d057806352313461146103e35780635b158b3c146103f65780635d799f87146104095780635e38c9541461041c57600080fd5b80633a98ef391461036b5780633c6b16ab14610374578063400250dc146103875780634e48ad3a146103b057600080fd5b80631959a002116101ef5780631959a002146102975780631e29653c1461030e5780632401273c146103245780632e1a7d4d1461034f57806336d421951461036257600080fd5b806301bc71131461022157806302fb0c5e146102365780630b78f9c014610258578063150b7a021461026b575b600080fd5b61023461022f366004612f74565b610513565b005b6011546102439060ff1681565b60405190151581526020015b60405180910390f35b610234610266366004612f98565b6105b3565b61027e610279366004613003565b610608565b6040516001600160e01b0319909116815260200161024f565b6102dd6102a5366004612f74565b601260205260009081526040902080546001820154600283015460038401546004909401549293919290916001600160a01b03169085565b604080519586526020860194909452928401919091526001600160a01b03166060830152608082015260a00161024f565b610316610791565b60405190815260200161024f565b600c54610337906001600160a01b031681565b6040516001600160a01b03909116815260200161024f565b61023461035d366004613076565b610803565b61031660105481565b610316600b5481565b610234610382366004613076565b6109d2565b610337610395366004612f74565b6014602052600090815260409020546001600160a01b031681565b6103166103be366004612f74565b60136020526000908152604090205481565b600554610337906001600160a01b031681565b600854610337906001600160a01b031681565b610234610404366004612f74565b610a02565b61023461041736600461308f565b610b28565b610234610d06565b600e54610337906001600160a01b031681565b61023461044536600461319e565b610e86565b610234610458366004613260565b6110a5565b61023461137d565b61033761152c565b61031660095481565b61023461159a565b61023461048c3660046132ca565b611691565b61023461049f366004612f74565b6116d3565b600d54610337906001600160a01b031681565b610316611763565b6102346117ad565b6104cf6118fe565b60405161024f9291906132e7565b6103166104eb366004612f74565b611a54565b610316600f5481565b61033761dead81565b610316600a5481565b610316611c63565b3361051c61152c565b6001600160a01b03161461054b5760405162461bcd60e51b81526004016105429061336b565b60405180910390fd5b6001600160a01b03811661055e57600080fd5b600880546001600160a01b0319166001600160a01b0383169081179091556040519081527f4cc2fbf2911e773499430576cc26e11ebc7a7d9bca28a2456b2040b2e2a5e338906020015b60405180910390a150565b336105bc61152c565b6001600160a01b0316146105e25760405162461bcd60e51b81526004016105429061336b565b612710821080156105f4575061271081105b6105fd57600080fd5b600a91909155600955565b600060016004600082825461061d91906133a5565b9091555050600454610630600633611ed7565b61066e5760405162461bcd60e51b815260206004820152600f60248201526e139bdd081848189bdbdcdd08139195608a1b6044820152606401610542565b6001600160a01b0380871660009081526012602052604090206003810154909116156106d05760405162461bcd60e51b815260206004820152601160248201527013919508185b1c9958591e481859191959607a1b6044820152606401610542565b6106d861159a565b6106e187611efb565b6003810180546001600160a01b03191633908117909155600090815260136020526040812054600283018190556004830188905560649061072290826133a5565b835461072e91906133b8565b61073891906133cf565b9050816000015481600b5461074d91906133a5565b61075791906133f1565b600b5550630a85bd0160e11b92505060045481146107875760405162461bcd60e51b815260040161054290613404565b5095945050505050565b60055460405163389bbbfd60e21b81523060048201526000916001600160a01b03169063e26eeff490602401602060405180830381865afa1580156107da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fe919061343b565b905090565b60016004600082825461081691906133a5565b909155505060045433600090815260126020526040902080548311156108735760405162461bcd60e51b81526020600482015260126024820152711dda5d1a191c985dce881b9bdd0819dbdbd960721b6044820152606401610542565b61087b61159a565b61088433611efb565b821561097757600060648260020154606461089f91906133a5565b83546108ab91906133b8565b6108b591906133cf565b82549091506108c59085906133f1565b825560028201546000906064906108dc90826133a5565b84546108e891906133b8565b6108f291906133cf565b90508181600b5461090391906133a5565b61090d91906133f1565b600b55600e5460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb906109429033908990600401613454565b600060405180830381600087803b15801561095c57600080fd5b505af1158015610970573d6000803e3d6000fd5b5050505050505b60405183815233907f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a94243649060200160405180910390a25060045481146109ce5760405162461bcd60e51b815260040161054290613404565b5050565b6040518181527fde88a922e0d3b88b24e9623efeb464919c6bf9f66857a65e2bfcf2ce87a9433d906020016105a8565b33610a0b61152c565b6001600160a01b031614610a315760405162461bcd60e51b81526004016105429061336b565b6001600160a01b038116610a4457600080fd5b336001600160a01b0316816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab0919061346d565b6001600160a01b031614610b065760405162461bcd60e51b815260206004820152601e60248201527f4e657720636f6e74726163742068617320616e6f74686572206f776e657200006044820152606401610542565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b33610b3161152c565b6001600160a01b031614610b575760405162461bcd60e51b81526004016105429061336b565b600d546001600160a01b0390811690831603610bc75760405162461bcd60e51b815260206004820152602960248201527f52657761726420746f6b656e206973206e6f742070726f6e6520746f2045524360448201526832302069737375657360b81b6064820152608401610542565b600e546001600160a01b0390811690831603610c335760405162461bcd60e51b815260206004820152602560248201527f4c5020746f6b656e206973206e6f742070726f6e6520746f2045524332302069604482015264737375657360d81b6064820152608401610542565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610c7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c9e919061343b565b60405163a9059cbb60e01b81529091506001600160a01b0384169063a9059cbb90610ccf9085908590600401613454565b600060405180830381600087803b158015610ce957600080fd5b505af1158015610cfd573d6000803e3d6000fd5b50505050505050565b600160046000828254610d1991906133a5565b909155505060045433600090815260126020526040902060038101546001600160a01b031680610d745760405162461bcd60e51b8152602060048201526006602482015265139bc813919560d21b6044820152606401610542565b6003820180546001600160a01b0319169055610d8e61159a565b610d9733611efb565b6000606483600201546064610dac91906133a5565b8454610db891906133b8565b610dc291906133cf565b9050808360000154600b54610dd791906133a5565b610de191906133f1565b600b5560006002840155600480840154604051633263830f60e21b81526001600160a01b0385169263c98e0c3c92610e1b92339201613454565b6020604051808303816000875af1158015610e3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e5e919061348a565b505050506004548114610e835760405162461bcd60e51b815260040161054290613404565b50565b33610e8f61152c565b6001600160a01b031614610eb55760405162461bcd60e51b81526004016105429061336b565b8051825114610ef55760405162461bcd60e51b815260206004820152600c60248201526b0eee4dedcce40d8cadccee8d60a31b6044820152606401610542565b60005b81518110156110a05760006001600160a01b0316838281518110610f1e57610f1e6134a7565b60200260200101516001600160a01b031603610f6b5760405162461bcd60e51b815260206004820152600c60248201526b5a65726f206164647265737360a01b6044820152606401610542565b818181518110610f7d57610f7d6134a7565b602002602001015160000361100357610fb9838281518110610fa157610fa16134a7565b60200260200101516006611fba90919063ffffffff16565b50600060136000858481518110610fd257610fd26134a7565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000208190555061108e565b611030838281518110611018576110186134a7565b602002602001015160066120fc90919063ffffffff16565b50818181518110611043576110436134a7565b602002602001015160136000858481518110611061576110616134a7565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055505b80611098816134bd565b915050610ef8565b505050565b6001600460008282546110b891906133a5565b909155505060045460115460ff1661111c5760405162461bcd60e51b815260206004820152602160248201527f546865206661726d206973206e6f7420656e61626c6564206279206f776e65726044820152602160f81b6064820152608401610542565b600e546001600160a01b038681169116148061115157506001600160a01b038581166000908152601460205260409020541633145b61135557600e546001600160a01b031633146111af5760405162461bcd60e51b815260206004820152601d60248201527f547279696e6720746f206465706f7369742077726f6e6720746f6b656e0000006044820152606401610542565b6001600160a01b038516600090815260126020526040902054701d6329f1c35ca4bfabb9f56100000000006111e486836133a5565b11156112235760405162461bcd60e51b815260206004820152600e60248201526d06578636565642074686520746f760941b6044820152606401610542565b61122b61159a565b61123486611efb565b8415611310576001600160a01b03861660009081526012602052604081206002015460649061126390826133a5565b61126d90846133b8565b61127791906133cf565b6001600160a01b038816600090815260126020526040812060020154919250906064906112a490826133a5565b6112ae89866133a5565b6112b891906133b8565b6112c291906133cf565b90508181600b546112d391906133a5565b6112dd91906133f1565b600b556001600160a01b038816600090815260126020526040812080548992906113089084906133a5565b909155505050505b856001600160a01b03167f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d8660405161134b91815260200190565b60405180910390a2505b60045481146113765760405162461bcd60e51b815260040161054290613404565b5050505050565b3361138661152c565b6001600160a01b0316146113ac5760405162461bcd60e51b81526004016105429061336b565b600554604051630d18304560e21b81523060048201526001600160a01b0390911690633460c11490602401602060405180830381865afa1580156113f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611418919061348a565b156114655760405162461bcd60e51b815260206004820152601760248201527f4661726d206d757374206e6f74206265206163746976650000000000000000006044820152606401610542565b600d546040516370a0823160e01b81523060048201526001600160a01b039091169063a9059cbb90339083906370a0823190602401602060405180830381865afa1580156114b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114db919061343b565b6040518363ffffffff1660e01b81526004016114f8929190613454565b600060405180830381600087803b15801561151257600080fd5b505af1158015611526573d6000803e3d6000fd5b50505050565b60055460408051638da5cb5b60e01b815290516000926001600160a01b031691638da5cb5b9160048083019260209291908290030181865afa158015611576573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fe919061346d565b60055460405163032453f160e51b81523060048201526001600160a01b039091169063648a7e2090602401600060405180830381600087803b1580156115df57600080fd5b505af11580156115f3573d6000803e3d6000fd5b50505050600f54421161160257565b600b546000036116125742600f55565b6000600f544261162291906133f1565b905060006103e8611631610791565b611639611763565b61164390856133b8565b61164d91906133b8565b61165791906133cf565b600b5490915061166f82670de0b6b3a76400006133b8565b61167991906133cf565b60105461168691906133a5565b601055505042600f55565b3361169a61152c565b6001600160a01b0316146116c05760405162461bcd60e51b81526004016105429061336b565b6011805460ff1916911515919091179055565b336116dc61152c565b6001600160a01b0316146117025760405162461bcd60e51b81526004016105429061336b565b6001600160a01b03811661171557600080fd5b600c80546001600160a01b0319166001600160a01b0383169081179091556040519081527f624b5eb8351863c55d945dc0de9319fcb2547eef7e762196fd564d95eb9d44c0906020016105a8565b6005546040805163da5b4ee760e01b815290516000926001600160a01b03169163da5b4ee79160048083019260209291908290030181865afa1580156107da573d6000803e3d6000fd5b6001600460008282546117c091906133a5565b9091555050600480543360008181526012602052604090819020600e548154925163a9059cbb60e01b8152949591946001600160a01b039091169363a9059cbb9361180f939192909101613454565b600060405180830381600087803b15801561182957600080fd5b505af115801561183d573d6000803e3d6000fd5b505082546040519081523392507f5fafa99d0643513820be26656b45130b01e1c03062e1266bf36f88cbd3bd9695915060200160405180910390a2600060648260020154606461188d91906133a5565b835461189991906133b8565b6118a391906133cf565b905080600b54106118cb5780600b60008282546118c091906133f1565b909155506118d19050565b6000600b555b5060008082556001909101556004548114610e835760405162461bcd60e51b815260040161054290613404565b606080600061190c60065490565b90508067ffffffffffffffff811115611927576119276130c8565b604051908082528060200260200182016040528015611950578160200160208202803683370190505b5092508067ffffffffffffffff81111561196c5761196c6130c8565b604051908082528060200260200182016040528015611995578160200160208202803683370190505b50915060005b81811015611a4e576119ae60068261215f565b8482815181106119c0576119c06134a7565b60200260200101906001600160a01b031690816001600160a01b031681525050601360008583815181106119f6576119f66134a7565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054838281518110611a3157611a316134a7565b602090810291909101015280611a46816134bd565b91505061199b565b50509091565b6001600160a01b0381166000908152601260205260408120601054600f5442118015611a815750600b5415155b15611aff576000600f5442611a9691906133f1565b905060006103e8611aa5610791565b611aad611763565b611ab790856133b8565b611ac191906133b8565b611acb91906133cf565b600b54909150611ae382670de0b6b3a76400006133b8565b611aed91906133cf565b601054611afa91906133a5565b925050505b6000606483600201546064611b1491906133a5565b8454611b2091906133b8565b611b2a91906133cf565b9050670de0b6b3a7640000836001015483611b4591906133f1565b611b4f90836133b8565b611b5991906133cf565b6008549094506000906001600160a01b031615611bfa576008546040516356c5f34960e01b81526001600160a01b038881166004830152909116906356c5f34990602401602060405180830381865afa158015611bba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bde919061343b565b9050612710611bed82876133b8565b611bf791906133cf565b90505b6000612710600a5487611c0d91906133b8565b611c1791906133cf565b9050600061271060095488611c2c91906133b8565b611c3691906133cf565b905081611c4382856133a5565b611c4d91906133a5565b611c5790886133f1565b98975050505050505050565b6000611c6d61159a565b6000611c78336121ee565b91508115611df957600e5460408051630dfe168160e01b815290516000926001600160a01b031691630dfe16819160048083019260209291908290030181865afa158015611cca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cee919061346d565b90506000600e60009054906101000a90046001600160a01b03166001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d69919061346d565b600d549091506001600160a01b0390811690831603611d9357611d8c8482612501565b9250611dc1565b600d546001600160a01b0390811690821603611db357611d8c8483612501565b611dbe84838361272f565b92505b60405184815233907f7fc89d3ed4e23fda6ebcec646a642fe679e98dfc053a073434dfaf6ec6f4ed6f9060200160405180910390a250505b8015611ed3573360009081526012602052604081208054600282015491929091606490611e2690826133a5565b611e3090846133b8565b611e3a91906133cf565b90506000606484600201546064611e5191906133a5565b611e5b87866133a5565b611e6591906133b8565b611e6f91906133cf565b90508181600b54611e8091906133a5565b611e8a91906133f1565b600b55611e9785846133a5565b845560405185815233907f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d9060200160405180910390a2505050505b5090565b6001600160a01b038116600090815260018301602052604090205415155b92915050565b6000611f06826121ee565b90508015611f7357600d5460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb90611f409085908590600401613454565b600060405180830381600087803b158015611f5a57600080fd5b505af1158015611f6e573d6000803e3d6000fd5b505050505b816001600160a01b03167fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e048682604051611fae91815260200190565b60405180910390a25050565b6001600160a01b038116600090815260018301602052604081205480156120f2576000611fe86001836133f1565b8554909150600090611ffc906001906133f1565b90506000866000018281548110612015576120156134a7565b60009182526020909120015487546001600160a01b0390911691508190889085908110612044576120446134a7565b600091825260209091200180546001600160a01b0319166001600160a01b03929092169190911790556120788360016133a5565b6001600160a01b038216600090815260018901602052604090205586548790806120a4576120a46134d6565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0388168252600189810190915260408220919091559450611ef59350505050565b6000915050611ef5565b60006121088383611ed7565b61215757508154600180820184556000848152602080822090930180546001600160a01b0319166001600160a01b03861690811790915585549082528286019093526040902091909155611ef5565b506000611ef5565b815460009082106121bd5760405162461bcd60e51b815260206004820152602260248201527f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e604482015261647360f01b6064820152608401610542565b8260000182815481106121d2576121d26134a7565b6000918252602090912001546001600160a01b03169392505050565b6001600160a01b03811660009081526012602052604081206002810154829060649061221a90826133a5565b835461222691906133b8565b61223091906133cf565b9050670de0b6b3a7640000826001015460105461224d91906133f1565b61225790836133b8565b61226191906133cf565b925082156124f2576008546000906001600160a01b0316156122ee576008546040516356c5f34960e01b81526001600160a01b038781166004830152909116906356c5f34990602401602060405180830381865afa1580156122c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122eb919061343b565b90505b80156123b35761271061230182866133b8565b61230b91906133cf565b604080516001600160a01b03881660208201529192506000910160408051601f1981840301815290829052600d54600854635f22feb160e11b84529193506001600160a01b039081169263be45fd629261236d92169086908690600401613532565b6020604051808303816000875af115801561238c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123b0919061348a565b50505b6000612710600a54866123c691906133b8565b6123d091906133cf565b9050801561243f57600d5460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb9061240c9061dead908590600401613454565b600060405180830381600087803b15801561242657600080fd5b505af115801561243a573d6000803e3d6000fd5b505050505b60006127106009548761245291906133b8565b61245c91906133cf565b905080156124cd57600d54600c5460405163a9059cbb60e01b81526001600160a01b039283169263a9059cbb9261249a929116908590600401613454565b600060405180830381600087803b1580156124b457600080fd5b505af11580156124c8573d6000803e3d6000fd5b505050505b816124d882856133a5565b6124e291906133a5565b6124ec90876133f1565b95505050505b50601054600190910155919050565b6000806000600e60009054906101000a90046001600160a01b03166001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015612559573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257d9190613579565b50600d546001600160701b039283169450911691506001600160a01b0390811690851610156125a857905b60006125b48684612967565b905060006125c38285856129da565b600e549091506125de906001600160a01b0316838389612a1e565b6125e882886133f1565b600d54600e5460405163a9059cbb60e01b81529294506001600160a01b039182169263a9059cbb926126209216908690600401613454565b600060405180830381600087803b15801561263a57600080fd5b505af115801561264e573d6000803e3d6000fd5b5050600e5460405163a9059cbb60e01b81526001600160a01b03808b16945063a9059cbb93506126849216908590600401613454565b600060405180830381600087803b15801561269e57600080fd5b505af11580156126b2573d6000803e3d6000fd5b5050600e546040516335313c2160e11b81523060048201526001600160a01b039091169250636a62784291506024016020604051808303816000875af1158015612700573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612724919061343b565b979650505050505050565b60008060008061273f8686612b26565b600e5492955090935091506001600160a01b038083169116146127945760405162461bcd60e51b815260206004820152600d60248201526c77726f6e6720666163746f727960981b6044820152606401610542565b600d54600090819081906127b1906001600160a01b03168a612b26565b600d549295509093509150600090819081906127d6906001600160a01b03168c612b26565b9250925092506127eb8d878786868e8e612c2a565b929850909650935091506128018487878f612a1e565b61280d8184848e612a1e565b600e5460405163a9059cbb60e01b81526001600160a01b038e81169263a9059cbb9261284192909116908990600401613454565b600060405180830381600087803b15801561285b57600080fd5b505af115801561286f573d6000803e3d6000fd5b505050508a6001600160a01b031663a9059cbb600e60009054906101000a90046001600160a01b0316846040518363ffffffff1660e01b81526004016128b6929190613454565b600060405180830381600087803b1580156128d057600080fd5b505af11580156128e4573d6000803e3d6000fd5b5050600e546040516335313c2160e11b81523060048201526001600160a01b039091169250636a62784291506024016020604051808303816000875af1158015612932573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612956919061343b565b9d9c50505050505050505050505050565b6000808361297884623ce9c06133b8565b61298291906133b8565b8361299081623ce9c46133b8565b61299a91906133b8565b6129a491906133a5565b90506107cc6129b5846107ce6133b8565b6129be83612d4b565b6129c891906133f1565b6129d291906133cf565b949350505050565b6000806129e9856103e66133b8565b905060006129f784836133b8565b9050600082612a08876103e86133b8565b612a1291906133a5565b905061272481836133cf565b600d5460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb90612a509087908790600401613454565b600060405180830381600087803b158015612a6a57600080fd5b505af1158015612a7e573d6000803e3d6000fd5b5050600d54600092508291506001600160a01b03808516911610612aa457836000612aa8565b6000845b6040805160008152602081019182905263022c0d9f60e01b90915291935091506001600160a01b0387169063022c0d9f90612aec90859085903090602481016135c9565b600060405180830381600087803b158015612b0657600080fd5b505af1158015612b1a573d6000803e3d6000fd5b50505050505050505050565b6000806000612b358585612dbb565b9050806001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015612b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b999190613579565b506001600160701b0391821694501691508215801590612bb95750600082115b612c055760405162461bcd60e51b815260206004820152601960248201527f7265696e76657374506f6f6c733a2070616972206572726f72000000000000006044820152606401610542565b846001600160a01b0316846001600160a01b03161015612c23579091905b9250925092565b60008080808085612c3b888a6133b8565b612c4591906133cf565b905060006103e8612c588e6103e66133b8565b612c6291906133cf565b905080612c6f8b8e6133a5565b612c7991906133a5565b9750612c85818d6133a5565b612c8f90836133b8565b612c99828c6133a5565b612ca3908d6133b8565b612cad91906133a5565b9650612cba8860026133b8565b612cc490886133cf565b96508088612cd2848e6133b8565b612cdc91906133cf565b612ce691906133b8565b9050612d0581612cf689806133b8565b612d0091906133f1565b612d4b565b612d0f90886133f1565b9050612d1c818d8d612ebb565b9b50995089612d2b8c8e6133f1565b9050612d38818b8b6129da565b9b9d9a9c509a9998505050505050505050565b60006003821115612dac5750806000612d656002836133cf565b612d709060016133a5565b90505b81811015612da657905080600281612d8b81866133cf565b612d9591906133a5565b612d9f91906133cf565b9050612d73565b50919050565b8115612db6575060015b919050565b6000739cc7c769ea3b37f1af0ad642a268b80dc80754c581806001600160a01b0380861690871610612dee578486612df1565b85855b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b1660348201529193509150839060480160405160208183030381529060405280519060200120604051602001612e999291906001600160f81b0319815260609290921b6bffffffffffffffffffffffff1916600183015260158201527fe410ea0a25ce340e309f2f0fe9d58d787bb87dd63d02333e8a9a747230f61758603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b6000808411612f0c5760405162461bcd60e51b815260206004820152601a60248201527f494e53554646494349454e545f4f55545055545f414d4f554e540000000000006044820152606401610542565b6000612f1885856133b8565b612f24906103e86133b8565b90506000612f3286856133f1565b612f3e906103e66133b8565b9050612f4a81836133cf565b612f559060016133a5565b9695505050505050565b6001600160a01b0381168114610e8357600080fd5b600060208284031215612f8657600080fd5b8135612f9181612f5f565b9392505050565b60008060408385031215612fab57600080fd5b50508035926020909101359150565b60008083601f840112612fcc57600080fd5b50813567ffffffffffffffff811115612fe457600080fd5b602083019150836020828501011115612ffc57600080fd5b9250929050565b60008060008060006080868803121561301b57600080fd5b853561302681612f5f565b9450602086013561303681612f5f565b935060408601359250606086013567ffffffffffffffff81111561305957600080fd5b61306588828901612fba565b969995985093965092949392505050565b60006020828403121561308857600080fd5b5035919050565b600080604083850312156130a257600080fd5b82356130ad81612f5f565b915060208301356130bd81612f5f565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613107576131076130c8565b604052919050565b600067ffffffffffffffff821115613129576131296130c8565b5060051b60200190565b600082601f83011261314457600080fd5b813560206131596131548361310f565b6130de565b82815260059290921b8401810191818101908684111561317857600080fd5b8286015b84811015613193578035835291830191830161317c565b509695505050505050565b600080604083850312156131b157600080fd5b823567ffffffffffffffff808211156131c957600080fd5b818501915085601f8301126131dd57600080fd5b813560206131ed6131548361310f565b82815260059290921b8401810191818101908984111561320c57600080fd5b948201945b8386101561323357853561322481612f5f565b82529482019490820190613211565b9650508601359250508082111561324957600080fd5b5061325685828601613133565b9150509250929050565b6000806000806060858703121561327657600080fd5b843561328181612f5f565b935060208501359250604085013567ffffffffffffffff8111156132a457600080fd5b6132b087828801612fba565b95989497509550505050565b8015158114610e8357600080fd5b6000602082840312156132dc57600080fd5b8135612f91816132bc565b604080825283519082018190526000906020906060840190828701845b828110156133295781516001600160a01b031684529284019290840190600101613304565b5050508381038285015284518082528583019183019060005b8181101561335e57835183529284019291840191600101613342565b5090979650505050505050565b6020808252600a908201526937b7363c9037bbb732b960b11b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b80820180821115611ef557611ef561338f565b8082028115828204841417611ef557611ef561338f565b6000826133ec57634e487b7160e01b600052601260045260246000fd5b500490565b81810381811115611ef557611ef561338f565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60006020828403121561344d57600080fd5b5051919050565b6001600160a01b03929092168252602082015260400190565b60006020828403121561347f57600080fd5b8151612f9181612f5f565b60006020828403121561349c57600080fd5b8151612f91816132bc565b634e487b7160e01b600052603260045260246000fd5b6000600182016134cf576134cf61338f565b5060010190565b634e487b7160e01b600052603160045260246000fd5b6000815180845260005b81811015613512576020818501810151868301820152016134f6565b506000602082860101526020601f19601f83011685010191505092915050565b60018060a01b038416815282602082015260606040820152600061355960608301846134ec565b95945050505050565b80516001600160701b0381168114612db657600080fd5b60008060006060848603121561358e57600080fd5b61359784613562565b92506135a560208501613562565b9150604084015163ffffffff811681146135be57600080fd5b809150509250925092565b84815283602082015260018060a01b0383166040820152608060608201526000612f5560808301846134ec56fea2646970667358221220c576146de5bd9eddef1936e5eb619b08d3df4998fd9db0c3b381cab6e0f6235d64736f6c63430008120033