More Info
Private Name Tags
ContractCreator
Latest 9 from a total of 9 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Pool Remove | 56434090 | 592 days ago | IN | 0 FTM | 0.01149388 | ||||
Swap Pool | 56433980 | 592 days ago | IN | 0 FTM | 0.01599284 | ||||
Pool Create | 56433626 | 592 days ago | IN | 1.01 FTM | 0.04545687 | ||||
Update Valid Off... | 56431647 | 592 days ago | IN | 0 FTM | 0.01197315 | ||||
Update Valid Off... | 56431630 | 592 days ago | IN | 0 FTM | 0.01267663 | ||||
Update Valid Off... | 56431615 | 592 days ago | IN | 0 FTM | 0.01267663 | ||||
Update Valid Off... | 56431601 | 592 days ago | IN | 0 FTM | 0.01170541 | ||||
Transfer Ownersh... | 56429779 | 592 days ago | IN | 0 FTM | 0.0040382 | ||||
0x60806040 | 56428644 | 592 days ago | IN | 0 FTM | 0.33897733 |
Loading...
Loading
Contract Name:
OverTheCounter
Compiler Version
v0.8.16+commit.07a7930e
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import '@openzeppelin/contracts/access/Ownable.sol'; import '@openzeppelin/contracts/interfaces/IERC20.sol'; import '@openzeppelin/contracts/interfaces/IERC1155.sol'; import '@openzeppelin/contracts/security/ReentrancyGuard.sol'; import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; import '@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol'; import '@openzeppelin/contracts/utils/Counters.sol'; import './interfaces/IFeeReducer.sol'; import './interfaces/IWETH.sol'; import './otcYDF.sol'; contract OverTheCounter is IERC721Receiver, Ownable, ReentrancyGuard { using SafeERC20 for IERC20; uint256 private constant PERC_DEN = 100000; enum AssetType { ERC20, ERC721, ERC1155 } bool public enabled = true; uint32 public maxAssetsPerPackage = 10; uint256 public createServiceFeeETH = 1 ether / 100; // 0.01 ETH uint256 public poolSwapFeePerc = (PERC_DEN * 1) / 100; // 1% uint256 public buyPackageFeePerc = (PERC_DEN * 1) / 100; // 1% uint256 public referrerFeePerc = (PERC_DEN * 50) / 100; // 50% uint256 public addOfferFee = 1 ether / 1000; // 0.001 ETH uint256 public tradeOTCFee; address public treasury; IFeeReducer public feeReducer; IWETH public weth; otcYDF public otcNFT; // ERC20 token => amount volume mapping(address => uint256) public totalVolume; // ERC20 token => whether it's valid mapping(address => bool) public validOfferERC20; address[] _validOfferTokens; mapping(address => uint256) _validOfferTokensIdx; struct OTC { address creator; bool isPool; address referrer; Package package; Pool pool; } struct Asset { address assetContract; // address(0) means native AssetType assetType; uint256 amount; // ERC20 or native uint256 id; // For ERC721 will be tokenId, for ERC1155 will be asset ID } struct Package { Asset[] assets; uint256 creationTime; uint256 unlockStart; // if > 0, specified when ERC20/native begins vesting and can begin being withdrawn uint256 unlockEnd; // if > 0, ERC20/native will support continuous vesting until this date uint256 lastWithdraw; // NOTE: if buyItNowAmount > 0, the package can be // bought immediately if another user offers this asset/amount combo. // Make sure it's an appropriate amount. address buyItNowAsset; uint256 buyItNowAmount; address buyItNowWhitelist; // if present, is the only address that can buy this package instantly } struct PkgOffer { address owner; address assetContract; // address(0) == ETH/native uint256 amount; uint256 timestamp; uint256 expiration; address referrer; } // One-way OTC ERC20 pool where a creator can deposit token0 and users can // purchase token0 at price18 specified by creator w/ no slippage. // Users can only purchase token0 by sending token1 and will receive // token0 based on price18 provided struct Pool { address token0; // ERC20 address token1; // ERC20 uint256 amount0Deposited; uint256 amount0Remaining; uint256 amount1Deposited; uint256 price18; // amount1 * 10**18 / amount0 } // tokenId => OTC mapping(uint256 => OTC) public otcs; // tokenId[] uint256[] public allOTCs; // tokenId => allOTCs index mapping(uint256 => uint256) internal _otcsIndexed; // tokenId => PkgOffer[] mapping(uint256 => PkgOffer[]) public pkgOffers; // address => sourceTokenId => targetTokenId mapping(address => mapping(uint256 => uint256)) public userOtcTradeWhitelist; event CreatePool( uint256 indexed tokenId, address indexed user, address token0, address token1, uint256 amount0, uint256 price18 ); event UpdatePool( uint256 indexed tokenId, address indexed owner, uint256 newPrice18, uint256 amount0Adding, bool withdrawToken1 ); event RemovePool(uint256 indexed tokenId, address indexed owner); event SwapPool( uint256 indexed tokenId, address indexed swapper, address token0, uint256 token0Amount, address token1, uint256 token1Amount ); event CreatePackage( uint256 indexed tokenId, address indexed user, uint256 numberAssets ); event UpdatePackage( uint256 indexed tokenId, address indexed owner, address buyItNowAsset, uint256 buyItNowAmount, address buyItNowWhitelist, uint256 unlockStart, uint256 unlockEnd ); event WithdrawFromPackage(uint256 indexed tokenId, address indexed user); event AddPackageOffer( uint256 indexed tokenId, address indexed offerer, address offerAsset, uint256 offerAmount ); event AcceptPackageOffer( uint256 indexed tokenId, address indexed pkgOwner, address buyer, address buyToken, uint256 amount ); event RemovePackageOffer( uint256 indexed tokenId, address indexed pkgOwner, uint256 offerIndex ); event BuyItNow( uint256 indexed tokenId, address indexed pkgOwner, address buyer, address buyToken, uint256 amount ); event Trade( address indexed user1, address indexed user2, uint256 user1TokenIdSent, uint256 user2TokenIdSent ); modifier onlyNFT() { require(msg.sender == address(otcNFT), 'ONLYNFT'); _; } constructor(IWETH _weth, string memory _baseTokenURI) { weth = _weth; otcNFT = new otcYDF(_baseTokenURI); otcNFT.transferOwnership(msg.sender); } function onERC721Received( address, /* operator */ address, /* from */ uint256, /* tokenId */ bytes calldata /* data */ ) external pure returns (bytes4) { return this.onERC721Received.selector; } function getAllValidOfferTokens() external view returns (address[] memory) { return _validOfferTokens; } function getAllActiveOTCTokenIds() external view returns (uint256[] memory) { return allOTCs; } function getAllPackageOffers(uint256 _tokenId) external view returns (PkgOffer[] memory) { return pkgOffers[_tokenId]; } function getFeeDiscount(address _wallet) public view returns (uint256, uint256) { return address(feeReducer) != address(0) ? feeReducer.percentDiscount(_wallet) : (0, 0); } function poolCreate( address _token0, address _token1, uint256 _amount0, uint256 _price18, address _referrer ) external payable nonReentrant { require(enabled || msg.sender == owner(), 'POOLCR: enabled'); require(_amount0 > 0, 'POOLCR: need to provide amount0'); require(_price18 > 0, 'POOLCR: need valid price'); // at least one token in the pool needs to be a valid ERC20 require( _token0 != address(0) || _token1 != address(0), 'POOLCR: invalid pool' ); _sendETHOrERC20( msg.sender, address(this), _token0, _token0 == address(0) ? _amount0 + createServiceFeeETH : _amount0 ); require( _token1 == address(0) || IERC20(_token1).totalSupply() > 0, 'POOLCR: token1 validate' ); if (createServiceFeeETH > 0) { require(msg.value >= createServiceFeeETH, 'POOLCR: service fee ETH'); _sendETHOrERC20( address(this), _getTreasury(), address(0), createServiceFeeETH ); } uint256 _tokenId = otcNFT.mint(msg.sender); OTC storage _otc = otcs[_tokenId]; Pool storage _newPool = _otc.pool; _newPool.token0 = _token0; _newPool.token1 = _token1; _newPool.amount0Deposited = _amount0; _newPool.amount0Remaining = _amount0; _newPool.price18 = _price18; _otc.creator = msg.sender; _otc.referrer = _referrer; _otc.isPool = true; otcNFT.approveOverTheCounter(_tokenId); _otcsIndexed[_tokenId] = allOTCs.length; allOTCs.push(_tokenId); emit CreatePool(_tokenId, msg.sender, _token0, _token1, _amount0, _price18); } function poolUpdate( uint256 _tokenId, uint256 _newPrice18, uint256 _amount0ToAdd, bool _withdrawToken1 ) external payable nonReentrant { Pool storage _pool = otcs[_tokenId].pool; require(msg.sender == otcNFT.ownerOf(_tokenId), 'POOLUPD: owner'); if (_newPrice18 > 0 && _pool.price18 != _newPrice18) { _pool.price18 = _newPrice18; } if (_pool.token0 == address(0)) { _amount0ToAdd = msg.value; } if (_amount0ToAdd > 0) { _pool.amount0Deposited += _amount0ToAdd; _pool.amount0Remaining += _amount0ToAdd; _sendETHOrERC20(msg.sender, address(this), _pool.token0, _amount0ToAdd); } if (_withdrawToken1 && _pool.amount1Deposited > 0) { uint256 _amount1ToWithdraw = _pool.amount1Deposited; _pool.amount1Deposited = 0; _sendETHOrERC20( address(this), msg.sender, _pool.token1, _amount1ToWithdraw ); } _refundExcessETH(_pool.token0, _amount0ToAdd); emit UpdatePool( _tokenId, msg.sender, _newPrice18, _amount0ToAdd, _withdrawToken1 ); } function poolRemove(uint256 _tokenId) external nonReentrant { Pool memory _pool = otcs[_tokenId].pool; require(msg.sender == otcNFT.ownerOf(_tokenId), 'POOLRM: owner'); // at least one token in the pool needs to be a valid ERC20 require( _pool.token0 != address(0) || _pool.token1 != address(0), 'POOLRM: invalid pool' ); _deleteOTC(_tokenId); // send remaining token0 to pool owner if (_pool.amount0Remaining > 0) { _sendETHOrERC20( address(this), msg.sender, _pool.token0, _pool.amount0Remaining ); } // send remaining token1 to pool owner if (_pool.amount1Deposited > 0) { _sendETHOrERC20( address(this), msg.sender, _pool.token1, _pool.amount1Deposited ); } emit RemovePool(_tokenId, msg.sender); } function swapPool( uint256 _tokenId, uint256 _amount1Provided, uint256 _price18Max, address _referrer ) external payable nonReentrant { require(enabled || msg.sender == owner(), 'POOLSW: enabled'); Pool storage _pool = otcs[_tokenId].pool; require(_pool.price18 <= _price18Max, 'POOLSW: expected swap price'); require(_pool.amount0Remaining > 0, 'POOLSW: liquidity'); // validate enough token0 assets in pool to swap based on _amount1Provided and price uint256 _amount0ToSend = (_amount1Provided * 10**(18 * 2)) / _pool.price18 / 10**18; // fallback to max liquidity if trying to swap more than available if (_amount0ToSend > _pool.amount0Remaining) { uint256 _origAmount1Provided = _amount1Provided; _amount1Provided = (_pool.amount0Remaining * _pool.price18) / 10**18; require(_amount1Provided <= _origAmount1Provided, 'POOLSW: backup check'); _amount0ToSend = _pool.amount0Remaining; } _pool.amount0Remaining -= _amount0ToSend; // process token1 including any associated fees uint256 _poolFee = (_amount1Provided * poolSwapFeePerc) / PERC_DEN; (uint256 _percentOff, uint256 _percOffDenom) = getFeeDiscount(msg.sender); if (_percentOff > 0) { _poolFee -= (_poolFee * _percentOff) / _percOffDenom; } uint256 _amount1LessFee = _amount1Provided - _poolFee; _pool.amount1Deposited += _amount1LessFee; address _from = msg.sender; if (_pool.token1 == address(0)) { _from = address(this); require(msg.value >= _amount1Provided, 'POOLSW: not enough ETH'); } _processFees(_tokenId, _from, _referrer, _pool.token1, _poolFee); _sendETHOrERC20(_from, address(this), _pool.token1, _amount1LessFee); _refundExcessETH(_pool.token1, _amount1Provided); // swap and send token0 to swapper _sendETHOrERC20(address(this), msg.sender, _pool.token0, _amount0ToSend); totalVolume[_pool.token0] += _amount0ToSend; emit SwapPool( _tokenId, msg.sender, _pool.token0, _amount0ToSend, _pool.token1, _amount1Provided ); } function packageCreate( // OTC asset(s) info Asset[] memory _assets, // OTC package info uint256 _unlockStart, uint256 _unlockEnd, address _buyItNowAsset, uint256 _buyItNowAmount, address _buyItNowWhitelist, address _referrer ) external payable nonReentrant { require(enabled || msg.sender == owner(), 'PKGCR: enabled'); require(_assets.length <= maxAssetsPerPackage, 'PKGCR: max assets'); require( _buyItNowAsset == address(0) || validOfferERC20[_buyItNowAsset], 'PKGCR: asset not valid' ); uint256 _tokenId = otcNFT.mint(msg.sender); OTC storage _otc = otcs[_tokenId]; Package storage _newPkg = _otc.package; uint256 _nativeCheck; for (uint256 _i; _i < _assets.length; _i++) { if (_assets[_i].assetContract == address(0)) { _nativeCheck += _assets[_i].amount; } _validateAndSupplyPackageAsset(msg.sender, _assets[_i]); Asset memory _newAsset = Asset({ assetContract: _assets[_i].assetContract, assetType: _assets[_i].assetType, amount: _assets[_i].amount, id: _assets[_i].id }); _newPkg.assets.push(_newAsset); } require( msg.value >= _nativeCheck + createServiceFeeETH, 'PKGCR: ETH assets plus service' ); if (createServiceFeeETH > 0) { _sendETHOrERC20( address(this), _getTreasury(), address(0), createServiceFeeETH ); } require( (_unlockEnd == 0 && _unlockStart == 0) || (_unlockEnd != 0 && _unlockStart != 0 && _unlockEnd > _unlockStart), 'PKGCR: validate unlock period' ); _newPkg.creationTime = block.timestamp; _newPkg.unlockStart = _unlockStart; _newPkg.unlockEnd = _unlockEnd; _newPkg.buyItNowAsset = _buyItNowAsset; _newPkg.buyItNowAmount = _buyItNowAmount; _newPkg.buyItNowWhitelist = _buyItNowWhitelist; _otc.creator = msg.sender; _otc.referrer = _referrer; otcNFT.approveOverTheCounter(_tokenId); _otcsIndexed[_tokenId] = allOTCs.length; allOTCs.push(_tokenId); emit CreatePackage(_tokenId, msg.sender, _assets.length); } function packageWithdrawal(uint256 _tokenId, bool _silenceErrors) external nonReentrant { _packageWithdrawal(msg.sender, _tokenId, _silenceErrors); } function addPackageOffer( uint256 _tokenId, address _offerAsset, uint256 _assetAmount, uint256 _expiration, address _referrer ) external payable { require(enabled || msg.sender == owner(), 'PKGOFF: enabled'); PkgOffer storage _newOffer = pkgOffers[_tokenId].push(); _newOffer.owner = msg.sender; _newOffer.referrer = _referrer; _newOffer.timestamp = block.timestamp; address _finalOfferToken; uint256 _finalOfferAmount; if (_offerAsset == address(0)) { require(msg.value > addOfferFee, 'PKGOFF: need ETH'); require(validOfferERC20[address(weth)], 'PKGOFF: WETH not valid'); uint256 _ethOfferAmount = msg.value - addOfferFee; IERC20 _wethIERC20 = IERC20(address(weth)); uint256 _wethBalBefore = _wethIERC20.balanceOf(address(this)); weth.deposit{ value: _ethOfferAmount }(); _wethIERC20.transfer( msg.sender, _wethIERC20.balanceOf(address(this)) - _wethBalBefore ); _finalOfferToken = address(weth); _finalOfferAmount = (_ethOfferAmount * 10**weth.decimals()) / 10**18; } else { require(msg.value == addOfferFee, 'PKGOFF: offer fee'); require(validOfferERC20[_offerAsset], 'PKGOFF: invalid offer token'); _finalOfferToken = _offerAsset; _finalOfferAmount = _assetAmount; } if (addOfferFee > 0) { _sendETHOrERC20(address(this), _getTreasury(), address(0), addOfferFee); } IERC20 _offTokenCont = IERC20(_finalOfferToken); require( _offTokenCont.balanceOf(msg.sender) >= _finalOfferAmount, 'PKGOFF: bad balance' ); require( _offTokenCont.allowance(msg.sender, address(this)) >= _finalOfferAmount, 'PKGOFF: need allowance' ); _newOffer.assetContract = _finalOfferToken; _newOffer.amount = _finalOfferAmount; _newOffer.expiration = _expiration; emit AddPackageOffer( _tokenId, msg.sender, _finalOfferToken, _finalOfferAmount ); } function acceptPackageOffer( uint256 _tokenId, uint256 _offerIndex, address _offerAssetCheck, uint256 _offerAmountCheck ) external nonReentrant { require(enabled || msg.sender == owner(), 'ACCEPTOFF: enabled'); require(otcNFT.ownerOf(_tokenId) == msg.sender, 'ACCEPTOFF: owner'); PkgOffer memory _offer = pkgOffers[_tokenId][_offerIndex]; require(_offer.assetContract == _offerAssetCheck, 'ACCEPTOFF: bad asset'); require(_offer.amount == _offerAmountCheck, 'ACCEPTOFF: bad amount'); require( _offer.expiration == 0 || _offer.expiration > block.timestamp, 'ACCEPTOFF: expired' ); Package memory _pkg = otcs[_tokenId].package; require(_offer.timestamp > _pkg.lastWithdraw, 'ACCEPTOFF: last withdrawal'); uint256 _buyFee = (_offer.amount * buyPackageFeePerc) / PERC_DEN; (uint256 _percentOff, uint256 _percOffDenom) = getFeeDiscount(msg.sender); if (_percentOff > 0) { _buyFee -= (_buyFee * _percentOff) / _percOffDenom; } uint256 _remainingAmount = _offer.amount - _buyFee; _processFees( _tokenId, _offer.owner, _offer.referrer, _offer.assetContract, _buyFee ); _sendETHOrERC20( _offer.owner, msg.sender, _offer.assetContract, _remainingAmount ); otcNFT.safeTransferFrom(msg.sender, _offer.owner, _tokenId); otcNFT.approveOverTheCounter(_tokenId); pkgOffers[_tokenId][_offerIndex] = pkgOffers[_tokenId][ pkgOffers[_tokenId].length - 1 ]; pkgOffers[_tokenId].pop(); totalVolume[_offer.assetContract] += _offer.amount; emit AcceptPackageOffer( _tokenId, msg.sender, _offer.owner, _offer.assetContract, _offer.amount ); } function removePackageOffer(uint256 _tokenId, uint256 _offerIndex) external nonReentrant { PkgOffer memory _offer = pkgOffers[_tokenId][_offerIndex]; require( otcNFT.ownerOf(_tokenId) == msg.sender || _offer.owner == msg.sender, 'REJECTOFF: owner' ); pkgOffers[_tokenId][_offerIndex] = pkgOffers[_tokenId][ pkgOffers[_tokenId].length - 1 ]; pkgOffers[_tokenId].pop(); emit RemovePackageOffer(_tokenId, msg.sender, _offerIndex); } function buyItNow( uint256 _tokenId, address _buyItNowToken, uint256 _buyItNowAmount, bool _unpack, address _referrer ) external payable nonReentrant { require(enabled || msg.sender == owner(), 'BIN: enabled'); address _owner = otcNFT.ownerOf(_tokenId); Package memory _pkg = otcs[_tokenId].package; require(_pkg.buyItNowAmount > 0, 'BIN: not configured'); require(_pkg.buyItNowAsset == _buyItNowToken, 'BIN: bad token'); require(_pkg.buyItNowAmount == _buyItNowAmount, 'BIN: bad amount'); if (_pkg.buyItNowWhitelist != address(0)) { require(msg.sender == _pkg.buyItNowWhitelist, 'BIN: not whitelisted'); } uint256 _buyFee = (_pkg.buyItNowAmount * buyPackageFeePerc) / PERC_DEN; (uint256 _percentOff, uint256 _percOffDenom) = getFeeDiscount(_owner); if (_percentOff > 0) { _buyFee -= (_buyFee * _percentOff) / _percOffDenom; } uint256 _remainingAmount = _pkg.buyItNowAmount - _buyFee; address _from = msg.sender; if (_pkg.buyItNowAsset == address(0)) { _from = address(this); require(msg.value == _buyItNowAmount, 'BIN: not enough ETH'); } _processFees(_tokenId, _from, _referrer, _pkg.buyItNowAsset, _buyFee); _sendETHOrERC20(_from, _owner, _pkg.buyItNowAsset, _remainingAmount); otcNFT.safeTransferFrom(_owner, msg.sender, _tokenId); otcNFT.approveOverTheCounter(_tokenId); totalVolume[_pkg.buyItNowAsset] += _pkg.buyItNowAmount; // unpack now if buying user would like if (_unpack) { _packageWithdrawal(msg.sender, _tokenId, false); } emit BuyItNow( _tokenId, _owner, msg.sender, _buyItNowToken, _buyItNowAmount ); } function updatePackageInfo( uint256 _tokenId, uint256 _unlockStart, uint256 _unlockEnd, address _buyItNowAsset, uint256 _buyItNowAmount, address _buyItNowWhitelist ) external nonReentrant { require(otcNFT.ownerOf(_tokenId) == msg.sender, 'UDPATEPKG: owner'); require( _buyItNowAsset == address(0) || validOfferERC20[_buyItNowAsset], 'UPDATEPKG: asset not valid' ); Package storage _pkg = otcs[_tokenId].package; _pkg.buyItNowAsset = _buyItNowAsset; _pkg.buyItNowAmount = _buyItNowAmount; _pkg.buyItNowWhitelist = _buyItNowWhitelist; // can only update unlock info if OTC package creator if (msg.sender == otcs[_tokenId].creator) { _pkg.unlockStart = _unlockStart; _pkg.unlockEnd = _unlockEnd; } else { // don't update from current config if not creator (update here though for event below) _unlockStart = _pkg.unlockStart; _unlockEnd = _pkg.unlockEnd; } emit UpdatePackage( _tokenId, msg.sender, _buyItNowAsset, _buyItNowAmount, _buyItNowWhitelist, _pkg.unlockStart, _pkg.unlockEnd ); } function tradeOTC(uint256 _sourceTokenId, uint256 _desiredTokenId) external payable nonReentrant { require( otcNFT.ownerOf(_sourceTokenId) == msg.sender, 'TRADE: bad source owner' ); // short circuit if the user is just removing the trade flag if (_desiredTokenId == 0) { delete userOtcTradeWhitelist[msg.sender][_sourceTokenId]; return; } userOtcTradeWhitelist[msg.sender][_sourceTokenId] = _desiredTokenId; address _desiredOwner = otcNFT.ownerOf(_desiredTokenId); if ( userOtcTradeWhitelist[_desiredOwner][_desiredTokenId] == _sourceTokenId ) { if (tradeOTCFee > 0) { require(msg.value == tradeOTCFee, 'TRADE: need ETH'); _sendETHOrERC20(address(this), _getTreasury(), address(0), tradeOTCFee); } otcNFT.transferFrom(msg.sender, _desiredOwner, _sourceTokenId); otcNFT.transferFrom(_desiredOwner, msg.sender, _desiredTokenId); otcNFT.approveOverTheCounter(_sourceTokenId); otcNFT.approveOverTheCounter(_desiredTokenId); delete userOtcTradeWhitelist[msg.sender][_sourceTokenId]; delete userOtcTradeWhitelist[_desiredOwner][_desiredTokenId]; emit Trade(msg.sender, _desiredOwner, _sourceTokenId, _desiredTokenId); } else { // refund any ETH provided here if (msg.value > 0) { _sendETHOrERC20(address(this), msg.sender, address(0), msg.value); } } } function _packageWithdrawal( address _authdUser, uint256 _tokenId, bool _silenceErrors ) internal { OTC storage _otc = otcs[_tokenId]; Package storage _pkg = _otc.package; address _user = otcNFT.ownerOf(_tokenId); require(_authdUser == _user, 'PKGWITH: owner'); require(_pkg.assets.length > 0, 'PKGWITH: invalid package'); for (uint256 _i; _i < _pkg.assets.length; _i++) { _withdrawAssetFromPackage(_user, _tokenId, _i, _silenceErrors); } _pkg.lastWithdraw = block.timestamp; if ( _otc.creator == _user || _pkg.unlockEnd == 0 || block.timestamp >= _pkg.unlockEnd ) { _deleteOTC(_tokenId); } emit WithdrawFromPackage(_tokenId, _user); } function _validateAndSupplyPackageAsset(address _user, Asset memory _asset) internal { if (_asset.assetType == AssetType.ERC20) { // ETH or ERC20 _sendETHOrERC20( _user, address(this), _asset.assetContract, _asset.amount ); } else if (_asset.assetType == AssetType.ERC721) { // ERC721 require(_asset.id > 0, 'VALIDPKG: token ID'); IERC721(_asset.assetContract).safeTransferFrom( _user, address(this), _asset.id ); } else { // ERC1155 IERC1155(_asset.assetContract).safeTransferFrom( _user, address(this), _asset.id, _asset.amount, '' ); } } function _withdrawAssetFromPackage( address _withdrawer, uint256 _tokenId, uint256 _assetIdx, bool _silenceErrors ) internal { Package storage _package = otcs[_tokenId].package; Asset storage _asset = _package.assets[_assetIdx]; uint256 _amountCache = _asset.amount; if ( otcs[_tokenId].creator != _withdrawer && _package.unlockEnd > 0 && block.timestamp < _package.unlockEnd ) { // if it's NFT, short circuit as it cannot be withdrawn until unlock period is over if (_asset.assetType == AssetType.ERC721) { return; } uint256 _fullVestingPeriod = _package.unlockEnd - _package.unlockStart; uint256 _lastWithdraw = _package.lastWithdraw > 0 ? _package.lastWithdraw : _package.unlockStart > 0 ? _package.unlockStart : _package.creationTime; require(block.timestamp >= _lastWithdraw, 'WITH: last withdraw'); _amountCache = ((block.timestamp - _lastWithdraw) * _amountCache) / _fullVestingPeriod; // if there is nothing to withdraw for this asset, short circuit if (_amountCache == 0) { return; } _asset.amount -= _amountCache; } else { _asset.amount = 0; } if (_asset.assetType == AssetType.ERC20) { _sendETHOrERC20( address(this), _withdrawer, _asset.assetContract, _amountCache ); } else if (_asset.assetType == AssetType.ERC721) { // NFT if (_silenceErrors) { try IERC721(_asset.assetContract).safeTransferFrom( address(this), _withdrawer, _asset.id ) {} catch {} } else { IERC721(_asset.assetContract).safeTransferFrom( address(this), _withdrawer, _asset.id ); } } else { // ERC1155 if (_silenceErrors) { try IERC1155(_asset.assetContract).safeTransferFrom( address(this), _withdrawer, _asset.id, _amountCache, '' ) {} catch {} } else { IERC1155(_asset.assetContract).safeTransferFrom( address(this), _withdrawer, _asset.id, _amountCache, '' ); } } } function _processFees( uint256 _tokenId, address _source, address _txnReferrer, address _feeToken, uint256 _feeAmount ) internal { if (_feeAmount == 0) { return; } address _otcReferrer = otcs[_tokenId].referrer; uint256 _referrerAmount = (_feeAmount * referrerFeePerc) / PERC_DEN; uint256 _protocolAmount = _feeAmount - _referrerAmount; if (_referrerAmount > 0) { // only send tokens to one address if either of them are address(0) if (_otcReferrer != address(0) && _txnReferrer != address(0)) { uint256 _half = _referrerAmount / 2; uint256 _otherHalf = _referrerAmount - _half; _sendETHOrERC20(_source, _otcReferrer, _feeToken, _half); _sendETHOrERC20(_source, _txnReferrer, _feeToken, _otherHalf); } else { _sendETHOrERC20( _source, _txnReferrer == address(0) ? _otcReferrer : _txnReferrer, _feeToken, _referrerAmount ); } } if (_protocolAmount > 0) { _sendETHOrERC20(_source, _getTreasury(), _feeToken, _protocolAmount); } } function _refundExcessETH(address _tokenCheck, uint256 _desiredAmt) internal { uint256 _refundAmount = _tokenCheck == address(0) ? msg.value - _desiredAmt : msg.value; if (_refundAmount > 0) { _sendETHOrERC20(address(this), msg.sender, address(0), _refundAmount); } } function _sendETHOrERC20( address _source, address _target, address _token, uint256 _amount ) internal { if (_source == _target) return; _target = _target == address(0) ? _getTreasury() : _target; if (_token == address(0)) { if (_target == address(this)) { require(msg.value >= _amount, 'SEND: not enough ETH'); } else { require(_source == address(this), 'SEND: bad source'); uint256 _balBefore = address(this).balance; (bool _sent, ) = payable(_target).call{ value: _amount }(''); require(_sent, 'SEND: could not send'); require(address(this).balance >= _balBefore - _amount, 'SEND: ETH'); } } else { // NOTE: tokens w/ taxes on transfer should whitelist this OTC // contract as we don't want end users to experience unexpected // results by losing tokens as they're moving between here and their wallet IERC20 _cont = IERC20(_token); uint256 _tokenBalBefore = _cont.balanceOf(_target); if (_source == address(this)) { _cont.safeTransfer(_target, _amount); } else { _cont.safeTransferFrom(_source, _target, _amount); } require( _cont.balanceOf(_target) >= _amount + _tokenBalBefore, 'SEND: ERC20 amount' ); } } function _deleteOTC(uint256 _tokenId) internal { otcNFT.burn(_tokenId); uint256 _deletingOTCIndex = _otcsIndexed[_tokenId]; uint256 _tokenIdMoving = allOTCs[allOTCs.length - 1]; delete _otcsIndexed[_tokenId]; _otcsIndexed[_tokenIdMoving] = _deletingOTCIndex; allOTCs[_deletingOTCIndex] = _tokenIdMoving; allOTCs.pop(); } function _getTreasury() internal view returns (address) { return treasury == address(0) ? owner() : treasury; } function turnOffPackageTrading(uint256 _tokenId) external onlyNFT { otcs[_tokenId].package.buyItNowAmount = 0; } function setFeeReducer(IFeeReducer _reducer) external onlyOwner { feeReducer = _reducer; } function setTreasury(address _treasury) external onlyOwner { treasury = _treasury; } function setMaxAssetsPerPackage(uint8 _max) external onlyOwner { maxAssetsPerPackage = _max; } function setServiceFeeETH(uint256 _wei) external onlyOwner { createServiceFeeETH = _wei; } function setPoolSwapFeePerc(uint256 _percent) external onlyOwner { require(_percent <= (PERC_DEN * 25) / 100, 'must be less than 25%'); poolSwapFeePerc = _percent; } function setBuyPackageFeePerc(uint256 _percent) external onlyOwner { require(_percent <= (PERC_DEN * 20) / 100, 'must be less than 20%'); buyPackageFeePerc = _percent; } function setReferrerFeePerc(uint256 _percent) external onlyOwner { require(_percent <= PERC_DEN, 'must be less than 100%'); referrerFeePerc = _percent; } function setAddOfferFee(uint256 _wei) external onlyOwner { addOfferFee = _wei; } function setTradeOTCFee(uint256 _wei) external onlyOwner { tradeOTCFee = _wei; } function setEnabled(bool _enabled) external onlyOwner { require(enabled != _enabled, 'SETENABLED: toggle'); enabled = _enabled; } function updateValidOfferToken(address _token, bool _isValid) external onlyOwner { require(validOfferERC20[_token] != _isValid, 'must toggle'); validOfferERC20[_token] = _isValid; if (_isValid) { _validOfferTokensIdx[_token] = _validOfferTokens.length; _validOfferTokens.push(_token); } else { uint256 _idx = _validOfferTokensIdx[_token]; delete _validOfferTokensIdx[_token]; _validOfferTokens[_idx] = _validOfferTokens[_validOfferTokens.length - 1]; _validOfferTokens.pop(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol) pragma solidity ^0.8.0; import "../token/ERC20/IERC20.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC1155.sol) pragma solidity ^0.8.0; import "../token/ERC1155/IERC1155.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/draft-IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Counters.sol) pragma solidity ^0.8.0; /** * @title Counters * @author Matt Condon (@shrugs) * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number * of elements in a mapping, issuing ERC721 ids, or counting request ids. * * Include with `using Counters for Counters.Counter;` */ library Counters { struct Counter { // This variable should never be directly accessed by users of the library: interactions must be restricted to // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add // this feature: see https://github.com/ethereum/solidity/issues/4637 uint256 _value; // default: 0 } function current(Counter storage counter) internal view returns (uint256) { return counter._value; } function increment(Counter storage counter) internal { unchecked { counter._value += 1; } } function decrement(Counter storage counter) internal { uint256 value = counter._value; require(value > 0, "Counter: decrement overflow"); unchecked { counter._value = value - 1; } } function reset(Counter storage counter) internal { counter._value = 0; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; interface IFeeReducer { function percentDiscount(address wallet) external view returns (uint256, uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; interface IWETH { function decimals() external view returns (uint8); function deposit() external payable; function withdraw(uint256 wad) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import '@openzeppelin/contracts/access/Ownable.sol'; import '@openzeppelin/contracts/interfaces/IERC20.sol'; import '@openzeppelin/contracts/token/ERC721/ERC721.sol'; import '@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol'; import '@openzeppelin/contracts/utils/Counters.sol'; import './interfaces/IOverTheCounterSlim.sol'; contract otcYDF is ERC721Enumerable, Ownable { using Strings for uint256; using Counters for Counters.Counter; address public overTheCounter; Counters.Counter internal _ids; string private baseTokenURI; // baseTokenURI can point to IPFS folder like https://ipfs.io/ipfs/{cid}/ while address public royaltyAddress; // Royalties basis points (percentage using 2 decimals - 1000 = 100, 500 = 50, 0 = 0) uint256 private royaltyBasisPoints = 50; // 5% // array of all the NFT token IDs owned by a user mapping(address => uint256[]) public allUserOwned; // the index in the token ID array at allUserOwned to save gas on operations mapping(uint256 => uint256) public ownedIndex; mapping(uint256 => uint256) public tokenMintedAt; event Burn(uint256 indexed tokenId, address indexed owner); event Mint(uint256 indexed tokenId, address indexed owner); event SetPaymentAddress(address indexed user); event SetRoyaltyAddress(address indexed user); event SetRoyaltyBasisPoints(uint256 indexed _royaltyBasisPoints); event SetBaseTokenURI(string indexed newUri); modifier onlyOTC() { require(msg.sender == overTheCounter, 'only OTC'); _; } constructor(string memory _baseTokenURI) ERC721('Yieldification OTC', 'otcYDF') { baseTokenURI = _baseTokenURI; overTheCounter = msg.sender; } function mint(address owner) external onlyOTC returns (uint256) { _ids.increment(); _safeMint(owner, _ids.current()); tokenMintedAt[_ids.current()] = block.timestamp; emit Mint(_ids.current(), owner); return _ids.current(); } function burn(uint256 _tokenId) external onlyOTC { address _user = ownerOf(_tokenId); require(_exists(_tokenId)); _burn(_tokenId); emit Burn(_tokenId, _user); } function approveOverTheCounter(uint256 _tokenId) external onlyOTC { _approve(overTheCounter, _tokenId); } // Support royalty info - See {EIP-2981}: https://eips.ethereum.org/EIPS/eip-2981 function royaltyInfo(uint256, uint256 _salePrice) external view returns (address receiver, uint256 royaltyAmount) { return (royaltyAddress, (_salePrice * royaltyBasisPoints) / 1000); } function tokenURI(uint256 _tokenId) public view virtual override returns (string memory) { require(_exists(_tokenId)); return string(abi.encodePacked(_baseURI(), _tokenId.toString(), '.json')); } // Contract metadata URI - Support for OpenSea: https://docs.opensea.io/docs/contract-level-metadata function contractURI() public view returns (string memory) { return string(abi.encodePacked(_baseURI(), 'contract.json')); } // Override supportsInterface - See {IERC165-supportsInterface} function supportsInterface(bytes4 _interfaceId) public view virtual override(ERC721Enumerable) returns (bool) { return super.supportsInterface(_interfaceId); } function getLastMintedTokenId() external view returns (uint256) { return _ids.current(); } function doesTokenExist(uint256 _tokenId) external view returns (bool) { return _exists(_tokenId); } function setRoyaltyAddress(address _address) external onlyOwner { royaltyAddress = _address; emit SetRoyaltyAddress(_address); } function setRoyaltyBasisPoints(uint256 _points) external onlyOwner { royaltyBasisPoints = _points; emit SetRoyaltyBasisPoints(_points); } function setBaseURI(string memory _uri) external onlyOwner { baseTokenURI = _uri; emit SetBaseTokenURI(_uri); } function setPerpetualFutures(address _otc) external onlyOwner { overTheCounter = _otc; } function getAllUserOwned(address _user) external view returns (uint256[] memory) { return allUserOwned[_user]; } function _baseURI() internal view override returns (string memory) { return baseTokenURI; } function _afterTokenTransfer( address _from, address _to, uint256 _tokenId ) internal virtual override(ERC721) { // if from == address(0), token is being minted if (_from != address(0)) { uint256 _currIndex = ownedIndex[_tokenId]; uint256 _tokenIdMovingIndices = allUserOwned[_from][ allUserOwned[_from].length - 1 ]; allUserOwned[_from][_currIndex] = allUserOwned[_from][ allUserOwned[_from].length - 1 ]; allUserOwned[_from].pop(); ownedIndex[_tokenIdMovingIndices] = _currIndex; } // if to == address(0), token is being burned if (_to != address(0)) { ownedIndex[_tokenId] = allUserOwned[_to].length; allUserOwned[_to].push(_tokenId); } // if this package is just moving wallets, turn off trading // so the new wallet can control if/when they would like to trade if (_from != address(0) && _to != address(0)) { IOverTheCounterSlim(overTheCounter).turnOffPackageTrading(_tokenId); } super._afterTokenTransfer(_from, _to, _tokenId); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/ERC721.sol) pragma solidity ^0.8.0; import "./IERC721.sol"; import "./IERC721Receiver.sol"; import "./extensions/IERC721Metadata.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/Strings.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { using Address for address; using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to owner address mapping(uint256 => address) private _owners; // Mapping owner address to token count mapping(address => uint256) private _balances; // Mapping from token ID to approved address mapping(uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: address zero is not a valid owner"); return _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _owners[tokenId]; require(owner != address(0), "ERC721: invalid token ID"); return owner; } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { _requireMinted(tokenId); string memory baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : ""; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ""; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ERC721.ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require( _msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not token owner nor approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { _requireMinted(tokenId); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom( address from, address to, uint256 tokenId ) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory data ) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved"); _safeTransfer(from, to, tokenId, data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer( address from, address to, uint256 tokenId, bytes memory data ) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _owners[tokenId] != address(0); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { address owner = ERC721.ownerOf(tokenId); return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: * * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint( address to, uint256 tokenId, bytes memory data ) internal virtual { _mint(to, tokenId); require( _checkOnERC721Received(address(0), to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer" ); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _beforeTokenTransfer(address(0), to, tokenId); _balances[to] += 1; _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); _afterTokenTransfer(address(0), to, tokenId); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId); // Clear approvals _approve(address(0), tokenId); _balances[owner] -= 1; delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(owner, address(0), tokenId); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer( address from, address to, uint256 tokenId ) internal virtual { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId); // Clear approvals from the previous owner _approve(address(0), tokenId); _balances[from] -= 1; _balances[to] += 1; _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId); } /** * @dev Approve `to` to operate on `tokenId` * * Emits an {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721.ownerOf(tokenId), to, tokenId); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll( address owner, address operator, bool approved ) internal virtual { require(owner != operator, "ERC721: approve to caller"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Reverts if the `tokenId` has not been minted yet. */ function _requireMinted(uint256 tokenId) internal view virtual { require(_exists(tokenId), "ERC721: invalid token ID"); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory data ) private returns (bool) { if (to.isContract()) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) { return retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert("ERC721: transfer to non ERC721Receiver implementer"); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /** * @dev Hook that is called before any token transfer. This includes minting * and burning. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, ``from``'s `tokenId` will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol) pragma solidity ^0.8.0; import "../ERC721.sol"; import "./IERC721Enumerable.sol"; /** * @dev This implements an optional extension of {ERC721} defined in the EIP that adds * enumerability of all the token ids in the contract as well as all token ids owned by each * account. */ abstract contract ERC721Enumerable is ERC721, IERC721Enumerable { // Mapping from owner to list of owned token IDs mapping(address => mapping(uint256 => uint256)) private _ownedTokens; // Mapping from token ID to index of the owner tokens list mapping(uint256 => uint256) private _ownedTokensIndex; // Array with all token ids, used for enumeration uint256[] private _allTokens; // Mapping from token id to position in the allTokens array mapping(uint256 => uint256) private _allTokensIndex; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) { return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. */ function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) { require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds"); return _ownedTokens[owner][index]; } /** * @dev See {IERC721Enumerable-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _allTokens.length; } /** * @dev See {IERC721Enumerable-tokenByIndex}. */ function tokenByIndex(uint256 index) public view virtual override returns (uint256) { require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds"); return _allTokens[index]; } /** * @dev Hook that is called before any token transfer. This includes minting * and burning. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, ``from``'s `tokenId` will be burned. * - `from` cannot be the zero address. * - `to` cannot be the zero address. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual override { super._beforeTokenTransfer(from, to, tokenId); if (from == address(0)) { _addTokenToAllTokensEnumeration(tokenId); } else if (from != to) { _removeTokenFromOwnerEnumeration(from, tokenId); } if (to == address(0)) { _removeTokenFromAllTokensEnumeration(tokenId); } else if (to != from) { _addTokenToOwnerEnumeration(to, tokenId); } } /** * @dev Private function to add a token to this extension's ownership-tracking data structures. * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private { uint256 length = ERC721.balanceOf(to); _ownedTokens[to][length] = tokenId; _ownedTokensIndex[tokenId] = length; } /** * @dev Private function to add a token to this extension's token tracking data structures. * @param tokenId uint256 ID of the token to be added to the tokens list */ function _addTokenToAllTokensEnumeration(uint256 tokenId) private { _allTokensIndex[tokenId] = _allTokens.length; _allTokens.push(tokenId); } /** * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for * gas optimizations e.g. when performing a transfer operation (avoiding double writes). * This has O(1) time complexity, but alters the order of the _ownedTokens array. * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private { // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = ERC721.balanceOf(from) - 1; uint256 tokenIndex = _ownedTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary if (tokenIndex != lastTokenIndex) { uint256 lastTokenId = _ownedTokens[from][lastTokenIndex]; _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index } // This also deletes the contents at the last position of the array delete _ownedTokensIndex[tokenId]; delete _ownedTokens[from][lastTokenIndex]; } /** * @dev Private function to remove a token from this extension's token tracking data structures. * This has O(1) time complexity, but alters the order of the _allTokens array. * @param tokenId uint256 ID of the token to be removed from the tokens list */ function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private { // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = _allTokens.length - 1; uint256 tokenIndex = _allTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding // an 'if' statement (like in _removeTokenFromOwnerEnumeration) uint256 lastTokenId = _allTokens[lastTokenIndex]; _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index // This also deletes the contents at the last position of the array delete _allTokensIndex[tokenId]; _allTokens.pop(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; interface IOverTheCounterSlim { function turnOffPackageTrading(uint256 tokenId) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Enumerable is IERC721 { /** * @dev Returns the total amount of tokens stored by the contract. */ function totalSupply() external view returns (uint256); /** * @dev Returns a token ID owned by `owner` at a given `index` of its token list. * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. */ function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256); /** * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. * Use along with {totalSupply} to enumerate all tokens. */ function tokenByIndex(uint256 index) external view returns (uint256); }
{ "metadata": { "bytecodeHash": "none" }, "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract IWETH","name":"_weth","type":"address"},{"internalType":"string","name":"_baseTokenURI","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"pkgOwner","type":"address"},{"indexed":false,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"address","name":"buyToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"AcceptPackageOffer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"offerer","type":"address"},{"indexed":false,"internalType":"address","name":"offerAsset","type":"address"},{"indexed":false,"internalType":"uint256","name":"offerAmount","type":"uint256"}],"name":"AddPackageOffer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"pkgOwner","type":"address"},{"indexed":false,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"address","name":"buyToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BuyItNow","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"numberAssets","type":"uint256"}],"name":"CreatePackage","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"token0","type":"address"},{"indexed":false,"internalType":"address","name":"token1","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price18","type":"uint256"}],"name":"CreatePool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"pkgOwner","type":"address"},{"indexed":false,"internalType":"uint256","name":"offerIndex","type":"uint256"}],"name":"RemovePackageOffer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"RemovePool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"swapper","type":"address"},{"indexed":false,"internalType":"address","name":"token0","type":"address"},{"indexed":false,"internalType":"uint256","name":"token0Amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"token1","type":"address"},{"indexed":false,"internalType":"uint256","name":"token1Amount","type":"uint256"}],"name":"SwapPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user1","type":"address"},{"indexed":true,"internalType":"address","name":"user2","type":"address"},{"indexed":false,"internalType":"uint256","name":"user1TokenIdSent","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"user2TokenIdSent","type":"uint256"}],"name":"Trade","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"address","name":"buyItNowAsset","type":"address"},{"indexed":false,"internalType":"uint256","name":"buyItNowAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"buyItNowWhitelist","type":"address"},{"indexed":false,"internalType":"uint256","name":"unlockStart","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unlockEnd","type":"uint256"}],"name":"UpdatePackage","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"newPrice18","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount0Adding","type":"uint256"},{"indexed":false,"internalType":"bool","name":"withdrawToken1","type":"bool"}],"name":"UpdatePool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"WithdrawFromPackage","type":"event"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_offerIndex","type":"uint256"},{"internalType":"address","name":"_offerAssetCheck","type":"address"},{"internalType":"uint256","name":"_offerAmountCheck","type":"uint256"}],"name":"acceptPackageOffer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"addOfferFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_offerAsset","type":"address"},{"internalType":"uint256","name":"_assetAmount","type":"uint256"},{"internalType":"uint256","name":"_expiration","type":"uint256"},{"internalType":"address","name":"_referrer","type":"address"}],"name":"addPackageOffer","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allOTCs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_buyItNowToken","type":"address"},{"internalType":"uint256","name":"_buyItNowAmount","type":"uint256"},{"internalType":"bool","name":"_unpack","type":"bool"},{"internalType":"address","name":"_referrer","type":"address"}],"name":"buyItNow","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"buyPackageFeePerc","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"createServiceFeeETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"enabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeReducer","outputs":[{"internalType":"contract IFeeReducer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllActiveOTCTokenIds","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getAllPackageOffers","outputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"assetContract","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"expiration","type":"uint256"},{"internalType":"address","name":"referrer","type":"address"}],"internalType":"struct OverTheCounter.PkgOffer[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllValidOfferTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_wallet","type":"address"}],"name":"getFeeDiscount","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxAssetsPerPackage","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"otcNFT","outputs":[{"internalType":"contract otcYDF","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"otcs","outputs":[{"internalType":"address","name":"creator","type":"address"},{"internalType":"bool","name":"isPool","type":"bool"},{"internalType":"address","name":"referrer","type":"address"},{"components":[{"components":[{"internalType":"address","name":"assetContract","type":"address"},{"internalType":"enum OverTheCounter.AssetType","name":"assetType","type":"uint8"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"}],"internalType":"struct OverTheCounter.Asset[]","name":"assets","type":"tuple[]"},{"internalType":"uint256","name":"creationTime","type":"uint256"},{"internalType":"uint256","name":"unlockStart","type":"uint256"},{"internalType":"uint256","name":"unlockEnd","type":"uint256"},{"internalType":"uint256","name":"lastWithdraw","type":"uint256"},{"internalType":"address","name":"buyItNowAsset","type":"address"},{"internalType":"uint256","name":"buyItNowAmount","type":"uint256"},{"internalType":"address","name":"buyItNowWhitelist","type":"address"}],"internalType":"struct OverTheCounter.Package","name":"package","type":"tuple"},{"components":[{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"},{"internalType":"uint256","name":"amount0Deposited","type":"uint256"},{"internalType":"uint256","name":"amount0Remaining","type":"uint256"},{"internalType":"uint256","name":"amount1Deposited","type":"uint256"},{"internalType":"uint256","name":"price18","type":"uint256"}],"internalType":"struct OverTheCounter.Pool","name":"pool","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"assetContract","type":"address"},{"internalType":"enum OverTheCounter.AssetType","name":"assetType","type":"uint8"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"}],"internalType":"struct OverTheCounter.Asset[]","name":"_assets","type":"tuple[]"},{"internalType":"uint256","name":"_unlockStart","type":"uint256"},{"internalType":"uint256","name":"_unlockEnd","type":"uint256"},{"internalType":"address","name":"_buyItNowAsset","type":"address"},{"internalType":"uint256","name":"_buyItNowAmount","type":"uint256"},{"internalType":"address","name":"_buyItNowWhitelist","type":"address"},{"internalType":"address","name":"_referrer","type":"address"}],"name":"packageCreate","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bool","name":"_silenceErrors","type":"bool"}],"name":"packageWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"pkgOffers","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"assetContract","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"expiration","type":"uint256"},{"internalType":"address","name":"referrer","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token0","type":"address"},{"internalType":"address","name":"_token1","type":"address"},{"internalType":"uint256","name":"_amount0","type":"uint256"},{"internalType":"uint256","name":"_price18","type":"uint256"},{"internalType":"address","name":"_referrer","type":"address"}],"name":"poolCreate","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"poolRemove","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"poolSwapFeePerc","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_newPrice18","type":"uint256"},{"internalType":"uint256","name":"_amount0ToAdd","type":"uint256"},{"internalType":"bool","name":"_withdrawToken1","type":"bool"}],"name":"poolUpdate","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"referrerFeePerc","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_offerIndex","type":"uint256"}],"name":"removePackageOffer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_wei","type":"uint256"}],"name":"setAddOfferFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_percent","type":"uint256"}],"name":"setBuyPackageFeePerc","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_enabled","type":"bool"}],"name":"setEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IFeeReducer","name":"_reducer","type":"address"}],"name":"setFeeReducer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_max","type":"uint8"}],"name":"setMaxAssetsPerPackage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_percent","type":"uint256"}],"name":"setPoolSwapFeePerc","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_percent","type":"uint256"}],"name":"setReferrerFeePerc","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_wei","type":"uint256"}],"name":"setServiceFeeETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_wei","type":"uint256"}],"name":"setTradeOTCFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_treasury","type":"address"}],"name":"setTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_amount1Provided","type":"uint256"},{"internalType":"uint256","name":"_price18Max","type":"uint256"},{"internalType":"address","name":"_referrer","type":"address"}],"name":"swapPool","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalVolume","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sourceTokenId","type":"uint256"},{"internalType":"uint256","name":"_desiredTokenId","type":"uint256"}],"name":"tradeOTC","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"tradeOTCFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"turnOffPackageTrading","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_unlockStart","type":"uint256"},{"internalType":"uint256","name":"_unlockEnd","type":"uint256"},{"internalType":"address","name":"_buyItNowAsset","type":"address"},{"internalType":"uint256","name":"_buyItNowAmount","type":"uint256"},{"internalType":"address","name":"_buyItNowWhitelist","type":"address"}],"name":"updatePackageInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"bool","name":"_isValid","type":"bool"}],"name":"updateValidOfferToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userOtcTradeWhitelist","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"validOfferERC20","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"contract IWETH","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60806040526002805464ffffffffff1916610a01179055662386f26fc10000600355606462000033620186a06001620001f8565b6200003f919062000226565b600455606462000054620186a06001620001f8565b62000060919062000226565b600555606462000075620186a06032620001f8565b62000081919062000226565b60065566038d7ea4c680006007553480156200009c57600080fd5b506040516200898638038062008986833981016040819052620000bf9162000285565b620000ca336200019a565b60018055600b80546001600160a01b0319166001600160a01b0384161790556040518190620000f990620001ea565b62000105919062000360565b604051809103906000f08015801562000122573d6000803e3d6000fd5b50600c80546001600160a01b0319166001600160a01b0392909216918217905560405163f2fde38b60e01b815233600482015263f2fde38b90602401600060405180830381600087803b1580156200017957600080fd5b505af11580156200018e573d6000803e3d6000fd5b50505050505062000395565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b612746806200624083390190565b60008160001904831182151516156200022157634e487b7160e01b600052601160045260246000fd5b500290565b6000826200024457634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200027c57818101518382015260200162000262565b50506000910152565b600080604083850312156200029957600080fd5b82516001600160a01b0381168114620002b157600080fd5b60208401519092506001600160401b0380821115620002cf57600080fd5b818501915085601f830112620002e457600080fd5b815181811115620002f957620002f962000249565b604051601f8201601f19908116603f0116810190838211818310171562000324576200032462000249565b816040528281528860208487010111156200033e57600080fd5b620003518360208301602088016200025f565b80955050505050509250929050565b6020815260008251806020840152620003818160408501602087016200025f565b601f01601f19169190910160400192915050565b615e9b80620003a56000396000f3fe6080604052600436106102c95760003560e01c8063a47a5e6111610175578063daea4706116100dc578063ec29c39d11610095578063f2fde38b1161006f578063f2fde38b146108ff578063f8143e2e1461091f578063fa3f97b914610935578063ffc965471461095557600080fd5b8063ec29c39d1461089f578063ef040646146108bf578063f0f44260146108df57600080fd5b8063daea4706146107d9578063dd2b7022146107ec578063dd6923111461080c578063e62b9e6c1461083d578063e9d640801461086a578063eb3207c61461087d57600080fd5b8063c1dc1a301161012e578063c1dc1a3014610726578063c52aeaaf14610746578063c7c3796614610766578063d834123e14610786578063d9a37c49146107a6578063da597489146107c657600080fd5b8063a47a5e6114610672578063a9860a6514610688578063b1b7407d146106a8578063b1c87eb7146106c8578063b7fa7cfc146106de578063bf8987b11461071357600080fd5b8063328d8f7211610234578063720d5db9116101ed57806392f5a348116101c757806392f5a348146105d957806395bd9d3b146105fb5780639b485a531461061b578063a21f0e0c1461065257600080fd5b8063720d5db91461054c5780638da5cb5b146105a857806392e86e99146105c657600080fd5b8063328d8f72146104895780633fc8cef3146104a9578063474a0a9b146104e15780634bba74a61461050157806361d027b314610517578063715018a61461053757600080fd5b80631616e4a7116102865780631616e4a7146103a45780631dcbb5b3146103dc57806320a5656d14610409578063238dafe0146104295780632c1904791461045357806330eac4471461047357600080fd5b8063064851d4146102ce5780630c45f7c8146102f05780630e51dab2146103105780630f02206214610323578063126acd2f14610336578063150b7a021461035f575b600080fd5b3480156102da57600080fd5b506102ee6102e9366004615360565b610985565b005b3480156102fc57600080fd5b506102ee61030b366004615399565b610b4c565b6102ee61031e3660046153b2565b610ba4565b6102ee6103313660046153f3565b610dc7565b34801561034257600080fd5b5061034c60035481565b6040519081526020015b60405180910390f35b34801561036b57600080fd5b5061038b61037a366004615449565b630a85bd0160e11b95945050505050565b6040516001600160e01b03199091168152602001610356565b3480156103b057600080fd5b5061034c6103bf3660046154e8565b601560209081526000928352604080842090915290825290205481565b3480156103e857600080fd5b506103fc6103f7366004615399565b611452565b6040516103569190615514565b34801561041557600080fd5b5061034c610424366004615399565b61150a565b34801561043557600080fd5b506002546104439060ff1681565b6040519015158152602001610356565b34801561045f57600080fd5b506102ee61046e366004615399565b61152b565b34801561047f57600080fd5b5061034c60085481565b34801561049557600080fd5b506102ee6104a436600461559a565b611584565b3480156104b557600080fd5b50600b546104c9906001600160a01b031681565b6040516001600160a01b039091168152602001610356565b3480156104ed57600080fd5b506102ee6104fc366004615399565b6115ee565b34801561050d57600080fd5b5061034c60055481565b34801561052357600080fd5b506009546104c9906001600160a01b031681565b34801561054357600080fd5b506102ee6115fb565b34801561055857600080fd5b5061056c6105673660046155b7565b61160f565b604080516001600160a01b03978816815295871660208701528501939093526060840191909152608083015290911660a082015260c001610356565b3480156105b457600080fd5b506000546001600160a01b03166104c9565b6102ee6105d4366004615649565b611673565b3480156105e557600080fd5b506105ee611c5a565b604051610356919061578f565b34801561060757600080fd5b506102ee610616366004615399565b611cbc565b34801561062757600080fd5b5060025461063d90610100900463ffffffff1681565b60405163ffffffff9091168152602001610356565b34801561065e57600080fd5b506102ee61066d366004615399565b611d2a565b34801561067e57600080fd5b5061034c60065481565b34801561069457600080fd5b506102ee6106a3366004615399565b611d98565b3480156106b457600080fd5b506102ee6106c33660046157dc565b611da5565b3480156106d457600080fd5b5061034c60075481565b3480156106ea57600080fd5b506106fe6106f9366004615801565b611ddf565b60408051928352602083019190915201610356565b6102ee61072136600461581e565b611e72565b34801561073257600080fd5b506102ee61074136600461586f565b612447565b34801561075257600080fd5b506102ee6107613660046155b7565b61268a565b34801561077257600080fd5b506102ee6107813660046158dc565b612986565b34801561079257600080fd5b506102ee6107a1366004615801565b6129ac565b3480156107b257600080fd5b50600c546104c9906001600160a01b031681565b6102ee6107d43660046155b7565b6129d6565b6102ee6107e73660046158f9565b612e20565b3480156107f857600080fd5b506102ee61080736600461592f565b613207565b34801561081857600080fd5b5061082c610827366004615399565b61396f565b604051610356959493929190615984565b34801561084957600080fd5b5061034c610858366004615801565b600d6020526000908152604090205481565b6102ee610878366004615ace565b613b1e565b34801561088957600080fd5b50610892613ff6565b6040516103569190615b01565b3480156108ab57600080fd5b506102ee6108ba366004615399565b61404d565b3480156108cb57600080fd5b506102ee6108da366004615399565b61405a565b3480156108eb57600080fd5b506102ee6108fa366004615801565b61427a565b34801561090b57600080fd5b506102ee61091a366004615801565b6142a4565b34801561092b57600080fd5b5061034c60045481565b34801561094157600080fd5b50600a546104c9906001600160a01b031681565b34801561096157600080fd5b50610443610970366004615801565b600e6020526000908152604090205460ff1681565b61098d61431d565b6001600160a01b0382166000908152600e602052604090205481151560ff9091161515036109f05760405162461bcd60e51b815260206004820152600b60248201526a6d75737420746f67676c6560a81b60448201526064015b60405180910390fd5b6001600160a01b0382166000908152600e60205260409020805460ff19168215801591909117909155610a7d57600f80546001600160a01b0384166000818152601060205260408120839055600183018455929092527f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac8020180546001600160a01b03191690911790555050565b6001600160a01b03821660009081526010602052604081208054919055600f8054610aaa90600190615b4f565b81548110610aba57610aba615b68565b600091825260209091200154600f80546001600160a01b039092169183908110610ae657610ae6615b68565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600f805480610b2557610b25615b7e565b600082815260209020810160001990810180546001600160a01b0319169055019055505050565b600c546001600160a01b03163314610b905760405162461bcd60e51b815260206004820152600760248201526613d3931653919560ca1b60448201526064016109e7565b600090815260116020526040812060080155565b600260015403610bc65760405162461bcd60e51b81526004016109e790615b94565b600260015560008481526011602052604090819020600c5491516331a9108f60e11b815260048101879052600a909101916001600160a01b031690636352211e90602401602060405180830381865afa158015610c27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4b9190615bcb565b6001600160a01b0316336001600160a01b031614610c9c5760405162461bcd60e51b815260206004820152600e60248201526d2827a7a62aa8221d1037bbb732b960911b60448201526064016109e7565b600084118015610cb0575083816005015414155b15610cbd57600581018490555b80546001600160a01b0316610cd0573492505b8215610d235782816002016000828254610cea9190615be8565b9250508190555082816003016000828254610d059190615be8565b90915550508054610d2390339030906001600160a01b031686614377565b818015610d34575060008160040154115b15610d625760048101805460009091556001820154610d6090309033906001600160a01b031684614377565b505b8054610d77906001600160a01b0316846146ba565b6040805185815260208101859052831515818301529051339187917f58e6712c5d6a0df543cfa5ba45a39269057354622387fc3f19d385b36049922c9181900360600190a3505060018055505050565b60025460ff1680610de257506000546001600160a01b031633145b610e205760405162461bcd60e51b815260206004820152600f60248201526e1412d1d3d1918e88195b98589b1959608a1b60448201526064016109e7565b60008581526014602090815260408220805460018101825590835290822060069091020180546001600160a01b0319908116331782556005820180546001600160a01b0386811691909316179055426003830155909190819087166111a4576007543411610ec35760405162461bcd60e51b815260206004820152601060248201526f0a0968e9e8c8c7440dccacac8408aa8960831b60448201526064016109e7565b600b546001600160a01b03166000908152600e602052604090205460ff16610f265760405162461bcd60e51b81526020600482015260166024820152751412d1d3d1918e8815d15512081b9bdd081d985b1a5960521b60448201526064016109e7565b600060075434610f369190615b4f565b600b546040516370a0823160e01b81523060048201529192506001600160a01b03169060009082906370a0823190602401602060405180830381865afa158015610f84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa89190615bfb565b9050600b60009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0846040518263ffffffff1660e01b81526004016000604051808303818588803b158015610ffa57600080fd5b505af115801561100e573d6000803e3d6000fd5b50506040516370a0823160e01b81523060048201526001600160a01b038616935063a9059cbb9250339150849084906370a0823190602401602060405180830381865afa158015611063573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110879190615bfb565b6110919190615b4f565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af11580156110dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111009190615c14565b50600b546040805163313ce56760e01b815290516001600160a01b039092169650670de0b6b3a764000091879163313ce5679160048083019260209291908290030181865afa158015611157573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117b9190615c31565b61118690600a615d32565b6111909085615d41565b61119a9190615d60565b9350505050611257565b60075434146111e95760405162461bcd60e51b8152602060048201526011602482015270504b474f46463a206f666665722066656560781b60448201526064016109e7565b6001600160a01b0387166000908152600e602052604090205460ff166112515760405162461bcd60e51b815260206004820152601b60248201527f504b474f46463a20696e76616c6964206f6666657220746f6b656e000000000060448201526064016109e7565b50859050845b60075415611275576112753061126b6146f5565b6000600754614377565b6040516370a0823160e01b8152336004820152829082906001600160a01b038316906370a0823190602401602060405180830381865afa1580156112bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e19190615bfb565b10156113255760405162461bcd60e51b8152602060048201526013602482015272504b474f46463a206261642062616c616e636560681b60448201526064016109e7565b604051636eb1769f60e11b815233600482015230602482015282906001600160a01b0383169063dd62ed3e90604401602060405180830381865afa158015611371573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113959190615bfb565b10156113dc5760405162461bcd60e51b8152602060048201526016602482015275504b474f46463a206e65656420616c6c6f77616e636560501b60448201526064016109e7565b6001840180546001600160a01b0319166001600160a01b0385169081179091556002850183905560048501879055604080519182526020820184905233918b917f01fd1259a9f3b93d5a2865e6f3824ab8d2f7a0e6ebf001b3974acfce0e44d24b910160405180910390a3505050505050505050565b606060146000838152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156114ff5760008481526020908190206040805160c0810182526006860290920180546001600160a01b03908116845260018083015482168587015260028301549385019390935260038201546060850152600482015460808501526005909101541660a08301529083529092019101611487565b505050509050919050565b6012818154811061151a57600080fd5b600091825260209091200154905081565b61153361431d565b620186a081111561157f5760405162461bcd60e51b81526020600482015260166024820152756d757374206265206c657373207468616e203130302560501b60448201526064016109e7565b600655565b61158c61431d565b60025481151560ff9091161515036115db5760405162461bcd60e51b8152602060048201526012602482015271534554454e41424c45443a20746f67676c6560701b60448201526064016109e7565b6002805460ff1916911515919091179055565b6115f661431d565b600355565b61160361431d565b61160d6000614729565b565b6014602052816000526040600020818154811061162b57600080fd5b60009182526020909120600690910201805460018201546002830154600384015460048501546005909501546001600160a01b03948516975092841695509093909290911686565b6002600154036116955760405162461bcd60e51b81526004016109e790615b94565b600260018190555460ff16806116b557506000546001600160a01b031633145b6116f25760405162461bcd60e51b815260206004820152600e60248201526d1412d1d0d48e88195b98589b195960921b60448201526064016109e7565b600254875161010090910463ffffffff1610156117455760405162461bcd60e51b8152602060048201526011602482015270504b4743523a206d61782061737365747360781b60448201526064016109e7565b6001600160a01b038416158061177357506001600160a01b0384166000908152600e602052604090205460ff165b6117b85760405162461bcd60e51b81526020600482015260166024820152751412d1d0d48e88185cdcd95d081b9bdd081d985b1a5960521b60448201526064016109e7565b600c546040516335313c2160e11b81523360048201526000916001600160a01b031690636a627842906024016020604051808303816000875af1158015611803573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118279190615bfb565b60008181526011602052604081209192506002820190805b8b51811015611a175760006001600160a01b03168c828151811061186557611865615b68565b6020026020010151600001516001600160a01b0316036118ab578b818151811061189157611891615b68565b602002602001015160400151826118a89190615be8565b91505b6118ce338d83815181106118c1576118c1615b68565b6020026020010151614779565b600060405180608001604052808e84815181106118ed576118ed615b68565b6020026020010151600001516001600160a01b031681526020018e848151811061191957611919615b68565b60200260200101516020015160028111156119365761193661596e565b81526020018e848151811061194d5761194d615b68565b60200260200101516040015181526020018e848151811061197057611970615b68565b6020908102919091018101516060015190915285546001810187556000878152829020835160039092020180546001600160a01b031981166001600160a01b0390931692831782559284015193945084939092909183916001600160a81b03191617600160a01b8360028111156119e9576119e961596e565b0217905550604082015160018201556060909101516002909101555080611a0f81615d82565b91505061183f565b50600354611a259082615be8565b341015611a745760405162461bcd60e51b815260206004820152601e60248201527f504b4743523a204554482061737365747320706c75732073657276696365000060448201526064016109e7565b60035415611a9257611a9230611a886146f5565b6000600354614377565b88158015611a9e575089155b80611abd57508815801590611ab257508915155b8015611abd57508989115b611b095760405162461bcd60e51b815260206004820152601d60248201527f504b4743523a2076616c696461746520756e6c6f636b20706572696f6400000060448201526064016109e7565b42600183810191909155600283018b9055600383018a90556005830180546001600160a01b038b81166001600160a01b031992831617909255600685018a90556007850180548a841690831617905585548116331786559185018054888316931692909217909155600c5460405163be606dbb60e01b81526004810187905291169063be606dbb90602401600060405180830381600087803b158015611bae57600080fd5b505af1158015611bc2573d6000803e3d6000fd5b5050601280546000888152601360205260408082208390556001830184559290527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444018790558d5190513393508792507f027aa4f47f9c239d6955ac82ff10adafd9f5fd184d731d73b9e674f836920c5e91611c419190815260200190565b60405180910390a3505060018055505050505050505050565b6060600f805480602002602001604051908101604052809291908181526020018280548015611cb257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611c94575b5050505050905090565b611cc461431d565b6064611cd4620186a06014615d41565b611cde9190615d60565b811115611d255760405162461bcd60e51b81526020600482015260156024820152746d757374206265206c657373207468616e2032302560581b60448201526064016109e7565b600555565b611d3261431d565b6064611d42620186a06019615d41565b611d4c9190615d60565b811115611d935760405162461bcd60e51b81526020600482015260156024820152746d757374206265206c657373207468616e2032352560581b60448201526064016109e7565b600455565b611da061431d565b600855565b600260015403611dc75760405162461bcd60e51b81526004016109e790615b94565b6002600155611dd73383836148b5565b505060018055565b600a5460009081906001600160a01b0316611dfc57600080611e69565b600a5460405163a310e73960e01b81526001600160a01b0385811660048301529091169063a310e739906024016040805180830381865afa158015611e45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e699190615d9b565b91509150915091565b600260015403611e945760405162461bcd60e51b81526004016109e790615b94565b600260018190555460ff1680611eb457506000546001600160a01b031633145b611eef5760405162461bcd60e51b815260206004820152600c60248201526b1092538e88195b98589b195960a21b60448201526064016109e7565b600c546040516331a9108f60e11b8152600481018790526000916001600160a01b031690636352211e90602401602060405180830381865afa158015611f39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5d9190615bcb565b6000878152601160209081526040808320815160029091018054610120948102830185019093526101008201838152959650939490939284928491879085015b8282101561202b57600084815260209081902060408051608081019091526003850290910180546001600160a01b03811683529192909190830190600160a01b900460ff166002811115611ff357611ff361596e565b60028111156120045761200461596e565b81526020016001820154815260200160028201548152505081526020019060010190611f9d565b505050908252506001820154602082015260028201546040820152600382015460608201526004820154608082015260058201546001600160a01b0390811660a0830152600683015460c0808401919091526007909301541660e0909101528101519091506120d25760405162461bcd60e51b81526020600482015260136024820152721092538e881b9bdd0818dbdb999a59dd5c9959606a1b60448201526064016109e7565b856001600160a01b03168160a001516001600160a01b0316146121285760405162461bcd60e51b815260206004820152600e60248201526d2124a71d103130b2103a37b5b2b760911b60448201526064016109e7565b848160c001511461216d5760405162461bcd60e51b815260206004820152600f60248201526e1092538e8818985908185b5bdd5b9d608a1b60448201526064016109e7565b60e08101516001600160a01b0316156121dc578060e001516001600160a01b0316336001600160a01b0316146121dc5760405162461bcd60e51b81526020600482015260146024820152731092538e881b9bdd081dda1a5d195b1a5cdd195960621b60448201526064016109e7565b6000620186a06005548360c001516121f49190615d41565b6121fe9190615d60565b905060008061220c85611ddf565b9092509050811561223957806122228385615d41565b61222c9190615d60565b6122369084615b4f565b92505b6000838560c0015161224b9190615b4f565b60a086015190915033906001600160a01b03166122a9575030348a146122a95760405162461bcd60e51b8152602060048201526013602482015272084929c7440dcdee840cadcdeeaced0408aa89606b1b60448201526064016109e7565b6122ba8c828a8960a0015189614a84565b6122ca81888860a0015185614377565b600c60009054906101000a90046001600160a01b03166001600160a01b03166342842e0e88338f6040518463ffffffff1660e01b815260040161230f93929190615dbf565b600060405180830381600087803b15801561232957600080fd5b505af115801561233d573d6000803e3d6000fd5b5050600c5460405163be606dbb60e01b81526001600160a01b03909116925063be606dbb9150612375908f9060040190815260200190565b600060405180830381600087803b15801561238f57600080fd5b505af11580156123a3573d6000803e3d6000fd5b50505060c087015160a08801516001600160a01b03166000908152600d602052604081208054929350916123d8908490615be8565b909155505088156123ef576123ef338d60006148b5565b866001600160a01b03168c7ff523bee1c395e32783207e84ef1826e9d5e9b43b3179a55b83a75377f38077b5338e8e60405161242d93929190615dbf565b60405180910390a350506001805550505050505050505050565b6002600154036124695760405162461bcd60e51b81526004016109e790615b94565b6002600155600c546040516331a9108f60e11b81526004810188905233916001600160a01b031690636352211e90602401602060405180830381865afa1580156124b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124db9190615bcb565b6001600160a01b0316146125245760405162461bcd60e51b815260206004820152601060248201526f2aa22820aa22a825a39d1037bbb732b960811b60448201526064016109e7565b6001600160a01b038316158061255257506001600160a01b0383166000908152600e602052604090205460ff165b61259e5760405162461bcd60e51b815260206004820152601a60248201527f555044415445504b473a206173736574206e6f742076616c696400000000000060448201526064016109e7565b60008681526011602052604090206007810180546001600160a01b038087166001600160a01b0319928316179092556008830185905560098301805485841692169190911790558154600290920191163303612607576002810186905560038101859055612616565b80600201549550806003015494505b60028101546003820154604080516001600160a01b038881168252602082018890528616818301526060810193909352608083019190915251339189917f2efaa9c195616ac6d1b5d9691b59d9ea46789e66b70118ea08ba025ebf08a6b59181900360a00190a35050600180555050505050565b6002600154036126ac5760405162461bcd60e51b81526004016109e790615b94565b600260015560008281526014602052604081208054839081106126d1576126d1615b68565b60009182526020918290206040805160c08101825260069390930290910180546001600160a01b0390811684526001820154811694840194909452600281015483830152600381015460608401526004808201546080850152600590910154841660a0840152600c5491516331a9108f60e11b815290810187905291935033921690636352211e90602401602060405180830381865afa158015612779573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061279d9190615bcb565b6001600160a01b031614806127bb575080516001600160a01b031633145b6127fa5760405162461bcd60e51b815260206004820152601060248201526f2922a522a1aa27a3231d1037bbb732b960811b60448201526064016109e7565b6000838152601460205260409020805461281690600190615b4f565b8154811061282657612826615b68565b906000526020600020906006020160146000858152602001908152602001600020838154811061285857612858615b68565b60009182526020808320845460069093020180546001600160a01b03199081166001600160a01b0394851617825560018087015490830180548316918616919091179055600280870154908301556003808701549083015560048087015490830155600595860154959091018054909116949092169390931790558481526014909152604090208054806128ee576128ee615b7e565b60008281526020812060066000199093019283020180546001600160a01b031990811682556001820180548216905560028201839055600382018390556004820192909255600501805490911690559055604051339084907fbe4a9d5e7c5889dba51d4be13ca36cc0eec3014f0f6b6eb6bfdd5b415483540b906129759086815260200190565b60405180910390a350506001805550565b61298e61431d565b6002805464ffffffff00191660ff9290921661010002919091179055565b6129b461431d565b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b6002600154036129f85760405162461bcd60e51b81526004016109e790615b94565b6002600155600c546040516331a9108f60e11b81526004810184905233916001600160a01b031690636352211e90602401602060405180830381865afa158015612a46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a6a9190615bcb565b6001600160a01b031614612ac05760405162461bcd60e51b815260206004820152601760248201527f54524144453a2062616420736f75726365206f776e657200000000000000000060448201526064016109e7565b80600003612ae857336000908152601560209081526040808320858452909152812055611dd7565b336000908152601560209081526040808320858452909152808220839055600c5490516331a9108f60e11b8152600481018490526001600160a01b0390911690636352211e90602401602060405180830381865afa158015612b4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b729190615bcb565b6001600160a01b0381166000908152601560209081526040808320868452909152902054909150839003612e045760085415612c01576008543414612beb5760405162461bcd60e51b815260206004820152600f60248201526e0a8a482888a7440dccacac8408aa89608b1b60448201526064016109e7565b612c0130612bf76146f5565b6000600854614377565b600c546040516323b872dd60e01b81526001600160a01b03909116906323b872dd90612c3590339085908890600401615dbf565b600060405180830381600087803b158015612c4f57600080fd5b505af1158015612c63573d6000803e3d6000fd5b5050600c546040516323b872dd60e01b81526001600160a01b0390911692506323b872dd9150612c9b90849033908790600401615dbf565b600060405180830381600087803b158015612cb557600080fd5b505af1158015612cc9573d6000803e3d6000fd5b5050600c5460405163be606dbb60e01b8152600481018790526001600160a01b03909116925063be606dbb9150602401600060405180830381600087803b158015612d1357600080fd5b505af1158015612d27573d6000803e3d6000fd5b5050600c5460405163be606dbb60e01b8152600481018690526001600160a01b03909116925063be606dbb9150602401600060405180830381600087803b158015612d7157600080fd5b505af1158015612d85573d6000803e3d6000fd5b50503360008181526015602081815260408084208a855282528084208490556001600160a01b03881680855292825280842089855282528084209390935582518981529081018890529094509192507f4b5796113f074ebf8f11d5bcdeb6349b2fbe47abed78419cdcdbbc15c6fcf845910160405180910390a3612e17565b3415612e1757612e173033600034614377565b50505060018055565b600260015403612e425760405162461bcd60e51b81526004016109e790615b94565b600260018190555460ff1680612e6257506000546001600160a01b031633145b612ea05760405162461bcd60e51b815260206004820152600f60248201526e1413d3d314d5ce88195b98589b1959608a1b60448201526064016109e7565b6000848152601160205260409020600f810154600a90910190831015612f085760405162461bcd60e51b815260206004820152601b60248201527f504f4f4c53573a2065787065637465642073776170207072696365000000000060448201526064016109e7565b6000816003015411612f505760405162461bcd60e51b8152602060048201526011602482015270504f4f4c53573a206c697175696469747960781b60448201526064016109e7565b6000670de0b6b3a76400008260050154866ec097ce7bc90715b34b9f1000000000612f7b9190615d41565b612f859190615d60565b612f8f9190615d60565b9050816003015481111561301857600582015460038301548691670de0b6b3a764000091612fbd9190615d41565b612fc79190615d60565b9550808611156130105760405162461bcd60e51b8152602060048201526014602482015273504f4f4c53573a206261636b757020636865636b60601b60448201526064016109e7565b505060038101545b8082600301600082825461302c9190615b4f565b9091555050600454600090620186a0906130469088615d41565b6130509190615d60565b905060008061305e33611ddf565b9092509050811561308b57806130748385615d41565b61307e9190615d60565b6130889084615b4f565b92505b6000613097848a615b4f565b9050808660040160008282546130ad9190615be8565b9091555050600186015433906001600160a01b031661311257309050893410156131125760405162461bcd60e51b81526020600482015260166024820152750a09e9e98a6ae7440dcdee840cadcdeeaced0408aa8960531b60448201526064016109e7565b6001870154613130908c9083908b906001600160a01b031689614a84565b600187015461314c90829030906001600160a01b031685614377565b6001870154613164906001600160a01b03168b6146ba565b865461317d90309033906001600160a01b031689614377565b86546001600160a01b03166000908152600d6020526040812080548892906131a6908490615be8565b909155505086546001880154604080516001600160a01b039384168152602081018a90529290911690820152606081018b905233908c907fc0400bc4a7d71dd0136e5c1772e5cf3fdb9c90d825057feb726622fbc86b256090608001611c41565b6002600154036132295760405162461bcd60e51b81526004016109e790615b94565b600260018190555460ff168061324957506000546001600160a01b031633145b61328a5760405162461bcd60e51b81526020600482015260126024820152711050d0d1541513d1918e88195b98589b195960721b60448201526064016109e7565b600c546040516331a9108f60e11b81526004810186905233916001600160a01b031690636352211e90602401602060405180830381865afa1580156132d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132f79190615bcb565b6001600160a01b0316146133405760405162461bcd60e51b815260206004820152601060248201526f20a1a1a2a82a27a3231d1037bbb732b960811b60448201526064016109e7565b600084815260146020526040812080548590811061336057613360615b68565b60009182526020918290206040805160c081018252600690930290910180546001600160a01b03908116845260018201548116948401859052600282015492840192909252600381015460608401526004810154608084015260050154811660a083015290925084161461340d5760405162461bcd60e51b81526020600482015260146024820152731050d0d1541513d1918e8818985908185cdcd95d60621b60448201526064016109e7565b818160400151146134585760405162461bcd60e51b81526020600482015260156024820152741050d0d1541513d1918e8818985908185b5bdd5b9d605a1b60448201526064016109e7565b6080810151158061346c5750428160800151115b6134ad5760405162461bcd60e51b81526020600482015260126024820152711050d0d1541513d1918e88195e1c1a5c995960721b60448201526064016109e7565b600085815260116020908152604080832081516002909101805461012094810283018501909352610100820183815291939092849291849190879085015b8282101561357957600084815260209081902060408051608081019091526003850290910180546001600160a01b03811683529192909190830190600160a01b900460ff1660028111156135415761354161596e565b60028111156135525761355261596e565b815260200160018201548152602001600282015481525050815260200190600101906134eb565b5050509082525060018201546020820152600282015460408201526003820154606080830191909152600483015460808084019190915260058401546001600160a01b0390811660a0850152600685015460c085015260079094015490931660e0909201919091529082015190840151919250106136395760405162461bcd60e51b815260206004820152601a60248201527f4143434550544f46463a206c617374207769746864726177616c00000000000060448201526064016109e7565b6000620186a060055484604001516136519190615d41565b61365b9190615d60565b905060008061366933611ddf565b90925090508115613696578061367f8385615d41565b6136899190615d60565b6136939084615b4f565b92505b60008386604001516136a89190615b4f565b90506136c38a87600001518860a00151896020015188614a84565b6136d7866000015133886020015184614377565b600c548651604051632142170760e11b81526001600160a01b03909216916342842e0e9161370c913391908f90600401615dbf565b600060405180830381600087803b15801561372657600080fd5b505af115801561373a573d6000803e3d6000fd5b5050600c5460405163be606dbb60e01b8152600481018e90526001600160a01b03909116925063be606dbb9150602401600060405180830381600087803b15801561378457600080fd5b505af1158015613798573d6000803e3d6000fd5b50505060008b815260146020526040902080549091506137ba90600190615b4f565b815481106137ca576137ca615b68565b9060005260206000209060060201601460008c81526020019081526020016000208a815481106137fc576137fc615b68565b60009182526020808320845460069093020180546001600160a01b03199081166001600160a01b0394851617825560018087015490830180548316918616919091179055600280870154908301556003808701549083015560048087015490830155600595860154959091018054909116949092169390931790558b815260149091526040902080548061389257613892615b7e565b6000828152602080822060066000199094019384020180546001600160a01b031990811682556001820180548216905560028201849055600382018490556004820184905560059091018054909116905591909255604080890151898301516001600160a01b03168452600d9092528220805491929091613914908490615be8565b909155505085516020870151604080890151905133938e937fa2e6f53e775c6ebbe3fab4ba06b07381ae41384f7bfc96a475b1979a1ca0919f9361395793615dbf565b60405180910390a35050600180555050505050505050565b6011602090815260009182526040808320805460018201548351600284018054968702820161012090810190965261010082018781526001600160a01b0380861699600160a01b90960460ff16989416969294919385939192859285015b82821015613a5b57600084815260209081902060408051608081019091526003850290910180546001600160a01b03811683529192909190830190600160a01b900460ff166002811115613a2357613a2361596e565b6002811115613a3457613a3461596e565b815260200160018201548152602001600282015481525050815260200190600101906139cd565b50505090825250600182015460208083019190915260028301546040808401919091526003840154606080850191909152600485015460808086019190915260058601546001600160a01b0390811660a080880191909152600688015460c080890191909152600790980154821660e09097019690965283519687018452600a89015481168752600b8901541693860193909352600c87015491850191909152600d86015490840152600e85015490830152600f90930154928101929092529085565b600260015403613b405760405162461bcd60e51b81526004016109e790615b94565b600260018190555460ff1680613b6057506000546001600160a01b031633145b613b9e5760405162461bcd60e51b815260206004820152600f60248201526e1413d3d310d48e88195b98589b1959608a1b60448201526064016109e7565b60008311613bee5760405162461bcd60e51b815260206004820152601f60248201527f504f4f4c43523a206e65656420746f2070726f7669646520616d6f756e74300060448201526064016109e7565b60008211613c3e5760405162461bcd60e51b815260206004820152601860248201527f504f4f4c43523a206e6565642076616c6964207072696365000000000000000060448201526064016109e7565b6001600160a01b038516151580613c5d57506001600160a01b03841615155b613ca05760405162461bcd60e51b81526020600482015260146024820152731413d3d310d48e881a5b9d985b1a59081c1bdbdb60621b60448201526064016109e7565b613ccd3330876001600160a01b03811615613cbb5786614377565b600354613cc89088615be8565b614377565b6001600160a01b0384161580613d4457506000846001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613d1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d429190615bfb565b115b613d905760405162461bcd60e51b815260206004820152601760248201527f504f4f4c43523a20746f6b656e312076616c696461746500000000000000000060448201526064016109e7565b60035415613df657600354341015613dea5760405162461bcd60e51b815260206004820152601760248201527f504f4f4c43523a2073657276696365206665652045544800000000000000000060448201526064016109e7565b613df630611a886146f5565b600c546040516335313c2160e11b81523360048201526000916001600160a01b031690636a627842906024016020604051808303816000875af1158015613e41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e659190615bfb565b60008181526011602052604090819020600a810180546001600160a01b03199081166001600160a01b038c8116919091178355600b8401805483168c8316179055600c8085018b9055600d85018b9055600f85018a905584546001860180549094168a841617909355600160a01b6001600160a81b03199093163360ff60a01b1916179290921784559054935163be606dbb60e01b815260048101869052949550919390929091169063be606dbb90602401600060405180830381600087803b158015613f3157600080fd5b505af1158015613f45573d6000803e3d6000fd5b5050601280546000878152601360209081526040808320849055600184018555939091527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec344490910187905581516001600160a01b03808e1682528c1691810191909152908101899052606081018890523392508591507f020c7d113c93ec461c5a54f7f999095b38bf3e9428d1fdc12d158c875bda1ee29060800160405180910390a3505060018055505050505050565b60606012805480602002602001604051908101604052809291908181526020018280548015611cb257602002820191906000526020600020905b815481526020019060010190808311614030575050505050905090565b61405561431d565b600755565b60026001540361407c5760405162461bcd60e51b81526004016109e790615b94565b6002600155600081815260116020908152604091829020825160c081018452600a8201546001600160a01b039081168252600b830154811693820193909352600c8083015482860152600d8301546060830152600e8301546080830152600f9092015460a0820152905492516331a9108f60e11b815260048101859052909290911690636352211e90602401602060405180830381865afa158015614125573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141499190615bcb565b6001600160a01b0316336001600160a01b0316146141995760405162461bcd60e51b815260206004820152600d60248201526c2827a7a629269d1037bbb732b960991b60448201526064016109e7565b80516001600160a01b03161515806141bd575060208101516001600160a01b031615155b6142005760405162461bcd60e51b81526020600482015260146024820152731413d3d314934e881a5b9d985b1a59081c1bdbdb60621b60448201526064016109e7565b61420982614b82565b60608101511561422757614227303383600001518460600151614377565b60808101511561424557614245303383602001518460800151614377565b604051339083907f31070a32ba1763d3c4bba8a23f2a3c7e695943aba7ac3c104746c2fe744555d190600090a3505060018055565b61428261431d565b600980546001600160a01b0319166001600160a01b0392909216919091179055565b6142ac61431d565b6001600160a01b0381166143115760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016109e7565b61431a81614729565b50565b6000546001600160a01b0316331461160d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016109e7565b826001600160a01b0316846001600160a01b031603156146b4576001600160a01b038316156143a657826143ae565b6143ae6146f5565b92506001600160a01b03821661454b57306001600160a01b0384160361441a57803410156144155760405162461bcd60e51b81526020600482015260146024820152730a68a9c887440dcdee840cadcdeeaced0408aa8960631b60448201526064016109e7565b6146b4565b6001600160a01b03841630146144655760405162461bcd60e51b815260206004820152601060248201526f53454e443a2062616420736f7572636560801b60448201526064016109e7565b60405147906000906001600160a01b0386169084908381818185875af1925050503d80600081146144b2576040519150601f19603f3d011682016040523d82523d6000602084013e6144b7565b606091505b50509050806144ff5760405162461bcd60e51b815260206004820152601460248201527314d153910e8818dbdd5b19081b9bdd081cd95b9960621b60448201526064016109e7565b6145098383615b4f565b4710156145445760405162461bcd60e51b81526020600482015260096024820152680a68a9c8874408aa8960bb1b60448201526064016109e7565b50506146b4565b6040516370a0823160e01b81526001600160a01b03848116600483015283916000918316906370a0823190602401602060405180830381865afa158015614596573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145ba9190615bfb565b9050306001600160a01b038716036145e5576145e06001600160a01b0383168685614c8a565b6145fa565b6145fa6001600160a01b038316878786614ced565b6146048184615be8565b6040516370a0823160e01b81526001600160a01b0387811660048301528416906370a0823190602401602060405180830381865afa15801561464a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061466e9190615bfb565b10156146b15760405162461bcd60e51b815260206004820152601260248201527114d153910e88115490cc8c08185b5bdd5b9d60721b60448201526064016109e7565b50505b50505050565b60006001600160a01b038316156146d157346146db565b6146db8234615b4f565b905080156146f0576146f03033600084614377565b505050565b6009546000906001600160a01b03161561471957506009546001600160a01b031690565b506000546001600160a01b031690565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000816020015160028111156147915761479161596e565b036147ae576147aa823083600001518460400151614377565b5050565b6001816020015160028111156147c6576147c661596e565b036148785760008160600151116148145760405162461bcd60e51b815260206004820152601260248201527115905312511412d1ce881d1bdad95b88125160721b60448201526064016109e7565b80516060820151604051632142170760e11b81526001600160a01b03909216916342842e0e9161484a9186913091600401615dbf565b600060405180830381600087803b15801561486457600080fd5b505af11580156146b1573d6000803e3d6000fd5b805160608201516040808401519051637921219560e11b81526001600160a01b039093169263f242432a9261484a92879230929190600401615de3565b600082815260116020526040808220600c5491516331a9108f60e11b8152600481018690529092600284019290916001600160a01b0390911690636352211e90602401602060405180830381865afa158015614915573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149399190615bcb565b9050806001600160a01b0316866001600160a01b03161461498d5760405162461bcd60e51b815260206004820152600e60248201526d2825a3aba4aa241d1037bbb732b960911b60448201526064016109e7565b81546149db5760405162461bcd60e51b815260206004820152601860248201527f504b47574954483a20696e76616c6964207061636b616765000000000000000060448201526064016109e7565b60005b8254811015614a05576149f382878388614d0e565b806149fd81615d82565b9150506149de565b5042600483015582546001600160a01b0382811691161480614a2957506003820154155b80614a38575081600301544210155b15614a4657614a4685614b82565b6040516001600160a01b0382169086907f88dc50c8f473f203c7debe6f7be35d0bc0c5c9c76ecee50da2c24902a3727dcf90600090a3505050505050565b8015614b7b576000858152601160205260408120600101546006546001600160a01b039091169190620186a090614abb9085615d41565b614ac59190615d60565b90506000614ad38285615b4f565b90508115614b5e576001600160a01b03831615801590614afb57506001600160a01b03861615155b15614b3c576000614b0d600284615d60565b90506000614b1b8285615b4f565b9050614b2989868985614377565b614b3589898984614377565b5050614b5e565b614b5e876001600160a01b03881615614b555787614b57565b845b8785614377565b8015614b7757614b7787614b706146f5565b8784614377565b5050505b5050505050565b600c54604051630852cd8d60e31b8152600481018390526001600160a01b03909116906342966c6890602401600060405180830381600087803b158015614bc857600080fd5b505af1158015614bdc573d6000803e3d6000fd5b5050506000828152601360205260408120546012805491935090614c0290600190615b4f565b81548110614c1257614c12615b68565b60009182526020808320909101548583526013909152604080832083905581835290912083905560128054919250829184908110614c5257614c52615b68565b6000918252602090912001556012805480614c6f57614c6f615b7e565b60019003818190600052602060002001600090559055505050565b6040516001600160a01b0383166024820152604481018290526146f090849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526150d8565b6146b4846323b872dd60e01b858585604051602401614cb693929190615dbf565b60008381526011602052604081206002018054909190829085908110614d3657614d36615b68565b6000918252602080832060016003909302019182015488845260119091526040909220549092506001600160a01b0390811690881614801590614d7d575060008360030154115b8015614d8c5750826003015442105b15614ea55760018254600160a01b900460ff166002811115614db057614db061596e565b03614dbd575050506146b4565b600083600201548460030154614dd39190615b4f565b9050600080856004015411614e02576000856002015411614df8578460010154614e08565b8460020154614e08565b84600401545b905080421015614e505760405162461bcd60e51b8152602060048201526013602482015272574954483a206c61737420776974686472617760681b60448201526064016109e7565b8183614e5c8342615b4f565b614e669190615d41565b614e709190615d60565b925082600003614e845750505050506146b4565b82846001016000828254614e989190615b4f565b90915550614ead92505050565b600060018301555b60008254600160a01b900460ff166002811115614ecc57614ecc61596e565b03614eef578154614eea90309089906001600160a01b031684614377565b6150cf565b60018254600160a01b900460ff166002811115614f0e57614f0e61596e565b03614ff1578315614f845781546002830154604051632142170760e11b81526001600160a01b03909216916342842e0e91614f4f9130918c91600401615dbf565b600060405180830381600087803b158015614f6957600080fd5b505af1925050508015614f7a575060015b15614eea576150cf565b81546002830154604051632142170760e11b81526001600160a01b03909216916342842e0e91614fba9130918c91600401615dbf565b600060405180830381600087803b158015614fd457600080fd5b505af1158015614fe8573d6000803e3d6000fd5b505050506150cf565b83156150645781546002830154604051637921219560e11b81526001600160a01b039092169163f242432a9161502f9130918c918790600401615de3565b600060405180830381600087803b15801561504957600080fd5b505af192505050801561505a575060015b156150cf576150cf565b81546002830154604051637921219560e11b81526001600160a01b039092169163f242432a9161509c9130918c918790600401615de3565b600060405180830381600087803b1580156150b657600080fd5b505af11580156150ca573d6000803e3d6000fd5b505050505b50505050505050565b600061512d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166151aa9092919063ffffffff16565b8051909150156146f0578080602001905181019061514b9190615c14565b6146f05760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016109e7565b60606151b984846000856151c3565b90505b9392505050565b6060824710156152245760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109e7565b6001600160a01b0385163b61527b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109e7565b600080866001600160a01b031685876040516152979190615e3f565b60006040518083038185875af1925050503d80600081146152d4576040519150601f19603f3d011682016040523d82523d6000602084013e6152d9565b606091505b50915091506152e98282866152f4565b979650505050505050565b606083156153035750816151bc565b8251156153135782518084602001fd5b8160405162461bcd60e51b81526004016109e79190615e5b565b6001600160a01b038116811461431a57600080fd5b803561534d8161532d565b919050565b801515811461431a57600080fd5b6000806040838503121561537357600080fd5b823561537e8161532d565b9150602083013561538e81615352565b809150509250929050565b6000602082840312156153ab57600080fd5b5035919050565b600080600080608085870312156153c857600080fd5b84359350602085013592506040850135915060608501356153e881615352565b939692955090935050565b600080600080600060a0868803121561540b57600080fd5b85359450602086013561541d8161532d565b93506040860135925060608601359150608086013561543b8161532d565b809150509295509295909350565b60008060008060006080868803121561546157600080fd5b853561546c8161532d565b9450602086013561547c8161532d565b935060408601359250606086013567ffffffffffffffff808211156154a057600080fd5b818801915088601f8301126154b457600080fd5b8135818111156154c357600080fd5b8960208285010111156154d557600080fd5b9699959850939650602001949392505050565b600080604083850312156154fb57600080fd5b82356155068161532d565b946020939093013593505050565b602080825282518282018190526000919060409081850190868401855b8281101561558d57815180516001600160a01b039081168652878201518116888701528682015187870152606080830151908701526080808301519087015260a091820151169085015260c09093019290850190600101615531565b5091979650505050505050565b6000602082840312156155ac57600080fd5b81356151bc81615352565b600080604083850312156155ca57600080fd5b50508035926020909101359150565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715615612576156126155d9565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715615641576156416155d9565b604052919050565b600080600080600080600060e0888a03121561566457600080fd5b873567ffffffffffffffff8082111561567c57600080fd5b818a0191508a601f83011261569057600080fd5b81356020828211156156a4576156a46155d9565b6156b2818360051b01615618565b828152818101935060079290921b84018101918d8311156156d257600080fd5b938101935b82851015615740576080858f0312156156f05760008081fd5b6156f86155ef565b85356157038161532d565b815285830135600381106157175760008081fd5b8184015260408681013590820152606080870135908201528452608090940193928101926156d7565b9a508b0135985050506040890135955061575e905060608901615342565b93506080880135925061577360a08901615342565b915061578160c08901615342565b905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b818110156157d05783516001600160a01b0316835292840192918401916001016157ab565b50909695505050505050565b600080604083850312156157ef57600080fd5b82359150602083013561538e81615352565b60006020828403121561581357600080fd5b81356151bc8161532d565b600080600080600060a0868803121561583657600080fd5b8535945060208601356158488161532d565b935060408601359250606086013561585f81615352565b9150608086013561543b8161532d565b60008060008060008060c0878903121561588857600080fd5b86359550602087013594506040870135935060608701356158a88161532d565b92506080870135915060a08701356158bf8161532d565b809150509295509295509295565b60ff8116811461431a57600080fd5b6000602082840312156158ee57600080fd5b81356151bc816158cd565b6000806000806080858703121561590f57600080fd5b84359350602085013592506040850135915060608501356153e88161532d565b6000806000806080858703121561594557600080fd5b8435935060208501359250604085013561595e8161532d565b9396929550929360600135925050565b634e487b7160e01b600052602160045260246000fd5b600061014060018060a01b0380891684526020881515818601526040828916818701526060848188015261024087018951610100878a015281965080518083526102608a019750858201925060009150815b81811015615a2b578351888151168a528781015160038110615a0657634e487b7160e01b85526021600452602485fd5b8a89015280870151878b0152850151858a0152608090980197928601926001016159d6565b50505050918801516101608701528701516101808601528601516101a0850152506080808601516101c085015260a0808701516001600160a01b039081166101e087015260c08089015161020088015260e0808a0151831661022089015288518316858901526020890151909216838801526040880151908701526060870151908601529085015161010085015284015161012084015290509695505050505050565b600080600080600060a08688031215615ae657600080fd5b8535615af18161532d565b9450602086013561541d8161532d565b6020808252825182820181905260009190848201906040850190845b818110156157d057835183529284019291840191600101615b1d565b634e487b7160e01b600052601160045260246000fd5b81810381811115615b6257615b62615b39565b92915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b600060208284031215615bdd57600080fd5b81516151bc8161532d565b80820180821115615b6257615b62615b39565b600060208284031215615c0d57600080fd5b5051919050565b600060208284031215615c2657600080fd5b81516151bc81615352565b600060208284031215615c4357600080fd5b81516151bc816158cd565b600181815b80851115615c89578160001904821115615c6f57615c6f615b39565b80851615615c7c57918102915b93841c9390800290615c53565b509250929050565b600082615ca057506001615b62565b81615cad57506000615b62565b8160018114615cc35760028114615ccd57615ce9565b6001915050615b62565b60ff841115615cde57615cde615b39565b50506001821b615b62565b5060208310610133831016604e8410600b8410161715615d0c575081810a615b62565b615d168383615c4e565b8060001904821115615d2a57615d2a615b39565b029392505050565b60006151bc60ff841683615c91565b6000816000190483118215151615615d5b57615d5b615b39565b500290565b600082615d7d57634e487b7160e01b600052601260045260246000fd5b500490565b600060018201615d9457615d94615b39565b5060010190565b60008060408385031215615dae57600080fd5b505080516020909101519092909150565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260009082015260c00190565b60005b83811015615e36578181015183820152602001615e1e565b50506000910152565b60008251615e51818460208701615e1b565b9190910192915050565b6020815260008251806020840152615e7a816040850160208701615e1b565b601f01601f1916919091016040019291505056fea164736f6c6343000810000a60806040526032600f553480156200001657600080fd5b506040516200274638038062002746833981016040819052620000399162000154565b604051806040016040528060128152602001715969656c64696669636174696f6e204f544360701b8152506040518060400160405280600681526020016537ba31aca22360d11b8152508160009081620000949190620002b8565b506001620000a38282620002b8565b505050620000c0620000ba620000e860201b60201c565b620000ec565b600d620000ce8282620002b8565b5050600b80546001600160a01b0319163317905562000384565b3390565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b634e487b7160e01b600052604160045260246000fd5b600060208083850312156200016857600080fd5b82516001600160401b03808211156200018057600080fd5b818501915085601f8301126200019557600080fd5b815181811115620001aa57620001aa6200013e565b604051601f8201601f19908116603f01168101908382118183101715620001d557620001d56200013e565b816040528281528886848701011115620001ee57600080fd5b600093505b82841015620002125784840186015181850187015292850192620001f3565b600086848301015280965050505050505092915050565b600181811c908216806200023e57607f821691505b6020821081036200025f57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002b357600081815260208120601f850160051c810160208610156200028e5750805b601f850160051c820191505b81811015620002af578281556001016200029a565b5050505b505050565b81516001600160401b03811115620002d457620002d46200013e565b620002ec81620002e5845462000229565b8462000265565b602080601f8311600181146200032457600084156200030b5750858301515b600019600386901b1c1916600185901b178555620002af565b600085815260208120601f198616915b82811015620003555788860151825594840194600190910190840162000334565b5085821015620003745787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6123b280620003946000396000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c806370a0823111610125578063b6b81940116100ad578063c87b56dd1161007c578063c87b56dd146104b4578063e8a3d485146104c7578063e985e9c5146104cf578063f2fde38b1461050b578063ffa801361461051e57600080fd5b8063b6b8194014610468578063b88d4fde1461047b578063be606dbb1461048e578063c3738f3f146104a157600080fd5b80638da5cb5b116100f45780638da5cb5b1461041657806395d89b4114610427578063a22cb4651461042f578063ad2f852a14610442578063b22f443c1461045557600080fd5b806370a08231146103d3578063715018a6146103e657806376772cf8146103ee5780637974e46a1461040e57600080fd5b80632a55205a116101a857806342966c681161017757806342966c68146103745780634f6ccce71461038757806355f804b31461039a5780636352211e146103ad5780636a627842146103c057600080fd5b80632a55205a146103095780632d88931b1461033b5780632f745c591461034e57806342842e0e1461036157600080fd5b8063095ea7b3116101ef578063095ea7b31461029e57806318160ddd146102b157806320e3fa50146102c357806323b872dd146102d6578063274de61e146102e957600080fd5b806301ffc9a71461022157806306d254da1461024957806306fdde031461025e578063081812fc14610273575b600080fd5b61023461022f366004611c79565b61053e565b60405190151581526020015b60405180910390f35b61025c610257366004611cb4565b61054f565b005b6102666105a1565b6040516102409190611d1f565b610286610281366004611d32565b610633565b6040516001600160a01b039091168152602001610240565b61025c6102ac366004611d4b565b61065a565b6008545b604051908152602001610240565b6102b56102d1366004611d4b565b610774565b61025c6102e4366004611d75565b6107a5565b6102b56102f7366004611d32565b60116020526000908152604090205481565b61031c610317366004611db1565b6107d6565b604080516001600160a01b039093168352602083019190915201610240565b61025c610349366004611cb4565b610810565b6102b561035c366004611d4b565b61083a565b61025c61036f366004611d75565b6108d0565b61025c610382366004611d32565b6108eb565b6102b5610395366004611d32565b610987565b61025c6103a8366004611e5f565b610a1a565b6102866103bb366004611d32565b610a70565b6102b56103ce366004611cb4565b610ad0565b6102b56103e1366004611cb4565b610b85565b61025c610c0b565b6102b56103fc366004611d32565b60126020526000908152604090205481565b6102b5610c1f565b600a546001600160a01b0316610286565b610266610c2f565b61025c61043d366004611ea8565b610c3e565b600e54610286906001600160a01b031681565b600b54610286906001600160a01b031681565b61025c610476366004611d32565b610c4d565b61025c610489366004611ee4565b610c88565b61025c61049c366004611d32565b610cc0565b6102346104af366004611d32565b610d03565b6102666104c2366004611d32565b610d22565b610266610d7e565b6102346104dd366004611f60565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b61025c610519366004611cb4565b610dac565b61053161052c366004611cb4565b610e22565b6040516102409190611f93565b600061054982610e8e565b92915050565b610557610eb3565b600e80546001600160a01b0319166001600160a01b0383169081179091556040517f0f2a87e68f9d4311c1d18e960f7873198e70403a037237cdd2c583c69cdddf1f90600090a250565b6060600080546105b090611fd7565b80601f01602080910402602001604051908101604052809291908181526020018280546105dc90611fd7565b80156106295780601f106105fe57610100808354040283529160200191610629565b820191906000526020600020905b81548152906001019060200180831161060c57829003601f168201915b5050505050905090565b600061063e82610f0d565b506000908152600460205260409020546001600160a01b031690565b600061066582610a70565b9050806001600160a01b0316836001600160a01b0316036106d75760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b03821614806106f357506106f381336104dd565b6107655760405162461bcd60e51b815260206004820152603e60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206e6f7220617070726f76656420666f7220616c6c000060648201526084016106ce565b61076f8383610f6c565b505050565b6010602052816000526040600020818154811061079057600080fd5b90600052602060002001600091509150505481565b6107af3382610fda565b6107cb5760405162461bcd60e51b81526004016106ce90612011565b61076f838383611059565b600e54600f5460009182916001600160a01b03909116906103e8906107fb9086612075565b61080591906120aa565b915091509250929050565b610818610eb3565b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b600061084583610b85565b82106108a75760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b60648201526084016106ce565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b61076f83838360405180602001604052806000815250610c88565b600b546001600160a01b031633146109155760405162461bcd60e51b81526004016106ce906120be565b600061092082610a70565b6000838152600260205260409020549091506001600160a01b031661094457600080fd5b61094d82611206565b6040516001600160a01b0382169083907ff6554c3a5d28e08c120b5a69c7edbaf52f935bd2596a60b8a18e282cd257cddb90600090a35050565b600061099260085490565b82106109f55760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b60648201526084016106ce565b60088281548110610a0857610a086120e0565b90600052602060002001549050919050565b610a22610eb3565b600d610a2e8282612144565b5080604051610a3d9190612204565b604051908190038120907f199e933997358e1789d8b56ea8c551befeb05ce2fe3fe506199f1230f5a591b490600090a250565b6000818152600260205260408120546001600160a01b0316806105495760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b60448201526064016106ce565b600b546000906001600160a01b03163314610afd5760405162461bcd60e51b81526004016106ce906120be565b610b0b600c80546001019055565b610b1d82610b18600c5490565b6112b5565b4260126000610b2b600c5490565b81526020810191909152604001600020556001600160a01b038216610b4f600c5490565b6040517ff3cea5493d790af0133817606f7350a91d7f154ea52eaa79d179d4d231e5010290600090a3600c54610549565b919050565b60006001600160a01b038216610bef5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b60648201526084016106ce565b506001600160a01b031660009081526003602052604090205490565b610c13610eb3565b610c1d60006112cf565b565b6000610c2a600c5490565b905090565b6060600180546105b090611fd7565b610c49338383611321565b5050565b610c55610eb3565b600f81905560405181907f2ad2ae73af42f598ecb723109218def6abfe2e801eb5719ab4acbf9adc91c65d90600090a250565b610c923383610fda565b610cae5760405162461bcd60e51b81526004016106ce90612011565b610cba848484846113ef565b50505050565b600b546001600160a01b03163314610cea5760405162461bcd60e51b81526004016106ce906120be565b600b54610d00906001600160a01b031682610f6c565b50565b6000818152600260205260408120546001600160a01b03161515610549565b6000818152600260205260409020546060906001600160a01b0316610d4657600080fd5b610d4e611422565b610d5783611431565b604051602001610d68929190612220565b6040516020818303038152906040529050919050565b6060610d88611422565b604051602001610d98919061225f565b604051602081830303815290604052905090565b610db4610eb3565b6001600160a01b038116610e195760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016106ce565b610d00816112cf565b6001600160a01b038116600090815260106020908152604091829020805483518184028101840190945280845260609392830182828015610e8257602002820191906000526020600020905b815481526020019060010190808311610e6e575b50505050509050919050565b60006001600160e01b0319821663780e9d6360e01b1480610549575061054982611532565b600a546001600160a01b03163314610c1d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106ce565b6000818152600260205260409020546001600160a01b0316610d005760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b60448201526064016106ce565b600081815260046020526040902080546001600160a01b0319166001600160a01b0384169081179091558190610fa182610a70565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600080610fe683610a70565b9050806001600160a01b0316846001600160a01b0316148061102d57506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b806110515750836001600160a01b031661104684610633565b6001600160a01b0316145b949350505050565b826001600160a01b031661106c82610a70565b6001600160a01b0316146110d05760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b60648201526084016106ce565b6001600160a01b0382166111325760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b60648201526084016106ce565b61113d838383611582565b611148600082610f6c565b6001600160a01b0383166000908152600360205260408120805460019290611171908490612290565b90915550506001600160a01b038216600090815260036020526040812080546001929061119f9084906122a3565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a461076f83838361163a565b600061121182610a70565b905061121f81600084611582565b61122a600083610f6c565b6001600160a01b0381166000908152600360205260408120805460019290611253908490612290565b909155505060008281526002602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a4610c498160008461163a565b610c49828260405180602001604052806000815250611849565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b816001600160a01b0316836001600160a01b0316036113825760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c65720000000000000060448201526064016106ce565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6113fa848484611059565b6114068484848461187c565b610cba5760405162461bcd60e51b81526004016106ce906122b6565b6060600d80546105b090611fd7565b6060816000036114585750506040805180820190915260018152600360fc1b602082015290565b8160005b8115611482578061146c81612308565b915061147b9050600a836120aa565b915061145c565b60008167ffffffffffffffff81111561149d5761149d611dd3565b6040519080825280601f01601f1916602001820160405280156114c7576020820181803683370190505b5090505b8415611051576114dc600183612290565b91506114e9600a86612321565b6114f49060306122a3565b60f81b818381518110611509576115096120e0565b60200101906001600160f81b031916908160001a90535061152b600a866120aa565b94506114cb565b60006001600160e01b031982166380ac58cd60e01b148061156357506001600160e01b03198216635b5e139f60e01b145b8061054957506301ffc9a760e01b6001600160e01b0319831614610549565b6001600160a01b0383166115dd576115d881600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b611600565b816001600160a01b0316836001600160a01b03161461160057611600838261197d565b6001600160a01b0382166116175761076f81611a1a565b826001600160a01b0316826001600160a01b03161461076f5761076f8282611ac9565b6001600160a01b03831615611774576000818152601160209081526040808320546001600160a01b038716845260109092528220805491929161167f90600190612290565b8154811061168f5761168f6120e0565b60009182526020808320909101546001600160a01b0388168352601090915260409091208054919250906116c590600190612290565b815481106116d5576116d56120e0565b906000526020600020015460106000876001600160a01b03166001600160a01b031681526020019081526020016000208381548110611716576117166120e0565b60009182526020808320909101929092556001600160a01b038716815260109091526040902080548061174b5761174b612335565b600082815260208082208301600019908101839055909201909255918152601190915260409020555b6001600160a01b038216156117c1576001600160a01b0382166000908152601060208181526040808420805486865260118452918520829055928252600181018355918352909120018190555b6001600160a01b038316158015906117e157506001600160a01b03821615155b1561076f57600b54604051630188bef960e31b8152600481018390526001600160a01b0390911690630c45f7c890602401600060405180830381600087803b15801561182c57600080fd5b505af1158015611840573d6000803e3d6000fd5b50505050505050565b6118538383611b0d565b611860600084848461187c565b61076f5760405162461bcd60e51b81526004016106ce906122b6565b60006001600160a01b0384163b1561197257604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906118c090339089908890889060040161234b565b6020604051808303816000875af19250505080156118fb575060408051601f3d908101601f191682019092526118f891810190612388565b60015b611958573d808015611929576040519150601f19603f3d011682016040523d82523d6000602084013e61192e565b606091505b5080516000036119505760405162461bcd60e51b81526004016106ce906122b6565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611051565b506001949350505050565b6000600161198a84610b85565b6119949190612290565b6000838152600760205260409020549091508082146119e7576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b600854600090611a2c90600190612290565b60008381526009602052604081205460088054939450909284908110611a5457611a546120e0565b906000526020600020015490508060088381548110611a7557611a756120e0565b6000918252602080832090910192909255828152600990915260408082208490558582528120556008805480611aad57611aad612335565b6001900381819060005260206000200160009055905550505050565b6000611ad483610b85565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b6001600160a01b038216611b635760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f206164647265737360448201526064016106ce565b6000818152600260205260409020546001600160a01b031615611bc85760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000060448201526064016106ce565b611bd460008383611582565b6001600160a01b0382166000908152600360205260408120805460019290611bfd9084906122a3565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4610c496000838361163a565b6001600160e01b031981168114610d0057600080fd5b600060208284031215611c8b57600080fd5b8135611c9681611c63565b9392505050565b80356001600160a01b0381168114610b8057600080fd5b600060208284031215611cc657600080fd5b611c9682611c9d565b60005b83811015611cea578181015183820152602001611cd2565b50506000910152565b60008151808452611d0b816020860160208601611ccf565b601f01601f19169290920160200192915050565b602081526000611c966020830184611cf3565b600060208284031215611d4457600080fd5b5035919050565b60008060408385031215611d5e57600080fd5b611d6783611c9d565b946020939093013593505050565b600080600060608486031215611d8a57600080fd5b611d9384611c9d565b9250611da160208501611c9d565b9150604084013590509250925092565b60008060408385031215611dc457600080fd5b50508035926020909101359150565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff80841115611e0457611e04611dd3565b604051601f8501601f19908116603f01168101908282118183101715611e2c57611e2c611dd3565b81604052809350858152868686011115611e4557600080fd5b858560208301376000602087830101525050509392505050565b600060208284031215611e7157600080fd5b813567ffffffffffffffff811115611e8857600080fd5b8201601f81018413611e9957600080fd5b61105184823560208401611de9565b60008060408385031215611ebb57600080fd5b611ec483611c9d565b915060208301358015158114611ed957600080fd5b809150509250929050565b60008060008060808587031215611efa57600080fd5b611f0385611c9d565b9350611f1160208601611c9d565b925060408501359150606085013567ffffffffffffffff811115611f3457600080fd5b8501601f81018713611f4557600080fd5b611f5487823560208401611de9565b91505092959194509250565b60008060408385031215611f7357600080fd5b611f7c83611c9d565b9150611f8a60208401611c9d565b90509250929050565b6020808252825182820181905260009190848201906040850190845b81811015611fcb57835183529284019291840191600101611faf565b50909695505050505050565b600181811c90821680611feb57607f821691505b60208210810361200b57634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252602e908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526d1c881b9bdc88185c1c1c9bdd995960921b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b600081600019048311821515161561208f5761208f61205f565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826120b9576120b9612094565b500490565b6020808252600890820152676f6e6c79204f544360c01b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b601f82111561076f57600081815260208120601f850160051c8101602086101561211d5750805b601f850160051c820191505b8181101561213c57828155600101612129565b505050505050565b815167ffffffffffffffff81111561215e5761215e611dd3565b6121728161216c8454611fd7565b846120f6565b602080601f8311600181146121a7576000841561218f5750858301515b600019600386901b1c1916600185901b17855561213c565b600085815260208120601f198616915b828110156121d6578886015182559484019460019091019084016121b7565b50858210156121f45787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008251612216818460208701611ccf565b9190910192915050565b60008351612232818460208801611ccf565b835190830190612246818360208801611ccf565b64173539b7b760d91b9101908152600501949350505050565b60008251612271818460208701611ccf565b6c31b7b73a3930b1ba173539b7b760991b920191825250600d01919050565b818103818111156105495761054961205f565b808201808211156105495761054961205f565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60006001820161231a5761231a61205f565b5060010190565b60008261233057612330612094565b500690565b634e487b7160e01b600052603160045260246000fd5b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061237e90830184611cf3565b9695505050505050565b60006020828403121561239a57600080fd5b8151611c9681611c6356fea164736f6c6343000810000a00000000000000000000000021be370d5312f44cb42ce377bc9b8a0cef1a4c830000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000003368747470733a2f2f6170692e7969656c64696669636174696f6e2e636f6d2f6f74637964662f66746d2f6d657461646174612f00000000000000000000000000
Deployed Bytecode
0x6080604052600436106102c95760003560e01c8063a47a5e6111610175578063daea4706116100dc578063ec29c39d11610095578063f2fde38b1161006f578063f2fde38b146108ff578063f8143e2e1461091f578063fa3f97b914610935578063ffc965471461095557600080fd5b8063ec29c39d1461089f578063ef040646146108bf578063f0f44260146108df57600080fd5b8063daea4706146107d9578063dd2b7022146107ec578063dd6923111461080c578063e62b9e6c1461083d578063e9d640801461086a578063eb3207c61461087d57600080fd5b8063c1dc1a301161012e578063c1dc1a3014610726578063c52aeaaf14610746578063c7c3796614610766578063d834123e14610786578063d9a37c49146107a6578063da597489146107c657600080fd5b8063a47a5e6114610672578063a9860a6514610688578063b1b7407d146106a8578063b1c87eb7146106c8578063b7fa7cfc146106de578063bf8987b11461071357600080fd5b8063328d8f7211610234578063720d5db9116101ed57806392f5a348116101c757806392f5a348146105d957806395bd9d3b146105fb5780639b485a531461061b578063a21f0e0c1461065257600080fd5b8063720d5db91461054c5780638da5cb5b146105a857806392e86e99146105c657600080fd5b8063328d8f72146104895780633fc8cef3146104a9578063474a0a9b146104e15780634bba74a61461050157806361d027b314610517578063715018a61461053757600080fd5b80631616e4a7116102865780631616e4a7146103a45780631dcbb5b3146103dc57806320a5656d14610409578063238dafe0146104295780632c1904791461045357806330eac4471461047357600080fd5b8063064851d4146102ce5780630c45f7c8146102f05780630e51dab2146103105780630f02206214610323578063126acd2f14610336578063150b7a021461035f575b600080fd5b3480156102da57600080fd5b506102ee6102e9366004615360565b610985565b005b3480156102fc57600080fd5b506102ee61030b366004615399565b610b4c565b6102ee61031e3660046153b2565b610ba4565b6102ee6103313660046153f3565b610dc7565b34801561034257600080fd5b5061034c60035481565b6040519081526020015b60405180910390f35b34801561036b57600080fd5b5061038b61037a366004615449565b630a85bd0160e11b95945050505050565b6040516001600160e01b03199091168152602001610356565b3480156103b057600080fd5b5061034c6103bf3660046154e8565b601560209081526000928352604080842090915290825290205481565b3480156103e857600080fd5b506103fc6103f7366004615399565b611452565b6040516103569190615514565b34801561041557600080fd5b5061034c610424366004615399565b61150a565b34801561043557600080fd5b506002546104439060ff1681565b6040519015158152602001610356565b34801561045f57600080fd5b506102ee61046e366004615399565b61152b565b34801561047f57600080fd5b5061034c60085481565b34801561049557600080fd5b506102ee6104a436600461559a565b611584565b3480156104b557600080fd5b50600b546104c9906001600160a01b031681565b6040516001600160a01b039091168152602001610356565b3480156104ed57600080fd5b506102ee6104fc366004615399565b6115ee565b34801561050d57600080fd5b5061034c60055481565b34801561052357600080fd5b506009546104c9906001600160a01b031681565b34801561054357600080fd5b506102ee6115fb565b34801561055857600080fd5b5061056c6105673660046155b7565b61160f565b604080516001600160a01b03978816815295871660208701528501939093526060840191909152608083015290911660a082015260c001610356565b3480156105b457600080fd5b506000546001600160a01b03166104c9565b6102ee6105d4366004615649565b611673565b3480156105e557600080fd5b506105ee611c5a565b604051610356919061578f565b34801561060757600080fd5b506102ee610616366004615399565b611cbc565b34801561062757600080fd5b5060025461063d90610100900463ffffffff1681565b60405163ffffffff9091168152602001610356565b34801561065e57600080fd5b506102ee61066d366004615399565b611d2a565b34801561067e57600080fd5b5061034c60065481565b34801561069457600080fd5b506102ee6106a3366004615399565b611d98565b3480156106b457600080fd5b506102ee6106c33660046157dc565b611da5565b3480156106d457600080fd5b5061034c60075481565b3480156106ea57600080fd5b506106fe6106f9366004615801565b611ddf565b60408051928352602083019190915201610356565b6102ee61072136600461581e565b611e72565b34801561073257600080fd5b506102ee61074136600461586f565b612447565b34801561075257600080fd5b506102ee6107613660046155b7565b61268a565b34801561077257600080fd5b506102ee6107813660046158dc565b612986565b34801561079257600080fd5b506102ee6107a1366004615801565b6129ac565b3480156107b257600080fd5b50600c546104c9906001600160a01b031681565b6102ee6107d43660046155b7565b6129d6565b6102ee6107e73660046158f9565b612e20565b3480156107f857600080fd5b506102ee61080736600461592f565b613207565b34801561081857600080fd5b5061082c610827366004615399565b61396f565b604051610356959493929190615984565b34801561084957600080fd5b5061034c610858366004615801565b600d6020526000908152604090205481565b6102ee610878366004615ace565b613b1e565b34801561088957600080fd5b50610892613ff6565b6040516103569190615b01565b3480156108ab57600080fd5b506102ee6108ba366004615399565b61404d565b3480156108cb57600080fd5b506102ee6108da366004615399565b61405a565b3480156108eb57600080fd5b506102ee6108fa366004615801565b61427a565b34801561090b57600080fd5b506102ee61091a366004615801565b6142a4565b34801561092b57600080fd5b5061034c60045481565b34801561094157600080fd5b50600a546104c9906001600160a01b031681565b34801561096157600080fd5b50610443610970366004615801565b600e6020526000908152604090205460ff1681565b61098d61431d565b6001600160a01b0382166000908152600e602052604090205481151560ff9091161515036109f05760405162461bcd60e51b815260206004820152600b60248201526a6d75737420746f67676c6560a81b60448201526064015b60405180910390fd5b6001600160a01b0382166000908152600e60205260409020805460ff19168215801591909117909155610a7d57600f80546001600160a01b0384166000818152601060205260408120839055600183018455929092527f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac8020180546001600160a01b03191690911790555050565b6001600160a01b03821660009081526010602052604081208054919055600f8054610aaa90600190615b4f565b81548110610aba57610aba615b68565b600091825260209091200154600f80546001600160a01b039092169183908110610ae657610ae6615b68565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600f805480610b2557610b25615b7e565b600082815260209020810160001990810180546001600160a01b0319169055019055505050565b600c546001600160a01b03163314610b905760405162461bcd60e51b815260206004820152600760248201526613d3931653919560ca1b60448201526064016109e7565b600090815260116020526040812060080155565b600260015403610bc65760405162461bcd60e51b81526004016109e790615b94565b600260015560008481526011602052604090819020600c5491516331a9108f60e11b815260048101879052600a909101916001600160a01b031690636352211e90602401602060405180830381865afa158015610c27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4b9190615bcb565b6001600160a01b0316336001600160a01b031614610c9c5760405162461bcd60e51b815260206004820152600e60248201526d2827a7a62aa8221d1037bbb732b960911b60448201526064016109e7565b600084118015610cb0575083816005015414155b15610cbd57600581018490555b80546001600160a01b0316610cd0573492505b8215610d235782816002016000828254610cea9190615be8565b9250508190555082816003016000828254610d059190615be8565b90915550508054610d2390339030906001600160a01b031686614377565b818015610d34575060008160040154115b15610d625760048101805460009091556001820154610d6090309033906001600160a01b031684614377565b505b8054610d77906001600160a01b0316846146ba565b6040805185815260208101859052831515818301529051339187917f58e6712c5d6a0df543cfa5ba45a39269057354622387fc3f19d385b36049922c9181900360600190a3505060018055505050565b60025460ff1680610de257506000546001600160a01b031633145b610e205760405162461bcd60e51b815260206004820152600f60248201526e1412d1d3d1918e88195b98589b1959608a1b60448201526064016109e7565b60008581526014602090815260408220805460018101825590835290822060069091020180546001600160a01b0319908116331782556005820180546001600160a01b0386811691909316179055426003830155909190819087166111a4576007543411610ec35760405162461bcd60e51b815260206004820152601060248201526f0a0968e9e8c8c7440dccacac8408aa8960831b60448201526064016109e7565b600b546001600160a01b03166000908152600e602052604090205460ff16610f265760405162461bcd60e51b81526020600482015260166024820152751412d1d3d1918e8815d15512081b9bdd081d985b1a5960521b60448201526064016109e7565b600060075434610f369190615b4f565b600b546040516370a0823160e01b81523060048201529192506001600160a01b03169060009082906370a0823190602401602060405180830381865afa158015610f84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa89190615bfb565b9050600b60009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0846040518263ffffffff1660e01b81526004016000604051808303818588803b158015610ffa57600080fd5b505af115801561100e573d6000803e3d6000fd5b50506040516370a0823160e01b81523060048201526001600160a01b038616935063a9059cbb9250339150849084906370a0823190602401602060405180830381865afa158015611063573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110879190615bfb565b6110919190615b4f565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af11580156110dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111009190615c14565b50600b546040805163313ce56760e01b815290516001600160a01b039092169650670de0b6b3a764000091879163313ce5679160048083019260209291908290030181865afa158015611157573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117b9190615c31565b61118690600a615d32565b6111909085615d41565b61119a9190615d60565b9350505050611257565b60075434146111e95760405162461bcd60e51b8152602060048201526011602482015270504b474f46463a206f666665722066656560781b60448201526064016109e7565b6001600160a01b0387166000908152600e602052604090205460ff166112515760405162461bcd60e51b815260206004820152601b60248201527f504b474f46463a20696e76616c6964206f6666657220746f6b656e000000000060448201526064016109e7565b50859050845b60075415611275576112753061126b6146f5565b6000600754614377565b6040516370a0823160e01b8152336004820152829082906001600160a01b038316906370a0823190602401602060405180830381865afa1580156112bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e19190615bfb565b10156113255760405162461bcd60e51b8152602060048201526013602482015272504b474f46463a206261642062616c616e636560681b60448201526064016109e7565b604051636eb1769f60e11b815233600482015230602482015282906001600160a01b0383169063dd62ed3e90604401602060405180830381865afa158015611371573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113959190615bfb565b10156113dc5760405162461bcd60e51b8152602060048201526016602482015275504b474f46463a206e65656420616c6c6f77616e636560501b60448201526064016109e7565b6001840180546001600160a01b0319166001600160a01b0385169081179091556002850183905560048501879055604080519182526020820184905233918b917f01fd1259a9f3b93d5a2865e6f3824ab8d2f7a0e6ebf001b3974acfce0e44d24b910160405180910390a3505050505050505050565b606060146000838152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156114ff5760008481526020908190206040805160c0810182526006860290920180546001600160a01b03908116845260018083015482168587015260028301549385019390935260038201546060850152600482015460808501526005909101541660a08301529083529092019101611487565b505050509050919050565b6012818154811061151a57600080fd5b600091825260209091200154905081565b61153361431d565b620186a081111561157f5760405162461bcd60e51b81526020600482015260166024820152756d757374206265206c657373207468616e203130302560501b60448201526064016109e7565b600655565b61158c61431d565b60025481151560ff9091161515036115db5760405162461bcd60e51b8152602060048201526012602482015271534554454e41424c45443a20746f67676c6560701b60448201526064016109e7565b6002805460ff1916911515919091179055565b6115f661431d565b600355565b61160361431d565b61160d6000614729565b565b6014602052816000526040600020818154811061162b57600080fd5b60009182526020909120600690910201805460018201546002830154600384015460048501546005909501546001600160a01b03948516975092841695509093909290911686565b6002600154036116955760405162461bcd60e51b81526004016109e790615b94565b600260018190555460ff16806116b557506000546001600160a01b031633145b6116f25760405162461bcd60e51b815260206004820152600e60248201526d1412d1d0d48e88195b98589b195960921b60448201526064016109e7565b600254875161010090910463ffffffff1610156117455760405162461bcd60e51b8152602060048201526011602482015270504b4743523a206d61782061737365747360781b60448201526064016109e7565b6001600160a01b038416158061177357506001600160a01b0384166000908152600e602052604090205460ff165b6117b85760405162461bcd60e51b81526020600482015260166024820152751412d1d0d48e88185cdcd95d081b9bdd081d985b1a5960521b60448201526064016109e7565b600c546040516335313c2160e11b81523360048201526000916001600160a01b031690636a627842906024016020604051808303816000875af1158015611803573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118279190615bfb565b60008181526011602052604081209192506002820190805b8b51811015611a175760006001600160a01b03168c828151811061186557611865615b68565b6020026020010151600001516001600160a01b0316036118ab578b818151811061189157611891615b68565b602002602001015160400151826118a89190615be8565b91505b6118ce338d83815181106118c1576118c1615b68565b6020026020010151614779565b600060405180608001604052808e84815181106118ed576118ed615b68565b6020026020010151600001516001600160a01b031681526020018e848151811061191957611919615b68565b60200260200101516020015160028111156119365761193661596e565b81526020018e848151811061194d5761194d615b68565b60200260200101516040015181526020018e848151811061197057611970615b68565b6020908102919091018101516060015190915285546001810187556000878152829020835160039092020180546001600160a01b031981166001600160a01b0390931692831782559284015193945084939092909183916001600160a81b03191617600160a01b8360028111156119e9576119e961596e565b0217905550604082015160018201556060909101516002909101555080611a0f81615d82565b91505061183f565b50600354611a259082615be8565b341015611a745760405162461bcd60e51b815260206004820152601e60248201527f504b4743523a204554482061737365747320706c75732073657276696365000060448201526064016109e7565b60035415611a9257611a9230611a886146f5565b6000600354614377565b88158015611a9e575089155b80611abd57508815801590611ab257508915155b8015611abd57508989115b611b095760405162461bcd60e51b815260206004820152601d60248201527f504b4743523a2076616c696461746520756e6c6f636b20706572696f6400000060448201526064016109e7565b42600183810191909155600283018b9055600383018a90556005830180546001600160a01b038b81166001600160a01b031992831617909255600685018a90556007850180548a841690831617905585548116331786559185018054888316931692909217909155600c5460405163be606dbb60e01b81526004810187905291169063be606dbb90602401600060405180830381600087803b158015611bae57600080fd5b505af1158015611bc2573d6000803e3d6000fd5b5050601280546000888152601360205260408082208390556001830184559290527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444018790558d5190513393508792507f027aa4f47f9c239d6955ac82ff10adafd9f5fd184d731d73b9e674f836920c5e91611c419190815260200190565b60405180910390a3505060018055505050505050505050565b6060600f805480602002602001604051908101604052809291908181526020018280548015611cb257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611c94575b5050505050905090565b611cc461431d565b6064611cd4620186a06014615d41565b611cde9190615d60565b811115611d255760405162461bcd60e51b81526020600482015260156024820152746d757374206265206c657373207468616e2032302560581b60448201526064016109e7565b600555565b611d3261431d565b6064611d42620186a06019615d41565b611d4c9190615d60565b811115611d935760405162461bcd60e51b81526020600482015260156024820152746d757374206265206c657373207468616e2032352560581b60448201526064016109e7565b600455565b611da061431d565b600855565b600260015403611dc75760405162461bcd60e51b81526004016109e790615b94565b6002600155611dd73383836148b5565b505060018055565b600a5460009081906001600160a01b0316611dfc57600080611e69565b600a5460405163a310e73960e01b81526001600160a01b0385811660048301529091169063a310e739906024016040805180830381865afa158015611e45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e699190615d9b565b91509150915091565b600260015403611e945760405162461bcd60e51b81526004016109e790615b94565b600260018190555460ff1680611eb457506000546001600160a01b031633145b611eef5760405162461bcd60e51b815260206004820152600c60248201526b1092538e88195b98589b195960a21b60448201526064016109e7565b600c546040516331a9108f60e11b8152600481018790526000916001600160a01b031690636352211e90602401602060405180830381865afa158015611f39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5d9190615bcb565b6000878152601160209081526040808320815160029091018054610120948102830185019093526101008201838152959650939490939284928491879085015b8282101561202b57600084815260209081902060408051608081019091526003850290910180546001600160a01b03811683529192909190830190600160a01b900460ff166002811115611ff357611ff361596e565b60028111156120045761200461596e565b81526020016001820154815260200160028201548152505081526020019060010190611f9d565b505050908252506001820154602082015260028201546040820152600382015460608201526004820154608082015260058201546001600160a01b0390811660a0830152600683015460c0808401919091526007909301541660e0909101528101519091506120d25760405162461bcd60e51b81526020600482015260136024820152721092538e881b9bdd0818dbdb999a59dd5c9959606a1b60448201526064016109e7565b856001600160a01b03168160a001516001600160a01b0316146121285760405162461bcd60e51b815260206004820152600e60248201526d2124a71d103130b2103a37b5b2b760911b60448201526064016109e7565b848160c001511461216d5760405162461bcd60e51b815260206004820152600f60248201526e1092538e8818985908185b5bdd5b9d608a1b60448201526064016109e7565b60e08101516001600160a01b0316156121dc578060e001516001600160a01b0316336001600160a01b0316146121dc5760405162461bcd60e51b81526020600482015260146024820152731092538e881b9bdd081dda1a5d195b1a5cdd195960621b60448201526064016109e7565b6000620186a06005548360c001516121f49190615d41565b6121fe9190615d60565b905060008061220c85611ddf565b9092509050811561223957806122228385615d41565b61222c9190615d60565b6122369084615b4f565b92505b6000838560c0015161224b9190615b4f565b60a086015190915033906001600160a01b03166122a9575030348a146122a95760405162461bcd60e51b8152602060048201526013602482015272084929c7440dcdee840cadcdeeaced0408aa89606b1b60448201526064016109e7565b6122ba8c828a8960a0015189614a84565b6122ca81888860a0015185614377565b600c60009054906101000a90046001600160a01b03166001600160a01b03166342842e0e88338f6040518463ffffffff1660e01b815260040161230f93929190615dbf565b600060405180830381600087803b15801561232957600080fd5b505af115801561233d573d6000803e3d6000fd5b5050600c5460405163be606dbb60e01b81526001600160a01b03909116925063be606dbb9150612375908f9060040190815260200190565b600060405180830381600087803b15801561238f57600080fd5b505af11580156123a3573d6000803e3d6000fd5b50505060c087015160a08801516001600160a01b03166000908152600d602052604081208054929350916123d8908490615be8565b909155505088156123ef576123ef338d60006148b5565b866001600160a01b03168c7ff523bee1c395e32783207e84ef1826e9d5e9b43b3179a55b83a75377f38077b5338e8e60405161242d93929190615dbf565b60405180910390a350506001805550505050505050505050565b6002600154036124695760405162461bcd60e51b81526004016109e790615b94565b6002600155600c546040516331a9108f60e11b81526004810188905233916001600160a01b031690636352211e90602401602060405180830381865afa1580156124b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124db9190615bcb565b6001600160a01b0316146125245760405162461bcd60e51b815260206004820152601060248201526f2aa22820aa22a825a39d1037bbb732b960811b60448201526064016109e7565b6001600160a01b038316158061255257506001600160a01b0383166000908152600e602052604090205460ff165b61259e5760405162461bcd60e51b815260206004820152601a60248201527f555044415445504b473a206173736574206e6f742076616c696400000000000060448201526064016109e7565b60008681526011602052604090206007810180546001600160a01b038087166001600160a01b0319928316179092556008830185905560098301805485841692169190911790558154600290920191163303612607576002810186905560038101859055612616565b80600201549550806003015494505b60028101546003820154604080516001600160a01b038881168252602082018890528616818301526060810193909352608083019190915251339189917f2efaa9c195616ac6d1b5d9691b59d9ea46789e66b70118ea08ba025ebf08a6b59181900360a00190a35050600180555050505050565b6002600154036126ac5760405162461bcd60e51b81526004016109e790615b94565b600260015560008281526014602052604081208054839081106126d1576126d1615b68565b60009182526020918290206040805160c08101825260069390930290910180546001600160a01b0390811684526001820154811694840194909452600281015483830152600381015460608401526004808201546080850152600590910154841660a0840152600c5491516331a9108f60e11b815290810187905291935033921690636352211e90602401602060405180830381865afa158015612779573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061279d9190615bcb565b6001600160a01b031614806127bb575080516001600160a01b031633145b6127fa5760405162461bcd60e51b815260206004820152601060248201526f2922a522a1aa27a3231d1037bbb732b960811b60448201526064016109e7565b6000838152601460205260409020805461281690600190615b4f565b8154811061282657612826615b68565b906000526020600020906006020160146000858152602001908152602001600020838154811061285857612858615b68565b60009182526020808320845460069093020180546001600160a01b03199081166001600160a01b0394851617825560018087015490830180548316918616919091179055600280870154908301556003808701549083015560048087015490830155600595860154959091018054909116949092169390931790558481526014909152604090208054806128ee576128ee615b7e565b60008281526020812060066000199093019283020180546001600160a01b031990811682556001820180548216905560028201839055600382018390556004820192909255600501805490911690559055604051339084907fbe4a9d5e7c5889dba51d4be13ca36cc0eec3014f0f6b6eb6bfdd5b415483540b906129759086815260200190565b60405180910390a350506001805550565b61298e61431d565b6002805464ffffffff00191660ff9290921661010002919091179055565b6129b461431d565b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b6002600154036129f85760405162461bcd60e51b81526004016109e790615b94565b6002600155600c546040516331a9108f60e11b81526004810184905233916001600160a01b031690636352211e90602401602060405180830381865afa158015612a46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a6a9190615bcb565b6001600160a01b031614612ac05760405162461bcd60e51b815260206004820152601760248201527f54524144453a2062616420736f75726365206f776e657200000000000000000060448201526064016109e7565b80600003612ae857336000908152601560209081526040808320858452909152812055611dd7565b336000908152601560209081526040808320858452909152808220839055600c5490516331a9108f60e11b8152600481018490526001600160a01b0390911690636352211e90602401602060405180830381865afa158015612b4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b729190615bcb565b6001600160a01b0381166000908152601560209081526040808320868452909152902054909150839003612e045760085415612c01576008543414612beb5760405162461bcd60e51b815260206004820152600f60248201526e0a8a482888a7440dccacac8408aa89608b1b60448201526064016109e7565b612c0130612bf76146f5565b6000600854614377565b600c546040516323b872dd60e01b81526001600160a01b03909116906323b872dd90612c3590339085908890600401615dbf565b600060405180830381600087803b158015612c4f57600080fd5b505af1158015612c63573d6000803e3d6000fd5b5050600c546040516323b872dd60e01b81526001600160a01b0390911692506323b872dd9150612c9b90849033908790600401615dbf565b600060405180830381600087803b158015612cb557600080fd5b505af1158015612cc9573d6000803e3d6000fd5b5050600c5460405163be606dbb60e01b8152600481018790526001600160a01b03909116925063be606dbb9150602401600060405180830381600087803b158015612d1357600080fd5b505af1158015612d27573d6000803e3d6000fd5b5050600c5460405163be606dbb60e01b8152600481018690526001600160a01b03909116925063be606dbb9150602401600060405180830381600087803b158015612d7157600080fd5b505af1158015612d85573d6000803e3d6000fd5b50503360008181526015602081815260408084208a855282528084208490556001600160a01b03881680855292825280842089855282528084209390935582518981529081018890529094509192507f4b5796113f074ebf8f11d5bcdeb6349b2fbe47abed78419cdcdbbc15c6fcf845910160405180910390a3612e17565b3415612e1757612e173033600034614377565b50505060018055565b600260015403612e425760405162461bcd60e51b81526004016109e790615b94565b600260018190555460ff1680612e6257506000546001600160a01b031633145b612ea05760405162461bcd60e51b815260206004820152600f60248201526e1413d3d314d5ce88195b98589b1959608a1b60448201526064016109e7565b6000848152601160205260409020600f810154600a90910190831015612f085760405162461bcd60e51b815260206004820152601b60248201527f504f4f4c53573a2065787065637465642073776170207072696365000000000060448201526064016109e7565b6000816003015411612f505760405162461bcd60e51b8152602060048201526011602482015270504f4f4c53573a206c697175696469747960781b60448201526064016109e7565b6000670de0b6b3a76400008260050154866ec097ce7bc90715b34b9f1000000000612f7b9190615d41565b612f859190615d60565b612f8f9190615d60565b9050816003015481111561301857600582015460038301548691670de0b6b3a764000091612fbd9190615d41565b612fc79190615d60565b9550808611156130105760405162461bcd60e51b8152602060048201526014602482015273504f4f4c53573a206261636b757020636865636b60601b60448201526064016109e7565b505060038101545b8082600301600082825461302c9190615b4f565b9091555050600454600090620186a0906130469088615d41565b6130509190615d60565b905060008061305e33611ddf565b9092509050811561308b57806130748385615d41565b61307e9190615d60565b6130889084615b4f565b92505b6000613097848a615b4f565b9050808660040160008282546130ad9190615be8565b9091555050600186015433906001600160a01b031661311257309050893410156131125760405162461bcd60e51b81526020600482015260166024820152750a09e9e98a6ae7440dcdee840cadcdeeaced0408aa8960531b60448201526064016109e7565b6001870154613130908c9083908b906001600160a01b031689614a84565b600187015461314c90829030906001600160a01b031685614377565b6001870154613164906001600160a01b03168b6146ba565b865461317d90309033906001600160a01b031689614377565b86546001600160a01b03166000908152600d6020526040812080548892906131a6908490615be8565b909155505086546001880154604080516001600160a01b039384168152602081018a90529290911690820152606081018b905233908c907fc0400bc4a7d71dd0136e5c1772e5cf3fdb9c90d825057feb726622fbc86b256090608001611c41565b6002600154036132295760405162461bcd60e51b81526004016109e790615b94565b600260018190555460ff168061324957506000546001600160a01b031633145b61328a5760405162461bcd60e51b81526020600482015260126024820152711050d0d1541513d1918e88195b98589b195960721b60448201526064016109e7565b600c546040516331a9108f60e11b81526004810186905233916001600160a01b031690636352211e90602401602060405180830381865afa1580156132d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132f79190615bcb565b6001600160a01b0316146133405760405162461bcd60e51b815260206004820152601060248201526f20a1a1a2a82a27a3231d1037bbb732b960811b60448201526064016109e7565b600084815260146020526040812080548590811061336057613360615b68565b60009182526020918290206040805160c081018252600690930290910180546001600160a01b03908116845260018201548116948401859052600282015492840192909252600381015460608401526004810154608084015260050154811660a083015290925084161461340d5760405162461bcd60e51b81526020600482015260146024820152731050d0d1541513d1918e8818985908185cdcd95d60621b60448201526064016109e7565b818160400151146134585760405162461bcd60e51b81526020600482015260156024820152741050d0d1541513d1918e8818985908185b5bdd5b9d605a1b60448201526064016109e7565b6080810151158061346c5750428160800151115b6134ad5760405162461bcd60e51b81526020600482015260126024820152711050d0d1541513d1918e88195e1c1a5c995960721b60448201526064016109e7565b600085815260116020908152604080832081516002909101805461012094810283018501909352610100820183815291939092849291849190879085015b8282101561357957600084815260209081902060408051608081019091526003850290910180546001600160a01b03811683529192909190830190600160a01b900460ff1660028111156135415761354161596e565b60028111156135525761355261596e565b815260200160018201548152602001600282015481525050815260200190600101906134eb565b5050509082525060018201546020820152600282015460408201526003820154606080830191909152600483015460808084019190915260058401546001600160a01b0390811660a0850152600685015460c085015260079094015490931660e0909201919091529082015190840151919250106136395760405162461bcd60e51b815260206004820152601a60248201527f4143434550544f46463a206c617374207769746864726177616c00000000000060448201526064016109e7565b6000620186a060055484604001516136519190615d41565b61365b9190615d60565b905060008061366933611ddf565b90925090508115613696578061367f8385615d41565b6136899190615d60565b6136939084615b4f565b92505b60008386604001516136a89190615b4f565b90506136c38a87600001518860a00151896020015188614a84565b6136d7866000015133886020015184614377565b600c548651604051632142170760e11b81526001600160a01b03909216916342842e0e9161370c913391908f90600401615dbf565b600060405180830381600087803b15801561372657600080fd5b505af115801561373a573d6000803e3d6000fd5b5050600c5460405163be606dbb60e01b8152600481018e90526001600160a01b03909116925063be606dbb9150602401600060405180830381600087803b15801561378457600080fd5b505af1158015613798573d6000803e3d6000fd5b50505060008b815260146020526040902080549091506137ba90600190615b4f565b815481106137ca576137ca615b68565b9060005260206000209060060201601460008c81526020019081526020016000208a815481106137fc576137fc615b68565b60009182526020808320845460069093020180546001600160a01b03199081166001600160a01b0394851617825560018087015490830180548316918616919091179055600280870154908301556003808701549083015560048087015490830155600595860154959091018054909116949092169390931790558b815260149091526040902080548061389257613892615b7e565b6000828152602080822060066000199094019384020180546001600160a01b031990811682556001820180548216905560028201849055600382018490556004820184905560059091018054909116905591909255604080890151898301516001600160a01b03168452600d9092528220805491929091613914908490615be8565b909155505085516020870151604080890151905133938e937fa2e6f53e775c6ebbe3fab4ba06b07381ae41384f7bfc96a475b1979a1ca0919f9361395793615dbf565b60405180910390a35050600180555050505050505050565b6011602090815260009182526040808320805460018201548351600284018054968702820161012090810190965261010082018781526001600160a01b0380861699600160a01b90960460ff16989416969294919385939192859285015b82821015613a5b57600084815260209081902060408051608081019091526003850290910180546001600160a01b03811683529192909190830190600160a01b900460ff166002811115613a2357613a2361596e565b6002811115613a3457613a3461596e565b815260200160018201548152602001600282015481525050815260200190600101906139cd565b50505090825250600182015460208083019190915260028301546040808401919091526003840154606080850191909152600485015460808086019190915260058601546001600160a01b0390811660a080880191909152600688015460c080890191909152600790980154821660e09097019690965283519687018452600a89015481168752600b8901541693860193909352600c87015491850191909152600d86015490840152600e85015490830152600f90930154928101929092529085565b600260015403613b405760405162461bcd60e51b81526004016109e790615b94565b600260018190555460ff1680613b6057506000546001600160a01b031633145b613b9e5760405162461bcd60e51b815260206004820152600f60248201526e1413d3d310d48e88195b98589b1959608a1b60448201526064016109e7565b60008311613bee5760405162461bcd60e51b815260206004820152601f60248201527f504f4f4c43523a206e65656420746f2070726f7669646520616d6f756e74300060448201526064016109e7565b60008211613c3e5760405162461bcd60e51b815260206004820152601860248201527f504f4f4c43523a206e6565642076616c6964207072696365000000000000000060448201526064016109e7565b6001600160a01b038516151580613c5d57506001600160a01b03841615155b613ca05760405162461bcd60e51b81526020600482015260146024820152731413d3d310d48e881a5b9d985b1a59081c1bdbdb60621b60448201526064016109e7565b613ccd3330876001600160a01b03811615613cbb5786614377565b600354613cc89088615be8565b614377565b6001600160a01b0384161580613d4457506000846001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613d1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d429190615bfb565b115b613d905760405162461bcd60e51b815260206004820152601760248201527f504f4f4c43523a20746f6b656e312076616c696461746500000000000000000060448201526064016109e7565b60035415613df657600354341015613dea5760405162461bcd60e51b815260206004820152601760248201527f504f4f4c43523a2073657276696365206665652045544800000000000000000060448201526064016109e7565b613df630611a886146f5565b600c546040516335313c2160e11b81523360048201526000916001600160a01b031690636a627842906024016020604051808303816000875af1158015613e41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e659190615bfb565b60008181526011602052604090819020600a810180546001600160a01b03199081166001600160a01b038c8116919091178355600b8401805483168c8316179055600c8085018b9055600d85018b9055600f85018a905584546001860180549094168a841617909355600160a01b6001600160a81b03199093163360ff60a01b1916179290921784559054935163be606dbb60e01b815260048101869052949550919390929091169063be606dbb90602401600060405180830381600087803b158015613f3157600080fd5b505af1158015613f45573d6000803e3d6000fd5b5050601280546000878152601360209081526040808320849055600184018555939091527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec344490910187905581516001600160a01b03808e1682528c1691810191909152908101899052606081018890523392508591507f020c7d113c93ec461c5a54f7f999095b38bf3e9428d1fdc12d158c875bda1ee29060800160405180910390a3505060018055505050505050565b60606012805480602002602001604051908101604052809291908181526020018280548015611cb257602002820191906000526020600020905b815481526020019060010190808311614030575050505050905090565b61405561431d565b600755565b60026001540361407c5760405162461bcd60e51b81526004016109e790615b94565b6002600155600081815260116020908152604091829020825160c081018452600a8201546001600160a01b039081168252600b830154811693820193909352600c8083015482860152600d8301546060830152600e8301546080830152600f9092015460a0820152905492516331a9108f60e11b815260048101859052909290911690636352211e90602401602060405180830381865afa158015614125573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141499190615bcb565b6001600160a01b0316336001600160a01b0316146141995760405162461bcd60e51b815260206004820152600d60248201526c2827a7a629269d1037bbb732b960991b60448201526064016109e7565b80516001600160a01b03161515806141bd575060208101516001600160a01b031615155b6142005760405162461bcd60e51b81526020600482015260146024820152731413d3d314934e881a5b9d985b1a59081c1bdbdb60621b60448201526064016109e7565b61420982614b82565b60608101511561422757614227303383600001518460600151614377565b60808101511561424557614245303383602001518460800151614377565b604051339083907f31070a32ba1763d3c4bba8a23f2a3c7e695943aba7ac3c104746c2fe744555d190600090a3505060018055565b61428261431d565b600980546001600160a01b0319166001600160a01b0392909216919091179055565b6142ac61431d565b6001600160a01b0381166143115760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016109e7565b61431a81614729565b50565b6000546001600160a01b0316331461160d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016109e7565b826001600160a01b0316846001600160a01b031603156146b4576001600160a01b038316156143a657826143ae565b6143ae6146f5565b92506001600160a01b03821661454b57306001600160a01b0384160361441a57803410156144155760405162461bcd60e51b81526020600482015260146024820152730a68a9c887440dcdee840cadcdeeaced0408aa8960631b60448201526064016109e7565b6146b4565b6001600160a01b03841630146144655760405162461bcd60e51b815260206004820152601060248201526f53454e443a2062616420736f7572636560801b60448201526064016109e7565b60405147906000906001600160a01b0386169084908381818185875af1925050503d80600081146144b2576040519150601f19603f3d011682016040523d82523d6000602084013e6144b7565b606091505b50509050806144ff5760405162461bcd60e51b815260206004820152601460248201527314d153910e8818dbdd5b19081b9bdd081cd95b9960621b60448201526064016109e7565b6145098383615b4f565b4710156145445760405162461bcd60e51b81526020600482015260096024820152680a68a9c8874408aa8960bb1b60448201526064016109e7565b50506146b4565b6040516370a0823160e01b81526001600160a01b03848116600483015283916000918316906370a0823190602401602060405180830381865afa158015614596573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145ba9190615bfb565b9050306001600160a01b038716036145e5576145e06001600160a01b0383168685614c8a565b6145fa565b6145fa6001600160a01b038316878786614ced565b6146048184615be8565b6040516370a0823160e01b81526001600160a01b0387811660048301528416906370a0823190602401602060405180830381865afa15801561464a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061466e9190615bfb565b10156146b15760405162461bcd60e51b815260206004820152601260248201527114d153910e88115490cc8c08185b5bdd5b9d60721b60448201526064016109e7565b50505b50505050565b60006001600160a01b038316156146d157346146db565b6146db8234615b4f565b905080156146f0576146f03033600084614377565b505050565b6009546000906001600160a01b03161561471957506009546001600160a01b031690565b506000546001600160a01b031690565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000816020015160028111156147915761479161596e565b036147ae576147aa823083600001518460400151614377565b5050565b6001816020015160028111156147c6576147c661596e565b036148785760008160600151116148145760405162461bcd60e51b815260206004820152601260248201527115905312511412d1ce881d1bdad95b88125160721b60448201526064016109e7565b80516060820151604051632142170760e11b81526001600160a01b03909216916342842e0e9161484a9186913091600401615dbf565b600060405180830381600087803b15801561486457600080fd5b505af11580156146b1573d6000803e3d6000fd5b805160608201516040808401519051637921219560e11b81526001600160a01b039093169263f242432a9261484a92879230929190600401615de3565b600082815260116020526040808220600c5491516331a9108f60e11b8152600481018690529092600284019290916001600160a01b0390911690636352211e90602401602060405180830381865afa158015614915573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149399190615bcb565b9050806001600160a01b0316866001600160a01b03161461498d5760405162461bcd60e51b815260206004820152600e60248201526d2825a3aba4aa241d1037bbb732b960911b60448201526064016109e7565b81546149db5760405162461bcd60e51b815260206004820152601860248201527f504b47574954483a20696e76616c6964207061636b616765000000000000000060448201526064016109e7565b60005b8254811015614a05576149f382878388614d0e565b806149fd81615d82565b9150506149de565b5042600483015582546001600160a01b0382811691161480614a2957506003820154155b80614a38575081600301544210155b15614a4657614a4685614b82565b6040516001600160a01b0382169086907f88dc50c8f473f203c7debe6f7be35d0bc0c5c9c76ecee50da2c24902a3727dcf90600090a3505050505050565b8015614b7b576000858152601160205260408120600101546006546001600160a01b039091169190620186a090614abb9085615d41565b614ac59190615d60565b90506000614ad38285615b4f565b90508115614b5e576001600160a01b03831615801590614afb57506001600160a01b03861615155b15614b3c576000614b0d600284615d60565b90506000614b1b8285615b4f565b9050614b2989868985614377565b614b3589898984614377565b5050614b5e565b614b5e876001600160a01b03881615614b555787614b57565b845b8785614377565b8015614b7757614b7787614b706146f5565b8784614377565b5050505b5050505050565b600c54604051630852cd8d60e31b8152600481018390526001600160a01b03909116906342966c6890602401600060405180830381600087803b158015614bc857600080fd5b505af1158015614bdc573d6000803e3d6000fd5b5050506000828152601360205260408120546012805491935090614c0290600190615b4f565b81548110614c1257614c12615b68565b60009182526020808320909101548583526013909152604080832083905581835290912083905560128054919250829184908110614c5257614c52615b68565b6000918252602090912001556012805480614c6f57614c6f615b7e565b60019003818190600052602060002001600090559055505050565b6040516001600160a01b0383166024820152604481018290526146f090849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526150d8565b6146b4846323b872dd60e01b858585604051602401614cb693929190615dbf565b60008381526011602052604081206002018054909190829085908110614d3657614d36615b68565b6000918252602080832060016003909302019182015488845260119091526040909220549092506001600160a01b0390811690881614801590614d7d575060008360030154115b8015614d8c5750826003015442105b15614ea55760018254600160a01b900460ff166002811115614db057614db061596e565b03614dbd575050506146b4565b600083600201548460030154614dd39190615b4f565b9050600080856004015411614e02576000856002015411614df8578460010154614e08565b8460020154614e08565b84600401545b905080421015614e505760405162461bcd60e51b8152602060048201526013602482015272574954483a206c61737420776974686472617760681b60448201526064016109e7565b8183614e5c8342615b4f565b614e669190615d41565b614e709190615d60565b925082600003614e845750505050506146b4565b82846001016000828254614e989190615b4f565b90915550614ead92505050565b600060018301555b60008254600160a01b900460ff166002811115614ecc57614ecc61596e565b03614eef578154614eea90309089906001600160a01b031684614377565b6150cf565b60018254600160a01b900460ff166002811115614f0e57614f0e61596e565b03614ff1578315614f845781546002830154604051632142170760e11b81526001600160a01b03909216916342842e0e91614f4f9130918c91600401615dbf565b600060405180830381600087803b158015614f6957600080fd5b505af1925050508015614f7a575060015b15614eea576150cf565b81546002830154604051632142170760e11b81526001600160a01b03909216916342842e0e91614fba9130918c91600401615dbf565b600060405180830381600087803b158015614fd457600080fd5b505af1158015614fe8573d6000803e3d6000fd5b505050506150cf565b83156150645781546002830154604051637921219560e11b81526001600160a01b039092169163f242432a9161502f9130918c918790600401615de3565b600060405180830381600087803b15801561504957600080fd5b505af192505050801561505a575060015b156150cf576150cf565b81546002830154604051637921219560e11b81526001600160a01b039092169163f242432a9161509c9130918c918790600401615de3565b600060405180830381600087803b1580156150b657600080fd5b505af11580156150ca573d6000803e3d6000fd5b505050505b50505050505050565b600061512d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166151aa9092919063ffffffff16565b8051909150156146f0578080602001905181019061514b9190615c14565b6146f05760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016109e7565b60606151b984846000856151c3565b90505b9392505050565b6060824710156152245760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109e7565b6001600160a01b0385163b61527b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109e7565b600080866001600160a01b031685876040516152979190615e3f565b60006040518083038185875af1925050503d80600081146152d4576040519150601f19603f3d011682016040523d82523d6000602084013e6152d9565b606091505b50915091506152e98282866152f4565b979650505050505050565b606083156153035750816151bc565b8251156153135782518084602001fd5b8160405162461bcd60e51b81526004016109e79190615e5b565b6001600160a01b038116811461431a57600080fd5b803561534d8161532d565b919050565b801515811461431a57600080fd5b6000806040838503121561537357600080fd5b823561537e8161532d565b9150602083013561538e81615352565b809150509250929050565b6000602082840312156153ab57600080fd5b5035919050565b600080600080608085870312156153c857600080fd5b84359350602085013592506040850135915060608501356153e881615352565b939692955090935050565b600080600080600060a0868803121561540b57600080fd5b85359450602086013561541d8161532d565b93506040860135925060608601359150608086013561543b8161532d565b809150509295509295909350565b60008060008060006080868803121561546157600080fd5b853561546c8161532d565b9450602086013561547c8161532d565b935060408601359250606086013567ffffffffffffffff808211156154a057600080fd5b818801915088601f8301126154b457600080fd5b8135818111156154c357600080fd5b8960208285010111156154d557600080fd5b9699959850939650602001949392505050565b600080604083850312156154fb57600080fd5b82356155068161532d565b946020939093013593505050565b602080825282518282018190526000919060409081850190868401855b8281101561558d57815180516001600160a01b039081168652878201518116888701528682015187870152606080830151908701526080808301519087015260a091820151169085015260c09093019290850190600101615531565b5091979650505050505050565b6000602082840312156155ac57600080fd5b81356151bc81615352565b600080604083850312156155ca57600080fd5b50508035926020909101359150565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715615612576156126155d9565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715615641576156416155d9565b604052919050565b600080600080600080600060e0888a03121561566457600080fd5b873567ffffffffffffffff8082111561567c57600080fd5b818a0191508a601f83011261569057600080fd5b81356020828211156156a4576156a46155d9565b6156b2818360051b01615618565b828152818101935060079290921b84018101918d8311156156d257600080fd5b938101935b82851015615740576080858f0312156156f05760008081fd5b6156f86155ef565b85356157038161532d565b815285830135600381106157175760008081fd5b8184015260408681013590820152606080870135908201528452608090940193928101926156d7565b9a508b0135985050506040890135955061575e905060608901615342565b93506080880135925061577360a08901615342565b915061578160c08901615342565b905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b818110156157d05783516001600160a01b0316835292840192918401916001016157ab565b50909695505050505050565b600080604083850312156157ef57600080fd5b82359150602083013561538e81615352565b60006020828403121561581357600080fd5b81356151bc8161532d565b600080600080600060a0868803121561583657600080fd5b8535945060208601356158488161532d565b935060408601359250606086013561585f81615352565b9150608086013561543b8161532d565b60008060008060008060c0878903121561588857600080fd5b86359550602087013594506040870135935060608701356158a88161532d565b92506080870135915060a08701356158bf8161532d565b809150509295509295509295565b60ff8116811461431a57600080fd5b6000602082840312156158ee57600080fd5b81356151bc816158cd565b6000806000806080858703121561590f57600080fd5b84359350602085013592506040850135915060608501356153e88161532d565b6000806000806080858703121561594557600080fd5b8435935060208501359250604085013561595e8161532d565b9396929550929360600135925050565b634e487b7160e01b600052602160045260246000fd5b600061014060018060a01b0380891684526020881515818601526040828916818701526060848188015261024087018951610100878a015281965080518083526102608a019750858201925060009150815b81811015615a2b578351888151168a528781015160038110615a0657634e487b7160e01b85526021600452602485fd5b8a89015280870151878b0152850151858a0152608090980197928601926001016159d6565b50505050918801516101608701528701516101808601528601516101a0850152506080808601516101c085015260a0808701516001600160a01b039081166101e087015260c08089015161020088015260e0808a0151831661022089015288518316858901526020890151909216838801526040880151908701526060870151908601529085015161010085015284015161012084015290509695505050505050565b600080600080600060a08688031215615ae657600080fd5b8535615af18161532d565b9450602086013561541d8161532d565b6020808252825182820181905260009190848201906040850190845b818110156157d057835183529284019291840191600101615b1d565b634e487b7160e01b600052601160045260246000fd5b81810381811115615b6257615b62615b39565b92915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b600060208284031215615bdd57600080fd5b81516151bc8161532d565b80820180821115615b6257615b62615b39565b600060208284031215615c0d57600080fd5b5051919050565b600060208284031215615c2657600080fd5b81516151bc81615352565b600060208284031215615c4357600080fd5b81516151bc816158cd565b600181815b80851115615c89578160001904821115615c6f57615c6f615b39565b80851615615c7c57918102915b93841c9390800290615c53565b509250929050565b600082615ca057506001615b62565b81615cad57506000615b62565b8160018114615cc35760028114615ccd57615ce9565b6001915050615b62565b60ff841115615cde57615cde615b39565b50506001821b615b62565b5060208310610133831016604e8410600b8410161715615d0c575081810a615b62565b615d168383615c4e565b8060001904821115615d2a57615d2a615b39565b029392505050565b60006151bc60ff841683615c91565b6000816000190483118215151615615d5b57615d5b615b39565b500290565b600082615d7d57634e487b7160e01b600052601260045260246000fd5b500490565b600060018201615d9457615d94615b39565b5060010190565b60008060408385031215615dae57600080fd5b505080516020909101519092909150565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260009082015260c00190565b60005b83811015615e36578181015183820152602001615e1e565b50506000910152565b60008251615e51818460208701615e1b565b9190910192915050565b6020815260008251806020840152615e7a816040850160208701615e1b565b601f01601f1916919091016040019291505056fea164736f6c6343000810000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000021be370d5312f44cb42ce377bc9b8a0cef1a4c830000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000003368747470733a2f2f6170692e7969656c64696669636174696f6e2e636f6d2f6f74637964662f66746d2f6d657461646174612f00000000000000000000000000
-----Decoded View---------------
Arg [0] : _weth (address): 0x21be370D5312f44cB42ce377BC9b8a0cEF1A4C83
Arg [1] : _baseTokenURI (string): https://api.yieldification.com/otcydf/ftm/metadata/
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 00000000000000000000000021be370d5312f44cb42ce377bc9b8a0cef1a4c83
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000033
Arg [3] : 68747470733a2f2f6170692e7969656c64696669636174696f6e2e636f6d2f6f
Arg [4] : 74637964662f66746d2f6d657461646174612f00000000000000000000000000
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.